@x12i/editor 0.0.0-stage → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +361 -3
- package/dist/chunk-FYXMOAJT.js +1890 -0
- package/dist/chunk-FYXMOAJT.js.map +1 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.js +1326 -0
- package/dist/index.js.map +1 -0
- package/dist/outline-Drc3E0C1.d.ts +339 -0
- package/dist/react.d.ts +546 -0
- package/dist/react.js +4439 -0
- package/dist/react.js.map +1 -0
- package/dist/styles.css +1219 -0
- package/package.json +88 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/markdown-import.ts","../src/diff.ts","../src/validate.ts"],"sourcesContent":["/**\n * Markdown import: a CommonMark subset plus GitHub tables, task lists and\n * alerts, and the kit's own forms (see `documentToMarkdown`).\n *\n * Supported: ATX and setext headings (level 5 and 6 clamp to 4), paragraphs\n * with hard breaks, emphasis, strong, strike, code spans, links, autolinks,\n * images (a lone image becomes an image block), block quotes, `> [!INFO]`\n * callouts, bulleted, numbered and task lists with nesting, fenced code,\n * `$$` equations, thematic breaks, GFM tables, `<details>` toggles, page\n * breaks, `[TOC]`, `<video>` and `<audio>`, and the `kit-*` JSON fences.\n *\n * Not supported: indented code blocks, reference links and footnotes, raw\n * HTML other than what is listed (it stays as visible text, never as markup).\n * Output is always the schema, so imported text cannot carry scripts.\n */\nimport { generateBlockId } from \"./ids\";\nimport { normalizeInline } from \"./convert\";\nimport { emojiForShortcode } from \"./emoji\";\nimport {\n DOCUMENT_VERSION,\n type Block,\n type CalloutVariant,\n type EditorDocument,\n type Inline,\n type InlineNode,\n type ListItem,\n type Mark,\n type TableCell,\n type TaskItem,\n} from \"./schema\";\nimport { isHighlightToken, isTextColorToken } from \"./tokens\";\n\nexport interface MarkdownImportOptions {\n /** Creates block ids. Defaults to `generateBlockId`. */\n generateId?: () => string;\n /** Document title to set. */\n title?: string;\n}\n\ninterface Ctx {\n generateId: () => string;\n}\n\n// ---------------------------------------------------------------------------\n// Inline\n// ---------------------------------------------------------------------------\n\nconst ENTITIES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n \""\": '\"',\n \"'\": \"'\",\n \"'\": \"'\",\n \" \": \"\\u00a0\",\n};\n\nfunction decodeEntities(text: string): string {\n return text.replace(/&(?:amp|lt|gt|quot|apos|nbsp|#39);/g, (entity) => ENTITIES[entity] ?? entity);\n}\n\nconst PUNCTUATION = /[!-/:-@[-`{-~\\p{P}\\p{S}]/u;\nconst WHITESPACE = /\\s/;\n\ntype Token =\n | { k: \"text\"; text: string }\n | { k: \"nodes\"; nodes: InlineNode[] }\n | { k: \"delim\"; char: \"*\" | \"_\" | \"~\"; count: number; open: boolean; close: boolean }\n | { k: \"span\"; mark: Mark; children: Token[] }\n | { k: \"mark\"; mark: Mark; open: boolean };\n\n/** Finds the `]` that closes the `[` at `start`, skipping escapes and code spans. */\nfunction findClosingBracket(text: string, start: number): number {\n let depth = 0;\n for (let index = start; index < text.length; index += 1) {\n const char = text[index];\n if (char === \"\\\\\") {\n index += 1;\n } else if (char === \"`\") {\n const run = /^`+/.exec(text.slice(index))?.[0] ?? \"`\";\n const close = text.indexOf(run, index + run.length);\n if (close !== -1) index = close + run.length - 1;\n else index += run.length - 1;\n } else if (char === \"[\") {\n depth += 1;\n } else if (char === \"]\") {\n depth -= 1;\n if (depth === 0) return index;\n }\n }\n return -1;\n}\n\ninterface LinkTarget {\n href: string;\n title: string | undefined;\n end: number;\n}\n\n/** Parses `(destination \"title\")` starting at the `(` at `start`. */\nfunction parseLinkTarget(text: string, start: number): LinkTarget | null {\n if (text[start] !== \"(\") return null;\n let index = start + 1;\n while (index < text.length && /\\s/.test(text[index] ?? \"\")) index += 1;\n let href: string;\n if (text[index] === \"<\") {\n const close = text.indexOf(\">\", index);\n if (close === -1) return null;\n href = text.slice(index + 1, close);\n index = close + 1;\n } else {\n let depth = 0;\n const begin = index;\n while (index < text.length) {\n const char = text[index] as string;\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === \"(\") depth += 1;\n else if (char === \")\") {\n if (depth === 0) break;\n depth -= 1;\n } else if (/\\s/.test(char)) break;\n index += 1;\n }\n href = text.slice(begin, index).replace(/\\\\([!-/:-@[-`{-~])/g, \"$1\");\n }\n while (index < text.length && /\\s/.test(text[index] ?? \"\")) index += 1;\n let title: string | undefined;\n const quote = text[index];\n if (quote === '\"' || quote === \"'\") {\n let close = index + 1;\n while (close < text.length && text[close] !== quote) close += text[close] === \"\\\\\" ? 2 : 1;\n if (close >= text.length) return null;\n title = text.slice(index + 1, close).replace(/\\\\([\"'\\\\])/g, \"$1\");\n index = close + 1;\n while (index < text.length && /\\s/.test(text[index] ?? \"\")) index += 1;\n }\n if (text[index] !== \")\") return null;\n return { href: decodeEntities(href), title, end: index + 1 };\n}\n\nfunction withMark(nodes: InlineNode[], mark: Mark): InlineNode[] {\n return nodes.map((node) => (node.type === \"text\" ? { ...node, marks: [...(node.marks ?? []), mark] } : node));\n}\n\nconst TAG = /^<(\\/?)([a-zA-Z][a-zA-Z0-9]*)((?:\\s+[a-zA-Z-]+(?:=\"[^\"]*\")?)*)\\s*(\\/?)>/;\nconst AUTOLINK = /^<((?:https?:\\/\\/|mailto:)[^<>\\s]+)>/i;\nconst BARE_URL = /^https?:\\/\\/[^\\s<]+/i;\n\nfunction attributeOf(source: string, name: string): string | undefined {\n const match = new RegExp(`\\\\s${name}=\"([^\"]*)\"`).exec(source);\n return match ? decodeEntities(match[1] ?? \"\") : undefined;\n}\n\nfunction htmlMark(tag: string, attributes: string, closing: boolean): Mark | null {\n // A closing tag has no attributes; only its mark type is used to pair it with the opener.\n if (closing && tag === \"mark\") return { type: \"highlight\", token: \"\" };\n if (closing && tag === \"span\") return { type: \"color\", token: \"\" };\n switch (tag) {\n case \"u\":\n return { type: \"underline\" };\n case \"strong\":\n case \"b\":\n return { type: \"bold\" };\n case \"em\":\n case \"i\":\n return { type: \"italic\" };\n case \"s\":\n case \"del\":\n case \"strike\":\n return { type: \"strike\" };\n case \"mark\": {\n const token = attributeOf(attributes, \"data-token\");\n return token !== undefined && isHighlightToken(token) ? { type: \"highlight\", token } : null;\n }\n case \"span\": {\n const token = attributeOf(attributes, \"data-color-token\");\n return token !== undefined && isTextColorToken(token) ? { type: \"color\", token } : null;\n }\n default:\n return null;\n }\n}\n\nfunction tokenize(text: string): Token[] {\n const tokens: Token[] = [];\n let buffer = \"\";\n const flush = () => {\n if (buffer !== \"\") {\n tokens.push({ k: \"text\", text: buffer });\n buffer = \"\";\n }\n };\n\n let index = 0;\n while (index < text.length) {\n const char = text[index] as string;\n const rest = text.slice(index);\n\n // Escapes and hard breaks.\n if (char === \"\\\\\") {\n const next = text[index + 1];\n if (next === \"\\n\") {\n buffer += \"\\n\";\n index += 2;\n continue;\n }\n if (next !== undefined && /[!-/:-@[-`{-~]/.test(next)) {\n buffer += next;\n index += 2;\n continue;\n }\n buffer += char;\n index += 1;\n continue;\n }\n if (char === \"\\n\") {\n // A soft break is a space; two trailing spaces made it a hard break.\n if (/ {2,}$/.test(buffer)) buffer = `${buffer.replace(/ +$/, \"\")}\\n`;\n else buffer = `${buffer.replace(/ +$/, \"\")} `;\n index += 1;\n while (text[index] === \" \") index += 1;\n continue;\n }\n\n // Code spans.\n if (char === \"`\") {\n const run = /^`+/.exec(rest)?.[0] ?? \"`\";\n let close = -1;\n let search = index + run.length;\n while (search < text.length) {\n const found = text.indexOf(run, search);\n if (found === -1) break;\n const after = text[found + run.length];\n if (after !== \"`\" && text[found - 1] !== \"`\") {\n close = found;\n break;\n }\n search = found + 1;\n }\n if (close === -1) {\n buffer += run;\n index += run.length;\n continue;\n }\n let code = text.slice(index + run.length, close).replace(/\\n/g, \" \");\n if (code.length > 1 && code.startsWith(\" \") && code.endsWith(\" \") && code.trim() !== \"\") code = code.slice(1, -1);\n flush();\n tokens.push({ k: \"nodes\", nodes: [{ type: \"text\", text: code, marks: [{ type: \"code\" }] }] });\n index = close + run.length;\n continue;\n }\n\n // Images (inline images become links to the source) and links.\n if (char === \"[\" || (char === \"!\" && text[index + 1] === \"[\")) {\n const isImage = char === \"!\";\n const bracket = isImage ? index + 1 : index;\n const close = findClosingBracket(text, bracket);\n if (close !== -1) {\n const target = parseLinkTarget(text, close + 1);\n if (target) {\n const label = text.slice(bracket + 1, close);\n flush();\n const mention = /^kit:mention\\/(person|page|date)\\/(.+)$/.exec(target.href);\n if (!isImage && mention) {\n tokens.push({\n k: \"nodes\",\n nodes: [\n {\n type: \"mention\",\n kind: mention[1] as \"person\" | \"page\" | \"date\",\n id: decodeURIComponent(mention[2] ?? \"\"),\n label: label.replace(/^@/, \"\").replace(/\\\\([!-/:-@[-`{-~])/g, \"$1\"),\n },\n ],\n });\n } else {\n const inner = parseInlineNodes(isImage && label === \"\" ? target.href : label);\n tokens.push({ k: \"nodes\", nodes: withMark(inner, { type: \"link\", href: target.href }) });\n }\n index = target.end;\n continue;\n }\n }\n }\n\n // Autolinks and HTML.\n if (char === \"<\") {\n const auto = AUTOLINK.exec(rest);\n if (auto) {\n flush();\n const href = auto[1] as string;\n tokens.push({\n k: \"nodes\",\n nodes: [{ type: \"text\", text: href.replace(/^mailto:/i, \"\"), marks: [{ type: \"link\", href }] }],\n });\n index += auto[0].length;\n continue;\n }\n const tag = TAG.exec(rest);\n if (tag) {\n const name = (tag[2] as string).toLowerCase();\n if (name === \"br\") {\n buffer += \"\\n\";\n index += tag[0].length;\n continue;\n }\n const mark = htmlMark(name, tag[3] as string, tag[1] === \"/\");\n if (mark) {\n flush();\n tokens.push({ k: \"mark\", mark, open: tag[1] !== \"/\" });\n index += tag[0].length;\n continue;\n }\n }\n }\n\n // Emphasis delimiters.\n if (char === \"*\" || char === \"_\" || char === \"~\") {\n const run = new RegExp(`^\\\\${char}+`).exec(rest)?.[0] ?? char;\n if (char === \"~\" && run.length !== 2) {\n buffer += run;\n index += run.length;\n continue;\n }\n const before = index === 0 ? \" \" : (text[index - 1] as string);\n const after = index + run.length >= text.length ? \" \" : (text[index + run.length] as string);\n const beforeSpace = WHITESPACE.test(before);\n const afterSpace = WHITESPACE.test(after);\n const beforePunct = PUNCTUATION.test(before);\n const afterPunct = PUNCTUATION.test(after);\n const leftFlanking = !afterSpace && (!afterPunct || beforeSpace || beforePunct);\n const rightFlanking = !beforeSpace && (!beforePunct || afterSpace || afterPunct);\n const open = char === \"_\" ? leftFlanking && (!rightFlanking || beforePunct) : leftFlanking;\n const close = char === \"_\" ? rightFlanking && (!leftFlanking || afterPunct) : rightFlanking;\n flush();\n tokens.push({ k: \"delim\", char, count: run.length, open, close });\n index += run.length;\n continue;\n }\n\n // Emoji shortcodes and bare URLs.\n if (char === \":\") {\n const shortcode = /^:([a-z0-9_+-]+):/i.exec(rest);\n if (shortcode && emojiForShortcode(shortcode[1] as string) !== null) {\n flush();\n tokens.push({ k: \"nodes\", nodes: [{ type: \"emoji\", shortcode: shortcode[1] as string }] });\n index += shortcode[0].length;\n continue;\n }\n }\n if ((char === \"h\" || char === \"H\") && (index === 0 || !/[\\p{L}\\p{N}]/u.test(text[index - 1] as string))) {\n const url = BARE_URL.exec(rest);\n if (url) {\n let value = url[0];\n while (/[.,;:!?'\"*_~]$/.test(value) || (value.endsWith(\")\") && !value.includes(\"(\"))) value = value.slice(0, -1);\n if (value.length > \"https://\".length) {\n flush();\n tokens.push({ k: \"nodes\", nodes: [{ type: \"text\", text: value, marks: [{ type: \"link\", href: value }] }] });\n index += value.length;\n continue;\n }\n }\n }\n\n buffer += char;\n index += 1;\n }\n flush();\n return tokens;\n}\n\n/** Resolves delimiter runs into spans (the CommonMark emphasis algorithm, simplified). */\nfunction resolveEmphasis(tokens: Token[]): Token[] {\n const list = [...tokens];\n\n // HTML-style marks first: pair each open with the next matching close.\n for (let index = 0; index < list.length; index += 1) {\n const token = list[index] as Token;\n if (token.k !== \"mark\" || !token.open) continue;\n let closeAt = -1;\n for (let search = index + 1; search < list.length; search += 1) {\n const candidate = list[search] as Token;\n if (candidate.k === \"mark\" && !candidate.open && candidate.mark.type === token.mark.type) {\n closeAt = search;\n break;\n }\n }\n if (closeAt === -1) {\n list[index] = { k: \"text\", text: \"\" };\n continue;\n }\n const children = list.slice(index + 1, closeAt);\n list.splice(index, closeAt - index + 1, { k: \"span\", mark: token.mark, children: resolveEmphasis(children) });\n }\n for (let index = 0; index < list.length; index += 1) {\n const token = list[index] as Token;\n if (token.k === \"mark\") list[index] = { k: \"text\", text: \"\" };\n }\n\n for (let closerIndex = 0; closerIndex < list.length; closerIndex += 1) {\n let closer = list[closerIndex] as Token;\n if (closer.k !== \"delim\" || !closer.close) continue;\n while (closer.k === \"delim\" && closer.count > 0 && closer.close) {\n let openerIndex = -1;\n for (let search = closerIndex - 1; search >= 0; search -= 1) {\n const candidate = list[search] as Token;\n if (candidate.k === \"delim\" && candidate.char === closer.char && candidate.open && candidate.count > 0) {\n // `~~` needs two on each side; `*` and `_` match one or two.\n if (closer.char === \"~\" && (candidate.count < 2 || closer.count < 2)) continue;\n openerIndex = search;\n break;\n }\n }\n if (openerIndex === -1) break;\n const opener = list[openerIndex] as Extract<Token, { k: \"delim\" }>;\n const use = closer.char === \"~\" ? 2 : opener.count >= 2 && closer.count >= 2 ? 2 : 1;\n const mark: Mark = closer.char === \"~\" ? { type: \"strike\" } : use === 2 ? { type: \"bold\" } : { type: \"italic\" };\n const children = list.slice(openerIndex + 1, closerIndex);\n opener.count -= use;\n closer.count -= use;\n list.splice(openerIndex + 1, closerIndex - openerIndex - 1, { k: \"span\", mark, children });\n closerIndex = openerIndex + 2;\n closer = list[closerIndex] as Token;\n if (closer.k !== \"delim\") break;\n }\n }\n return list;\n}\n\nfunction tokensToNodes(tokens: Token[], inherited: Mark[]): InlineNode[] {\n const out: InlineNode[] = [];\n const push = (text: string, marks: Mark[]) => {\n if (text !== \"\") out.push(marks.length > 0 ? { type: \"text\", text, marks } : { type: \"text\", text });\n };\n for (const token of tokens) {\n switch (token.k) {\n case \"text\":\n push(decodeEntities(token.text), inherited);\n break;\n case \"delim\":\n push(token.char.repeat(token.count), inherited);\n break;\n case \"nodes\":\n for (const node of token.nodes) {\n out.push(node.type === \"text\" ? { ...node, marks: [...inherited, ...(node.marks ?? [])] } : node);\n }\n break;\n case \"span\":\n out.push(...tokensToNodes(token.children, [...inherited, token.mark]));\n break;\n default:\n break;\n }\n }\n return out;\n}\n\nfunction parseInlineNodes(text: string): InlineNode[] {\n return tokensToNodes(resolveEmphasis(tokenize(text)), []);\n}\n\n/** Parses inline Markdown into schema inline content (canonical form). */\nexport function markdownToInline(markdown: string): Inline {\n return normalizeInline(parseInlineNodes(markdown.trim()));\n}\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nconst HEADING = /^ {0,3}(#{1,6})(?:[ \\t]+(.*?))?(?:[ \\t]+#+)?[ \\t]*$/;\nconst FENCE = /^ {0,3}(`{3,}|~{3,})[ \\t]*([^`]*?)[ \\t]*$/;\nconst THEMATIC = /^ {0,3}([-*_])(?:[ \\t]*\\1){2,}[ \\t]*$/;\nconst BULLET = /^( {0,3})([-+*])(?:[ \\t]+(.*))?$/;\nconst ORDERED = /^( {0,3})(\\d{1,9})([.)])(?:[ \\t]+(.*))?$/;\nconst QUOTE = /^ {0,3}>[ ]?(.*)$/;\nconst TABLE_DELIMITER = /^\\s*\\|?\\s*:?-+:?\\s*(?:\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;\nconst SETEXT = /^ {0,3}(=+|-+)[ \\t]*$/;\nconst EQUATION_FENCE = /^ {0,3}\\$\\$[ \\t]*$/;\nconst EQUATION_ONE_LINE = /^ {0,3}\\$\\$(.+)\\$\\$[ \\t]*$/;\n\nfunction expandTabs(line: string): string {\n return line.replace(/^[ \\t]+/, (indent) => indent.replace(/\\t/g, \" \"));\n}\n\nfunction indentOf(line: string): number {\n return /^ */.exec(line)?.[0].length ?? 0;\n}\n\nfunction isBlank(line: string | undefined): boolean {\n return line === undefined || line.trim() === \"\";\n}\n\ninterface ListMarker {\n ordered: boolean;\n delimiter: string;\n indent: number;\n contentOffset: number;\n text: string;\n}\n\nfunction matchListMarker(line: string): ListMarker | null {\n if (THEMATIC.test(line)) return null;\n const bullet = BULLET.exec(line);\n if (bullet) {\n const indent = (bullet[1] as string).length;\n const text = bullet[3] ?? \"\";\n const gap = text === \"\" ? 1 : /^( {0,3}[-+*])([ \\t]+)/.exec(line)?.[2]?.replace(/\\t/g, \" \").length ?? 1;\n return { ordered: false, delimiter: bullet[2] as string, indent, contentOffset: indent + 1 + Math.min(gap, 4), text };\n }\n const ordered = ORDERED.exec(line);\n if (ordered) {\n const indent = (ordered[1] as string).length;\n const text = ordered[4] ?? \"\";\n const marker = (ordered[2] as string).length + 1;\n const gap = text === \"\" ? 1 : /^( {0,3}\\d{1,9}[.)])([ \\t]+)/.exec(line)?.[2]?.replace(/\\t/g, \" \").length ?? 1;\n return { ordered: true, delimiter: ordered[3] as string, indent, contentOffset: indent + marker + Math.min(gap, 4), text };\n }\n return null;\n}\n\nfunction startsBlock(line: string, previousIsParagraph: boolean): boolean {\n if (HEADING.test(line) || FENCE.test(line) || THEMATIC.test(line) || QUOTE.test(line)) return true;\n if (EQUATION_FENCE.test(line) || EQUATION_ONE_LINE.test(line)) return true;\n if (/^ {0,3}<(details|!--|video|audio)/i.test(line) || /^ {0,3}\\[TOC\\]\\s*$/i.test(line)) return true;\n const marker = matchListMarker(line);\n if (marker) {\n // An ordered list only interrupts a paragraph when it starts at 1, and an empty item never does.\n if (previousIsParagraph && (marker.text === \"\" || (marker.ordered && !/^ {0,3}1[.)]/.test(line)))) return false;\n return true;\n }\n return false;\n}\n\nconst CALLOUT_ALIASES: Record<string, CalloutVariant> = {\n info: \"info\",\n note: \"info\",\n tip: \"success\",\n success: \"success\",\n warning: \"warning\",\n caution: \"danger\",\n danger: \"danger\",\n important: \"neutral\",\n neutral: \"neutral\",\n};\n\nfunction splitTableRow(line: string): string[] {\n let trimmed = line.trim();\n if (trimmed.startsWith(\"|\")) trimmed = trimmed.slice(1);\n if (trimmed.endsWith(\"|\") && !trimmed.endsWith(\"\\\\|\")) trimmed = trimmed.slice(0, -1);\n const cells: string[] = [];\n let current = \"\";\n let inCode = false;\n for (let index = 0; index < trimmed.length; index += 1) {\n const char = trimmed[index] as string;\n if (char === \"\\\\\" && trimmed[index + 1] === \"|\") {\n current += \"|\";\n index += 1;\n } else if (char === \"`\") {\n inCode = !inCode;\n current += char;\n } else if (char === \"|\" && !inCode) {\n cells.push(current.trim());\n current = \"\";\n } else {\n current += char;\n }\n }\n cells.push(current.trim());\n return cells;\n}\n\nfunction joinParagraphInline(parts: Inline[]): Inline {\n const joined: Inline = [];\n parts.forEach((part, index) => {\n if (index > 0) joined.push({ type: \"text\", text: \"\\n\" });\n joined.push(...part);\n });\n return normalizeInline(joined);\n}\n\nfunction plainOf(block: Block): string {\n if (\"content\" in block && Array.isArray(block.content)) {\n return block.content.map((node) => (node.type === \"text\" ? node.text : node.type === \"mention\" ? `@${node.label}` : `:${node.shortcode}:`)).join(\"\");\n }\n if (block.type === \"code\") return block.code;\n return \"\";\n}\n\ntype AnyItem = ListItem | TaskItem;\n\nfunction itemFromLines(lines: string[], task: boolean, ctx: Ctx): AnyItem {\n const blocks = parseBlocks(lines, ctx);\n const children: AnyItem[] = [];\n const runs: Inline[] = [];\n for (const block of blocks) {\n if (block.type === \"paragraph\") runs.push(block.content);\n else if (block.type === \"bulleted-list\" || block.type === \"numbered-list\" || block.type === \"task-list\") {\n for (const item of block.items) children.push(item as AnyItem);\n } else {\n const text = plainOf(block);\n if (text !== \"\") runs.push([{ type: \"text\", text }]);\n }\n }\n const base = { id: ctx.generateId(), content: joinParagraphInline(runs) };\n const item = (task ? { ...base, checked: false } : base) as AnyItem;\n if (children.length > 0) item.children = children as never;\n return item;\n}\n\nfunction parseList(lines: string[], start: number, ctx: Ctx): { block: Block; next: number } {\n const first = matchListMarker(lines[start] as string) as ListMarker;\n const items: AnyItem[] = [];\n let index = start;\n let isTask: boolean | undefined;\n\n while (index < lines.length) {\n const marker = matchListMarker(lines[index] as string);\n if (!marker || marker.ordered !== first.ordered || marker.delimiter !== first.delimiter) break;\n if (index !== start && marker.indent >= first.contentOffset) break;\n\n const itemLines: string[] = [marker.text];\n let cursor = index + 1;\n let previousBlank = false;\n while (cursor < lines.length) {\n const line = lines[cursor] as string;\n if (isBlank(line)) {\n itemLines.push(\"\");\n previousBlank = true;\n cursor += 1;\n continue;\n }\n const indent = indentOf(line);\n if (indent >= marker.contentOffset) {\n itemLines.push(line.slice(marker.contentOffset));\n } else if (!previousBlank && !startsBlock(line, !isBlank(itemLines[itemLines.length - 1])) && !matchListMarker(line)) {\n itemLines.push(line.trimStart()); // lazy continuation\n } else {\n break;\n }\n previousBlank = false;\n cursor += 1;\n }\n // Trailing blank lines belong to the list, not the item.\n let trailing = 0;\n while (itemLines.length > 1 && isBlank(itemLines[itemLines.length - 1])) {\n itemLines.pop();\n trailing += 1;\n }\n cursor -= trailing;\n\n let checked: boolean | undefined;\n const taskMatch = /^\\[([ xX])\\](?:[ \\t]+(.*))?$/.exec(itemLines[0] as string);\n if (isTask === undefined) isTask = taskMatch !== null;\n // GitHub mixes tasks and plain items in one list; the schema has two list types, so a change starts a new list.\n else if ((taskMatch !== null) !== isTask) break;\n if (isTask && taskMatch) {\n checked = taskMatch[1] !== \" \";\n itemLines[0] = taskMatch[2] ?? \"\";\n }\n const item = itemFromLines(itemLines, isTask === true, ctx);\n if (isTask === true) (item as TaskItem).checked = checked === true;\n items.push(item);\n index = cursor;\n // Skip blank lines between items; stop when the next non-blank line is not a sibling.\n let lookahead = index;\n while (lookahead < lines.length && isBlank(lines[lookahead])) lookahead += 1;\n const sibling = lookahead < lines.length ? matchListMarker(lines[lookahead] as string) : null;\n if (sibling && sibling.ordered === first.ordered && sibling.delimiter === first.delimiter && sibling.indent < first.contentOffset) {\n index = lookahead;\n } else {\n break;\n }\n }\n\n const type = isTask ? \"task-list\" : first.ordered ? \"numbered-list\" : \"bulleted-list\";\n return { block: { id: ctx.generateId(), type, items } as Block, next: index };\n}\n\nfunction parseCalloutFromQuote(inner: Block[], ctx: Ctx): Block[] | null {\n const head = inner[0];\n if (!head || head.type !== \"paragraph\") return null;\n const firstText = head.content[0];\n if (!firstText || firstText.type !== \"text\") return null;\n const match = /^\\[!([A-Za-z]+)\\][ \\t]*\\n?/.exec(firstText.text);\n if (!match) return null;\n const variant = CALLOUT_ALIASES[(match[1] as string).toLowerCase()];\n if (!variant) return null;\n const content: Inline = [{ ...firstText, text: firstText.text.slice(match[0].length) }, ...head.content.slice(1)];\n const runs: Inline[] = [normalizeInline(content)];\n const trailing: Block[] = [];\n for (const block of inner.slice(1)) {\n if (block.type === \"paragraph\") runs.push(block.content);\n else trailing.push(block);\n }\n return [{ id: ctx.generateId(), type: \"callout\", variant, content: joinParagraphInline(runs) }, ...trailing];\n}\n\nfunction parseKitFence(info: string, code: string, ctx: Ctx): Block | null {\n const kind = info.toLowerCase();\n if (kind === \"mermaid\") {\n return { id: ctx.generateId(), type: \"diagram\", engine: \"mermaid\", source: code };\n }\n if (!kind.startsWith(\"kit-\")) return null;\n let data: unknown;\n try {\n data = JSON.parse(code);\n } catch {\n return null;\n }\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) return null;\n const record = data as Record<string, unknown>;\n switch (kind) {\n case \"kit-chart\":\n return { id: ctx.generateId(), type: \"chart\", spec: record as never };\n case \"kit-diagram\": {\n const engine = record.engine === \"canvas\" || record.engine === \"excalidraw\" ? record.engine : \"mermaid\";\n const block: Extract<Block, { type: \"diagram\" }> = { id: ctx.generateId(), type: \"diagram\", engine };\n if (typeof record.diagram === \"object\" && record.diagram !== null) block.diagram = record.diagram as never;\n if (typeof record.source === \"string\") block.source = record.source;\n return block;\n }\n case \"kit-data-view\":\n return {\n id: ctx.generateId(),\n type: \"data-view\",\n dataset: typeof record.dataset === \"string\" ? record.dataset : \"\",\n view: record.view as never,\n };\n case \"kit-ai\": {\n const block: Extract<Block, { type: \"ai\" }> = {\n id: ctx.generateId(),\n type: \"ai\",\n prompt: typeof record.prompt === \"string\" ? record.prompt : \"\",\n };\n if (Array.isArray(record.result)) block.result = record.result as Block[];\n return block;\n }\n case \"kit-block\":\n return typeof record.type === \"string\"\n ? ({ ...record, id: typeof record.id === \"string\" ? record.id : ctx.generateId() } as unknown as Block)\n : null;\n default:\n return null;\n }\n}\n\nfunction parseMediaTag(line: string, ctx: Ctx): Block | null {\n const match = /^ {0,3}<(video|audio)\\b([^>]*)>\\s*<\\/\\1>\\s*$|^ {0,3}<(video|audio)\\b([^>]*)\\/>\\s*$/i.exec(line);\n if (!match) return null;\n const kind = (match[1] ?? match[3] ?? \"video\").toLowerCase() as \"video\" | \"audio\";\n const attributes = ` ${match[2] ?? match[4] ?? \"\"}`;\n const src = attributeOf(attributes, \"src\");\n if (src === undefined) return null;\n const block: Extract<Block, { type: \"video\" | \"audio\" }> = { id: ctx.generateId(), type: kind, src };\n const title = attributeOf(attributes, \"title\");\n if (title !== undefined && title !== \"\") block.caption = [{ type: \"text\", text: title }];\n return block;\n}\n\nconst IMAGE_ONLY = /^\\s*!\\[((?:[^\\]\\\\]|\\\\.)*)\\]\\(\\s*(<[^>]*>|[^\\s)]*)(?:\\s+\"((?:[^\"\\\\]|\\\\.)*)\")?\\s*\\)\\s*$/;\n\nfunction parseImageOnly(text: string, ctx: Ctx): Block | null {\n const match = IMAGE_ONLY.exec(text);\n if (!match) return null;\n const src = decodeEntities((match[2] as string).replace(/^<|>$/g, \"\"));\n const block: Extract<Block, { type: \"image\" }> = {\n id: ctx.generateId(),\n type: \"image\",\n src,\n alt: (match[1] as string).replace(/\\\\([!-/:-@[-`{-~])/g, \"$1\"),\n };\n if (match[3] !== undefined && match[3] !== \"\") {\n block.caption = [{ type: \"text\", text: match[3].replace(/\\\\([\"\\\\])/g, \"$1\") }];\n }\n return block;\n}\n\nfunction parseDetails(lines: string[], start: number, ctx: Ctx): { block: Block; next: number } | null {\n if (!/^ {0,3}<details(\\s[^>]*)?>\\s*$/i.test(lines[start] as string)) return null;\n let depth = 0;\n let end = -1;\n for (let index = start; index < lines.length; index += 1) {\n const line = lines[index] as string;\n if (/^ {0,3}<details(\\s[^>]*)?>\\s*$/i.test(line)) depth += 1;\n if (/^ {0,3}<\\/details>\\s*$/i.test(line)) {\n depth -= 1;\n if (depth === 0) {\n end = index;\n break;\n }\n }\n }\n if (end === -1) return null;\n const body = lines.slice(start + 1, end);\n let summary: Inline = [];\n let rest = body;\n const summaryIndex = body.findIndex((line) => /<summary[^>]*>/i.test(line));\n if (summaryIndex !== -1) {\n const joined = body.slice(summaryIndex).join(\"\\n\");\n const match = /<summary[^>]*>([\\s\\S]*?)<\\/summary>/i.exec(joined);\n if (match) {\n const summaryText = decodeEntities((match[1] as string).replace(/<[^>]+>/g, \"\").trim());\n summary = summaryText === \"\" ? [] : [{ type: \"text\", text: summaryText }];\n const consumed = joined.slice(0, (match.index ?? 0) + match[0].length).split(\"\\n\").length;\n rest = [...body.slice(0, summaryIndex), ...body.slice(summaryIndex + consumed)];\n }\n }\n return {\n block: { id: ctx.generateId(), type: \"toggle\", summary, children: parseBlocks(rest, ctx) },\n next: end + 1,\n };\n}\n\nfunction parseBlocks(rawLines: string[], ctx: Ctx): Block[] {\n const lines = rawLines.map(expandTabs);\n const blocks: Block[] = [];\n let index = 0;\n\n while (index < lines.length) {\n const line = lines[index] as string;\n if (isBlank(line)) {\n index += 1;\n continue;\n }\n\n // Fenced code (and kit fences).\n const fenceMatch = FENCE.exec(line);\n if (fenceMatch) {\n const marker = fenceMatch[1] as string;\n const info = (fenceMatch[2] as string).split(/\\s+/)[0] ?? \"\";\n const fenceIndent = indentOf(line);\n const body: string[] = [];\n index += 1;\n while (index < lines.length) {\n const current = lines[index] as string;\n const closing = new RegExp(`^ {0,3}\\\\${marker[0]}{${marker.length},}[ \\\\t]*$`).test(current);\n if (closing) {\n index += 1;\n break;\n }\n body.push(current.replace(new RegExp(`^ {0,${fenceIndent}}`), \"\"));\n index += 1;\n }\n const code = body.join(\"\\n\");\n const kit = parseKitFence(info, code, ctx);\n if (kit) blocks.push(kit);\n else {\n const block: Extract<Block, { type: \"code\" }> = { id: ctx.generateId(), type: \"code\", code };\n if (info !== \"\") block.language = info;\n blocks.push(block);\n }\n continue;\n }\n\n // Equations.\n if (EQUATION_FENCE.test(line)) {\n const body: string[] = [];\n index += 1;\n while (index < lines.length && !EQUATION_FENCE.test(lines[index] as string)) {\n body.push((lines[index] as string).trimEnd());\n index += 1;\n }\n index += 1;\n blocks.push({ id: ctx.generateId(), type: \"equation\", latex: body.join(\"\\n\").trim() });\n continue;\n }\n const oneLine = EQUATION_ONE_LINE.exec(line);\n if (oneLine) {\n blocks.push({ id: ctx.generateId(), type: \"equation\", latex: (oneLine[1] as string).trim() });\n index += 1;\n continue;\n }\n\n // Headings.\n const heading = HEADING.exec(line);\n if (heading) {\n const level = Math.min(4, (heading[1] as string).length) as 1 | 2 | 3 | 4;\n blocks.push({ id: ctx.generateId(), type: \"heading\", level, content: markdownToInline(heading[2] ?? \"\") });\n index += 1;\n continue;\n }\n\n // Thematic break.\n if (THEMATIC.test(line)) {\n blocks.push({ id: ctx.generateId(), type: \"divider\" });\n index += 1;\n continue;\n }\n\n // HTML blocks we understand. An empty comment only separates two lists.\n if (/^ {0,3}<!--\\s*-->\\s*$/.test(line)) {\n index += 1;\n continue;\n }\n if (/^ {0,3}<!--\\s*page-break\\s*-->\\s*$/i.test(line)) {\n blocks.push({ id: ctx.generateId(), type: \"page-break\" });\n index += 1;\n continue;\n }\n if (/^ {0,3}(\\[TOC\\]|<!--\\s*toc\\s*-->)\\s*$/i.test(line)) {\n blocks.push({ id: ctx.generateId(), type: \"table-of-contents\" });\n index += 1;\n continue;\n }\n const media = parseMediaTag(line, ctx);\n if (media) {\n blocks.push(media);\n index += 1;\n continue;\n }\n const details = parseDetails(lines, index, ctx);\n if (details) {\n blocks.push(details.block);\n index = details.next;\n continue;\n }\n\n // Block quotes and callouts.\n if (QUOTE.test(line)) {\n const inner: string[] = [];\n while (index < lines.length) {\n const current = lines[index] as string;\n const quote = QUOTE.exec(current);\n if (quote) {\n inner.push(quote[1] as string);\n } else if (!isBlank(current) && !startsBlock(current, true) && inner.length > 0 && !isBlank(inner[inner.length - 1])) {\n inner.push(current.trim()); // lazy continuation\n } else break;\n index += 1;\n }\n const parsed = parseBlocks(inner, ctx);\n const callout = parseCalloutFromQuote(parsed, ctx);\n if (callout) {\n blocks.push(...callout);\n } else {\n const runs: Inline[] = [];\n const trailing: Block[] = [];\n for (const block of parsed) {\n if (block.type === \"paragraph\" || block.type === \"heading\") runs.push(block.content);\n else trailing.push(block);\n }\n if (runs.length > 0 || trailing.length === 0) {\n blocks.push({ id: ctx.generateId(), type: \"quote\", content: joinParagraphInline(runs) });\n }\n blocks.push(...trailing);\n }\n continue;\n }\n\n // Lists.\n if (matchListMarker(line)) {\n const result = parseList(lines, index, ctx);\n blocks.push(result.block);\n index = result.next;\n continue;\n }\n\n // Tables.\n if (line.includes(\"|\") && index + 1 < lines.length && TABLE_DELIMITER.test(lines[index + 1] as string) && (lines[index + 1] as string).includes(\"-\")) {\n const header = splitTableRow(line);\n const delimiter = splitTableRow(lines[index + 1] as string);\n if (header.length === delimiter.length) {\n const rows: TableCell[][] = [header.map((text) => ({ content: markdownToInline(text) }))];\n index += 2;\n while (index < lines.length && !isBlank(lines[index]) && (lines[index] as string).includes(\"|\")) {\n const cells = splitTableRow(lines[index] as string);\n const row: TableCell[] = [];\n for (let column = 0; column < header.length; column += 1) {\n row.push({ content: markdownToInline(cells[column] ?? \"\") });\n }\n rows.push(row);\n index += 1;\n }\n blocks.push({ id: ctx.generateId(), type: \"table\", headerRow: true, rows });\n continue;\n }\n }\n\n // Paragraph (and setext headings).\n const paragraph: string[] = [line];\n index += 1;\n let setext: 1 | 2 | null = null;\n while (index < lines.length) {\n const current = lines[index] as string;\n if (isBlank(current)) break;\n const underline = SETEXT.exec(current);\n if (underline) {\n setext = (underline[1] as string).startsWith(\"=\") ? 1 : 2;\n index += 1;\n break;\n }\n if (startsBlock(current, true)) break;\n if (current.includes(\"|\") && TABLE_DELIMITER.test(lines[index + 1] ?? \"\") && (lines[index + 1] ?? \"\").includes(\"-\")) break;\n paragraph.push(current);\n index += 1;\n }\n const text = paragraph.map((part, position) => (position === paragraph.length - 1 ? part.trimEnd() : part)).join(\"\\n\").trim();\n if (setext !== null) {\n blocks.push({ id: ctx.generateId(), type: \"heading\", level: setext, content: markdownToInline(text.replace(/\\n/g, \" \")) });\n continue;\n }\n const image = parseImageOnly(text, ctx);\n if (image) {\n blocks.push(image);\n continue;\n }\n blocks.push({ id: ctx.generateId(), type: \"paragraph\", content: markdownToInline(text) });\n }\n return blocks;\n}\n\n/**\n * Parses Markdown into a document. Block ids are generated; Markdown has no\n * ids. Line endings of any kind are accepted.\n */\nexport function markdownToDocument(markdown: string, options: MarkdownImportOptions = {}): EditorDocument {\n const ctx: Ctx = { generateId: options.generateId ?? generateBlockId };\n const lines = markdown.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n const doc: EditorDocument = { version: DOCUMENT_VERSION, blocks: parseBlocks(lines, ctx) };\n if (options.title !== undefined) doc.title = options.title;\n return doc;\n}\n","/**\n * Block-level document diff by id: which blocks were added, removed, changed\n * or moved. Useful for autosave payloads, \"what changed\" summaries, comment\n * anchors and as a cheap pre-check before a full collaboration merge.\n */\nimport { walkBlocks } from \"./ids\";\nimport type { Block, EditorDocument } from \"./schema\";\n\nexport interface DocumentDiff {\n /** Ids present only in the newer document. */\n added: string[];\n /** Ids present only in the older document. */\n removed: string[];\n /** Ids in both whose own content differs (children of containers are compared by their own ids). */\n changed: string[];\n /** Ids in both, with the same content, that sit in a different order or place. */\n moved: string[];\n /** Ids in both with no difference. */\n unchanged: string[];\n}\n\ninterface Entry {\n signature: string;\n parentId: string | null;\n}\n\n/** The block without its nested blocks; nested blocks are replaced by their ids. */\nfunction signatureOf(block: Block): string {\n const copy = { ...block } as Record<string, unknown>;\n if (block.type === \"toggle\") copy.children = (block.children ?? []).map((child) => child.id);\n if (block.type === \"columns\") copy.columns = (block.columns ?? []).map((column) => column.map((child) => child.id));\n if (block.type === \"ai\" && block.result) copy.result = block.result.map((child) => child.id);\n return JSON.stringify(copy);\n}\n\nfunction indexBlocks(doc: EditorDocument): { order: string[]; entries: Map<string, Entry> } {\n const order: string[] = [];\n const entries = new Map<string, Entry>();\n walkBlocks(doc.blocks ?? [], (block, parent) => {\n order.push(block.id);\n entries.set(block.id, { signature: signatureOf(block), parentId: parent?.id ?? null });\n });\n return { order, entries };\n}\n\n/** Longest common subsequence of two id lists; ids outside it were moved. */\nfunction longestCommonSubsequence(a: readonly string[], b: readonly string[]): Set<string> {\n const table: number[][] = Array.from({ length: a.length + 1 }, () => new Array<number>(b.length + 1).fill(0));\n for (let i = a.length - 1; i >= 0; i -= 1) {\n for (let j = b.length - 1; j >= 0; j -= 1) {\n const row = table[i] as number[];\n row[j] =\n a[i] === b[j]\n ? ((table[i + 1] as number[])[j + 1] as number) + 1\n : Math.max((table[i + 1] as number[])[j] as number, row[j + 1] as number);\n }\n }\n const common = new Set<string>();\n let i = 0;\n let j = 0;\n while (i < a.length && j < b.length) {\n if (a[i] === b[j]) {\n common.add(a[i] as string);\n i += 1;\n j += 1;\n } else if (((table[i + 1] as number[])[j] as number) >= ((table[i] as number[])[j + 1] as number)) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return common;\n}\n\n/** Compares two documents by block id (nested blocks included). */\nexport function diffDocuments(previous: EditorDocument, next: EditorDocument): DocumentDiff {\n const before = indexBlocks(previous);\n const after = indexBlocks(next);\n\n const added = after.order.filter((id) => !before.entries.has(id));\n const removed = before.order.filter((id) => !after.entries.has(id));\n const shared = after.order.filter((id) => before.entries.has(id));\n\n const changed: string[] = [];\n const candidates: string[] = [];\n for (const id of shared) {\n if (before.entries.get(id)?.signature !== after.entries.get(id)?.signature) changed.push(id);\n else candidates.push(id);\n }\n\n const beforeShared = before.order.filter((id) => after.entries.has(id));\n const stable = longestCommonSubsequence(beforeShared, shared);\n const moved: string[] = [];\n const unchanged: string[] = [];\n for (const id of candidates) {\n const sameParent = before.entries.get(id)?.parentId === after.entries.get(id)?.parentId;\n if (stable.has(id) && sameParent) unchanged.push(id);\n else moved.push(id);\n }\n\n return { added, removed, changed, moved, unchanged };\n}\n","/**\n * Validation and sanitizing for documents that come from storage, a network\n * or a user. `validateDocument` reports problems without throwing;\n * `sanitizeDocument` returns a copy that is safe to render.\n */\nimport { collectIds } from \"./ids\";\nimport {\n CALLOUT_VARIANTS,\n DOCUMENT_VERSION,\n isKnownBlockType,\n type Block,\n type EditorDocument,\n type Inline,\n type ListItem,\n type TaskItem,\n} from \"./schema\";\nimport { isHighlightToken, isTextColorToken } from \"./tokens\";\nimport { sanitizeMediaUrl, sanitizeUrl } from \"./url\";\n\nexport type ValidationCode =\n | \"invalid-document\"\n | \"unsupported-version\"\n | \"invalid-block\"\n | \"unknown-block-type\"\n | \"missing-id\"\n | \"duplicate-id\"\n | \"invalid-field\"\n | \"invalid-inline\"\n | \"unsafe-url\"\n | \"unknown-token\";\n\nexport interface ValidationIssue {\n code: ValidationCode;\n /** `error` means the document cannot be rendered as is; `warning` means a renderer will neutralize it. */\n severity: \"error\" | \"warning\";\n /** A path such as `blocks[2].items[0].content[1]`. */\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n /** True when there are no errors. Warnings do not make a document invalid. */\n valid: boolean;\n issues: ValidationIssue[];\n}\n\ntype Json = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\ninterface Collector {\n issues: ValidationIssue[];\n add(code: ValidationCode, severity: \"error\" | \"warning\", path: string, message: string): void;\n}\n\nfunction createCollector(): Collector {\n const issues: ValidationIssue[] = [];\n return {\n issues,\n add(code, severity, path, message) {\n issues.push({ code, severity, path, message });\n },\n };\n}\n\nfunction checkInline(inline: unknown, path: string, c: Collector): void {\n if (!Array.isArray(inline)) {\n c.add(\"invalid-inline\", \"error\", path, \"Inline content must be an array.\");\n return;\n }\n inline.forEach((node, index) => {\n const here = `${path}[${index}]`;\n if (!isRecord(node)) {\n c.add(\"invalid-inline\", \"error\", here, \"An inline node must be an object.\");\n return;\n }\n if (node.type === \"text\") {\n if (typeof node.text !== \"string\") c.add(\"invalid-inline\", \"error\", here, \"A text node needs a string `text`.\");\n if (node.marks === undefined) return;\n if (!Array.isArray(node.marks)) {\n c.add(\"invalid-inline\", \"error\", `${here}.marks`, \"Marks must be an array.\");\n return;\n }\n node.marks.forEach((mark: unknown, markIndex: number) => {\n const markPath = `${here}.marks[${markIndex}]`;\n if (!isRecord(mark)) {\n c.add(\"invalid-inline\", \"error\", markPath, \"A mark must be an object.\");\n return;\n }\n switch (mark.type) {\n case \"bold\":\n case \"italic\":\n case \"underline\":\n case \"strike\":\n case \"code\":\n break;\n case \"link\":\n if (typeof mark.href !== \"string\") c.add(\"invalid-inline\", \"error\", markPath, \"A link mark needs a string `href`.\");\n else if (sanitizeUrl(mark.href) === null) c.add(\"unsafe-url\", \"warning\", markPath, `The link \"${mark.href}\" is not a safe URL and will not render.`);\n break;\n case \"color\":\n if (!isTextColorToken(mark.token)) c.add(\"unknown-token\", \"warning\", markPath, `\"${String(mark.token)}\" is not an allowed text color token.`);\n break;\n case \"highlight\":\n if (!isHighlightToken(mark.token)) c.add(\"unknown-token\", \"warning\", markPath, `\"${String(mark.token)}\" is not an allowed highlight token.`);\n break;\n default:\n c.add(\"invalid-inline\", \"warning\", markPath, `The mark \"${String(mark.type)}\" is not supported.`);\n }\n });\n } else if (node.type === \"mention\") {\n if (typeof node.id !== \"string\" || typeof node.label !== \"string\") c.add(\"invalid-inline\", \"error\", here, \"A mention needs string `id` and `label`.\");\n } else if (node.type === \"emoji\") {\n if (typeof node.shortcode !== \"string\") c.add(\"invalid-inline\", \"error\", here, \"An emoji needs a string `shortcode`.\");\n } else {\n c.add(\"invalid-inline\", \"warning\", here, `The inline node \"${String(node.type)}\" is not supported.`);\n }\n });\n}\n\nfunction checkItems(items: unknown, path: string, task: boolean, c: Collector): void {\n if (!Array.isArray(items)) {\n c.add(\"invalid-field\", \"error\", path, \"`items` must be an array.\");\n return;\n }\n items.forEach((item, index) => {\n const here = `${path}[${index}]`;\n if (!isRecord(item)) {\n c.add(\"invalid-field\", \"error\", here, \"A list item must be an object.\");\n return;\n }\n if (typeof item.id !== \"string\" || item.id === \"\") c.add(\"missing-id\", \"error\", here, \"A list item needs a string `id`.\");\n checkInline(item.content, `${here}.content`, c);\n if (task && typeof item.checked !== \"boolean\") c.add(\"invalid-field\", \"error\", `${here}.checked`, \"A task item needs a boolean `checked`.\");\n if (item.children !== undefined) checkItems(item.children, `${here}.children`, task, c);\n });\n}\n\nfunction checkUrl(value: unknown, path: string, c: Collector, media: boolean): void {\n if (typeof value !== \"string\") {\n c.add(\"invalid-field\", \"error\", path, \"Expected a string URL.\");\n return;\n }\n const safe = media ? sanitizeMediaUrl(value) : sanitizeUrl(value);\n if (safe === null && value !== \"\") c.add(\"unsafe-url\", \"warning\", path, `\"${value.slice(0, 40)}\" is not a safe URL and will not render.`);\n}\n\nfunction checkBlocks(blocks: unknown, path: string, c: Collector): void {\n if (!Array.isArray(blocks)) {\n c.add(\"invalid-field\", \"error\", path, \"Expected an array of blocks.\");\n return;\n }\n blocks.forEach((block, index) => checkBlock(block, `${path}[${index}]`, c));\n}\n\nfunction checkBlock(block: unknown, path: string, c: Collector): void {\n if (!isRecord(block)) {\n c.add(\"invalid-block\", \"error\", path, \"A block must be an object.\");\n return;\n }\n if (typeof block.id !== \"string\" || block.id === \"\") c.add(\"missing-id\", \"error\", path, \"A block needs a string `id`.\");\n if (!isKnownBlockType(block.type)) {\n c.add(\"unknown-block-type\", \"warning\", path, `The block type \"${String(block.type)}\" is not known; it is kept as an opaque block.`);\n return;\n }\n switch (block.type) {\n case \"paragraph\":\n case \"quote\":\n checkInline(block.content, `${path}.content`, c);\n break;\n case \"heading\":\n if (![1, 2, 3, 4].includes(block.level as number)) c.add(\"invalid-field\", \"error\", `${path}.level`, \"A heading level must be 1, 2, 3 or 4.\");\n checkInline(block.content, `${path}.content`, c);\n break;\n case \"callout\":\n if (!(CALLOUT_VARIANTS as readonly unknown[]).includes(block.variant)) c.add(\"invalid-field\", \"error\", `${path}.variant`, \"Unknown callout variant.\");\n checkInline(block.content, `${path}.content`, c);\n break;\n case \"toggle\":\n checkInline(block.summary, `${path}.summary`, c);\n checkBlocks(block.children, `${path}.children`, c);\n break;\n case \"bulleted-list\":\n case \"numbered-list\":\n checkItems(block.items, `${path}.items`, false, c);\n break;\n case \"task-list\":\n checkItems(block.items, `${path}.items`, true, c);\n break;\n case \"code\":\n if (typeof block.code !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.code`, \"A code block needs a string `code`.\");\n break;\n case \"equation\":\n if (typeof block.latex !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.latex`, \"An equation needs a string `latex`.\");\n break;\n case \"table\":\n if (!Array.isArray(block.rows) || block.rows.some((row: unknown) => !Array.isArray(row))) {\n c.add(\"invalid-field\", \"error\", `${path}.rows`, \"`rows` must be an array of arrays of cells.\");\n } else {\n (block.rows as unknown[][]).forEach((row, rowIndex) =>\n row.forEach((cell, columnIndex) => {\n const here = `${path}.rows[${rowIndex}][${columnIndex}]`;\n if (!isRecord(cell)) c.add(\"invalid-field\", \"error\", here, \"A table cell must be an object.\");\n else checkInline(cell.content, `${here}.content`, c);\n }),\n );\n }\n break;\n case \"image\":\n checkUrl(block.src, `${path}.src`, c, true);\n if (typeof block.alt !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.alt`, \"An image needs a string `alt` (an empty string marks it decorative).\");\n if (block.caption !== undefined) checkInline(block.caption, `${path}.caption`, c);\n break;\n case \"video\":\n case \"audio\":\n checkUrl(block.src, `${path}.src`, c, true);\n if (block.caption !== undefined) checkInline(block.caption, `${path}.caption`, c);\n break;\n case \"file\":\n checkUrl(block.src, `${path}.src`, c, false);\n if (typeof block.name !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.name`, \"A file needs a string `name`.\");\n break;\n case \"bookmark\":\n checkUrl(block.url, `${path}.url`, c, false);\n break;\n case \"columns\":\n if (!Array.isArray(block.columns)) c.add(\"invalid-field\", \"error\", `${path}.columns`, \"`columns` must be an array of block arrays.\");\n else (block.columns as unknown[]).forEach((column, index) => checkBlocks(column, `${path}.columns[${index}]`, c));\n break;\n case \"chart\":\n if (!isRecord(block.spec)) c.add(\"invalid-field\", \"error\", `${path}.spec`, \"A chart needs a `spec` object.\");\n break;\n case \"diagram\":\n if (![\"mermaid\", \"canvas\", \"excalidraw\"].includes(block.engine as string)) c.add(\"invalid-field\", \"error\", `${path}.engine`, \"Unknown diagram engine.\");\n break;\n case \"data-view\":\n if (typeof block.dataset !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.dataset`, \"A data view needs a string `dataset`.\");\n if (!isRecord(block.view)) c.add(\"invalid-field\", \"error\", `${path}.view`, \"A data view needs a `view` object.\");\n break;\n case \"ai\":\n if (typeof block.prompt !== \"string\") c.add(\"invalid-field\", \"error\", `${path}.prompt`, \"An AI block needs a string `prompt`.\");\n if (block.result !== undefined) checkBlocks(block.result, `${path}.result`, c);\n break;\n default:\n break;\n }\n}\n\n/** Checks an unknown value against the document schema and reports every problem found. */\nexport function validateDocument(value: unknown): ValidationResult {\n const c = createCollector();\n if (!isRecord(value)) {\n c.add(\"invalid-document\", \"error\", \"\", \"A document must be an object.\");\n return { valid: false, issues: c.issues };\n }\n if (value.version !== DOCUMENT_VERSION) {\n c.add(\"unsupported-version\", \"error\", \"version\", `Expected document version ${DOCUMENT_VERSION}, got ${String(value.version)}.`);\n }\n if (value.title !== undefined && typeof value.title !== \"string\") c.add(\"invalid-field\", \"error\", \"title\", \"`title` must be a string.\");\n checkBlocks(value.blocks, \"blocks\", c);\n\n if (c.issues.every((issue) => issue.code !== \"invalid-field\" || issue.path !== \"blocks\")) {\n const seen = new Set<string>();\n const reported = new Set<string>();\n try {\n for (const id of collectIds(value as unknown as EditorDocument)) {\n if (seen.has(id) && !reported.has(id)) {\n reported.add(id);\n c.add(\"duplicate-id\", \"error\", \"\", `The id \"${id}\" is used more than once.`);\n }\n seen.add(id);\n }\n } catch {\n // A malformed tree was already reported above.\n }\n }\n\n return { valid: c.issues.every((issue) => issue.severity !== \"error\"), issues: c.issues };\n}\n\n/** Type guard: the value has no structural errors (warnings are allowed). */\nexport function isEditorDocument(value: unknown): value is EditorDocument {\n return validateDocument(value).valid;\n}\n\n// ---------------------------------------------------------------------------\n// Sanitizing\n// ---------------------------------------------------------------------------\n\nfunction sanitizeInline(inline: Inline | undefined): Inline {\n return (inline ?? []).map((node) => {\n if (node.type !== \"text\" || !node.marks) return node;\n const marks = node.marks.filter((mark) => {\n if (mark.type === \"link\") return sanitizeUrl(mark.href) !== null;\n if (mark.type === \"color\") return isTextColorToken(mark.token);\n if (mark.type === \"highlight\") return isHighlightToken(mark.token);\n return true;\n });\n const { marks: _marks, ...rest } = node;\n void _marks;\n return marks.length > 0 ? { ...rest, marks } : rest;\n });\n}\n\nfunction sanitizeItems<T extends ListItem | TaskItem>(items: T[]): T[] {\n return items.map((item) => {\n const copy = { ...item, content: sanitizeInline(item.content) } as T;\n if (item.children) copy.children = sanitizeItems(item.children as T[]) as never;\n return copy;\n });\n}\n\nfunction sanitizeBlock(block: Block): Block {\n switch (block.type) {\n case \"paragraph\":\n case \"heading\":\n case \"quote\":\n case \"callout\":\n return { ...block, content: sanitizeInline(block.content) };\n case \"toggle\":\n return { ...block, summary: sanitizeInline(block.summary), children: sanitizeBlocks(block.children ?? []) };\n case \"bulleted-list\":\n case \"numbered-list\":\n return { ...block, items: sanitizeItems(block.items ?? []) };\n case \"task-list\":\n return { ...block, items: sanitizeItems(block.items ?? []) };\n case \"table\":\n return {\n ...block,\n rows: (block.rows ?? []).map((row) => row.map((cell) => ({ ...cell, content: sanitizeInline(cell.content) }))),\n };\n case \"image\": {\n const copy = { ...block, src: sanitizeMediaUrl(block.src) ?? \"\" };\n if (block.caption) copy.caption = sanitizeInline(block.caption);\n return copy;\n }\n case \"video\":\n case \"audio\": {\n const copy = { ...block, src: sanitizeMediaUrl(block.src) ?? \"\" };\n if (block.caption) copy.caption = sanitizeInline(block.caption);\n return copy;\n }\n case \"file\":\n return { ...block, src: sanitizeUrl(block.src) ?? \"\" };\n case \"bookmark\":\n return { ...block, url: sanitizeUrl(block.url) ?? \"\" };\n case \"columns\":\n return { ...block, columns: (block.columns ?? []).map(sanitizeBlocks) };\n case \"ai\":\n return block.result ? { ...block, result: sanitizeBlocks(block.result) } : block;\n default:\n return block;\n }\n}\n\nfunction sanitizeBlocks(blocks: Block[]): Block[] {\n return blocks.map(sanitizeBlock);\n}\n\n/**\n * Returns a copy of the document that is safe to render: links with unsafe\n * URLs lose the link mark, media with unsafe sources get an empty source,\n * and color marks outside the token allow-list are dropped. Structure and\n * ids are kept. Renderers already neutralize these values; sanitize when\n * you store or forward a document you do not control.\n */\nexport function sanitizeDocument(doc: EditorDocument): EditorDocument {\n return { ...doc, blocks: sanitizeBlocks(doc.blocks ?? []) };\n}\n"],"mappings":"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","names":["item","text","i","j"]}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { ChartSpec } from '@x12i/charts';
|
|
2
|
+
import { SavedView } from '@x12i/data';
|
|
3
|
+
import { DiagramDocument } from '@x12i/diagrams';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The stored document (spec section 11): versioned JSON owned by the kit, with
|
|
7
|
+
* converters to and from the engine's format. That keeps the editor engine
|
|
8
|
+
* (Tiptap by default) replaceable.
|
|
9
|
+
*
|
|
10
|
+
* This module is headless: no React, no DOM, no engine imports.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
declare const DOCUMENT_VERSION = 1;
|
|
14
|
+
type Mark = {
|
|
15
|
+
type: "bold";
|
|
16
|
+
} | {
|
|
17
|
+
type: "italic";
|
|
18
|
+
} | {
|
|
19
|
+
type: "underline";
|
|
20
|
+
} | {
|
|
21
|
+
type: "strike";
|
|
22
|
+
} | {
|
|
23
|
+
type: "code";
|
|
24
|
+
} | {
|
|
25
|
+
type: "link";
|
|
26
|
+
href: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: "color";
|
|
29
|
+
token: string;
|
|
30
|
+
} | {
|
|
31
|
+
type: "highlight";
|
|
32
|
+
token: string;
|
|
33
|
+
};
|
|
34
|
+
type InlineNode = {
|
|
35
|
+
type: "text";
|
|
36
|
+
text: string;
|
|
37
|
+
marks?: Mark[];
|
|
38
|
+
} | {
|
|
39
|
+
type: "mention";
|
|
40
|
+
kind: "person" | "page" | "date";
|
|
41
|
+
id: string;
|
|
42
|
+
label: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: "emoji";
|
|
45
|
+
shortcode: string;
|
|
46
|
+
};
|
|
47
|
+
type Inline = InlineNode[];
|
|
48
|
+
interface BlockBase {
|
|
49
|
+
id: string;
|
|
50
|
+
}
|
|
51
|
+
type CalloutVariant = "info" | "success" | "warning" | "danger" | "neutral";
|
|
52
|
+
interface TaskItem {
|
|
53
|
+
id: string;
|
|
54
|
+
content: Inline;
|
|
55
|
+
checked: boolean;
|
|
56
|
+
children?: TaskItem[];
|
|
57
|
+
}
|
|
58
|
+
interface ListItem {
|
|
59
|
+
id: string;
|
|
60
|
+
content: Inline;
|
|
61
|
+
children?: ListItem[];
|
|
62
|
+
}
|
|
63
|
+
interface TableCell {
|
|
64
|
+
content: Inline;
|
|
65
|
+
colSpan?: number;
|
|
66
|
+
rowSpan?: number;
|
|
67
|
+
header?: boolean;
|
|
68
|
+
}
|
|
69
|
+
type Block = BlockBase & ({
|
|
70
|
+
type: "paragraph";
|
|
71
|
+
content: Inline;
|
|
72
|
+
} | {
|
|
73
|
+
type: "heading";
|
|
74
|
+
level: 1 | 2 | 3 | 4;
|
|
75
|
+
content: Inline;
|
|
76
|
+
} | {
|
|
77
|
+
type: "quote";
|
|
78
|
+
content: Inline;
|
|
79
|
+
} | {
|
|
80
|
+
type: "callout";
|
|
81
|
+
variant: CalloutVariant;
|
|
82
|
+
content: Inline;
|
|
83
|
+
} | {
|
|
84
|
+
type: "toggle";
|
|
85
|
+
summary: Inline;
|
|
86
|
+
children: Block[];
|
|
87
|
+
} | {
|
|
88
|
+
type: "divider";
|
|
89
|
+
} | {
|
|
90
|
+
type: "bulleted-list";
|
|
91
|
+
items: ListItem[];
|
|
92
|
+
} | {
|
|
93
|
+
type: "numbered-list";
|
|
94
|
+
items: ListItem[];
|
|
95
|
+
} | {
|
|
96
|
+
type: "task-list";
|
|
97
|
+
items: TaskItem[];
|
|
98
|
+
} | {
|
|
99
|
+
type: "code";
|
|
100
|
+
language?: string;
|
|
101
|
+
code: string;
|
|
102
|
+
} | {
|
|
103
|
+
type: "equation";
|
|
104
|
+
latex: string;
|
|
105
|
+
} | {
|
|
106
|
+
type: "table";
|
|
107
|
+
headerRow?: boolean;
|
|
108
|
+
headerColumn?: boolean;
|
|
109
|
+
rows: TableCell[][];
|
|
110
|
+
} | {
|
|
111
|
+
type: "image";
|
|
112
|
+
src: string;
|
|
113
|
+
alt: string;
|
|
114
|
+
caption?: Inline;
|
|
115
|
+
align?: "start" | "center" | "end";
|
|
116
|
+
width?: number;
|
|
117
|
+
} | {
|
|
118
|
+
type: "video" | "audio";
|
|
119
|
+
src: string;
|
|
120
|
+
caption?: Inline;
|
|
121
|
+
} | {
|
|
122
|
+
type: "file";
|
|
123
|
+
src: string;
|
|
124
|
+
name: string;
|
|
125
|
+
size?: number;
|
|
126
|
+
} | {
|
|
127
|
+
type: "bookmark";
|
|
128
|
+
url: string;
|
|
129
|
+
title?: string;
|
|
130
|
+
description?: string;
|
|
131
|
+
} | {
|
|
132
|
+
type: "columns";
|
|
133
|
+
columns: Block[][];
|
|
134
|
+
} | {
|
|
135
|
+
type: "page-break";
|
|
136
|
+
} | {
|
|
137
|
+
type: "table-of-contents";
|
|
138
|
+
} | {
|
|
139
|
+
type: "chart";
|
|
140
|
+
spec: ChartSpec;
|
|
141
|
+
} | {
|
|
142
|
+
type: "diagram";
|
|
143
|
+
engine: "mermaid" | "canvas" | "excalidraw";
|
|
144
|
+
diagram?: DiagramDocument;
|
|
145
|
+
source?: string;
|
|
146
|
+
} | {
|
|
147
|
+
type: "data-view";
|
|
148
|
+
dataset: string;
|
|
149
|
+
view: SavedView;
|
|
150
|
+
} | {
|
|
151
|
+
type: "ai";
|
|
152
|
+
prompt: string;
|
|
153
|
+
result?: Block[];
|
|
154
|
+
});
|
|
155
|
+
type BlockType = Block["type"];
|
|
156
|
+
interface EditorDocument {
|
|
157
|
+
version: typeof DOCUMENT_VERSION;
|
|
158
|
+
title?: string;
|
|
159
|
+
blocks: Block[];
|
|
160
|
+
}
|
|
161
|
+
/** An empty document with one empty paragraph. */
|
|
162
|
+
declare function createEmptyDocument(id?: string): EditorDocument;
|
|
163
|
+
/**
|
|
164
|
+
* Shared document model behind a provider interface (Yjs and Hocuspocus
|
|
165
|
+
* planned). This version ships the contract only: there is no presence or
|
|
166
|
+
* cursor implementation.
|
|
167
|
+
*/
|
|
168
|
+
interface CollaborationProvider {
|
|
169
|
+
connect(documentId: string): Promise<void>;
|
|
170
|
+
disconnect(): void;
|
|
171
|
+
onPresence(listener: (users: Array<{
|
|
172
|
+
id: string;
|
|
173
|
+
name: string;
|
|
174
|
+
color: string;
|
|
175
|
+
}>) => void): () => void;
|
|
176
|
+
}
|
|
177
|
+
type AiCommand = "continue" | "summarize" | "rewrite" | "fix-grammar";
|
|
178
|
+
/** Provider-agnostic hook. The kit calls no model by itself. */
|
|
179
|
+
interface AiProvider {
|
|
180
|
+
run(input: {
|
|
181
|
+
command: AiCommand;
|
|
182
|
+
selection: string;
|
|
183
|
+
/** For `rewrite`, for example "formal". */
|
|
184
|
+
tone?: string;
|
|
185
|
+
signal?: AbortSignal;
|
|
186
|
+
}): AsyncIterable<string>;
|
|
187
|
+
}
|
|
188
|
+
/** Every block type the schema knows, in the order the slash menu groups them. */
|
|
189
|
+
declare const BLOCK_TYPES: readonly ["paragraph", "heading", "quote", "callout", "toggle", "divider", "bulleted-list", "numbered-list", "task-list", "code", "equation", "table", "image", "video", "audio", "file", "bookmark", "columns", "page-break", "table-of-contents", "chart", "diagram", "data-view", "ai"];
|
|
190
|
+
/** Every mark type the schema knows, in canonical (nesting) order. */
|
|
191
|
+
declare const MARK_TYPES: readonly ["bold", "italic", "underline", "strike", "code", "link", "color", "highlight"];
|
|
192
|
+
declare const CALLOUT_VARIANTS: readonly ["info", "success", "warning", "danger", "neutral"];
|
|
193
|
+
/** True when `type` names a block this version of the schema understands. */
|
|
194
|
+
declare function isKnownBlockType(type: unknown): type is BlockType;
|
|
195
|
+
/** Creates an empty paragraph block. */
|
|
196
|
+
declare function createParagraph(id: string, text?: string): Extract<Block, {
|
|
197
|
+
type: "paragraph";
|
|
198
|
+
}>;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Plain Tiptap / ProseMirror JSON shapes. The converters work on these, so the
|
|
202
|
+
* root entry needs no engine import and runs on the server.
|
|
203
|
+
*/
|
|
204
|
+
interface TiptapMark {
|
|
205
|
+
type: string;
|
|
206
|
+
attrs?: Record<string, unknown>;
|
|
207
|
+
}
|
|
208
|
+
interface TiptapNode {
|
|
209
|
+
type: string;
|
|
210
|
+
attrs?: Record<string, unknown>;
|
|
211
|
+
content?: TiptapNode[];
|
|
212
|
+
marks?: TiptapMark[];
|
|
213
|
+
text?: string;
|
|
214
|
+
}
|
|
215
|
+
interface TiptapDoc extends TiptapNode {
|
|
216
|
+
type: "doc";
|
|
217
|
+
content: TiptapNode[];
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Node and mark names of the editor schema. The React entry registers
|
|
221
|
+
* extensions with exactly these names; the converters emit and read them.
|
|
222
|
+
*/
|
|
223
|
+
declare const TIPTAP_NODES: {
|
|
224
|
+
readonly doc: "doc";
|
|
225
|
+
readonly text: "text";
|
|
226
|
+
readonly paragraph: "paragraph";
|
|
227
|
+
readonly heading: "heading";
|
|
228
|
+
readonly blockquote: "blockquote";
|
|
229
|
+
readonly callout: "callout";
|
|
230
|
+
readonly toggle: "toggle";
|
|
231
|
+
readonly toggleSummary: "toggleSummary";
|
|
232
|
+
readonly horizontalRule: "horizontalRule";
|
|
233
|
+
readonly bulletList: "bulletList";
|
|
234
|
+
readonly orderedList: "orderedList";
|
|
235
|
+
readonly listItem: "listItem";
|
|
236
|
+
readonly taskList: "taskList";
|
|
237
|
+
readonly taskItem: "taskItem";
|
|
238
|
+
readonly codeBlock: "codeBlock";
|
|
239
|
+
readonly equation: "equation";
|
|
240
|
+
readonly table: "table";
|
|
241
|
+
readonly tableRow: "tableRow";
|
|
242
|
+
readonly tableCell: "tableCell";
|
|
243
|
+
readonly tableHeader: "tableHeader";
|
|
244
|
+
readonly image: "image";
|
|
245
|
+
readonly media: "media";
|
|
246
|
+
readonly file: "file";
|
|
247
|
+
readonly bookmark: "bookmark";
|
|
248
|
+
readonly columns: "columns";
|
|
249
|
+
readonly column: "column";
|
|
250
|
+
readonly pageBreak: "pageBreak";
|
|
251
|
+
readonly tableOfContents: "tableOfContents";
|
|
252
|
+
readonly chart: "chart";
|
|
253
|
+
readonly diagram: "diagram";
|
|
254
|
+
readonly dataView: "dataView";
|
|
255
|
+
readonly aiBlock: "aiBlock";
|
|
256
|
+
readonly unknownBlock: "unknownBlock";
|
|
257
|
+
readonly hardBreak: "hardBreak";
|
|
258
|
+
readonly mention: "mention";
|
|
259
|
+
readonly emoji: "emoji";
|
|
260
|
+
};
|
|
261
|
+
type TiptapNodeName = (typeof TIPTAP_NODES)[keyof typeof TIPTAP_NODES];
|
|
262
|
+
declare const TIPTAP_MARKS: {
|
|
263
|
+
readonly bold: "bold";
|
|
264
|
+
readonly italic: "italic";
|
|
265
|
+
readonly underline: "underline";
|
|
266
|
+
readonly strike: "strike";
|
|
267
|
+
readonly code: "code";
|
|
268
|
+
readonly link: "link";
|
|
269
|
+
readonly color: "color";
|
|
270
|
+
readonly highlight: "highlight";
|
|
271
|
+
};
|
|
272
|
+
/** Nodes that carry a block id attribute in the editor schema. */
|
|
273
|
+
declare const BLOCK_ID_NODES: readonly string[];
|
|
274
|
+
|
|
275
|
+
type ConversionWarningCode = "unknown-block" | "unknown-node" | "unknown-mark" | "unknown-inline" | "invalid-mark" | "invalid-value" | "duplicate-id" | "lossy";
|
|
276
|
+
interface ConversionWarning {
|
|
277
|
+
code: ConversionWarningCode;
|
|
278
|
+
message: string;
|
|
279
|
+
/** Id of the block the warning is about, when known. */
|
|
280
|
+
blockId?: string;
|
|
281
|
+
/** Block type or node name the warning is about. */
|
|
282
|
+
nodeType?: string;
|
|
283
|
+
}
|
|
284
|
+
interface ConvertOptions {
|
|
285
|
+
/** Receives warnings (unknown blocks and marks, lossy structures). */
|
|
286
|
+
warnings?: ConversionWarning[];
|
|
287
|
+
/** Creates ids for blocks that have none. Defaults to `generateBlockId`. */
|
|
288
|
+
generateId?: () => string;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Rewrites inline content into canonical form: no empty text, adjacent text
|
|
292
|
+
* with equal marks merged, marks sorted and de-duplicated.
|
|
293
|
+
*/
|
|
294
|
+
declare function normalizeInline(inline: Inline | undefined): Inline;
|
|
295
|
+
/**
|
|
296
|
+
* Converts a stored document into Tiptap / ProseMirror JSON, ready for
|
|
297
|
+
* `editor.commands.setContent`. Blocks of an unknown type become `unknownBlock`
|
|
298
|
+
* atoms and add an `"unknown-block"` warning.
|
|
299
|
+
*/
|
|
300
|
+
declare function documentToTiptap(doc: EditorDocument, options?: ConvertOptions): TiptapDoc;
|
|
301
|
+
/**
|
|
302
|
+
* Converts Tiptap / ProseMirror JSON (for example from `editor.getJSON()`)
|
|
303
|
+
* back into a stored document. Ids are kept; blocks without one get a new id.
|
|
304
|
+
*/
|
|
305
|
+
declare function tiptapToDocument(json: TiptapNode, options?: ConvertOptions): EditorDocument;
|
|
306
|
+
/**
|
|
307
|
+
* Rewrites a document into canonical form (see the list at the top of this
|
|
308
|
+
* file). A document that is already canonical comes back deep-equal.
|
|
309
|
+
*/
|
|
310
|
+
declare function normalizeDocument(doc: EditorDocument, options?: ConvertOptions): EditorDocument;
|
|
311
|
+
|
|
312
|
+
interface OutlineItem {
|
|
313
|
+
/** Id of the heading block. */
|
|
314
|
+
id: string;
|
|
315
|
+
level: 1 | 2 | 3 | 4;
|
|
316
|
+
text: string;
|
|
317
|
+
}
|
|
318
|
+
interface OutlineNode extends OutlineItem {
|
|
319
|
+
children: OutlineNode[];
|
|
320
|
+
}
|
|
321
|
+
interface OutlineOptions {
|
|
322
|
+
/** Keep headings with no text. Defaults to false. */
|
|
323
|
+
includeEmpty?: boolean;
|
|
324
|
+
/** Deepest heading level to include (1 to 4). Defaults to 4. */
|
|
325
|
+
maxLevel?: 1 | 2 | 3 | 4;
|
|
326
|
+
}
|
|
327
|
+
/** Headings in document order. */
|
|
328
|
+
declare function getOutline(doc: EditorDocument, options?: OutlineOptions): OutlineItem[];
|
|
329
|
+
/**
|
|
330
|
+
* Nests a flat outline by level. A heading becomes a child of the nearest
|
|
331
|
+
* previous heading with a lower level; skipped levels (an H3 straight after
|
|
332
|
+
* an H1) nest under the closest ancestor.
|
|
333
|
+
*/
|
|
334
|
+
declare function buildOutlineTree(items: readonly OutlineItem[]): OutlineNode[];
|
|
335
|
+
/** A URL-safe, Unicode-aware slug: `Héllo Wörld` becomes `héllo-wörld`; Hebrew and Arabic letters stay. */
|
|
336
|
+
declare function slugifyHeading(text: string): string;
|
|
337
|
+
|
|
338
|
+
export { CALLOUT_VARIANTS as C, DOCUMENT_VERSION as D, isKnownBlockType as F, normalizeDocument as G, normalizeInline as H, slugifyHeading as J, tiptapToDocument as K, MARK_TYPES as M, TIPTAP_MARKS as T, BLOCK_ID_NODES as b, BLOCK_TYPES as c, TIPTAP_NODES as o, buildOutlineTree as v, createEmptyDocument as w, createParagraph as x, documentToTiptap as y, getOutline as z };
|
|
339
|
+
export type { AiCommand as A, Block as B, EditorDocument as E, Inline as I, ListItem as L, OutlineItem as O, AiProvider as a, BlockBase as d, BlockType as e, CalloutVariant as f, CollaborationProvider as g, ConversionWarning as h, ConversionWarningCode as i, ConvertOptions as j, InlineNode as k, Mark as l, OutlineNode as m, OutlineOptions as n, TableCell as p, TaskItem as q, TiptapDoc as r, TiptapMark as s, TiptapNode as t, TiptapNodeName as u };
|