From 0d37606088fe0a93eb3ff52ad8ba296ef21b41aa Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 02:31:31 -0700 Subject: [PATCH 01/18] start of new plugin --- .vscode/settings.json | 57 +- packages/studiocms_socialposter/.gitignore | 23 + packages/studiocms_socialposter/LICENSE | 21 + packages/studiocms_socialposter/astroenv.d.ts | 11 + packages/studiocms_socialposter/package.json | 62 +++ packages/studiocms_socialposter/src/index.ts | 151 ++++++ .../src/pages/socials.astro | 207 ++++++++ .../src/routes/postToBlueSky.ts | 1 + .../src/routes/postToThreads.ts | 1 + .../src/routes/postToTwitter.ts | 6 + .../src/styles/quill.core.css | 491 ++++++++++++++++++ .../src/utils/astroEnvConfig.ts | 12 + .../studiocms_socialposter/src/virtuals.d.ts | 4 + packages/studiocms_socialposter/tsconfig.json | 9 + packages/studiocms_socialposter/ui.d.ts | 291 +++++++++++ pnpm-lock.yaml | 76 ++- 16 files changed, 1395 insertions(+), 28 deletions(-) create mode 100644 packages/studiocms_socialposter/.gitignore create mode 100644 packages/studiocms_socialposter/LICENSE create mode 100644 packages/studiocms_socialposter/astroenv.d.ts create mode 100644 packages/studiocms_socialposter/package.json create mode 100644 packages/studiocms_socialposter/src/index.ts create mode 100644 packages/studiocms_socialposter/src/pages/socials.astro create mode 100644 packages/studiocms_socialposter/src/routes/postToBlueSky.ts create mode 100644 packages/studiocms_socialposter/src/routes/postToThreads.ts create mode 100644 packages/studiocms_socialposter/src/routes/postToTwitter.ts create mode 100644 packages/studiocms_socialposter/src/styles/quill.core.css create mode 100644 packages/studiocms_socialposter/src/utils/astroEnvConfig.ts create mode 100644 packages/studiocms_socialposter/src/virtuals.d.ts create mode 100644 packages/studiocms_socialposter/tsconfig.json create mode 100644 packages/studiocms_socialposter/ui.d.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 1809477..00d4e49 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,29 +1,32 @@ { - "cSpell.words": [ - "aligncenter", - "alignjustify", - "alignleft", - "alignright", - "Avenir", - "backcolor", - "bullist", - "cmdm", - "CMSWYSIWYG", - "compkeys", - "forecolor", - "fslightbox", - "grapesjs", - "grayscale", - "iconify", - "Lightbox", - "numlist", - "outdent", - "projectdata", - "strikethrough", - "studiocms", - "studiosdk", - "toastr", - "withstudiocms", - "WYSIWYGDB" - ] + "cSpell.words": [ + "aligncenter", + "alignjustify", + "alignleft", + "alignright", + "astroenv", + "Avenir", + "backcolor", + "bullist", + "cmdm", + "CMSWYSIWYG", + "compkeys", + "forecolor", + "fslightbox", + "grapesjs", + "grayscale", + "iconify", + "Lightbox", + "numlist", + "outdent", + "projectdata", + "socialposter", + "strikethrough", + "studiocms", + "studiosdk", + "toastr", + "virtuals", + "withstudiocms", + "WYSIWYGDB" + ] } diff --git a/packages/studiocms_socialposter/.gitignore b/packages/studiocms_socialposter/.gitignore new file mode 100644 index 0000000..8f18003 --- /dev/null +++ b/packages/studiocms_socialposter/.gitignore @@ -0,0 +1,23 @@ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +.npmrc + +dist/ \ No newline at end of file diff --git a/packages/studiocms_socialposter/LICENSE b/packages/studiocms_socialposter/LICENSE new file mode 100644 index 0000000..443a97b --- /dev/null +++ b/packages/studiocms_socialposter/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 StudioCMS - Adam Matthiesen, Jacob Jenkins, Paul Valladares + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/studiocms_socialposter/astroenv.d.ts b/packages/studiocms_socialposter/astroenv.d.ts new file mode 100644 index 0000000..80e50f8 --- /dev/null +++ b/packages/studiocms_socialposter/astroenv.d.ts @@ -0,0 +1,11 @@ +declare module 'astro:env/server' { + export const TWITTER_API_KEY: string | undefined; + export const TWITTER_API_SECRET: string | undefined; + export const TWITTER_ACCESS_TOKEN: string | undefined; + export const TWITTER_ACCESS_SECRET: string | undefined; + export const BLUESKY_SERVICE: string | undefined; + export const BLUESKY_USERNAME: string | undefined; + export const BLUESKY_PASSWORD: string | undefined; + export const THREADS_USER_ID: string | undefined; + export const THREADS_ACCESS_TOKEN: string | undefined; +} diff --git a/packages/studiocms_socialposter/package.json b/packages/studiocms_socialposter/package.json new file mode 100644 index 0000000..47e731e --- /dev/null +++ b/packages/studiocms_socialposter/package.json @@ -0,0 +1,62 @@ +{ + "name": "@studiocms/socialposter", + "version": "0.1.0-experimental.0", + "description": "Allow cross-posting to your social media accounts from your StudioCMS dashboard with ease!", + "author": { + "name": "Adam Matthiesen | Jacob Jenkins | Paul Valladares", + "url": "https://studiocms.dev" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/withstudiocms/experiments.git", + "directory": "packages/studiocms_socialposter" + }, + "contributors": ["Adammatthiesen", "jdtjenkins", "dreyfus92", "code.spirit"], + "license": "MIT", + "keywords": [ + "astro", + "astrocms", + "astrodb", + "astrostudio", + "astro-integration", + "astro-studio", + "astro-studiocms", + "cms", + "studiocms", + "withastro", + "plugin", + "studiocms-plugin" + ], + "homepage": "https://studiocms.dev", + "publishConfig": { + "access": "public", + "provenance": true + }, + "sideEffects": false, + "files": ["dist"], + "scripts": { + "build": "build-scripts build 'src/**/*.{ts,astro,css,js}'", + "dev": "build-scripts dev 'src/**/*.{ts,astro,css,js}'" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "type": "module", + "dependencies": { + "@studiocms/ui": "^0.4.16", + "astro-integration-kit": "catalog:", + "ultrahtml": "^1.5.3", + "quill": "^2.0.3" + }, + "devDependencies": { + "@types/node": "catalog:" + }, + "peerDependencies": { + "astro": "catalog:min", + "studiocms": "catalog:min", + "vite": "catalog:min" + } +} diff --git a/packages/studiocms_socialposter/src/index.ts b/packages/studiocms_socialposter/src/index.ts new file mode 100644 index 0000000..e45b7b2 --- /dev/null +++ b/packages/studiocms_socialposter/src/index.ts @@ -0,0 +1,151 @@ +/** + * These triple-slash directives defines dependencies to various declaration files that will be + * loaded when a user imports the StudioCMS plugin in their Astro configuration file. These + * directives must be first at the top of the file and can only be preceded by this comment. + */ +/// +/// +/// +/// +import { addVirtualImports, createResolver } from 'astro-integration-kit'; +import { type StudioCMSPlugin, definePlugin } from 'studiocms/plugins'; +import { addAstroEnvConfig } from './utils/astroEnvConfig'; +import { envField } from 'astro/config'; + +export interface StudioCMSSocialPosterOptions { + bluesky: boolean; + threads: boolean; + twitter: boolean; +} + +const defaultOptions: StudioCMSSocialPosterOptions = { + bluesky: false, + threads: false, + twitter: false, +}; + +function studiocmsSocialPoster(opts?: Partial): StudioCMSPlugin { + // Resolve the path to the current file + const { resolve } = createResolver(import.meta.url); + + // Define the package identifier + const packageIdentifier = '@studiocms/socialposter'; + + const options: StudioCMSSocialPosterOptions = { + ...defaultOptions, + ...opts, + }; + + return definePlugin({ + identifier: packageIdentifier, + name: 'StudioCMS Social Poster', + studiocmsMinimumVersion: '0.1.0-beta.14', + dashboardPages: { + user: [ + { + title: { + 'en-us': 'Share to Social Media', + }, + description: 'Share content on Social media', + sidebar: 'single', + pageBodyComponent: resolve('./pages/socials.astro'), + route: 'share', + requiredPermissions: 'editor', + icon: 'share', + }, + ], + }, + integration: { + name: packageIdentifier, + hooks: { + 'astro:config:setup': (params) => { + const { injectRoute } = params; + + addAstroEnvConfig(params, { + validateSecrets: true, + schema: { + BLUESKY_SERVICE: envField.string({ + context: 'server', + access: 'secret', + optional: !options.bluesky, + }), + BLUESKY_USERNAME: envField.string({ + context: 'server', + access: 'secret', + optional: !options.bluesky, + }), + BLUESKY_PASSWORD: envField.string({ + context: 'server', + access: 'secret', + optional: !options.bluesky, + }), + THREADS_USER_ID: envField.string({ + context: 'server', + access: 'secret', + optional: !options.threads, + }), + THREADS_ACCESS_TOKEN: envField.string({ + context: 'server', + access: 'secret', + optional: !options.threads, + }), + TWITTER_API_KEY: envField.string({ + context: 'server', + access: 'secret', + optional: !options.twitter, + }), + TWITTER_API_SECRET: envField.string({ + context: 'server', + access: 'secret', + optional: !options.twitter, + }), + TWITTER_ACCESS_TOKEN: envField.string({ + context: 'server', + access: 'secret', + optional: !options.twitter, + }), + TWITTER_ACCESS_SECRET: envField.string({ + context: 'server', + access: 'secret', + optional: !options.twitter, + }), + }, + }); + + addVirtualImports(params, { + name: packageIdentifier, + imports: { + 'studiocms:socialposter/config': `export default ${JSON.stringify(options)}`, + }, + }); + + if (options.bluesky) { + injectRoute({ + pattern: '/studiocms_api/socialposter/post-to-bluesky', + entrypoint: resolve('./routes/postToBlueSky.js'), + prerender: false, + }); + } + + if (options.threads) { + injectRoute({ + pattern: '/studiocms_api/socialposter/post-to-threads', + entrypoint: resolve('./routes/postToThreads.js'), + prerender: false, + }); + } + + if (options.twitter) { + injectRoute({ + pattern: '/studiocms_api/socialposter/post-to-twitter', + entrypoint: resolve('./routes/postToTwitter.js'), + prerender: false, + }); + } + }, + }, + }, + }); +} + +export default studiocmsSocialPoster; diff --git a/packages/studiocms_socialposter/src/pages/socials.astro b/packages/studiocms_socialposter/src/pages/socials.astro new file mode 100644 index 0000000..78e5f70 --- /dev/null +++ b/packages/studiocms_socialposter/src/pages/socials.astro @@ -0,0 +1,207 @@ +--- +import 'quill/dist/quill.snow.css'; +import socialsConfig from 'studiocms:socialposter/config'; +import { Card, Toggle, Button, Icon } from 'studiocms:ui/components'; + +const { bluesky, threads, twitter } = socialsConfig; +--- +
+ +
+

Create Your Post

+
+ +
+ +
+
0 / 280
+ + +
+ { bluesky && } + { threads && } + { twitter && } +
+
+
+ +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/packages/studiocms_socialposter/src/routes/postToBlueSky.ts b/packages/studiocms_socialposter/src/routes/postToBlueSky.ts new file mode 100644 index 0000000..ae503f7 --- /dev/null +++ b/packages/studiocms_socialposter/src/routes/postToBlueSky.ts @@ -0,0 +1 @@ +import { BLUESKY_PASSWORD, BLUESKY_SERVICE, BLUESKY_USERNAME } from 'astro:env/server'; diff --git a/packages/studiocms_socialposter/src/routes/postToThreads.ts b/packages/studiocms_socialposter/src/routes/postToThreads.ts new file mode 100644 index 0000000..0fb8742 --- /dev/null +++ b/packages/studiocms_socialposter/src/routes/postToThreads.ts @@ -0,0 +1 @@ +import { THREADS_ACCESS_TOKEN, THREADS_USER_ID } from 'astro:env/server'; diff --git a/packages/studiocms_socialposter/src/routes/postToTwitter.ts b/packages/studiocms_socialposter/src/routes/postToTwitter.ts new file mode 100644 index 0000000..5bd36f9 --- /dev/null +++ b/packages/studiocms_socialposter/src/routes/postToTwitter.ts @@ -0,0 +1,6 @@ +import { + TWITTER_ACCESS_SECRET, + TWITTER_ACCESS_TOKEN, + TWITTER_API_KEY, + TWITTER_API_SECRET, +} from 'astro:env/server'; diff --git a/packages/studiocms_socialposter/src/styles/quill.core.css b/packages/studiocms_socialposter/src/styles/quill.core.css new file mode 100644 index 0000000..7090dc4 --- /dev/null +++ b/packages/studiocms_socialposter/src/styles/quill.core.css @@ -0,0 +1,491 @@ +/*! + * Quill Editor v2.0.3 + * https://quilljs.com + * Copyright (c) 2017-2024, Slab + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */ +.ql-container { + box-sizing: border-box; + font-family: Helvetica, Arial, sans-serif; + font-size: 13px; + height: 100%; + margin: 0; + position: relative; +} +.ql-container.ql-disabled .ql-tooltip { + visibility: hidden; +} +.ql-container:not(.ql-disabled) li[data-list="checked"] > .ql-ui, +.ql-container:not(.ql-disabled) li[data-list="unchecked"] > .ql-ui { + cursor: pointer; +} +.ql-clipboard { + left: -100000px; + height: 1px; + overflow-y: hidden; + position: absolute; + top: 50%; +} +.ql-clipboard p { + margin: 0; + padding: 0; +} +.ql-editor { + box-sizing: border-box; + counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + line-height: 1.42; + height: 100%; + outline: none; + overflow-y: auto; + padding: 12px 15px; + tab-size: 4; + -moz-tab-size: 4; + text-align: left; + white-space: pre-wrap; + word-wrap: break-word; +} +.ql-editor > * { + cursor: text; +} +.ql-editor p, +.ql-editor ol, +.ql-editor pre, +.ql-editor blockquote, +.ql-editor h1, +.ql-editor h2, +.ql-editor h3, +.ql-editor h4, +.ql-editor h5, +.ql-editor h6 { + margin: 0; + padding: 0; +} +@supports (counter-set: none) { + .ql-editor p, + .ql-editor h1, + .ql-editor h2, + .ql-editor h3, + .ql-editor h4, + .ql-editor h5, + .ql-editor h6 { + counter-set: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor p, + .ql-editor h1, + .ql-editor h2, + .ql-editor h3, + .ql-editor h4, + .ql-editor h5, + .ql-editor h6 { + counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor table { + border-collapse: collapse; +} +.ql-editor td { + border: 1px solid #000; + padding: 2px 5px; +} +.ql-editor ol { + padding-left: 1.5em; +} +.ql-editor li { + list-style-type: none; + padding-left: 1.5em; + position: relative; +} +.ql-editor li > .ql-ui:before { + display: inline-block; + margin-left: -1.5em; + margin-right: .3em; + text-align: right; + white-space: nowrap; + width: 1.2em; +} +.ql-editor li[data-list="checked"] > .ql-ui, +.ql-editor li[data-list="unchecked"] > .ql-ui { + color: #777; +} +.ql-editor li[data-list="bullet"] > .ql-ui:before { + content: "\2022"; +} +.ql-editor li[data-list="checked"] > .ql-ui:before { + content: "\2611"; +} +.ql-editor li[data-list="unchecked"] > .ql-ui:before { + content: "\2610"; +} +@supports (counter-set: none) { + .ql-editor li[data-list] { + counter-set: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list] { + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"] { + counter-increment: list-0; +} +.ql-editor li[data-list="ordered"] > .ql-ui:before { + content: counter(list-0, decimal) ". "; +} +.ql-editor li[data-list="ordered"].ql-indent-1 { + counter-increment: list-1; +} +.ql-editor li[data-list="ordered"].ql-indent-1 > .ql-ui:before { + content: counter(list-1, lower-alpha) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-1 { + counter-set: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-1 { + counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-2 { + counter-increment: list-2; +} +.ql-editor li[data-list="ordered"].ql-indent-2 > .ql-ui:before { + content: counter(list-2, lower-roman) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-2 { + counter-set: list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-2 { + counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-3 { + counter-increment: list-3; +} +.ql-editor li[data-list="ordered"].ql-indent-3 > .ql-ui:before { + content: counter(list-3, decimal) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-3 { + counter-set: list-4 list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-3 { + counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-4 { + counter-increment: list-4; +} +.ql-editor li[data-list="ordered"].ql-indent-4 > .ql-ui:before { + content: counter(list-4, lower-alpha) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-4 { + counter-set: list-5 list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-4 { + counter-reset: list-5 list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-5 { + counter-increment: list-5; +} +.ql-editor li[data-list="ordered"].ql-indent-5 > .ql-ui:before { + content: counter(list-5, lower-roman) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-5 { + counter-set: list-6 list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-5 { + counter-reset: list-6 list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-6 { + counter-increment: list-6; +} +.ql-editor li[data-list="ordered"].ql-indent-6 > .ql-ui:before { + content: counter(list-6, decimal) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-6 { + counter-set: list-7 list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-6 { + counter-reset: list-7 list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-7 { + counter-increment: list-7; +} +.ql-editor li[data-list="ordered"].ql-indent-7 > .ql-ui:before { + content: counter(list-7, lower-alpha) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-7 { + counter-set: list-8 list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-7 { + counter-reset: list-8 list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-8 { + counter-increment: list-8; +} +.ql-editor li[data-list="ordered"].ql-indent-8 > .ql-ui:before { + content: counter(list-8, lower-roman) ". "; +} +@supports (counter-set: none) { + .ql-editor li[data-list].ql-indent-8 { + counter-set: list-9; + } +} +@supports not (counter-set: none) { + .ql-editor li[data-list].ql-indent-8 { + counter-reset: list-9; + } +} +.ql-editor li[data-list="ordered"].ql-indent-9 { + counter-increment: list-9; +} +.ql-editor li[data-list="ordered"].ql-indent-9 > .ql-ui:before { + content: counter(list-9, decimal) ". "; +} +.ql-editor .ql-indent-1:not(.ql-direction-rtl) { + padding-left: 3em; +} +.ql-editor li.ql-indent-1:not(.ql-direction-rtl) { + padding-left: 4.5em; +} +.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 3em; +} +.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 4.5em; +} +.ql-editor .ql-indent-2:not(.ql-direction-rtl) { + padding-left: 6em; +} +.ql-editor li.ql-indent-2:not(.ql-direction-rtl) { + padding-left: 7.5em; +} +.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 6em; +} +.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 7.5em; +} +.ql-editor .ql-indent-3:not(.ql-direction-rtl) { + padding-left: 9em; +} +.ql-editor li.ql-indent-3:not(.ql-direction-rtl) { + padding-left: 10.5em; +} +.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 9em; +} +.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 10.5em; +} +.ql-editor .ql-indent-4:not(.ql-direction-rtl) { + padding-left: 12em; +} +.ql-editor li.ql-indent-4:not(.ql-direction-rtl) { + padding-left: 13.5em; +} +.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 12em; +} +.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 13.5em; +} +.ql-editor .ql-indent-5:not(.ql-direction-rtl) { + padding-left: 15em; +} +.ql-editor li.ql-indent-5:not(.ql-direction-rtl) { + padding-left: 16.5em; +} +.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 15em; +} +.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 16.5em; +} +.ql-editor .ql-indent-6:not(.ql-direction-rtl) { + padding-left: 18em; +} +.ql-editor li.ql-indent-6:not(.ql-direction-rtl) { + padding-left: 19.5em; +} +.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 18em; +} +.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 19.5em; +} +.ql-editor .ql-indent-7:not(.ql-direction-rtl) { + padding-left: 21em; +} +.ql-editor li.ql-indent-7:not(.ql-direction-rtl) { + padding-left: 22.5em; +} +.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 21em; +} +.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 22.5em; +} +.ql-editor .ql-indent-8:not(.ql-direction-rtl) { + padding-left: 24em; +} +.ql-editor li.ql-indent-8:not(.ql-direction-rtl) { + padding-left: 25.5em; +} +.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 24em; +} +.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 25.5em; +} +.ql-editor .ql-indent-9:not(.ql-direction-rtl) { + padding-left: 27em; +} +.ql-editor li.ql-indent-9:not(.ql-direction-rtl) { + padding-left: 28.5em; +} +.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 27em; +} +.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 28.5em; +} +.ql-editor li.ql-direction-rtl { + padding-right: 1.5em; +} +.ql-editor li.ql-direction-rtl > .ql-ui:before { + margin-left: .3em; + margin-right: -1.5em; + text-align: left; +} +.ql-editor table { + table-layout: fixed; + width: 100%; +} +.ql-editor table td { + outline: none; +} +.ql-editor .ql-code-block-container { + font-family: monospace; +} +.ql-editor .ql-video { + display: block; + max-width: 100%; +} +.ql-editor .ql-video.ql-align-center { + margin: 0 auto; +} +.ql-editor .ql-video.ql-align-right { + margin: 0 0 0 auto; +} +.ql-editor .ql-bg-black { + background-color: #000; +} +.ql-editor .ql-bg-red { + background-color: #e60000; +} +.ql-editor .ql-bg-orange { + background-color: #f90; +} +.ql-editor .ql-bg-yellow { + background-color: #ff0; +} +.ql-editor .ql-bg-green { + background-color: #008a00; +} +.ql-editor .ql-bg-blue { + background-color: #06c; +} +.ql-editor .ql-bg-purple { + background-color: #93f; +} +.ql-editor .ql-color-white { + color: #fff; +} +.ql-editor .ql-color-red { + color: #e60000; +} +.ql-editor .ql-color-orange { + color: #f90; +} +.ql-editor .ql-color-yellow { + color: #ff0; +} +.ql-editor .ql-color-green { + color: #008a00; +} +.ql-editor .ql-color-blue { + color: #06c; +} +.ql-editor .ql-color-purple { + color: #93f; +} +.ql-editor .ql-font-serif { + font-family: Georgia, Times New Roman, serif; +} +.ql-editor .ql-font-monospace { + font-family: Monaco, Courier New, monospace; +} +.ql-editor .ql-size-small { + font-size: .75em; +} +.ql-editor .ql-size-large { + font-size: 1.5em; +} +.ql-editor .ql-size-huge { + font-size: 2.5em; +} +.ql-editor .ql-direction-rtl { + direction: rtl; + text-align: inherit; +} +.ql-editor .ql-align-center { + text-align: center; +} +.ql-editor .ql-align-justify { + text-align: justify; +} +.ql-editor .ql-align-right { + text-align: right; +} +.ql-editor .ql-ui { + position: absolute; +} +.ql-editor.ql-blank::before { + color: rgba(0, 0, 0, 0.6); + content: attr(data-placeholder); + font-style: italic; + left: 15px; + pointer-events: none; + position: absolute; + right: 15px; +} + +/*# sourceMappingURL=quill.core.css.map*/ diff --git a/packages/studiocms_socialposter/src/utils/astroEnvConfig.ts b/packages/studiocms_socialposter/src/utils/astroEnvConfig.ts new file mode 100644 index 0000000..1445c94 --- /dev/null +++ b/packages/studiocms_socialposter/src/utils/astroEnvConfig.ts @@ -0,0 +1,12 @@ +import type { AstroConfig } from 'astro'; +import { defineUtility } from 'astro-integration-kit'; + +/** + * Add Astro Environment Variables Config for using 'astro:env' + */ +export const addAstroEnvConfig = defineUtility('astro:config:setup')( + (params, env: AstroConfig['env']) => { + // Update Astro Config with Environment Variables (`astro:env`) + params.updateConfig({ env }); + } +); diff --git a/packages/studiocms_socialposter/src/virtuals.d.ts b/packages/studiocms_socialposter/src/virtuals.d.ts new file mode 100644 index 0000000..2b3bb8d --- /dev/null +++ b/packages/studiocms_socialposter/src/virtuals.d.ts @@ -0,0 +1,4 @@ +declare module 'studiocms:socialposter/config' { + const options: import('./index').StudioCMSSocialPosterOptions; + export default options; +} diff --git a/packages/studiocms_socialposter/tsconfig.json b/packages/studiocms_socialposter/tsconfig.json new file mode 100644 index 0000000..fbad20b --- /dev/null +++ b/packages/studiocms_socialposter/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist", + "emitDeclarationOnly": true, + "rootDir": "./src" + } +} diff --git a/packages/studiocms_socialposter/ui.d.ts b/packages/studiocms_socialposter/ui.d.ts new file mode 100644 index 0000000..837d851 --- /dev/null +++ b/packages/studiocms_socialposter/ui.d.ts @@ -0,0 +1,291 @@ +declare module 'studiocms:ui/version' { + const version: string; + export default version; +} + +declare module 'studiocms:ui/global-css' {} + +declare module 'studiocms:ui/custom-css' {} + +declare module 'studiocms:ui/scripts/*' {} + +declare module 'studiocms:ui/components' { + export const Button: typeof import('@studiocms/ui/components/Button/Button.astro').default; + export const Divider: typeof import('@studiocms/ui/components/Divider/Divider.astro').default; + export const Input: typeof import('@studiocms/ui/components/Input/Input.astro').default; + export const Row: typeof import('@studiocms/ui/components/Row/Row.astro').default; + export const Center: typeof import('@studiocms/ui/components/Center/Center.astro').default; + export const Textarea: typeof import('@studiocms/ui/components/Textarea/Textarea.astro').default; + export const Checkbox: typeof import('@studiocms/ui/components/Checkbox/Checkbox.astro').default; + export const Toggle: typeof import('@studiocms/ui/components/Toggle/Toggle.astro').default; + export const RadioGroup: typeof import( + '@studiocms/ui/components/RadioGroup/RadioGroup.astro' + ).default; + export const Toaster: typeof import('@studiocms/ui/components/Toast/Toaster.astro').default; + export const Card: typeof import('@studiocms/ui/components/Card/Card.astro').default; + export const Modal: typeof import('@studiocms/ui/components/Modal/Modal.astro').default; + export const Select: typeof import('@studiocms/ui/components/Select/Select.astro').default; + export const SearchSelect: typeof import( + '@studiocms/ui/components/SearchSelect/SearchSelect.astro' + ).default; + export const Dropdown: typeof import('@studiocms/ui/components/Dropdown/Dropdown.astro').default; + export const User: typeof import('@studiocms/ui/components/User/User.astro').default; + export const ThemeToggle: typeof import( + '@studiocms/ui/components/ThemeToggle/ThemeToggle.astro' + ).default; + export const Tabs: typeof import('@studiocms/ui/components/Tabs/Tabs.astro').default; + export const TabItem: typeof import('@studiocms/ui/components/Tabs/TabItem.astro').default; + export const Accordion: typeof import( + '@studiocms/ui/components/Accordion/Accordion.astro' + ).default; + export const AccordionItem: typeof import( + '@studiocms/ui/components/Accordion/Item.astro' + ).default; + export const Footer: typeof import('@studiocms/ui/components/Footer/Footer.astro').default; + export const Progress: typeof import('@studiocms/ui/components/Progress/Progress.astro').default; + export const Sidebar: typeof import('@studiocms/ui/components/Sidebar/Single.astro').default; + export const DoubleSidebar: typeof import( + '@studiocms/ui/components/Sidebar/Double.astro' + ).default; + export const Breadcrumbs: typeof import( + '@studiocms/ui/components/Breadcrumbs/Breadcrumbs.astro' + ).default; + export const Group: typeof import('@studiocms/ui/components/Group/Group.astro').default; + export const Badge: typeof import('@studiocms/ui/components/Badge/Badge.astro').default; + export const Icon: typeof import('@studiocms/ui/components/Icon/Icon.astro').default; + export const IconBase: typeof import('@studiocms/ui/components/Icon/IconBase.astro').default; + export const toast: typeof import('@studiocms/ui/components/Toast/toast.js').toast; + export type HeroIconName = import('@studiocms/ui/components/Icon/iconType.js').HeroIconName; + + export class ModalHelper { + private element; + private cancelButton; + private confirmButton; + private isForm; + private modalForm; + /** + * A helper to manage modals. + * @param id The ID of the modal. + * @param triggerID The ID of the element that should trigger the modal. + */ + constructor(id: string, triggerID?: string); + /** + * A helper function which adds event listeners to the modal buttons to close the modal when clicked. + * @param id The ID of the modal. + * @param dismissable Whether the modal is dismissable. + */ + private addButtonListeners; + /** + * A helper function to close the modal when the user clicks outside of it. + */ + private addDismissiveClickListener; + /** + * A function to show the modal. + */ + show: () => void; + /** + * A function to hide the modal. + */ + hide: () => void; + /** + * A function to add another trigger to show the modal with. + * @param elementID The ID of the element that should trigger the modal when clicked. + */ + bindTrigger: (elementID: string) => void; + /** + * Registers a callback for the cancel button. + * @param func The callback function. + */ + registerCancelCallback: (func: () => void) => void; + /** + * Registers a callback for the confirm button. + * @param func The callback function. If the modal is a form, the function will be called with + * the form data as the first argument. + */ + registerConfirmCallback: (func: (data?: FormData | undefined) => void) => void; + } + + export class DropdownHelper { + private container; + private toggleEl; + private dropdown; + private alignment; + private triggerOn; + private fullWidth; + private focusIndex; + active: boolean; + /** + * A helper function to interact with dropdowns. + * @param id The ID of the dropdown. + * @param fullWidth Whether the dropdown should be full width. Not needed normally. + */ + constructor(id: string, fullWidth?: boolean); + /** + * Registers a click callback for the dropdown options. Whenever one of the options + * is clicked, the callback will be called with the value of the option. + * @param func The callback function. + */ + registerClickCallback: (func: (value: string) => void) => void; + /** + * Sets up all listeners for the dropdown. + */ + private initialBehaviorRegistration; + /** + * Registers callbacks to hide the dropdown when an option is clicked. + */ + private initialOptClickRegistration; + /** + * A function to toggle the dropdown. + */ + toggle: () => void; + /** + * A function to hide the dropdown. + */ + hide: () => void; + /** + * A function to show the dropdown. + */ + show: () => void; + /** + * A jQuery-like function to hide the dropdown when clicking outside of it. + * @param element The element to hide when clicking outside of it. + */ + private hideOnClickOutside; + } + + export class ProgressHelper { + private bar; + private progress; + private value; + private max; + constructor(id: string); + getValue(): number; + setValue(value: number): void; + getMax(): number; + setMax(value: number): void; + getPercentage(): number; + } + + export class SingleSidebarHelper { + private sidebar; + private sidebarToggle?; + /** + * A helper to manage the sidebar with. + * @param toggleID The ID of the element that should toggle the sidebar. + */ + constructor(toggleID?: string); + /** + * A helper function register an element which should toggle the sidebar. + * @param elementID The ID of the element that should toggle the sidebar. + */ + toggleSidebarOnClick: (elementID: string) => void; + /** + * A helper function to hide the sidebar when an element is clicked. + * @param elementID The ID of the element that should hide the sidebar. + */ + hideSidebarOnClick: (elementID: string) => void; + /** + * A helper function to show the sidebar when an element is clicked. + * @param elementID The ID of the element that should show the sidebar. + */ + showSidebarOnClick: (elementID: string) => void; + /** + * A function to hide the sidebar. + */ + hideSidebar: () => void; + /** + * A function to show the sidebar. + */ + showSidebar: () => void; + } + + export class DoubleSidebarHelper { + private sidebarsContainer; + /** + * A helper to manage the double sidebar with. + */ + constructor(); + /** + * A helper function to hide the sidebar when an element is clicked. + * @param elementID The ID of the element that should hide the sidebar. + */ + hideSidebarOnClick: (elementID: string) => void; + /** + * A helper function to show the outer sidebar when an element is clicked. + * @param elementID The ID of the element that should show the outer sidebar. + */ + showOuterOnClick: (elementID: string) => void; + /** + * A helper function to show the inner sidebar when an element is clicked. + * @param elementID The ID of the element that should show the inner sidebar. + */ + showInnerOnClick: (elementID: string) => void; + /** + * A function to show the inner sidebar. + */ + showInnerSidebar: () => void; + /** + * A function to show the outer sidebar. + */ + showOuterSidebar: () => void; + /** + * A function to hide the sidebar altogether. + */ + hideSidebar: () => void; + } +} + +declare module 'studiocms:ui/utils' { + export type Theme = import('@studiocms/ui/utils/ThemeHelper.js').Theme; + + type ThemeChangeCallback = (newTheme: Theme, oldTheme: Theme) => void; + + /** + * A helper to toggle, set and get the current StudioCMS UI theme. + */ + export class ThemeHelper { + private themeManagerElement; + private observer; + private themeChangeCallbacks; + /** + * A helper to toggle, set and get the current StudioCMS UI theme. + * @param themeProvider The element that should carry the data-theme attribute (replaces the document root) + */ + constructor(themeProvider?: HTMLElement); + /** + * Get the current theme. + * @param {boolean} resolveSystemTheme Whether to resolve the `system` theme to the actual theme (`dark` or `light`) + * @returns {Theme} The current theme. + */ + getTheme: ( + resolveSystemTheme?: T + ) => T extends true ? 'dark' | 'light' : Theme; + /** + * Sets the current theme. + * @param theme The new theme. One of `dark`, `light` or `system`. + */ + setTheme: (theme: Theme) => void; + /** + * Toggles the current theme. + * + * If the theme is set to `system` (or no theme is set via the root element), + * the theme is set depending on the user's color scheme preference (set in the browser). + */ + toggleTheme: () => void; + /** + * Register an element to act as a toggle! When clicked, it will toggle the theme. + * @param toggle The HTML element that should act as the toggle + */ + registerToggle: (toggle: HTMLElement | null) => void; + /** + * Allows for adding a callback that gets called whenever the theme changes. + * @param callback The callback to be executed + */ + onThemeChange: (callback: ThemeChangeCallback) => void; + /** + * Simply gets the first mutation and calls all registered callbacks. + * @param mutations The mutations array from the observer. Due to the specified options, this will always be a 1-length array, + */ + private themeManagerMutationHandler; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 952d2cd..8de41d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,6 +103,34 @@ importers: specifier: ^4.1.3 version: 4.1.3(@types/node@22.13.13)(typescript@5.8.2) + packages/studiocms_socialposter: + dependencies: + '@studiocms/ui': + specifier: ^0.4.16 + version: 0.4.16(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + astro: + specifier: catalog:min + version: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) + astro-integration-kit: + specifier: 'catalog:' + version: 0.18.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) + quill: + specifier: ^2.0.3 + version: 2.0.3 + studiocms: + specifier: catalog:min + version: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + ultrahtml: + specifier: ^1.5.3 + version: 1.5.3 + vite: + specifier: catalog:min + version: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0) + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 22.13.13 + packages/studiocms_wysiwyg: dependencies: '@grapesjs/studio-sdk': @@ -2789,6 +2817,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -3464,7 +3495,6 @@ packages: libsql@0.5.3: resolution: {integrity: sha512-S3WR8WNCJV1VXraBFUKjDA6+8LcNDJMLm+83qohm1O3YM1iVqV2+/XN3SXOxpxVjuL4g/rLrjO5kzygkPefCFQ==} - cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] listr-silent-renderer@1.1.1: @@ -3497,9 +3527,15 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash._reinterpolate@3.0.0: resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -3509,6 +3545,10 @@ packages: lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + lodash.isinteger@4.0.4: resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} @@ -4014,6 +4054,9 @@ packages: param-case@3.0.4: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + parchment@3.0.0: + resolution: {integrity: sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==} + parse-latin@7.0.0: resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} @@ -4201,6 +4244,14 @@ packages: resolution: {integrity: sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg==} engines: {node: '>=18'} + quill-delta@5.1.0: + resolution: {integrity: sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==} + engines: {node: '>= 12.0.0'} + + quill@2.0.3: + resolution: {integrity: sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==} + engines: {npm: '>=8.2.3'} + radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} @@ -8182,6 +8233,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-diff@1.3.0: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -8987,14 +9040,20 @@ snapshots: dependencies: p-locate: 6.0.0 + lodash-es@4.17.21: {} + lodash._reinterpolate@3.0.0: {} + lodash.clonedeep@4.5.0: {} + lodash.debounce@4.0.8: {} lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} + lodash.isequal@4.5.0: {} + lodash.isinteger@4.0.4: {} lodash.isnumber@3.0.3: {} @@ -9642,6 +9701,8 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 + parchment@3.0.0: {} + parse-latin@7.0.0: dependencies: '@types/nlcst': 2.0.3 @@ -9851,6 +9912,19 @@ snapshots: quick-lru@7.0.0: {} + quill-delta@5.1.0: + dependencies: + fast-diff: 1.3.0 + lodash.clonedeep: 4.5.0 + lodash.isequal: 4.5.0 + + quill@2.0.3: + dependencies: + eventemitter3: 5.0.1 + lodash-es: 4.17.21 + parchment: 3.0.0 + quill-delta: 5.1.0 + radix3@1.1.2: {} randombytes@2.1.0: From a49ad5eed02d6c3d974b19e5c8ac15e6299de4dd Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 03:36:05 -0700 Subject: [PATCH 02/18] more progress --- packages/studiocms_socialposter/src/index.ts | 2 +- .../src/pages/socials.astro | 52 ++-- playground/package.json | 1 + playground/studiocms.config.mjs | 8 +- pnpm-lock.yaml | 265 ++---------------- pnpm-workspace.yaml | 8 +- 6 files changed, 76 insertions(+), 260 deletions(-) diff --git a/packages/studiocms_socialposter/src/index.ts b/packages/studiocms_socialposter/src/index.ts index e45b7b2..eb58e83 100644 --- a/packages/studiocms_socialposter/src/index.ts +++ b/packages/studiocms_socialposter/src/index.ts @@ -9,7 +9,7 @@ /// import { addVirtualImports, createResolver } from 'astro-integration-kit'; import { type StudioCMSPlugin, definePlugin } from 'studiocms/plugins'; -import { addAstroEnvConfig } from './utils/astroEnvConfig'; +import { addAstroEnvConfig } from './utils/astroEnvConfig.js'; import { envField } from 'astro/config'; export interface StudioCMSSocialPosterOptions { diff --git a/packages/studiocms_socialposter/src/pages/socials.astro b/packages/studiocms_socialposter/src/pages/socials.astro index 78e5f70..0e0ec07 100644 --- a/packages/studiocms_socialposter/src/pages/socials.astro +++ b/packages/studiocms_socialposter/src/pages/socials.astro @@ -6,6 +6,13 @@ import { Card, Toggle, Button, Icon } from 'studiocms:ui/components'; const { bluesky, threads, twitter } = socialsConfig; ---
+ + {/* + + // TODO: Add support for being able to display pages and their current content to make it easy to get excerpts for creating new posts. + + */} +

Create Your Post

@@ -14,21 +21,21 @@ const { bluesky, threads, twitter } = socialsConfig;
-
0 / 280
- -
- { bluesky && } - { threads && } - { twitter && } -
-
+
Select where to post:
+ + { bluesky && } + { threads && } + { twitter && } +
-
-
@@ -54,7 +61,7 @@ const { bluesky, threads, twitter } = socialsConfig; } calculate() { - const text = this.quill.getText(); + const text = this.quill.getText().trim(); return text.length; } @@ -62,9 +69,11 @@ const { bluesky, threads, twitter } = socialsConfig; const length = this.calculate(); this.container.innerText = `${length} / 280`; if (length > 280) { - this.container.style.color = 'hsl(var(--danger-base))'; + this.container.style.color = 'hsl(var(--danger-active))'; + this.container.style.backgroundColor = 'hsl(var(--danger-flat-active))' } else { this.container.style.color = 'hsl(var(--text-muted))'; + this.container.style.backgroundColor = 'hsl(var(--background-step-2))' } } } @@ -151,7 +160,8 @@ const { bluesky, threads, twitter } = socialsConfig; }) if (response.ok) { - responses.push(await response.json()); + const responseData = await response.json(); + responses.push(responseData); } } @@ -195,13 +205,19 @@ const { bluesky, threads, twitter } = socialsConfig; #editor { border: 1px solid hsl(var(--border)); + border-radius: var(--radius-md); + width: 100%; } #counter { border: 1px solid hsl(var(--border)); - border-width: 0px 1px 1px 1px; - color: (hsl(var(--text-muted))); - padding: 5px 15px; - text-align: right; + background-color: hsl(var(--background-step-2)); + border-radius: var(--radius-lg); + border-width: 1px 1px 1px 1px; + color: hsl(var(--text-muted)); + align-items: center; + text-align: center; + width: 6rem; + align-content: center; } \ No newline at end of file diff --git a/playground/package.json b/playground/package.json index 792d861..1e0b623 100644 --- a/playground/package.json +++ b/playground/package.json @@ -25,6 +25,7 @@ "sharp": "catalog:", "@studiocms/blog": "catalog:", "@studiocms/devapps": "catalog:", + "@studiocms/socialposter": "workspace:*", "@studiocms/wysiwyg": "workspace:*" } } diff --git a/playground/studiocms.config.mjs b/playground/studiocms.config.mjs index 2b78afd..2b20dc8 100644 --- a/playground/studiocms.config.mjs +++ b/playground/studiocms.config.mjs @@ -1,12 +1,18 @@ import blog from '@studiocms/blog'; import WYSIWYG from '@studiocms/wysiwyg'; import WYSIWYGStudio from '@studiocms/wysiwyg/studio'; +import socialPoster from '@studiocms/socialposter'; import { defineStudioCMSConfig } from 'studiocms/config'; export default defineStudioCMSConfig({ dbStartPage: false, verbose: true, - plugins: [blog(), WYSIWYGStudio({ licenseKey: 'LICENSE' }), WYSIWYG()], + plugins: [ + blog(), + WYSIWYGStudio({ licenseKey: 'LICENSE' }), + WYSIWYG(), + socialPoster({ bluesky: true }), + ], dashboardConfig: { developerConfig: { demoMode: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8de41d6..ae49b99 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,11 +13,11 @@ catalogs: specifier: ^9.1.2 version: 9.1.3 '@studiocms/blog': - specifier: 0.1.0-beta.13 - version: 0.1.0-beta.13 + specifier: 0.1.0-beta.14 + version: 0.1.0-beta.14 '@studiocms/devapps': - specifier: 0.1.0-beta.13 - version: 0.1.0-beta.13 + specifier: 0.1.0-beta.14 + version: 0.1.0-beta.14 '@types/node': specifier: ^22.0.0 version: 22.13.13 @@ -31,8 +31,8 @@ catalogs: specifier: ^0.33.5 version: 0.33.5 studiocms: - specifier: 0.1.0-beta.13 - version: 0.1.0-beta.13 + specifier: 0.1.0-beta.14 + version: 0.1.0-beta.14 typescript: specifier: ^5.7 version: 5.8.2 @@ -41,8 +41,8 @@ catalogs: specifier: ^5.5 version: 5.5.5 studiocms: - specifier: 0.1.0-beta.13 - version: 0.1.0-beta.13 + specifier: 0.1.0-beta.14 + version: 0.1.0-beta.14 vite: specifier: ^6.2.0 version: 6.2.3 @@ -119,7 +119,7 @@ importers: version: 2.0.3 studiocms: specifier: catalog:min - version: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + version: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) ultrahtml: specifier: ^1.5.3 version: 1.5.3 @@ -195,7 +195,7 @@ importers: version: 2.0.1 studiocms: specifier: catalog:min - version: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + version: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) ultrahtml: specifier: ^1.5.3 version: 1.5.3 @@ -217,10 +217,13 @@ importers: version: 9.1.3(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) '@studiocms/blog': specifier: 'catalog:' - version: 0.1.0-beta.13(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + version: 0.1.0-beta.14(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) '@studiocms/devapps': specifier: 'catalog:' - version: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + version: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + '@studiocms/socialposter': + specifier: workspace:* + version: link:../packages/studiocms_socialposter '@studiocms/wysiwyg': specifier: workspace:* version: link:../packages/studiocms_wysiwyg @@ -232,7 +235,7 @@ importers: version: 0.33.5 studiocms: specifier: 'catalog:' - version: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + version: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) devDependencies: '@types/node': specifier: 'catalog:' @@ -1303,11 +1306,6 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@matthiesenxyz/integration-utils@0.3.0': - resolution: {integrity: sha512-i0Cw7iH0H6YfcFny/lss/ZtgAX8eqDeMWzhvmgMIWlxgZAsrRdnI7BWiTHpjb3aMdLLsXEcY3vnQ+RaSQaaW8Q==} - peerDependencies: - astro: ^4.14 || ^5 - '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} @@ -1424,18 +1422,6 @@ packages: '@oslojs/jwt@0.2.0': resolution: {integrity: sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==} - '@pnpm/config.env-replace@1.1.0': - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - - '@pnpm/network.ca-file@1.0.2': - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} - - '@pnpm/npm-conf@2.3.1': - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} - engines: {node: '>=12'} - '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} @@ -1583,19 +1569,19 @@ packages: engines: {node: '>=8.10'} hasBin: true - '@studiocms/blog@0.1.0-beta.13': - resolution: {integrity: sha512-sTiiZFLftFNIUECAaidGulwp+/Koim0u6ebuOwZmAuG2Yj1MJQ+dD9SOQFSwAs6ZeBw+ygJn2hiy8/aHAMAGEg==} + '@studiocms/blog@0.1.0-beta.14': + resolution: {integrity: sha512-wyNPXBlkPCXO30dG0WxWmwSnlCuuA5YL2IEKVvKe3YEXC6SkOjXl2b8euZwU/dWZhkZqj/fD5/tdloPxHEY8ow==} peerDependencies: astro: ^5.5.0 - studiocms: 0.1.0-beta.13 + studiocms: 0.1.0-beta.14 vite: ^6.2.0 - '@studiocms/devapps@0.1.0-beta.13': - resolution: {integrity: sha512-5gPrusLYa9KICMpH8Xg4Wrin3HIIMpgfZ+I3i1Er9TQpIaf7QktoPMKR4ppZYFwNi81QNBnzrk0mSDFqsunvzg==} + '@studiocms/devapps@0.1.0-beta.14': + resolution: {integrity: sha512-RJJAU2APZCfdJmDUvxxXh1EwhHkmsDp39qwVth9ScA8L3/GmtXqsPnSXDP/NAPbraq/t3GuykshRLaloz730sg==} peerDependencies: '@astrojs/db': ^0.14.7 astro: ^5.5.0 - studiocms: 0.1.0-beta.13 + studiocms: 0.1.0-beta.14 vite: ^6.2.0 peerDependenciesMeta: studiocms: @@ -1967,11 +1953,6 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - astro-integration-kit@0.17.0: - resolution: {integrity: sha512-fe31CCKmrGYn/kkBd1J4b7P02gEdMdEIFBz14zdAud+YAmJeLtZD6wmrCz3LDau+lE1oM1hQnvmZXVSM/YveKw==} - peerDependencies: - astro: ^4.12.0 || ^5.0.0-beta - astro-integration-kit@0.18.0: resolution: {integrity: sha512-Z0QW5IQjosuKQDEGYYkvUX6EhEtrmE4/oViqWz23QveV8U7AuyFsTdg00WRNPevWZl/5a4lLUeDpv4bCRynRRg==} peerDependencies: @@ -2082,9 +2063,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - buffer-equal-constant-time@1.0.1: - resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -2308,9 +2286,6 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - connect-history-api-fallback@2.0.0: resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} engines: {node: '>=0.8'} @@ -2414,10 +2389,6 @@ packages: deep-diff@1.0.2: resolution: {integrity: sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==} - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - default-browser-id@5.0.0: resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} engines: {node: '>=18'} @@ -2659,9 +2630,6 @@ packages: easy-table@1.2.0: resolution: {integrity: sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==} - ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -3004,9 +2972,6 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -3254,9 +3219,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - inquirer@8.2.6: resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} engines: {node: '>=12.0.0'} @@ -3452,16 +3414,6 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - jsonwebtoken@9.0.2: - resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} - engines: {node: '>=12', npm: '>=6'} - - jwa@1.4.1: - resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} - - jws@3.2.2: - resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} - katex@0.16.21: resolution: {integrity: sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==} hasBin: true @@ -3486,10 +3438,6 @@ packages: '@types/node': '>=18' typescript: '>=5.0.4' - ky@1.7.5: - resolution: {integrity: sha512-HzhziW6sc5m0pwi5M196+7cEBtbt0lCYi67wNsiwMUmz833wloE0gbzJPWKs1gliFKQb34huItDQX97LyOdPdA==} - engines: {node: '>=18'} - launch-editor@2.10.0: resolution: {integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==} @@ -3539,31 +3487,10 @@ packages: lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.includes@4.3.0: - resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} - - lodash.isboolean@3.0.3: - resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} - lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - lodash.isinteger@4.0.4: - resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} - - lodash.isnumber@3.0.3: - resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} - - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - - lodash.isstring@4.0.1: - resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - - lodash.once@4.1.1: - resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -4041,10 +3968,6 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - package-json@10.0.1: - resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==} - engines: {node: '>=18'} - package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} @@ -4215,9 +4138,6 @@ packages: prosemirror-view@1.38.1: resolution: {integrity: sha512-4FH/uM1A4PNyrxXbD+RAbAsf0d/mM0D/wAKSVVWK7o0A9Q/oOXJBrw786mBf2Vnrs/Edly6dH6Z2gsb7zWwaUw==} - proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -4266,10 +4186,6 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - react-dom@19.0.0: resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} peerDependencies: @@ -4332,14 +4248,6 @@ packages: resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} - registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} - engines: {node: '>=14'} - - registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} - regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} @@ -4719,10 +4627,6 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - strip-json-comments@5.0.1: resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} engines: {node: '>=14.16'} @@ -4730,8 +4634,8 @@ packages: strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} - studiocms@0.1.0-beta.13: - resolution: {integrity: sha512-h8iH/DnOh+/qGcvhhauDzorDc+TwHXUnTmf9+LDLzQyDGA3x6Kj649sQNf3etCbUegO4n41t1HcF594gZt5Trw==} + studiocms@0.1.0-beta.14: + resolution: {integrity: sha512-BGwUqhkLUF82qqxEhnGtizwwCBI1EzQdHW1T3W57aMa4KOv0PWzr0pK85GQIMpIbOIcYbN/lV+/Wo5roptfC5g==} hasBin: true peerDependencies: '@astrojs/db': ^0.14.7 @@ -6665,13 +6569,6 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@matthiesenxyz/integration-utils@0.3.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))': - dependencies: - astro: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) - astro-integration-kit: 0.17.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) - package-json: 10.0.1 - semver: 7.7.1 - '@mixmark-io/domino@2.2.0': {} '@nanostores/i18n@0.12.2(nanostores@0.11.4)': @@ -6799,18 +6696,6 @@ snapshots: dependencies: '@oslojs/encoding': 0.4.1 - '@pnpm/config.env-replace@1.1.0': {} - - '@pnpm/network.ca-file@1.0.2': - dependencies: - graceful-fs: 4.2.10 - - '@pnpm/npm-conf@2.3.1': - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 - config-chain: 1.1.13 - '@rollup/pluginutils@5.1.4(rollup@4.37.0)': dependencies: '@types/estree': 1.0.7 @@ -6926,15 +6811,15 @@ snapshots: ignore: 5.3.2 p-map: 4.0.0 - '@studiocms/blog@0.1.0-beta.13(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0))': + '@studiocms/blog@0.1.0-beta.14(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0))': dependencies: '@astrojs/rss': 4.0.11 astro: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) astro-integration-kit: 0.18.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) - studiocms: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + studiocms: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0) - '@studiocms/devapps@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0))': + '@studiocms/devapps@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(studiocms@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0))': dependencies: '@astrojs/db': 0.14.9(@types/react@19.0.12)(react@19.0.0) astro: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) @@ -6944,7 +6829,7 @@ snapshots: turndown: 7.2.0 vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0) optionalDependencies: - studiocms: 0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + studiocms: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) '@studiocms/markdown-remark-processor@1.2.0': dependencies: @@ -7355,12 +7240,6 @@ snapshots: dependencies: tslib: 2.8.1 - astro-integration-kit@0.17.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)): - dependencies: - astro: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) - pathe: 1.1.2 - recast: 0.23.11 - astro-integration-kit@0.18.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)): dependencies: astro: 5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2) @@ -7591,8 +7470,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) - buffer-equal-constant-time@1.0.1: {} - buffer-from@1.1.2: {} buffer@5.7.1: @@ -7816,11 +7693,6 @@ snapshots: confbox@0.1.8: {} - config-chain@1.1.13: - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - connect-history-api-fallback@2.0.0: {} content-disposition@0.5.4: @@ -7903,8 +7775,6 @@ snapshots: deep-diff@1.0.2: {} - deep-extend@0.6.0: {} - default-browser-id@5.0.0: {} default-browser@5.2.1: @@ -8053,10 +7923,6 @@ snapshots: optionalDependencies: wcwidth: 1.0.1 - ecdsa-sig-formatter@1.0.11: - dependencies: - safe-buffer: 5.2.1 - ee-first@1.1.1: {} electron-to-chromium@1.5.128: {} @@ -8416,8 +8282,6 @@ snapshots: gopd@1.2.0: {} - graceful-fs@4.2.10: {} - graceful-fs@4.2.11: {} grapesjs-blocks-basic@1.0.2: {} @@ -8765,8 +8629,6 @@ snapshots: inherits@2.0.4: {} - ini@1.3.8: {} - inquirer@8.2.6: dependencies: ansi-escapes: 4.3.2 @@ -8919,30 +8781,6 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonwebtoken@9.0.2: - dependencies: - jws: 3.2.2 - lodash.includes: 4.3.0 - lodash.isboolean: 3.0.3 - lodash.isinteger: 4.0.4 - lodash.isnumber: 3.0.3 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.once: 4.1.1 - ms: 2.1.3 - semver: 7.7.1 - - jwa@1.4.1: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - - jws@3.2.2: - dependencies: - jwa: 1.4.1 - safe-buffer: 5.2.1 - katex@0.16.21: dependencies: commander: 8.3.0 @@ -8974,8 +8812,6 @@ snapshots: zod: 3.24.2 zod-validation-error: 3.4.0(zod@3.24.2) - ky@1.7.5: {} - launch-editor@2.10.0: dependencies: picocolors: 1.1.1 @@ -9048,22 +8884,8 @@ snapshots: lodash.debounce@4.0.8: {} - lodash.includes@4.3.0: {} - - lodash.isboolean@3.0.3: {} - lodash.isequal@4.5.0: {} - lodash.isinteger@4.0.4: {} - - lodash.isnumber@3.0.3: {} - - lodash.isplainobject@4.0.6: {} - - lodash.isstring@4.0.1: {} - - lodash.once@4.1.1: {} - lodash.startcase@4.4.0: {} lodash.template@4.5.0: @@ -9683,13 +9505,6 @@ snapshots: p-try@2.2.0: {} - package-json@10.0.1: - dependencies: - ky: 1.7.5 - registry-auth-token: 5.1.0 - registry-url: 6.0.1 - semver: 7.7.1 - package-manager-detector@0.2.11: dependencies: quansync: 0.2.10 @@ -9880,8 +9695,6 @@ snapshots: prosemirror-state: 1.4.3 prosemirror-transform: 1.10.3 - proto-list@1.2.4: {} - proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -9940,13 +9753,6 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - react-dom@19.0.0(react@19.0.0): dependencies: react: 19.0.0 @@ -10026,14 +9832,6 @@ snapshots: unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.0 - registry-auth-token@5.1.0: - dependencies: - '@pnpm/npm-conf': 2.3.1 - - registry-url@6.0.1: - dependencies: - rc: 1.2.8 - regjsgen@0.8.0: {} regjsparser@0.12.0: @@ -10551,13 +10349,11 @@ snapshots: strip-final-newline@2.0.0: {} - strip-json-comments@2.0.1: {} - strip-json-comments@5.0.1: {} strnum@1.1.2: {} - studiocms@0.1.0-beta.13(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)): + studiocms@0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)): dependencies: '@astrojs/db': 0.14.9(@types/react@19.0.12)(react@19.0.0) '@astrojs/markdown-remark': 6.3.1 @@ -10570,7 +10366,6 @@ snapshots: '@iconify-json/simple-icons': 1.2.29 '@inox-tools/inline-mod': 2.0.3(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) '@inox-tools/runtime-logger': 0.4.2(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) - '@matthiesenxyz/integration-utils': 0.3.0(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2)) '@nanostores/i18n': 0.12.2(nanostores@0.11.4) '@nanostores/persistent': 0.10.2(nanostores@0.11.4) '@oslojs/binary': 1.0.0 @@ -10594,7 +10389,6 @@ snapshots: figlet: 1.8.0 fuse.js: 7.1.0 is-unicode-supported: 2.1.0 - jsonwebtoken: 9.0.2 katex: 0.16.21 lodash: 4.17.21 mdast-util-from-markdown: 2.0.2 @@ -10603,7 +10397,6 @@ snapshots: mrmime: 2.0.1 nanostores: 0.11.4 nodemailer: 6.10.0 - package-json: 10.0.1 semver: 7.7.1 slice-ansi: 7.1.0 socks: 2.8.4 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b9a0d4c..f862fc7 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,20 +2,20 @@ catalog: '@astrojs/db': ^0.14.8 '@astrojs/check': ^0.9.4 '@astrojs/node': ^9.1.2 - '@studiocms/blog': 0.1.0-beta.13 - '@studiocms/devapps': 0.1.0-beta.13 + '@studiocms/blog': 0.1.0-beta.14 + '@studiocms/devapps': 0.1.0-beta.14 '@types/node': ^22.0.0 astro: ^5.5 astro-integration-kit: ^0.18 sharp: ^0.33.5 - studiocms: 0.1.0-beta.13 + studiocms: 0.1.0-beta.14 typescript: ^5.7 vite: ^6.2.5 catalogs: min: astro: ^5.5 - studiocms: 0.1.0-beta.13 + studiocms: 0.1.0-beta.14 '@astrojs/db': ^0.14.7 vite: ^6.2.0 From 1b461d1fea16dfa647011cf4a8722a650494e234 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:11:29 -0700 Subject: [PATCH 03/18] setup api endpoint for bluesky --- .vscode/settings.json | 61 +++++++------- packages/studiocms_socialposter/package.json | 1 + .../src/routes/postToBlueSky.ts | 55 +++++++++++- .../src/routes/postToThreads.ts | 3 + .../src/routes/postToTwitter.ts | 3 + .../src/utils/response.ts | 7 ++ pnpm-lock.yaml | 84 +++++++++++++++++++ 7 files changed, 183 insertions(+), 31 deletions(-) create mode 100644 packages/studiocms_socialposter/src/utils/response.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 00d4e49..7c7c231 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,32 +1,33 @@ { - "cSpell.words": [ - "aligncenter", - "alignjustify", - "alignleft", - "alignright", - "astroenv", - "Avenir", - "backcolor", - "bullist", - "cmdm", - "CMSWYSIWYG", - "compkeys", - "forecolor", - "fslightbox", - "grapesjs", - "grayscale", - "iconify", - "Lightbox", - "numlist", - "outdent", - "projectdata", - "socialposter", - "strikethrough", - "studiocms", - "studiosdk", - "toastr", - "virtuals", - "withstudiocms", - "WYSIWYGDB" - ] + "cSpell.words": [ + "aligncenter", + "alignjustify", + "alignleft", + "alignright", + "astroenv", + "atproto", + "Avenir", + "backcolor", + "bullist", + "cmdm", + "CMSWYSIWYG", + "compkeys", + "forecolor", + "fslightbox", + "grapesjs", + "grayscale", + "iconify", + "Lightbox", + "numlist", + "outdent", + "projectdata", + "socialposter", + "strikethrough", + "studiocms", + "studiosdk", + "toastr", + "virtuals", + "withstudiocms", + "WYSIWYGDB" + ] } diff --git a/packages/studiocms_socialposter/package.json b/packages/studiocms_socialposter/package.json index 47e731e..0b9886b 100644 --- a/packages/studiocms_socialposter/package.json +++ b/packages/studiocms_socialposter/package.json @@ -46,6 +46,7 @@ }, "type": "module", "dependencies": { + "@atproto/api": "^0.14.20", "@studiocms/ui": "^0.4.16", "astro-integration-kit": "catalog:", "ultrahtml": "^1.5.3", diff --git a/packages/studiocms_socialposter/src/routes/postToBlueSky.ts b/packages/studiocms_socialposter/src/routes/postToBlueSky.ts index ae503f7..578a622 100644 --- a/packages/studiocms_socialposter/src/routes/postToBlueSky.ts +++ b/packages/studiocms_socialposter/src/routes/postToBlueSky.ts @@ -1 +1,54 @@ -import { BLUESKY_PASSWORD, BLUESKY_SERVICE, BLUESKY_USERNAME } from 'astro:env/server'; +import type { APIContext, APIRoute } from "astro"; +import { AtpAgent } from "@atproto/api"; +import { + BLUESKY_PASSWORD, + BLUESKY_SERVICE, + BLUESKY_USERNAME, +} from "astro:env/server"; +import logger from "studiocms:logger"; +import { response } from "../utils/response.js"; + +export const POST: APIRoute = async (context: APIContext) => { + if (!BLUESKY_PASSWORD || !BLUESKY_SERVICE || !BLUESKY_USERNAME) { + return response(500, JSON.stringify({ error: "Missing ENV Variables" })); + } + + const { content } = await context.request.json(); + + if (!content) { + return response( + 500, + JSON.stringify({ error: "Content must not be empty" }), + ); + } + + const agent = new AtpAgent({ + service: new URL(BLUESKY_SERVICE), + }); + + try { + await agent.login({ + identifier: BLUESKY_USERNAME, + password: BLUESKY_PASSWORD, + }); + + await agent.post({ + text: content, + createdAt: new Date().toISOString(), + }); + + return response( + 200, + JSON.stringify({ message: "Successfully sent BlueSky message" }), + ); + } catch (e) { + logger.error(`Error posting to Bluesky: ${e}`); + + return response( + 500, + JSON.stringify({ + error: (e as Error).message || "Failed to post to BlueSky", + }), + ); + } +}; diff --git a/packages/studiocms_socialposter/src/routes/postToThreads.ts b/packages/studiocms_socialposter/src/routes/postToThreads.ts index 0fb8742..8690329 100644 --- a/packages/studiocms_socialposter/src/routes/postToThreads.ts +++ b/packages/studiocms_socialposter/src/routes/postToThreads.ts @@ -1 +1,4 @@ import { THREADS_ACCESS_TOKEN, THREADS_USER_ID } from 'astro:env/server'; +import logger from 'studiocms:logger'; +import { response } from '../utils/response.js'; +import type { APIContext, APIRoute } from 'astro'; diff --git a/packages/studiocms_socialposter/src/routes/postToTwitter.ts b/packages/studiocms_socialposter/src/routes/postToTwitter.ts index 5bd36f9..9ece044 100644 --- a/packages/studiocms_socialposter/src/routes/postToTwitter.ts +++ b/packages/studiocms_socialposter/src/routes/postToTwitter.ts @@ -4,3 +4,6 @@ import { TWITTER_API_KEY, TWITTER_API_SECRET, } from 'astro:env/server'; +import logger from 'studiocms:logger'; +import { response } from '../utils/response.js'; +import type { APIContext, APIRoute } from 'astro'; diff --git a/packages/studiocms_socialposter/src/utils/response.ts b/packages/studiocms_socialposter/src/utils/response.ts new file mode 100644 index 0000000..43d1dd7 --- /dev/null +++ b/packages/studiocms_socialposter/src/utils/response.ts @@ -0,0 +1,7 @@ +export const response = (status: number, data: string) => + new Response(data, { + status, + headers: { + 'Content-Type': 'application/json', + }, + }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae49b99..4d19d8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,9 @@ importers: packages/studiocms_socialposter: dependencies: + '@atproto/api': + specifier: ^0.14.20 + version: 0.14.20 '@studiocms/ui': specifier: ^0.4.16 version: 0.4.16(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) @@ -281,6 +284,21 @@ packages: resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} + '@atproto/api@0.14.20': + resolution: {integrity: sha512-Daip22+u9N+EVPk9PsEEVrTfjIqGczXnAT7o2EHGd0JsOzMbp3a6wmW1beKqYDzPf+Dc36/39JeUYYqhB3fKjg==} + + '@atproto/common-web@0.4.1': + resolution: {integrity: sha512-Ghh+djHYMAUCktLKwr2IuGgtjcwSWGudp+K7+N7KBA9pDDloOXUEY8Agjc5SHSo9B1QIEFkegClU5n+apn2e0w==} + + '@atproto/lexicon@0.4.10': + resolution: {integrity: sha512-uDbP20vetBgtXPuxoyRcvOGBt2gNe1dFc9yYKcb6jWmXfseHiGTnIlORJOLBXIT2Pz15Eap4fLxAu6zFAykD5A==} + + '@atproto/syntax@0.4.0': + resolution: {integrity: sha512-b9y5ceHS8YKOfP3mdKmwAx5yVj9294UN7FG2XzP6V5aKUdFazEYRnR9m5n5ZQFKa3GNvz7de9guZCJ/sUTcOAA==} + + '@atproto/xrpc@0.6.12': + resolution: {integrity: sha512-Ut3iISNLujlmY9Gu8sNU+SPDJDvqlVzWddU8qUr0Yae5oD4SguaUFjjhireMGhQ3M5E0KljQgDbTmnBo1kIZ3w==} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -1972,6 +1990,9 @@ packages: resolution: {integrity: sha512-TkOhqze98lP+6e7SPbrBpyhTpfvqqX8VYKGn4uckrgPan4WQIHnTaUD2zZzZS18eVVDj4rHPcIZa1PGgvo1DfA==} engines: {node: '>= 14'} + await-lock@2.2.2: + resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -3025,6 +3046,9 @@ packages: grapesjs@0.22.6: resolution: {integrity: sha512-V4sD0jDhE95bz3bwC3gD+DmZzelwgozlarcFrEQFGv7HwYmKOIVXni7i8NVj/DLRGCD5jVHmr4k/sV5oSXPajw==} + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + grapick@0.1.13: resolution: {integrity: sha512-2v7DdmXKbl9+GsL2ZRl2qEMD+PeczYJBSifwx+5SGbaSh0pZ+b6GLya87cBfN953wwXsZqyzuSVPBzqRz8F12g==} @@ -3361,6 +3385,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + iso-datestring-validator@2.2.2: + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} + isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} @@ -3764,6 +3791,9 @@ packages: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} hasBin: true + multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -4725,6 +4755,10 @@ packages: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} + tlds@1.256.0: + resolution: {integrity: sha512-ZmyVB9DAw+FFTmLElGYJgdZFsKLYd/I59Bg9NHkCGPwAbVZNRilFWDMAdX8UG+bHuv7kfursd5XGqo/9wi26lA==} + hasBin: true + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -4810,6 +4844,9 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + uint8arrays@3.0.0: + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} + ultrahtml@1.5.3: resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} @@ -5360,6 +5397,39 @@ snapshots: transitivePeerDependencies: - supports-color + '@atproto/api@0.14.20': + dependencies: + '@atproto/common-web': 0.4.1 + '@atproto/lexicon': 0.4.10 + '@atproto/syntax': 0.4.0 + '@atproto/xrpc': 0.6.12 + await-lock: 2.2.2 + multiformats: 9.9.0 + tlds: 1.256.0 + zod: 3.24.2 + + '@atproto/common-web@0.4.1': + dependencies: + graphemer: 1.4.0 + multiformats: 9.9.0 + uint8arrays: 3.0.0 + zod: 3.24.2 + + '@atproto/lexicon@0.4.10': + dependencies: + '@atproto/common-web': 0.4.1 + '@atproto/syntax': 0.4.0 + iso-datestring-validator: 2.2.2 + multiformats: 9.9.0 + zod: 3.24.2 + + '@atproto/syntax@0.4.0': {} + + '@atproto/xrpc@0.6.12': + dependencies: + '@atproto/lexicon': 0.4.10 + zod: 3.24.2 + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -7349,6 +7419,8 @@ snapshots: async-listen@3.1.0: {} + await-lock@2.2.2: {} + axobject-query@4.1.0: {} babel-loader@9.2.1(@babel/core@7.26.10)(webpack@5.98.0(webpack-cli@5.1.4)): @@ -8368,6 +8440,8 @@ snapshots: promise-polyfill: 8.3.0 underscore: 1.13.1 + graphemer@1.4.0: {} + grapick@0.1.13: {} h3@1.15.1: @@ -8742,6 +8816,8 @@ snapshots: isexe@2.0.0: {} + iso-datestring-validator@2.2.2: {} + isobject@3.0.1: {} jest-worker@27.5.1: @@ -9324,6 +9400,8 @@ snapshots: dns-packet: 5.6.1 thunky: 1.1.0 + multiformats@9.9.0: {} + mute-stream@0.0.8: {} nanoid@3.3.11: {} @@ -10495,6 +10573,8 @@ snapshots: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 + tlds@1.256.0: {} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -10566,6 +10646,10 @@ snapshots: ufo@1.5.4: {} + uint8arrays@3.0.0: + dependencies: + multiformats: 9.9.0 + ultrahtml@1.5.3: {} uncrypto@0.1.3: {} From f275b09cefdaad93bac482fce4f6813f6386c9d1 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:23:03 -0700 Subject: [PATCH 04/18] Setup Twitter posting API --- packages/studiocms_socialposter/package.json | 1 + .../src/routes/postToTwitter.ts | 37 +++++++++++++++++++ pnpm-lock.yaml | 8 ++++ 3 files changed, 46 insertions(+) diff --git a/packages/studiocms_socialposter/package.json b/packages/studiocms_socialposter/package.json index 0b9886b..fe4a9d3 100644 --- a/packages/studiocms_socialposter/package.json +++ b/packages/studiocms_socialposter/package.json @@ -49,6 +49,7 @@ "@atproto/api": "^0.14.20", "@studiocms/ui": "^0.4.16", "astro-integration-kit": "catalog:", + "twitter-api-v2": "^1.22.0", "ultrahtml": "^1.5.3", "quill": "^2.0.3" }, diff --git a/packages/studiocms_socialposter/src/routes/postToTwitter.ts b/packages/studiocms_socialposter/src/routes/postToTwitter.ts index 9ece044..dc26160 100644 --- a/packages/studiocms_socialposter/src/routes/postToTwitter.ts +++ b/packages/studiocms_socialposter/src/routes/postToTwitter.ts @@ -7,3 +7,40 @@ import { import logger from 'studiocms:logger'; import { response } from '../utils/response.js'; import type { APIContext, APIRoute } from 'astro'; +import { TwitterApi } from 'twitter-api-v2'; + +export const POST: APIRoute = async (context: APIContext) => { + if (!TWITTER_API_KEY || !TWITTER_API_SECRET || !TWITTER_ACCESS_TOKEN || !TWITTER_ACCESS_SECRET) { + return response(500, JSON.stringify({ error: 'Missing ENV Variables' })); + } + + // Initialize the Twitter client with credentials from environment variables + const client = new TwitterApi({ + appKey: TWITTER_API_KEY, + appSecret: TWITTER_API_SECRET, + accessToken: TWITTER_ACCESS_TOKEN, + accessSecret: TWITTER_ACCESS_SECRET, + }); + + const { content } = await context.request.json(); + + if (!content) { + return response(500, JSON.stringify({ error: 'Content must not be empty' })); + } + + try { + // Create the tweet + await client.v2.tweet(content); + + return response(200, JSON.stringify({ message: 'Successfully sent Twitter/X message' })); + } catch (e) { + logger.error(`Error posting to Twitter / X: ${e}`); + + return response( + 500, + JSON.stringify({ + error: (e as Error).message || 'Failed to post to Twitter / X', + }) + ); + } +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d19d8c..ccac445 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,9 @@ importers: studiocms: specifier: catalog:min version: 0.1.0-beta.14(@astrojs/db@0.14.9(@types/react@19.0.12)(react@19.0.0))(@astrojs/markdown-remark@6.3.1)(@libsql/client@0.15.1)(@types/react@19.0.12)(astro@5.5.5(@types/node@22.13.13)(jiti@2.4.2)(rollup@4.37.0)(terser@5.39.0)(typescript@5.8.2))(react@19.0.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0)) + twitter-api-v2: + specifier: ^1.22.0 + version: 1.22.0 ultrahtml: specifier: ^1.5.3 version: 1.5.3 @@ -4820,6 +4823,9 @@ packages: turndown@7.2.0: resolution: {integrity: sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==} + twitter-api-v2@1.22.0: + resolution: {integrity: sha512-KlcRL9vcBzjeS/PwxX33NziP+SHp9n35DOclKtpOmnNes7nNVnK7WG4pKlHfBqGrY5kAz/8J5ERS8DWkYOaiWw==} + type-detect@4.1.0: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} @@ -10631,6 +10637,8 @@ snapshots: dependencies: '@mixmark-io/domino': 2.2.0 + twitter-api-v2@1.22.0: {} + type-detect@4.1.0: {} type-fest@0.21.3: {} From 8d3dc5e278b6f0bf083a7a1d3ff07dc8e8ab4e00 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:35:39 -0700 Subject: [PATCH 05/18] Setup threads API --- .../src/routes/postToThreads.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/packages/studiocms_socialposter/src/routes/postToThreads.ts b/packages/studiocms_socialposter/src/routes/postToThreads.ts index 8690329..d8a48db 100644 --- a/packages/studiocms_socialposter/src/routes/postToThreads.ts +++ b/packages/studiocms_socialposter/src/routes/postToThreads.ts @@ -2,3 +2,69 @@ import { THREADS_ACCESS_TOKEN, THREADS_USER_ID } from 'astro:env/server'; import logger from 'studiocms:logger'; import { response } from '../utils/response.js'; import type { APIContext, APIRoute } from 'astro'; + +export const POST: APIRoute = async (context: APIContext) => { + if (!THREADS_ACCESS_TOKEN || !THREADS_USER_ID) { + return response(500, JSON.stringify({ error: 'Missing ENV Variables' })); + } + + const { content } = await context.request.json(); + + if (!content) { + return response(500, JSON.stringify({ error: 'Content must not be empty' })); + } + + try { + console.log('Creating Threads post container...'); + + const createResponseParams = new URLSearchParams({ + text: content, + access_token: THREADS_ACCESS_TOKEN, + media_type: 'TEXT', + }); + + const createResponse = await fetch( + `https://graph.threads.net/v1.0/${THREADS_USER_ID}/threads?${createResponseParams.toString()}`, + { + method: 'POST', + } + ); + + const createResponseData = await createResponse.json(); + + console.log('Create response:', createResponseData); + + if (!createResponseData.id) { + throw new Error('Failed to get post container ID'); + } + + console.log('Publishing Threads post...'); + + const params = new URLSearchParams({ + creation_id: createResponseData.id, + access_token: THREADS_ACCESS_TOKEN, + }); + + const publishResponse = await fetch( + `https://graph.threads.net/v1.0/${THREADS_USER_ID}/threads_publish?${params.toString()}`, + { + method: 'POST', + } + ); + + const publishResponseData = await publishResponse.json(); + + console.log('Publish response:', publishResponseData); + + return response(200, JSON.stringify('Successfully sent Threads message')); + } catch (e) { + logger.error(`Error posting to Threads: ${e}`); + + return response( + 500, + JSON.stringify({ + error: (e as Error).message || 'Failed to post to Threads', + }) + ); + } +}; From afd59bf41040d021606fc36d677abd9af6242b0d Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:38:12 -0700 Subject: [PATCH 06/18] update --- .../src/routes/postToThreads.ts | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/studiocms_socialposter/src/routes/postToThreads.ts b/packages/studiocms_socialposter/src/routes/postToThreads.ts index d8a48db..5a2ed22 100644 --- a/packages/studiocms_socialposter/src/routes/postToThreads.ts +++ b/packages/studiocms_socialposter/src/routes/postToThreads.ts @@ -1,5 +1,4 @@ import { THREADS_ACCESS_TOKEN, THREADS_USER_ID } from 'astro:env/server'; -import logger from 'studiocms:logger'; import { response } from '../utils/response.js'; import type { APIContext, APIRoute } from 'astro'; @@ -58,12 +57,34 @@ export const POST: APIRoute = async (context: APIContext) => { return response(200, JSON.stringify('Successfully sent Threads message')); } catch (e) { - logger.error(`Error posting to Threads: ${e}`); + console.error('Threads API Error:', { + // @ts-ignore + message: e.message, + // @ts-ignore + response: e.response?.data || e.response, + // @ts-ignore + status: e.response?.status, + config: { + // @ts-ignore + url: e.config?.url, + // @ts-ignore + params: e.config?.params, + }, + }); + + const errorMessage = + // @ts-ignore + e.response?.data?.error?.message || + // @ts-ignore + e.response?.data?.message || + // @ts-ignore + e.message || + 'Failed to post to Threads'; return response( 500, JSON.stringify({ - error: (e as Error).message || 'Failed to post to Threads', + error: errorMessage || 'Failed to post to Threads', }) ); } From 2474f0a2ec762bd2fc3e7d69eb86020676a04e6c Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:41:05 -0700 Subject: [PATCH 07/18] remove unused css --- .../src/styles/quill.core.css | 491 ------------------ 1 file changed, 491 deletions(-) delete mode 100644 packages/studiocms_socialposter/src/styles/quill.core.css diff --git a/packages/studiocms_socialposter/src/styles/quill.core.css b/packages/studiocms_socialposter/src/styles/quill.core.css deleted file mode 100644 index 7090dc4..0000000 --- a/packages/studiocms_socialposter/src/styles/quill.core.css +++ /dev/null @@ -1,491 +0,0 @@ -/*! - * Quill Editor v2.0.3 - * https://quilljs.com - * Copyright (c) 2017-2024, Slab - * Copyright (c) 2014, Jason Chen - * Copyright (c) 2013, salesforce.com - */ -.ql-container { - box-sizing: border-box; - font-family: Helvetica, Arial, sans-serif; - font-size: 13px; - height: 100%; - margin: 0; - position: relative; -} -.ql-container.ql-disabled .ql-tooltip { - visibility: hidden; -} -.ql-container:not(.ql-disabled) li[data-list="checked"] > .ql-ui, -.ql-container:not(.ql-disabled) li[data-list="unchecked"] > .ql-ui { - cursor: pointer; -} -.ql-clipboard { - left: -100000px; - height: 1px; - overflow-y: hidden; - position: absolute; - top: 50%; -} -.ql-clipboard p { - margin: 0; - padding: 0; -} -.ql-editor { - box-sizing: border-box; - counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - line-height: 1.42; - height: 100%; - outline: none; - overflow-y: auto; - padding: 12px 15px; - tab-size: 4; - -moz-tab-size: 4; - text-align: left; - white-space: pre-wrap; - word-wrap: break-word; -} -.ql-editor > * { - cursor: text; -} -.ql-editor p, -.ql-editor ol, -.ql-editor pre, -.ql-editor blockquote, -.ql-editor h1, -.ql-editor h2, -.ql-editor h3, -.ql-editor h4, -.ql-editor h5, -.ql-editor h6 { - margin: 0; - padding: 0; -} -@supports (counter-set: none) { - .ql-editor p, - .ql-editor h1, - .ql-editor h2, - .ql-editor h3, - .ql-editor h4, - .ql-editor h5, - .ql-editor h6 { - counter-set: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor p, - .ql-editor h1, - .ql-editor h2, - .ql-editor h3, - .ql-editor h4, - .ql-editor h5, - .ql-editor h6 { - counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor table { - border-collapse: collapse; -} -.ql-editor td { - border: 1px solid #000; - padding: 2px 5px; -} -.ql-editor ol { - padding-left: 1.5em; -} -.ql-editor li { - list-style-type: none; - padding-left: 1.5em; - position: relative; -} -.ql-editor li > .ql-ui:before { - display: inline-block; - margin-left: -1.5em; - margin-right: .3em; - text-align: right; - white-space: nowrap; - width: 1.2em; -} -.ql-editor li[data-list="checked"] > .ql-ui, -.ql-editor li[data-list="unchecked"] > .ql-ui { - color: #777; -} -.ql-editor li[data-list="bullet"] > .ql-ui:before { - content: "\2022"; -} -.ql-editor li[data-list="checked"] > .ql-ui:before { - content: "\2611"; -} -.ql-editor li[data-list="unchecked"] > .ql-ui:before { - content: "\2610"; -} -@supports (counter-set: none) { - .ql-editor li[data-list] { - counter-set: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list] { - counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"] { - counter-increment: list-0; -} -.ql-editor li[data-list="ordered"] > .ql-ui:before { - content: counter(list-0, decimal) ". "; -} -.ql-editor li[data-list="ordered"].ql-indent-1 { - counter-increment: list-1; -} -.ql-editor li[data-list="ordered"].ql-indent-1 > .ql-ui:before { - content: counter(list-1, lower-alpha) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-1 { - counter-set: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-1 { - counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-2 { - counter-increment: list-2; -} -.ql-editor li[data-list="ordered"].ql-indent-2 > .ql-ui:before { - content: counter(list-2, lower-roman) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-2 { - counter-set: list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-2 { - counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-3 { - counter-increment: list-3; -} -.ql-editor li[data-list="ordered"].ql-indent-3 > .ql-ui:before { - content: counter(list-3, decimal) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-3 { - counter-set: list-4 list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-3 { - counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-4 { - counter-increment: list-4; -} -.ql-editor li[data-list="ordered"].ql-indent-4 > .ql-ui:before { - content: counter(list-4, lower-alpha) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-4 { - counter-set: list-5 list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-4 { - counter-reset: list-5 list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-5 { - counter-increment: list-5; -} -.ql-editor li[data-list="ordered"].ql-indent-5 > .ql-ui:before { - content: counter(list-5, lower-roman) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-5 { - counter-set: list-6 list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-5 { - counter-reset: list-6 list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-6 { - counter-increment: list-6; -} -.ql-editor li[data-list="ordered"].ql-indent-6 > .ql-ui:before { - content: counter(list-6, decimal) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-6 { - counter-set: list-7 list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-6 { - counter-reset: list-7 list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-7 { - counter-increment: list-7; -} -.ql-editor li[data-list="ordered"].ql-indent-7 > .ql-ui:before { - content: counter(list-7, lower-alpha) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-7 { - counter-set: list-8 list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-7 { - counter-reset: list-8 list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-8 { - counter-increment: list-8; -} -.ql-editor li[data-list="ordered"].ql-indent-8 > .ql-ui:before { - content: counter(list-8, lower-roman) ". "; -} -@supports (counter-set: none) { - .ql-editor li[data-list].ql-indent-8 { - counter-set: list-9; - } -} -@supports not (counter-set: none) { - .ql-editor li[data-list].ql-indent-8 { - counter-reset: list-9; - } -} -.ql-editor li[data-list="ordered"].ql-indent-9 { - counter-increment: list-9; -} -.ql-editor li[data-list="ordered"].ql-indent-9 > .ql-ui:before { - content: counter(list-9, decimal) ". "; -} -.ql-editor .ql-indent-1:not(.ql-direction-rtl) { - padding-left: 3em; -} -.ql-editor li.ql-indent-1:not(.ql-direction-rtl) { - padding-left: 4.5em; -} -.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { - padding-right: 3em; -} -.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { - padding-right: 4.5em; -} -.ql-editor .ql-indent-2:not(.ql-direction-rtl) { - padding-left: 6em; -} -.ql-editor li.ql-indent-2:not(.ql-direction-rtl) { - padding-left: 7.5em; -} -.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { - padding-right: 6em; -} -.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { - padding-right: 7.5em; -} -.ql-editor .ql-indent-3:not(.ql-direction-rtl) { - padding-left: 9em; -} -.ql-editor li.ql-indent-3:not(.ql-direction-rtl) { - padding-left: 10.5em; -} -.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { - padding-right: 9em; -} -.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { - padding-right: 10.5em; -} -.ql-editor .ql-indent-4:not(.ql-direction-rtl) { - padding-left: 12em; -} -.ql-editor li.ql-indent-4:not(.ql-direction-rtl) { - padding-left: 13.5em; -} -.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { - padding-right: 12em; -} -.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { - padding-right: 13.5em; -} -.ql-editor .ql-indent-5:not(.ql-direction-rtl) { - padding-left: 15em; -} -.ql-editor li.ql-indent-5:not(.ql-direction-rtl) { - padding-left: 16.5em; -} -.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { - padding-right: 15em; -} -.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { - padding-right: 16.5em; -} -.ql-editor .ql-indent-6:not(.ql-direction-rtl) { - padding-left: 18em; -} -.ql-editor li.ql-indent-6:not(.ql-direction-rtl) { - padding-left: 19.5em; -} -.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { - padding-right: 18em; -} -.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { - padding-right: 19.5em; -} -.ql-editor .ql-indent-7:not(.ql-direction-rtl) { - padding-left: 21em; -} -.ql-editor li.ql-indent-7:not(.ql-direction-rtl) { - padding-left: 22.5em; -} -.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { - padding-right: 21em; -} -.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { - padding-right: 22.5em; -} -.ql-editor .ql-indent-8:not(.ql-direction-rtl) { - padding-left: 24em; -} -.ql-editor li.ql-indent-8:not(.ql-direction-rtl) { - padding-left: 25.5em; -} -.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { - padding-right: 24em; -} -.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { - padding-right: 25.5em; -} -.ql-editor .ql-indent-9:not(.ql-direction-rtl) { - padding-left: 27em; -} -.ql-editor li.ql-indent-9:not(.ql-direction-rtl) { - padding-left: 28.5em; -} -.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { - padding-right: 27em; -} -.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { - padding-right: 28.5em; -} -.ql-editor li.ql-direction-rtl { - padding-right: 1.5em; -} -.ql-editor li.ql-direction-rtl > .ql-ui:before { - margin-left: .3em; - margin-right: -1.5em; - text-align: left; -} -.ql-editor table { - table-layout: fixed; - width: 100%; -} -.ql-editor table td { - outline: none; -} -.ql-editor .ql-code-block-container { - font-family: monospace; -} -.ql-editor .ql-video { - display: block; - max-width: 100%; -} -.ql-editor .ql-video.ql-align-center { - margin: 0 auto; -} -.ql-editor .ql-video.ql-align-right { - margin: 0 0 0 auto; -} -.ql-editor .ql-bg-black { - background-color: #000; -} -.ql-editor .ql-bg-red { - background-color: #e60000; -} -.ql-editor .ql-bg-orange { - background-color: #f90; -} -.ql-editor .ql-bg-yellow { - background-color: #ff0; -} -.ql-editor .ql-bg-green { - background-color: #008a00; -} -.ql-editor .ql-bg-blue { - background-color: #06c; -} -.ql-editor .ql-bg-purple { - background-color: #93f; -} -.ql-editor .ql-color-white { - color: #fff; -} -.ql-editor .ql-color-red { - color: #e60000; -} -.ql-editor .ql-color-orange { - color: #f90; -} -.ql-editor .ql-color-yellow { - color: #ff0; -} -.ql-editor .ql-color-green { - color: #008a00; -} -.ql-editor .ql-color-blue { - color: #06c; -} -.ql-editor .ql-color-purple { - color: #93f; -} -.ql-editor .ql-font-serif { - font-family: Georgia, Times New Roman, serif; -} -.ql-editor .ql-font-monospace { - font-family: Monaco, Courier New, monospace; -} -.ql-editor .ql-size-small { - font-size: .75em; -} -.ql-editor .ql-size-large { - font-size: 1.5em; -} -.ql-editor .ql-size-huge { - font-size: 2.5em; -} -.ql-editor .ql-direction-rtl { - direction: rtl; - text-align: inherit; -} -.ql-editor .ql-align-center { - text-align: center; -} -.ql-editor .ql-align-justify { - text-align: justify; -} -.ql-editor .ql-align-right { - text-align: right; -} -.ql-editor .ql-ui { - position: absolute; -} -.ql-editor.ql-blank::before { - color: rgba(0, 0, 0, 0.6); - content: attr(data-placeholder); - font-style: italic; - left: 15px; - pointer-events: none; - position: absolute; - right: 15px; -} - -/*# sourceMappingURL=quill.core.css.map*/ From 995249e6f021cd7966261a1cc941217d69781da0 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:42:48 -0700 Subject: [PATCH 08/18] update deps --- packages/studiocms_socialposter/package.json | 1 - pnpm-lock.yaml | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/studiocms_socialposter/package.json b/packages/studiocms_socialposter/package.json index fe4a9d3..1d8a706 100644 --- a/packages/studiocms_socialposter/package.json +++ b/packages/studiocms_socialposter/package.json @@ -50,7 +50,6 @@ "@studiocms/ui": "^0.4.16", "astro-integration-kit": "catalog:", "twitter-api-v2": "^1.22.0", - "ultrahtml": "^1.5.3", "quill": "^2.0.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ccac445..fc9db8d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,9 +126,6 @@ importers: twitter-api-v2: specifier: ^1.22.0 version: 1.22.0 - ultrahtml: - specifier: ^1.5.3 - version: 1.5.3 vite: specifier: catalog:min version: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(terser@5.39.0) From b2bd004e292db6a1ed22b33e2093ab3f8ee3417e Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 04:47:15 -0700 Subject: [PATCH 09/18] update socials.astro --- .../src/pages/socials.astro | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/studiocms_socialposter/src/pages/socials.astro b/packages/studiocms_socialposter/src/pages/socials.astro index 0e0ec07..e392f04 100644 --- a/packages/studiocms_socialposter/src/pages/socials.astro +++ b/packages/studiocms_socialposter/src/pages/socials.astro @@ -139,13 +139,22 @@ const { bluesky, threads, twitter } = socialsConfig; const todo: { url: string, name: string }[] = [] if (bluesky) { - todo.push({name: 'BlueSky', url: '/studiocms_api/socialposter/post-to-bluesky'}); + todo.push({ + name: 'BlueSky', + url: '/studiocms_api/socialposter/post-to-bluesky' + }); } if (threads) { - todo.push({name: 'Threads', url: '/studiocms_api/socialposter/post-to-threads'}); + todo.push({ + name: 'Threads', + url: '/studiocms_api/socialposter/post-to-threads' + }); } if (twitter) { - todo.push({name: 'Twitter', url: '/studiocms_api/socialposter/post-to-twitter'}); + todo.push({ + name: 'Twitter', + url: '/studiocms_api/socialposter/post-to-twitter' + }); } const responses: any = [] From a72e18657cca5f782c07157df7f0027d6c1be4a0 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Mon, 7 Apr 2025 06:00:24 -0700 Subject: [PATCH 10/18] add social icons via css --- .../src/pages/socials.astro | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/studiocms_socialposter/src/pages/socials.astro b/packages/studiocms_socialposter/src/pages/socials.astro index e392f04..0bc7b7a 100644 --- a/packages/studiocms_socialposter/src/pages/socials.astro +++ b/packages/studiocms_socialposter/src/pages/socials.astro @@ -22,7 +22,7 @@ const { bluesky, threads, twitter } = socialsConfig;
-
Select where to post:
+
Select where to post
{ bluesky && } { threads && } @@ -197,6 +197,55 @@ const { bluesky, threads, twitter } = socialsConfig; }) + +