From b89aa6bed02fe4ac9b8a19b727aa00473d5b4c4b Mon Sep 17 00:00:00 2001 From: Claude Sonnet 5 Date: Sun, 5 Jul 2026 21:59:12 +0200 Subject: [PATCH] Add editor document schema in packages/shared (#24) ProseMirror schema (headings 1-4, lists incl. task lists, blockquote, code block, tables via prosemirror-tables, images, hard breaks; bold/ italic/code/strikethrough/link marks) plus docToMarkdown, markdownToDoc, docToPlainText, docToHtml, and extractOutline built on it. Markdown parsing extends markdown-it's default preset with a token-stream transform for GFM task lists and table-cell paragraph wrapping. docToHtml hand-rolls escaping and link-protocol allowlisting with zero DOM dependencies, so it runs in the API/collab server as well as the browser. Node names `wikilink` and `plugin_block` are reserved for later stories. Closes #24 --- packages/shared/package.json | 6 + .../shared/src/editor-schema/html.test.ts | 48 +++ packages/shared/src/editor-schema/html.ts | 130 ++++++++ packages/shared/src/editor-schema/index.ts | 5 + .../shared/src/editor-schema/markdown.test.ts | 62 ++++ packages/shared/src/editor-schema/markdown.ts | 315 ++++++++++++++++++ .../shared/src/editor-schema/outline.test.ts | 23 ++ packages/shared/src/editor-schema/outline.ts | 31 ++ .../src/editor-schema/plain-text.test.ts | 16 + .../shared/src/editor-schema/plain-text.ts | 9 + .../shared/src/editor-schema/schema.test.ts | 21 ++ packages/shared/src/editor-schema/schema.ts | 168 ++++++++++ packages/shared/src/index.ts | 1 + pnpm-lock.yaml | 148 ++++++++ 14 files changed, 983 insertions(+) create mode 100644 packages/shared/src/editor-schema/html.test.ts create mode 100644 packages/shared/src/editor-schema/html.ts create mode 100644 packages/shared/src/editor-schema/index.ts create mode 100644 packages/shared/src/editor-schema/markdown.test.ts create mode 100644 packages/shared/src/editor-schema/markdown.ts create mode 100644 packages/shared/src/editor-schema/outline.test.ts create mode 100644 packages/shared/src/editor-schema/outline.ts create mode 100644 packages/shared/src/editor-schema/plain-text.test.ts create mode 100644 packages/shared/src/editor-schema/plain-text.ts create mode 100644 packages/shared/src/editor-schema/schema.test.ts create mode 100644 packages/shared/src/editor-schema/schema.ts diff --git a/packages/shared/package.json b/packages/shared/package.json index 60e7141..bd3b662 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -25,9 +25,15 @@ "test": "vitest run --passWithNoTests" }, "dependencies": { + "markdown-it": "^14.3.0", + "prosemirror-markdown": "^1.13.4", + "prosemirror-model": "^1.25.9", + "prosemirror-tables": "^1.8.5", "zod": "^3.24.0" }, "devDependencies": { + "@types/markdown-it": "^14.1.2", + "@types/node": "^26.1.0", "tsup": "^8.3.0", "vitest": "^3.0.0" } diff --git a/packages/shared/src/editor-schema/html.test.ts b/packages/shared/src/editor-schema/html.test.ts new file mode 100644 index 0000000..62e57d6 --- /dev/null +++ b/packages/shared/src/editor-schema/html.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from 'vitest'; + +import { docToHtml } from './html'; +import { markdownToDoc } from './markdown'; +import { editorSchema } from './schema'; + +describe('docToHtml (issue #24)', () => { + it('escapes text content, including angle brackets and quotes', () => { + const doc = markdownToDoc('Contains literally.'); + const html = docToHtml(doc); + expect(html).not.toContain('