From 75bb028f9efec15176f92fbec9d30e5b60fe033b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 08:46:18 +0000 Subject: [PATCH 1/2] chore(deps): update dependency @sveltejs/kit to ^2.45.0 --- .templates/template-sveltekit/package.json | 2 +- sveltekit-full/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.templates/template-sveltekit/package.json b/.templates/template-sveltekit/package.json index 993893e3b..bbf260f08 100644 --- a/.templates/template-sveltekit/package.json +++ b/.templates/template-sveltekit/package.json @@ -14,7 +14,7 @@ "@egoist/tailwindcss-icons": "^1.9.0", "@iconify-json/lucide": "^1.2.68", "@sveltejs/adapter-auto": "^6.1.1", - "@sveltejs/kit": "^2.44.0", + "@sveltejs/kit": "^2.45.0", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.14", "postcss": "^8.5.6", diff --git a/sveltekit-full/package.json b/sveltekit-full/package.json index d084ce5a0..0a2ed9485 100644 --- a/sveltekit-full/package.json +++ b/sveltekit-full/package.json @@ -14,7 +14,7 @@ "@egoist/tailwindcss-icons": "^1.9.0", "@iconify-json/lucide": "^1.2.68", "@sveltejs/adapter-auto": "^6.1.1", - "@sveltejs/kit": "^2.44.0", + "@sveltejs/kit": "^2.45.0", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.14", "postcss": "^8.5.6", From cb03671365298ce80d0943d57f01c4fe29a07525 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 08:46:45 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- lit-dom/src/editor.ts | 2 +- next-full/src/default-content-full.ts | 2 +- nuxt-full/src/default-content-full.ts | 2 +- preact-image-view/.gitignore | 4 + preact-image-view/README.md | 15 +++ preact-image-view/index.html | 12 +++ preact-image-view/package.json | 26 ++++++ preact-image-view/src/app.css | 13 +++ preact-image-view/src/editor.tsx | 29 ++++++ preact-image-view/src/extension.ts | 25 +++++ preact-image-view/src/image-view.tsx | 93 +++++++++++++++++++ preact-image-view/src/main.tsx | 5 + preact-image-view/src/sample-doc-image.ts | 32 +++++++ preact-image-view/src/sample-uploader.ts | 54 +++++++++++ preact-image-view/tsconfig.json | 26 ++++++ preact-image-view/tsconfig.node.json | 10 ++ preact-image-view/vite.config.ts | 8 ++ preact-link-mark-view/.gitignore | 4 + preact-link-mark-view/README.md | 15 +++ preact-link-mark-view/index.html | 12 +++ preact-link-mark-view/package.json | 26 ++++++ preact-link-mark-view/src/app.css | 13 +++ preact-link-mark-view/src/editor.tsx | 31 +++++++ preact-link-mark-view/src/extension.ts | 17 ++++ preact-link-mark-view/src/link-view.tsx | 46 +++++++++ preact-link-mark-view/src/main.tsx | 5 + preact-link-mark-view/tsconfig.json | 26 ++++++ preact-link-mark-view/tsconfig.node.json | 10 ++ preact-link-mark-view/vite.config.ts | 8 ++ preact-typography/src/typography-content.ts | 2 +- react-code-block-themes/src/editor.tsx | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 react-code-block/src/editor.tsx | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 react-full/src/default-content-full.ts | 2 +- react-gap-cursor/src/editor.tsx | 4 +- react-image-view/src/sample-doc-image.ts | 12 +-- react-typography/src/typography-content.ts | 2 +- solid-code-block/src/editor.tsx | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 solid-drop-cursor/src/editor.tsx | 2 +- ...fault-doc.ts => sample-doc-drop-cursor.ts} | 8 +- solid-image-view/src/sample-doc-image.ts | 12 +-- solid-typography/src/typography-content.ts | 2 +- svelte-code-block-themes/src/editor.svelte | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 svelte-code-block/src/editor.svelte | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 svelte-drop-cursor/src/editor.svelte | 2 +- ...fault-doc.ts => sample-doc-drop-cursor.ts} | 8 +- svelte-full/src/default-content-full.ts | 2 +- svelte-image-view/src/sample-doc-image.ts | 12 +-- svelte-typography/src/typography-content.ts | 2 +- .../src/lib/default-content-full.ts | 2 +- vue-code-block-themes/src/editor.vue | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 vue-code-block/src/editor.vue | 2 +- ...efault-doc.ts => sample-doc-code-block.ts} | 0 vue-drop-cursor/src/editor.vue | 2 +- ...fault-doc.ts => sample-doc-drop-cursor.ts} | 8 +- vue-full/src/default-content-full.ts | 2 +- vue-image-view/src/sample-doc-image.ts | 12 +-- vue-typography/src/typography-content.ts | 2 +- 63 files changed, 625 insertions(+), 60 deletions(-) create mode 100644 preact-image-view/.gitignore create mode 100644 preact-image-view/README.md create mode 100644 preact-image-view/index.html create mode 100644 preact-image-view/package.json create mode 100644 preact-image-view/src/app.css create mode 100644 preact-image-view/src/editor.tsx create mode 100644 preact-image-view/src/extension.ts create mode 100644 preact-image-view/src/image-view.tsx create mode 100644 preact-image-view/src/main.tsx create mode 100644 preact-image-view/src/sample-doc-image.ts create mode 100644 preact-image-view/src/sample-uploader.ts create mode 100644 preact-image-view/tsconfig.json create mode 100644 preact-image-view/tsconfig.node.json create mode 100644 preact-image-view/vite.config.ts create mode 100644 preact-link-mark-view/.gitignore create mode 100644 preact-link-mark-view/README.md create mode 100644 preact-link-mark-view/index.html create mode 100644 preact-link-mark-view/package.json create mode 100644 preact-link-mark-view/src/app.css create mode 100644 preact-link-mark-view/src/editor.tsx create mode 100644 preact-link-mark-view/src/extension.ts create mode 100644 preact-link-mark-view/src/link-view.tsx create mode 100644 preact-link-mark-view/src/main.tsx create mode 100644 preact-link-mark-view/tsconfig.json create mode 100644 preact-link-mark-view/tsconfig.node.json create mode 100644 preact-link-mark-view/vite.config.ts rename react-code-block-themes/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename react-code-block/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename solid-code-block/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename solid-drop-cursor/src/{default-doc.ts => sample-doc-drop-cursor.ts} (67%) rename svelte-code-block-themes/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename svelte-code-block/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename svelte-drop-cursor/src/{default-doc.ts => sample-doc-drop-cursor.ts} (67%) rename vue-code-block-themes/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename vue-code-block/src/{default-doc.ts => sample-doc-code-block.ts} (100%) rename vue-drop-cursor/src/{default-doc.ts => sample-doc-drop-cursor.ts} (67%) diff --git a/lit-dom/src/editor.ts b/lit-dom/src/editor.ts index a9816c8ce..217be28b4 100644 --- a/lit-dom/src/editor.ts +++ b/lit-dom/src/editor.ts @@ -68,7 +68,7 @@ const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/120x80', + src: 'https://static.photos/minimal/320x240/42', }, }, { diff --git a/next-full/src/default-content-full.ts b/next-full/src/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/next-full/src/default-content-full.ts +++ b/next-full/src/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/nuxt-full/src/default-content-full.ts b/nuxt-full/src/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/nuxt-full/src/default-content-full.ts +++ b/nuxt-full/src/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/preact-image-view/.gitignore b/preact-image-view/.gitignore new file mode 100644 index 000000000..5d6225c6d --- /dev/null +++ b/preact-image-view/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.next +.svelte-kit diff --git a/preact-image-view/README.md b/preact-image-view/README.md new file mode 100644 index 000000000..11e4af847 --- /dev/null +++ b/preact-image-view/README.md @@ -0,0 +1,15 @@ +# preact-image-view + +A [ProseKit](https://prosekit.dev) example. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/prosekit/examples/tree/master/preact-image-view) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/prosekit/examples/tree/master/preact-image-view) + +Run the example locally with: + +```bash +npx degit prosekit/examples/preact-image-view preact-image-view +cd preact-image-view +npm install +npm run dev +``` diff --git a/preact-image-view/index.html b/preact-image-view/index.html new file mode 100644 index 000000000..b4f79f223 --- /dev/null +++ b/preact-image-view/index.html @@ -0,0 +1,12 @@ + + + + + + ProseKit + Preact + + +
+ + + diff --git a/preact-image-view/package.json b/preact-image-view/package.json new file mode 100644 index 000000000..0e7d3e51d --- /dev/null +++ b/preact-image-view/package.json @@ -0,0 +1,26 @@ +{ + "name": "example-preact-image-view", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "preview": "vite preview" + }, + "dependencies": { + "preact": "^10.27.2", + "prosekit": "^0.15.6" + }, + "devDependencies": { + "@egoist/tailwindcss-icons": "^1.9.0", + "@iconify-json/lucide": "^1.2.68", + "@preact/preset-vite": "^2.10.2", + "@tailwindcss/vite": "^4.1.14", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.14", + "tw-animate-css": "^1.4.0", + "typescript": "5.9.3", + "vite": "7.1.9" + } +} diff --git a/preact-image-view/src/app.css b/preact-image-view/src/app.css new file mode 100644 index 000000000..b1ff4f9bc --- /dev/null +++ b/preact-image-view/src/app.css @@ -0,0 +1,13 @@ +@import 'tailwindcss'; + +@plugin "@egoist/tailwindcss-icons"; +@import 'tw-animate-css'; + +body { + height: 100svh; + display: grid; + max-width: 900px; + padding: 16px; + margin-left: auto; + margin-right: auto; +} diff --git a/preact-image-view/src/editor.tsx b/preact-image-view/src/editor.tsx new file mode 100644 index 000000000..97db4ab47 --- /dev/null +++ b/preact-image-view/src/editor.tsx @@ -0,0 +1,29 @@ +import 'prosekit/basic/style.css' +import 'prosekit/basic/typography.css' + +import { useMemo } from 'preact/hooks' +import { createEditor } from 'prosekit/core' +import { ProseKit } from 'prosekit/preact' + +import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-image' + +export default function Editor() { + const editor = useMemo(() => { + const extension = defineExtension() + return createEditor({ extension, defaultContent }) + }, []) + + return ( + +
+
+
+
+
+
+ ) +} diff --git a/preact-image-view/src/extension.ts b/preact-image-view/src/extension.ts new file mode 100644 index 000000000..a2e63dc22 --- /dev/null +++ b/preact-image-view/src/extension.ts @@ -0,0 +1,25 @@ +import { defineBasicExtension } from 'prosekit/basic' +import { union } from 'prosekit/core' +import { defineImageUploadHandler } from 'prosekit/extensions/image' +import { + definePreactNodeView, + type PreactNodeViewComponent, +} from 'prosekit/preact' + +import ImageView from './image-view' +import { sampleUploader } from './sample-uploader' + +export function defineExtension() { + return union( + defineBasicExtension(), + definePreactNodeView({ + name: 'image', + component: ImageView satisfies PreactNodeViewComponent, + }), + defineImageUploadHandler({ + uploader: sampleUploader, + }), + ) +} + +export type EditorExtension = ReturnType diff --git a/preact-image-view/src/image-view.tsx b/preact-image-view/src/image-view.tsx new file mode 100644 index 000000000..c6a2a1782 --- /dev/null +++ b/preact-image-view/src/image-view.tsx @@ -0,0 +1,93 @@ +import type { JSX } from 'preact' +import { useEffect, useState } from 'preact/hooks' +import { UploadTask } from 'prosekit/extensions/file' +import type { ImageAttrs } from 'prosekit/extensions/image' +import type { PreactNodeViewProps } from 'prosekit/preact' +import { ResizableHandle, ResizableRoot } from 'prosekit/preact/resizable' + +export default function ImageView(props: PreactNodeViewProps) { + const { setAttrs, node } = props + const attrs = node.attrs as ImageAttrs + const url = attrs.src || '' + const uploading = url.startsWith('blob:') + + const [aspectRatio, setAspectRatio] = useState() + const [error, setError] = useState() + const [progress, setProgress] = useState(0) + + useEffect(() => { + if (!uploading) return + + const uploadTask = UploadTask.get(url) + if (!uploadTask) return + + let canceled = false + + uploadTask.finished.catch((error) => { + if (canceled) return + setError(String(error)) + }) + const unsubscribeProgress = uploadTask.subscribeProgress( + ({ loaded, total }) => { + if (canceled) return + setProgress(total ? loaded / total : 0) + }, + ) + + return () => { + canceled = true + unsubscribeProgress() + } + }, [url, uploading, setAttrs]) + + const handleImageLoad = (event: JSX.TargetedEvent) => { + const img = event.target as HTMLImageElement + const { naturalWidth, naturalHeight } = img + const ratio = naturalWidth / naturalHeight + if (ratio && Number.isFinite(ratio)) { + setAspectRatio(ratio) + } + if (naturalWidth && naturalHeight && (!attrs.width || !attrs.height)) { + setAttrs({ width: naturalWidth, height: naturalHeight }) + } + } + + return ( + setAttrs(event.detail)} + data-selected={props.selected ? '' : undefined} + className="relative flex items-center justify-center box-border overflow-hidden my-2 group max-h-[600px] max-w-full min-h-[64px] min-w-[64px] outline-2 outline-transparent data-selected:outline-blue-500 outline-solid" + > + {url && !error && ( + + )} + {uploading && !error && ( +
+
+
{Math.round(progress * 100)}%
+
+ )} + {error && ( +
+
+
+ Failed to upload image +
+
+ )} + +
+
+
+ ) +} diff --git a/preact-image-view/src/main.tsx b/preact-image-view/src/main.tsx new file mode 100644 index 000000000..78ffbf844 --- /dev/null +++ b/preact-image-view/src/main.tsx @@ -0,0 +1,5 @@ +import './app.css' +import { render } from 'preact' +import Editor from './editor.tsx' + +render(, document.getElementById('app')!) diff --git a/preact-image-view/src/sample-doc-image.ts b/preact-image-view/src/sample-doc-image.ts new file mode 100644 index 000000000..b62b561a2 --- /dev/null +++ b/preact-image-view/src/sample-doc-image.ts @@ -0,0 +1,32 @@ +import type { NodeJSON } from 'prosekit/core' + +export const defaultContent: NodeJSON = { + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Paste or drop an image to upload it.', + }, + ], + }, + { + type: 'image', + attrs: { + src: 'https://static.photos/white/200x200/1', + width: 160, + height: 160, + }, + }, + { + type: 'image', + attrs: { + src: 'https://static.photos/yellow/640x360/42', + width: 240, + height: 135, + }, + }, + ], +} diff --git a/preact-image-view/src/sample-uploader.ts b/preact-image-view/src/sample-uploader.ts new file mode 100644 index 000000000..8e86d9210 --- /dev/null +++ b/preact-image-view/src/sample-uploader.ts @@ -0,0 +1,54 @@ +import type { Uploader } from 'prosekit/extensions/file' + +/** + * Uploads the given file to https://tmpfiles.org/ and returns the URL of the + * uploaded file. + * + * This function is only for demonstration purposes. All uploaded files will be + * deleted by the server after 1 hour. + */ +export const sampleUploader: Uploader = ({ + file, + onProgress, +}): Promise => { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest() + const formData = new FormData() + formData.append('file', file) + + xhr.upload.addEventListener('progress', (event) => { + if (event.lengthComputable) { + onProgress({ + loaded: event.loaded, + total: event.total, + }) + } + }) + + xhr.addEventListener('load', () => { + if (xhr.status === 200) { + try { + const json = JSON.parse(xhr.responseText) as { data: { url: string } } + const url: string = json.data.url.replace( + 'tmpfiles.org/', + 'tmpfiles.org/dl/', + ) + + // Simulate a larger delay + setTimeout(() => resolve(url), 1000) + } catch (error) { + reject(new Error('Failed to parse response', { cause: error })) + } + } else { + reject(new Error(`Upload failed with status ${xhr.status}`)) + } + }) + + xhr.addEventListener('error', () => { + reject(new Error('Upload failed')) + }) + + xhr.open('POST', 'https://tmpfiles.org/api/v1/upload', true) + xhr.send(formData) + }) +} diff --git a/preact-image-view/tsconfig.json b/preact-image-view/tsconfig.json new file mode 100644 index 000000000..a0883e202 --- /dev/null +++ b/preact-image-view/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "jsxImportSource": "preact", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/preact-image-view/tsconfig.node.json b/preact-image-view/tsconfig.node.json new file mode 100644 index 000000000..42872c59f --- /dev/null +++ b/preact-image-view/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/preact-image-view/vite.config.ts b/preact-image-view/vite.config.ts new file mode 100644 index 000000000..5e0b3c9e1 --- /dev/null +++ b/preact-image-view/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite' +import preact from '@preact/preset-vite' +import tailwindcss from '@tailwindcss/vite' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [preact(), tailwindcss()], +}) diff --git a/preact-link-mark-view/.gitignore b/preact-link-mark-view/.gitignore new file mode 100644 index 000000000..5d6225c6d --- /dev/null +++ b/preact-link-mark-view/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.next +.svelte-kit diff --git a/preact-link-mark-view/README.md b/preact-link-mark-view/README.md new file mode 100644 index 000000000..34a7cee8f --- /dev/null +++ b/preact-link-mark-view/README.md @@ -0,0 +1,15 @@ +# preact-link-mark-view + +A [ProseKit](https://prosekit.dev) example. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/prosekit/examples/tree/master/preact-link-mark-view) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/prosekit/examples/tree/master/preact-link-mark-view) + +Run the example locally with: + +```bash +npx degit prosekit/examples/preact-link-mark-view preact-link-mark-view +cd preact-link-mark-view +npm install +npm run dev +``` diff --git a/preact-link-mark-view/index.html b/preact-link-mark-view/index.html new file mode 100644 index 000000000..b4f79f223 --- /dev/null +++ b/preact-link-mark-view/index.html @@ -0,0 +1,12 @@ + + + + + + ProseKit + Preact + + +
+ + + diff --git a/preact-link-mark-view/package.json b/preact-link-mark-view/package.json new file mode 100644 index 000000000..ef3214b07 --- /dev/null +++ b/preact-link-mark-view/package.json @@ -0,0 +1,26 @@ +{ + "name": "example-preact-link-mark-view", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "preview": "vite preview" + }, + "dependencies": { + "preact": "^10.27.2", + "prosekit": "^0.15.6" + }, + "devDependencies": { + "@egoist/tailwindcss-icons": "^1.9.0", + "@iconify-json/lucide": "^1.2.68", + "@preact/preset-vite": "^2.10.2", + "@tailwindcss/vite": "^4.1.14", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.14", + "tw-animate-css": "^1.4.0", + "typescript": "5.9.3", + "vite": "7.1.9" + } +} diff --git a/preact-link-mark-view/src/app.css b/preact-link-mark-view/src/app.css new file mode 100644 index 000000000..b1ff4f9bc --- /dev/null +++ b/preact-link-mark-view/src/app.css @@ -0,0 +1,13 @@ +@import 'tailwindcss'; + +@plugin "@egoist/tailwindcss-icons"; +@import 'tw-animate-css'; + +body { + height: 100svh; + display: grid; + max-width: 900px; + padding: 16px; + margin-left: auto; + margin-right: auto; +} diff --git a/preact-link-mark-view/src/editor.tsx b/preact-link-mark-view/src/editor.tsx new file mode 100644 index 000000000..1862b5930 --- /dev/null +++ b/preact-link-mark-view/src/editor.tsx @@ -0,0 +1,31 @@ +import 'prosekit/basic/style.css' +import 'prosekit/basic/typography.css' + +import { useMemo } from 'preact/hooks' +import { createEditor } from 'prosekit/core' +import { ProseKit } from 'prosekit/preact' + +import { defineExtension } from './extension' + +export default function Editor() { + const editor = useMemo(() => { + return createEditor({ extension: defineExtension(), defaultContent }) + }, []) + + return ( + +
+
+
+
+
+
+ ) +} + +const defaultContent = ` +

Here is a link that changes color every second: example link +` diff --git a/preact-link-mark-view/src/extension.ts b/preact-link-mark-view/src/extension.ts new file mode 100644 index 000000000..c9c2d7f7c --- /dev/null +++ b/preact-link-mark-view/src/extension.ts @@ -0,0 +1,17 @@ +import { defineBasicExtension } from 'prosekit/basic' +import { union } from 'prosekit/core' +import { definePreactMarkView } from 'prosekit/preact' + +import LinkView from './link-view' + +export function defineExtension() { + return union( + defineBasicExtension(), + definePreactMarkView({ + name: 'link', + component: LinkView, + }), + ) +} + +export type EditorExtension = ReturnType diff --git a/preact-link-mark-view/src/link-view.tsx b/preact-link-mark-view/src/link-view.tsx new file mode 100644 index 000000000..8306ed2ad --- /dev/null +++ b/preact-link-mark-view/src/link-view.tsx @@ -0,0 +1,46 @@ +import { useEffect, useState } from 'preact/hooks' +import type { PreactMarkViewProps } from 'prosekit/preact' + +const colors = [ + '#f06292', + '#ba68c8', + '#9575cd', + '#7986cb', + '#64b5f6', + '#4fc3f7', + '#4dd0e1', + '#4db6ac', + '#81c784', + '#aed581', + '#ffb74d', + '#ffa726', + '#ff8a65', + '#d4e157', + '#ffd54f', + '#ffecb3', +] + +function pickRandomColor() { + return colors[Math.floor(Math.random() * colors.length)] +} + +export default function Link(props: PreactMarkViewProps) { + const [color, setColor] = useState(colors[0]) + const { mark, contentRef } = props + const href = mark.attrs.href as string + + useEffect(() => { + const interval = setInterval(() => { + setColor(pickRandomColor()) + }, 1000) + return () => clearInterval(interval) + }, []) + + return ( + + ) +} diff --git a/preact-link-mark-view/src/main.tsx b/preact-link-mark-view/src/main.tsx new file mode 100644 index 000000000..78ffbf844 --- /dev/null +++ b/preact-link-mark-view/src/main.tsx @@ -0,0 +1,5 @@ +import './app.css' +import { render } from 'preact' +import Editor from './editor.tsx' + +render(, document.getElementById('app')!) diff --git a/preact-link-mark-view/tsconfig.json b/preact-link-mark-view/tsconfig.json new file mode 100644 index 000000000..a0883e202 --- /dev/null +++ b/preact-link-mark-view/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "jsxImportSource": "preact", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/preact-link-mark-view/tsconfig.node.json b/preact-link-mark-view/tsconfig.node.json new file mode 100644 index 000000000..42872c59f --- /dev/null +++ b/preact-link-mark-view/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/preact-link-mark-view/vite.config.ts b/preact-link-mark-view/vite.config.ts new file mode 100644 index 000000000..5e0b3c9e1 --- /dev/null +++ b/preact-link-mark-view/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite' +import preact from '@preact/preset-vite' +import tailwindcss from '@tailwindcss/vite' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [preact(), tailwindcss()], +}) diff --git a/preact-typography/src/typography-content.ts b/preact-typography/src/typography-content.ts index 302de32f6..9dc2ac317 100644 --- a/preact-typography/src/typography-content.ts +++ b/preact-typography/src/typography-content.ts @@ -51,7 +51,7 @@ export const typographyContent = `

Images

-Sample image +Sample image

Tables

diff --git a/react-code-block-themes/src/editor.tsx b/react-code-block-themes/src/editor.tsx index b54b6b57a..dc936416c 100644 --- a/react-code-block-themes/src/editor.tsx +++ b/react-code-block-themes/src/editor.tsx @@ -5,8 +5,8 @@ import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/react' import { useMemo } from 'react' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar' export default function Editor() { diff --git a/react-code-block-themes/src/default-doc.ts b/react-code-block-themes/src/sample-doc-code-block.ts similarity index 100% rename from react-code-block-themes/src/default-doc.ts rename to react-code-block-themes/src/sample-doc-code-block.ts diff --git a/react-code-block/src/editor.tsx b/react-code-block/src/editor.tsx index b54b6b57a..dc936416c 100644 --- a/react-code-block/src/editor.tsx +++ b/react-code-block/src/editor.tsx @@ -5,8 +5,8 @@ import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/react' import { useMemo } from 'react' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar' export default function Editor() { diff --git a/react-code-block/src/default-doc.ts b/react-code-block/src/sample-doc-code-block.ts similarity index 100% rename from react-code-block/src/default-doc.ts rename to react-code-block/src/sample-doc-code-block.ts diff --git a/react-full/src/default-content-full.ts b/react-full/src/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/react-full/src/default-content-full.ts +++ b/react-full/src/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/react-gap-cursor/src/editor.tsx b/react-gap-cursor/src/editor.tsx index 3b7d9cda7..b8bcc23ba 100644 --- a/react-gap-cursor/src/editor.tsx +++ b/react-gap-cursor/src/editor.tsx @@ -28,6 +28,6 @@ export default function Editor() { const defaultContent = `

Click the gap between two images or press arrow keys to see the gap cursor between two images

- - + + ` diff --git a/react-image-view/src/sample-doc-image.ts b/react-image-view/src/sample-doc-image.ts index 8e08ed894..b62b561a2 100644 --- a/react-image-view/src/sample-doc-image.ts +++ b/react-image-view/src/sample-doc-image.ts @@ -15,17 +15,17 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/150x150/8bd450/ffffff/png', - width: 150, - height: 150, + src: 'https://static.photos/white/200x200/1', + width: 160, + height: 160, }, }, { type: 'image', attrs: { - src: 'https://placehold.co/150x75/965fd4/ffffff/png', - width: 150, - height: 75, + src: 'https://static.photos/yellow/640x360/42', + width: 240, + height: 135, }, }, ], diff --git a/react-typography/src/typography-content.ts b/react-typography/src/typography-content.ts index 302de32f6..9dc2ac317 100644 --- a/react-typography/src/typography-content.ts +++ b/react-typography/src/typography-content.ts @@ -51,7 +51,7 @@ export const typographyContent = `

Images

-Sample image +Sample image

Tables

diff --git a/solid-code-block/src/editor.tsx b/solid-code-block/src/editor.tsx index 713cb9e78..e2190f2ba 100644 --- a/solid-code-block/src/editor.tsx +++ b/solid-code-block/src/editor.tsx @@ -4,8 +4,8 @@ import 'prosekit/basic/typography.css' import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/solid' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar' export default function Editor() { diff --git a/solid-code-block/src/default-doc.ts b/solid-code-block/src/sample-doc-code-block.ts similarity index 100% rename from solid-code-block/src/default-doc.ts rename to solid-code-block/src/sample-doc-code-block.ts diff --git a/solid-drop-cursor/src/editor.tsx b/solid-drop-cursor/src/editor.tsx index 9004d86b0..213dd46c2 100644 --- a/solid-drop-cursor/src/editor.tsx +++ b/solid-drop-cursor/src/editor.tsx @@ -4,8 +4,8 @@ import 'prosekit/basic/typography.css' import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/solid' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-drop-cursor' export default function Editor() { const editor = createEditor({ extension: defineExtension(), defaultContent }) diff --git a/solid-drop-cursor/src/default-doc.ts b/solid-drop-cursor/src/sample-doc-drop-cursor.ts similarity index 67% rename from solid-drop-cursor/src/default-doc.ts rename to solid-drop-cursor/src/sample-doc-drop-cursor.ts index 54e960d30..756fd4618 100644 --- a/solid-drop-cursor/src/default-doc.ts +++ b/solid-drop-cursor/src/sample-doc-drop-cursor.ts @@ -15,25 +15,25 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f59e0b/FFF?text=Amber', + src: 'https://static.photos/yellow/320x240/42', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/84cc16/FFF?text=Lime', + src: 'https://static.photos/green/320x240/40', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/06b6d4/FFF?text=Cyan', + src: 'https://static.photos/blue/320x240/187', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f43f5e/FFF?text=Rose', + src: 'https://static.photos/red/320x240/188', }, }, ], diff --git a/solid-image-view/src/sample-doc-image.ts b/solid-image-view/src/sample-doc-image.ts index 8e08ed894..b62b561a2 100644 --- a/solid-image-view/src/sample-doc-image.ts +++ b/solid-image-view/src/sample-doc-image.ts @@ -15,17 +15,17 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/150x150/8bd450/ffffff/png', - width: 150, - height: 150, + src: 'https://static.photos/white/200x200/1', + width: 160, + height: 160, }, }, { type: 'image', attrs: { - src: 'https://placehold.co/150x75/965fd4/ffffff/png', - width: 150, - height: 75, + src: 'https://static.photos/yellow/640x360/42', + width: 240, + height: 135, }, }, ], diff --git a/solid-typography/src/typography-content.ts b/solid-typography/src/typography-content.ts index 302de32f6..9dc2ac317 100644 --- a/solid-typography/src/typography-content.ts +++ b/solid-typography/src/typography-content.ts @@ -51,7 +51,7 @@ export const typographyContent = `

Images

-Sample image +Sample image

Tables

diff --git a/svelte-code-block-themes/src/editor.svelte b/svelte-code-block-themes/src/editor.svelte index 84b639eb1..faa8879f8 100644 --- a/svelte-code-block-themes/src/editor.svelte +++ b/svelte-code-block-themes/src/editor.svelte @@ -5,8 +5,8 @@ import 'prosekit/basic/typography.css' import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/svelte' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar.svelte' const extension = defineExtension() diff --git a/svelte-code-block-themes/src/default-doc.ts b/svelte-code-block-themes/src/sample-doc-code-block.ts similarity index 100% rename from svelte-code-block-themes/src/default-doc.ts rename to svelte-code-block-themes/src/sample-doc-code-block.ts diff --git a/svelte-code-block/src/editor.svelte b/svelte-code-block/src/editor.svelte index 4130b3e39..82f8e38ef 100644 --- a/svelte-code-block/src/editor.svelte +++ b/svelte-code-block/src/editor.svelte @@ -4,8 +4,8 @@ import 'prosekit/basic/typography.css' import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/svelte' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar.svelte' const extension = defineExtension() diff --git a/svelte-code-block/src/default-doc.ts b/svelte-code-block/src/sample-doc-code-block.ts similarity index 100% rename from svelte-code-block/src/default-doc.ts rename to svelte-code-block/src/sample-doc-code-block.ts diff --git a/svelte-drop-cursor/src/editor.svelte b/svelte-drop-cursor/src/editor.svelte index 7ff019454..225e29b8f 100644 --- a/svelte-drop-cursor/src/editor.svelte +++ b/svelte-drop-cursor/src/editor.svelte @@ -4,8 +4,8 @@ import 'prosekit/basic/typography.css' import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/svelte' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-drop-cursor' const editor = createEditor({ extension: defineExtension(), defaultContent }) diff --git a/svelte-drop-cursor/src/default-doc.ts b/svelte-drop-cursor/src/sample-doc-drop-cursor.ts similarity index 67% rename from svelte-drop-cursor/src/default-doc.ts rename to svelte-drop-cursor/src/sample-doc-drop-cursor.ts index 54e960d30..756fd4618 100644 --- a/svelte-drop-cursor/src/default-doc.ts +++ b/svelte-drop-cursor/src/sample-doc-drop-cursor.ts @@ -15,25 +15,25 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f59e0b/FFF?text=Amber', + src: 'https://static.photos/yellow/320x240/42', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/84cc16/FFF?text=Lime', + src: 'https://static.photos/green/320x240/40', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/06b6d4/FFF?text=Cyan', + src: 'https://static.photos/blue/320x240/187', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f43f5e/FFF?text=Rose', + src: 'https://static.photos/red/320x240/188', }, }, ], diff --git a/svelte-full/src/default-content-full.ts b/svelte-full/src/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/svelte-full/src/default-content-full.ts +++ b/svelte-full/src/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/svelte-image-view/src/sample-doc-image.ts b/svelte-image-view/src/sample-doc-image.ts index 8e08ed894..b62b561a2 100644 --- a/svelte-image-view/src/sample-doc-image.ts +++ b/svelte-image-view/src/sample-doc-image.ts @@ -15,17 +15,17 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/150x150/8bd450/ffffff/png', - width: 150, - height: 150, + src: 'https://static.photos/white/200x200/1', + width: 160, + height: 160, }, }, { type: 'image', attrs: { - src: 'https://placehold.co/150x75/965fd4/ffffff/png', - width: 150, - height: 75, + src: 'https://static.photos/yellow/640x360/42', + width: 240, + height: 135, }, }, ], diff --git a/svelte-typography/src/typography-content.ts b/svelte-typography/src/typography-content.ts index 302de32f6..9dc2ac317 100644 --- a/svelte-typography/src/typography-content.ts +++ b/svelte-typography/src/typography-content.ts @@ -51,7 +51,7 @@ export const typographyContent = `

Images

-Sample image +Sample image

Tables

diff --git a/sveltekit-full/src/lib/default-content-full.ts b/sveltekit-full/src/lib/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/sveltekit-full/src/lib/default-content-full.ts +++ b/sveltekit-full/src/lib/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/vue-code-block-themes/src/editor.vue b/vue-code-block-themes/src/editor.vue index 8c9eab506..90c4d453c 100644 --- a/vue-code-block-themes/src/editor.vue +++ b/vue-code-block-themes/src/editor.vue @@ -6,8 +6,8 @@ import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/vue' import { ref, watchPostEffect } from 'vue' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar.vue' const editor = createEditor({ extension: defineExtension(), defaultContent }) diff --git a/vue-code-block-themes/src/default-doc.ts b/vue-code-block-themes/src/sample-doc-code-block.ts similarity index 100% rename from vue-code-block-themes/src/default-doc.ts rename to vue-code-block-themes/src/sample-doc-code-block.ts diff --git a/vue-code-block/src/editor.vue b/vue-code-block/src/editor.vue index 8c9eab506..90c4d453c 100644 --- a/vue-code-block/src/editor.vue +++ b/vue-code-block/src/editor.vue @@ -6,8 +6,8 @@ import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/vue' import { ref, watchPostEffect } from 'vue' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-code-block' import Toolbar from './toolbar.vue' const editor = createEditor({ extension: defineExtension(), defaultContent }) diff --git a/vue-code-block/src/default-doc.ts b/vue-code-block/src/sample-doc-code-block.ts similarity index 100% rename from vue-code-block/src/default-doc.ts rename to vue-code-block/src/sample-doc-code-block.ts diff --git a/vue-drop-cursor/src/editor.vue b/vue-drop-cursor/src/editor.vue index de331c42e..355f06be0 100644 --- a/vue-drop-cursor/src/editor.vue +++ b/vue-drop-cursor/src/editor.vue @@ -6,8 +6,8 @@ import { createEditor } from 'prosekit/core' import { ProseKit } from 'prosekit/vue' import { ref, watchPostEffect } from 'vue' -import { defaultContent } from './default-doc' import { defineExtension } from './extension' +import { defaultContent } from './sample-doc-drop-cursor' const editor = createEditor({ extension: defineExtension(), defaultContent }) const editorRef = ref(null) diff --git a/vue-drop-cursor/src/default-doc.ts b/vue-drop-cursor/src/sample-doc-drop-cursor.ts similarity index 67% rename from vue-drop-cursor/src/default-doc.ts rename to vue-drop-cursor/src/sample-doc-drop-cursor.ts index 54e960d30..756fd4618 100644 --- a/vue-drop-cursor/src/default-doc.ts +++ b/vue-drop-cursor/src/sample-doc-drop-cursor.ts @@ -15,25 +15,25 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f59e0b/FFF?text=Amber', + src: 'https://static.photos/yellow/320x240/42', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/84cc16/FFF?text=Lime', + src: 'https://static.photos/green/320x240/40', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/06b6d4/FFF?text=Cyan', + src: 'https://static.photos/blue/320x240/187', }, }, { type: 'image', attrs: { - src: 'https://placehold.co/120x60/f43f5e/FFF?text=Rose', + src: 'https://static.photos/red/320x240/188', }, }, ], diff --git a/vue-full/src/default-content-full.ts b/vue-full/src/default-content-full.ts index 09e09f003..3656d3d13 100644 --- a/vue-full/src/default-content-full.ts +++ b/vue-full/src/default-content-full.ts @@ -43,7 +43,7 @@ magic.transform(thoughts)

Images that captivate.

-The future of writing +The future of writing

Drag the handle in the bottom right corner to resize.

diff --git a/vue-image-view/src/sample-doc-image.ts b/vue-image-view/src/sample-doc-image.ts index 8e08ed894..b62b561a2 100644 --- a/vue-image-view/src/sample-doc-image.ts +++ b/vue-image-view/src/sample-doc-image.ts @@ -15,17 +15,17 @@ export const defaultContent: NodeJSON = { { type: 'image', attrs: { - src: 'https://placehold.co/150x150/8bd450/ffffff/png', - width: 150, - height: 150, + src: 'https://static.photos/white/200x200/1', + width: 160, + height: 160, }, }, { type: 'image', attrs: { - src: 'https://placehold.co/150x75/965fd4/ffffff/png', - width: 150, - height: 75, + src: 'https://static.photos/yellow/640x360/42', + width: 240, + height: 135, }, }, ], diff --git a/vue-typography/src/typography-content.ts b/vue-typography/src/typography-content.ts index 302de32f6..9dc2ac317 100644 --- a/vue-typography/src/typography-content.ts +++ b/vue-typography/src/typography-content.ts @@ -51,7 +51,7 @@ export const typographyContent = `

Images

-Sample image +Sample image

Tables