@moraya/core 0.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/CHANGELOG.md +344 -0
- package/LICENSE +85 -0
- package/README.md +82 -0
- package/dist/adapters/browser-media-resolver.d.ts +21 -0
- package/dist/adapters/browser-media-resolver.js +24 -0
- package/dist/adapters/browser-media-resolver.js.map +1 -0
- package/dist/commands.d.ts +35 -0
- package/dist/commands.js +976 -0
- package/dist/commands.js.map +1 -0
- package/dist/doc-cache.d.ts +29 -0
- package/dist/doc-cache.js +50 -0
- package/dist/doc-cache.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +4534 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +46 -0
- package/dist/markdown.js +1553 -0
- package/dist/markdown.js.map +1 -0
- package/dist/plugins/code-block-view.d.ts +52 -0
- package/dist/plugins/code-block-view.js +686 -0
- package/dist/plugins/code-block-view.js.map +1 -0
- package/dist/plugins/cursor-syntax.d.ts +27 -0
- package/dist/plugins/cursor-syntax.js +122 -0
- package/dist/plugins/cursor-syntax.js.map +1 -0
- package/dist/plugins/definition-list.d.ts +23 -0
- package/dist/plugins/definition-list.js +12 -0
- package/dist/plugins/definition-list.js.map +1 -0
- package/dist/plugins/editor-props-plugin.d.ts +36 -0
- package/dist/plugins/editor-props-plugin.js +1963 -0
- package/dist/plugins/editor-props-plugin.js.map +1 -0
- package/dist/plugins/emoji.d.ts +21 -0
- package/dist/plugins/emoji.js +42 -0
- package/dist/plugins/emoji.js.map +1 -0
- package/dist/plugins/enter-handler.d.ts +26 -0
- package/dist/plugins/enter-handler.js +193 -0
- package/dist/plugins/enter-handler.js.map +1 -0
- package/dist/plugins/highlight.d.ts +39 -0
- package/dist/plugins/highlight.js +283 -0
- package/dist/plugins/highlight.js.map +1 -0
- package/dist/plugins/inline-code-convert.d.ts +32 -0
- package/dist/plugins/inline-code-convert.js +173 -0
- package/dist/plugins/inline-code-convert.js.map +1 -0
- package/dist/plugins/link-text-plugin.d.ts +22 -0
- package/dist/plugins/link-text-plugin.js +194 -0
- package/dist/plugins/link-text-plugin.js.map +1 -0
- package/dist/plugins/mermaid-renderer.d.ts +24 -0
- package/dist/plugins/mermaid-renderer.js +80 -0
- package/dist/plugins/mermaid-renderer.js.map +1 -0
- package/dist/schema.d.ts +48 -0
- package/dist/schema.js +847 -0
- package/dist/schema.js.map +1 -0
- package/dist/setup.d.ts +104 -0
- package/dist/setup.js +4393 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +121 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/highlight.ts","../src/plugins/emoji.ts","../src/plugins/mermaid-renderer.ts","../src/plugins/code-block-view.ts","../src/setup.ts","../src/schema.ts","../src/types.ts","../src/markdown.ts","../src/commands.ts","../src/plugins/definition-list.ts","../src/plugins/enter-handler.ts","../src/plugins/cursor-syntax.ts","../src/plugins/link-text-plugin.ts","../src/plugins/inline-code-convert.ts","../src/plugins/editor-props-plugin.ts","../src/doc-cache.ts"],"sourcesContent":["/**\n * Syntax highlighting plugin for `code_block` nodes.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/plugins/highlight.ts`\n * (replaces the prior no-op stub). Applies ProseMirror Decoration spans with\n * `hljs-*` CSS classes. Schema-agnostic via `state.schema` lookups.\n *\n * Performance contract (Moraya CLAUDE.md \"Performance Coding Standards\" §6):\n * - Per-block cache keyed by `(language, code)` — switching back to a\n * previously highlighted file skips all hljs calls.\n * - On doc change: cheap `decorationSet.map(tr.mapping)` keeps positions in\n * sync without re-highlighting (no hljs calls in the hot path).\n * - After 300 ms idle: full re-highlight via metadata-only transaction,\n * re-using the per-block cache where possible.\n * - File-switch path (`tr.getMeta('file-switch')`): rebuild from scratch.\n * - Full-delete path (`tr.getMeta('full-delete')`): rebuild on the tiny doc.\n *\n * Tier 1 lazy load: this module bundles hljs + 39 language definitions\n * (~250 KB minified). It is loaded via `dynamic import()` so it forms a\n * separate Vite/Rollup chunk and only ships to consumers that actually use\n * code blocks.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, type EditorView } from 'prosemirror-view'\nimport type { Node as PmNode } from 'prosemirror-model'\nimport hljs from 'highlight.js/lib/core'\n\n// Common languages\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport python from 'highlight.js/lib/languages/python'\nimport rust from 'highlight.js/lib/languages/rust'\nimport css from 'highlight.js/lib/languages/css'\nimport xml from 'highlight.js/lib/languages/xml'\nimport json from 'highlight.js/lib/languages/json'\nimport bash from 'highlight.js/lib/languages/bash'\nimport sql from 'highlight.js/lib/languages/sql'\nimport java from 'highlight.js/lib/languages/java'\nimport cpp from 'highlight.js/lib/languages/cpp'\nimport c from 'highlight.js/lib/languages/c'\nimport go from 'highlight.js/lib/languages/go'\nimport ruby from 'highlight.js/lib/languages/ruby'\nimport php from 'highlight.js/lib/languages/php'\nimport swift from 'highlight.js/lib/languages/swift'\nimport kotlin from 'highlight.js/lib/languages/kotlin'\nimport yaml from 'highlight.js/lib/languages/yaml'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport diff from 'highlight.js/lib/languages/diff'\nimport lua from 'highlight.js/lib/languages/lua'\nimport scss from 'highlight.js/lib/languages/scss'\nimport csharp from 'highlight.js/lib/languages/csharp'\nimport dart from 'highlight.js/lib/languages/dart'\nimport r from 'highlight.js/lib/languages/r'\nimport perl from 'highlight.js/lib/languages/perl'\nimport scala from 'highlight.js/lib/languages/scala'\nimport objectivec from 'highlight.js/lib/languages/objectivec'\nimport dockerfile from 'highlight.js/lib/languages/dockerfile'\nimport ini from 'highlight.js/lib/languages/ini'\nimport powershell from 'highlight.js/lib/languages/powershell'\nimport makefile from 'highlight.js/lib/languages/makefile'\nimport groovy from 'highlight.js/lib/languages/groovy'\nimport elixir from 'highlight.js/lib/languages/elixir'\nimport haskell from 'highlight.js/lib/languages/haskell'\nimport protobuf from 'highlight.js/lib/languages/protobuf'\nimport graphql from 'highlight.js/lib/languages/graphql'\nimport latex from 'highlight.js/lib/languages/latex'\nimport nginx from 'highlight.js/lib/languages/nginx'\nimport shell from 'highlight.js/lib/languages/shell'\n\n// Register languages (idempotent — no-op on subsequent calls)\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('js', javascript)\nhljs.registerLanguage('typescript', typescript)\nhljs.registerLanguage('ts', typescript)\nhljs.registerLanguage('python', python)\nhljs.registerLanguage('py', python)\nhljs.registerLanguage('rust', rust)\nhljs.registerLanguage('rs', rust)\nhljs.registerLanguage('css', css)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('xml', xml)\nhljs.registerLanguage('json', json)\nhljs.registerLanguage('bash', bash)\nhljs.registerLanguage('sh', bash)\nhljs.registerLanguage('sql', sql)\nhljs.registerLanguage('java', java)\nhljs.registerLanguage('cpp', cpp)\nhljs.registerLanguage('c', c)\nhljs.registerLanguage('go', go)\nhljs.registerLanguage('ruby', ruby)\nhljs.registerLanguage('rb', ruby)\nhljs.registerLanguage('php', php)\nhljs.registerLanguage('swift', swift)\nhljs.registerLanguage('kotlin', kotlin)\nhljs.registerLanguage('kt', kotlin)\nhljs.registerLanguage('yaml', yaml)\nhljs.registerLanguage('yml', yaml)\nhljs.registerLanguage('markdown', markdown)\nhljs.registerLanguage('md', markdown)\nhljs.registerLanguage('diff', diff)\nhljs.registerLanguage('lua', lua)\nhljs.registerLanguage('scss', scss)\nhljs.registerLanguage('svelte', xml)\nhljs.registerLanguage('jsx', javascript)\nhljs.registerLanguage('tsx', typescript)\n\nhljs.registerLanguage('csharp', csharp)\nhljs.registerLanguage('cs', csharp)\nhljs.registerLanguage('dart', dart)\nhljs.registerLanguage('r', r)\nhljs.registerLanguage('perl', perl)\nhljs.registerLanguage('pl', perl)\nhljs.registerLanguage('scala', scala)\nhljs.registerLanguage('objectivec', objectivec)\nhljs.registerLanguage('objc', objectivec)\nhljs.registerLanguage('dockerfile', dockerfile)\nhljs.registerLanguage('docker', dockerfile)\nhljs.registerLanguage('ini', ini)\nhljs.registerLanguage('toml', ini)\nhljs.registerLanguage('powershell', powershell)\nhljs.registerLanguage('ps', powershell)\nhljs.registerLanguage('ps1', powershell)\nhljs.registerLanguage('makefile', makefile)\nhljs.registerLanguage('make', makefile)\nhljs.registerLanguage('groovy', groovy)\nhljs.registerLanguage('elixir', elixir)\nhljs.registerLanguage('ex', elixir)\nhljs.registerLanguage('haskell', haskell)\nhljs.registerLanguage('hs', haskell)\nhljs.registerLanguage('protobuf', protobuf)\nhljs.registerLanguage('proto', protobuf)\nhljs.registerLanguage('graphql', graphql)\nhljs.registerLanguage('gql', graphql)\nhljs.registerLanguage('latex', latex)\nhljs.registerLanguage('tex', latex)\nhljs.registerLanguage('nginx', nginx)\nhljs.registerLanguage('nginxconf', nginx)\nhljs.registerLanguage('shell', shell)\n\nconst highlightPluginKey = new PluginKey('moraya-syntax-highlight')\n\ninterface HljsNode {\n scope?: string\n children?: (HljsNode | string)[]\n}\n\n/**\n * Convert an hljs scope string to CSS class names.\n * \"keyword\" → [\"hljs-keyword\"]\n * \"title.function\" → [\"hljs-title\", \"function_\"]\n */\nfunction scopeToClasses(scope: string): string[] {\n const parts = scope.split('.')\n const classes = [`hljs-${parts[0]}`]\n for (let i = 1; i < parts.length; i++) {\n classes.push(`${parts[i]}_`)\n }\n return classes\n}\n\n/**\n * Flatten the hljs emitter tree into a list of {text, classes} spans.\n */\nfunction flattenHljsTree(\n nodes: (HljsNode | string)[],\n parentClasses: string[] = [],\n): { text: string; classes: string[] }[] {\n const result: { text: string; classes: string[] }[] = []\n\n for (const node of nodes) {\n if (typeof node === 'string') {\n if (node.length > 0) {\n result.push({ text: node, classes: parentClasses })\n }\n } else {\n // hljs v11 uses `scope` (e.g. \"keyword\", \"title.function\").\n // Dotted scopes become multiple classes.\n const classes = node.scope\n ? [...parentClasses, ...scopeToClasses(node.scope)]\n : parentClasses\n if (node.children) {\n result.push(...flattenHljsTree(node.children, classes))\n }\n }\n }\n\n return result\n}\n\n// ── Per-block hljs result cache ────────────────────────────────\n// Caches the relative-offset spans for each (language, code) pair so that\n// switching back to a previously-highlighted file skips all hljs calls.\n// FIFO eviction at 100 entries.\n\ninterface CachedSpan {\n relOffset: number\n length: number\n classes: string\n}\n\nconst HLJS_CACHE_MAX = 100\nconst hljsCache = new Map<string, CachedSpan[]>()\n\nfunction hljsCacheKey(language: string, code: string): string {\n return language + '\\0' + code\n}\n\n/**\n * Build ProseMirror decorations for all `code_block` nodes in `doc`.\n */\nfunction getDecorations(doc: PmNode): DecorationSet {\n const decorations: Decoration[] = []\n\n doc.descendants((node, pos) => {\n if (node.type.name !== 'code_block') return\n\n const language = (node.attrs.language as string) || ''\n const code = node.textContent\n\n if (!code) return\n if (!language) return // No language label: skip (avoid expensive highlightAuto)\n if (!hljs.getLanguage(language)) return // Unrecognized language\n\n const cKey = hljsCacheKey(language, code)\n const blockStart = pos + 1 // code content starts after opening tag\n\n // Per-block cache hit\n const cachedSpans = hljsCache.get(cKey)\n if (cachedSpans) {\n for (const span of cachedSpans) {\n const from = blockStart + span.relOffset\n const to = from + span.length\n if (from < to) {\n decorations.push(Decoration.inline(from, to, { class: span.classes }))\n }\n }\n return\n }\n\n // Cache miss — run hljs\n let result\n try {\n result = hljs.highlight(code, { language, ignoreIllegals: true })\n } catch {\n return\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const emitter = result as any\n const rootNode = emitter._emitter?.rootNode ?? emitter._emitter?.root\n if (!rootNode?.children) return\n\n const spans = flattenHljsTree(rootNode.children)\n\n // Build relative-offset spans for caching + absolute decorations\n const toCache: CachedSpan[] = []\n let offset = 0\n\n for (const span of spans) {\n const relOffset = offset\n const length = span.text.length\n offset += length\n\n if (span.classes.length > 0 && length > 0) {\n const classes = span.classes.join(' ')\n toCache.push({ relOffset, length, classes })\n decorations.push(\n Decoration.inline(blockStart + relOffset, blockStart + relOffset + length, { class: classes }),\n )\n }\n }\n\n // Store in cache (FIFO eviction)\n if (hljsCache.size >= HLJS_CACHE_MAX) {\n const oldest = hljsCache.keys().next().value\n if (oldest !== undefined) hljsCache.delete(oldest)\n }\n hljsCache.set(cKey, toCache)\n })\n\n return DecorationSet.create(doc, decorations)\n}\n\n/**\n * Plugin that adds syntax highlighting to code blocks.\n *\n * highlight.js is expensive (especially `highlightAuto` which tests all\n * registered languages). Strategy:\n * 1. On doc change: cheaply map existing decorations through the transaction\n * (adjust positions for inserts/deletes — no hljs calls).\n * 2. After 300 ms idle: run a full re-highlight and dispatch a metadata-only\n * transaction to flush new decorations into the view.\n * 3. File-switch / full-delete metas: rebuild from scratch.\n */\nexport function createHighlightPlugin(): Plugin {\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n let needsRefresh = false\n let currentView: EditorView | null = null\n\n return new Plugin({\n key: highlightPluginKey,\n state: {\n init(_, state) {\n return getDecorations(state.doc)\n },\n apply(tr, decorationSet, _oldState, newState) {\n if (!tr.docChanged) {\n // Non-doc transaction: if a debounced refresh completed, apply it now.\n if (needsRefresh) {\n needsRefresh = false\n return getDecorations(newState.doc)\n }\n return decorationSet\n }\n\n // File switch: rebuild from scratch\n if (tr.getMeta('file-switch')) {\n if (debounceTimer !== null) { clearTimeout(debounceTimer); debounceTimer = null }\n return getDecorations(newState.doc)\n }\n\n // Full-delete: new doc is tiny (single empty paragraph)\n if (tr.getMeta('full-delete')) {\n if (debounceTimer !== null) { clearTimeout(debounceTimer); debounceTimer = null }\n needsRefresh = false\n return getDecorations(newState.doc)\n }\n\n // Map existing decorations cheaply through the transaction\n const mapped = decorationSet.map(tr.mapping, newState.doc)\n\n // Short-circuit: skip 300ms debounce + hljs re-parse if no code_block touched.\n let affectsCodeBlock = false\n const docSize = newState.doc.content.size\n tr.mapping.maps.forEach((stepMap) => {\n if (affectsCodeBlock) return\n stepMap.forEach((from, to) => {\n if (affectsCodeBlock) return\n newState.doc.nodesBetween(\n Math.max(0, from),\n Math.min(to, docSize),\n (node) => {\n if (node.type.name === 'code_block') affectsCodeBlock = true\n return !affectsCodeBlock\n },\n )\n })\n })\n\n if (!affectsCodeBlock) return mapped\n\n // Schedule a full re-highlight after typing pause\n if (debounceTimer !== null) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n needsRefresh = true\n // Dispatch a metadata-only transaction to trigger apply() which will\n // detect needsRefresh and rebuild decorations from scratch.\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (currentView && !(currentView as any).isDestroyed) {\n currentView.dispatch(currentView.state.tr.setMeta('highlight-refresh', true))\n }\n } catch { /* view may be destroyed */ }\n }, 300)\n\n return mapped\n },\n },\n props: {\n decorations(state) {\n return this.getState(state)\n },\n },\n view(editorView) {\n currentView = editorView\n return {\n destroy() {\n currentView = null\n if (debounceTimer !== null) {\n clearTimeout(debounceTimer)\n debounceTimer = null\n }\n },\n }\n },\n })\n}\n","/**\n * Lightweight emoji plugin.\n *\n * Converts emoji shortcodes like `:smile:` → 😄 using `node-emoji`.\n * Uses system native emoji rendering (no twemoji images).\n *\n * - Typing `:smile:` auto-converts to 😄 when the closing `:` is typed.\n *\n * `node-emoji` is declared as a peer dep so consumers control its version.\n * The conversion is purely textual via `view.state.schema.text(emoji)` so the\n * plugin works against any consumer-injected schema.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport { get as getEmoji } from 'node-emoji'\n\nconst emojiPluginKey = new PluginKey('moraya-emoji')\n\n/**\n * ProseMirror plugin that converts `:shortcode:` to native emoji on typing.\n */\nexport function createEmojiPlugin(): Plugin {\n return new Plugin({\n key: emojiPluginKey,\n props: {\n handleTextInput(view, from, to, text) {\n // Only trigger when user types \":\"\n if (text !== ':') return false\n\n const { state } = view\n const $pos = state.doc.resolve(from)\n // Get text content of the current text block up to cursor\n const textBefore = $pos.parent.textBetween(\n 0,\n $pos.parentOffset,\n undefined,\n '',\n )\n\n // Find the last unmatched \":\" before cursor\n const lastColon = textBefore.lastIndexOf(':')\n if (lastColon === -1) return false\n\n // Extract potential shortcode name between the two colons\n const shortcode = textBefore.slice(lastColon + 1)\n\n // Validate: must be non-empty and contain only valid chars\n if (!shortcode || !/^[a-zA-Z0-9_+-]+$/.test(shortcode)) return false\n\n const emoji = getEmoji(shortcode)\n if (!emoji) return false\n\n // Calculate absolute positions\n // The opening \":\" is at: from - (textBefore.length - lastColon)\n const openColonOffset = textBefore.length - lastColon\n const replaceFrom = from - openColonOffset\n\n // Replace `:shortcode:` (including the just-typed closing `:`) with emoji\n const tr = state.tr.replaceWith(\n replaceFrom,\n to, // `to` is where the closing \":\" would be inserted\n state.schema.text(emoji),\n )\n view.dispatch(tr)\n return true\n },\n },\n })\n}\n","/**\n * Mermaid renderer — lazy-loads the mermaid library and provides a render API.\n *\n * This is a utility module imported on-demand by `code-block-view.ts`,\n * NOT itself a ProseMirror plugin. The mermaid library (~2.4 MB) is loaded\n * only when the first mermaid code block is encountered, via dynamic\n * `import('mermaid')`. Consumers that want mermaid support must install\n * `mermaid` as a peer dependency.\n *\n * IMPORTANT: `mermaid.render()` manipulates global DOM state and is NOT safe\n * to call concurrently. All renders go through a serial queue.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet mermaidModule: any = null\nlet loadingPromise: Promise<void> | null = null\nlet renderCounter = 0\n\n// ── Serial render queue ──────────────────────────\n// Mermaid.render() creates a temp SVG in the DOM, measures text, then removes\n// it. If two renders overlap, the second corrupts the first's temp element,\n// causing \"Render failed\". This queue ensures only one render runs at a time.\nlet renderQueue: Promise<void> = Promise.resolve()\n\nfunction isDark(): boolean {\n if (typeof document === 'undefined') return false\n const dt = document.documentElement.getAttribute('data-theme')\n if (dt === 'dark') return true\n if (dt === 'light') return false\n if (typeof window === 'undefined' || !window.matchMedia) return false\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n}\n\n/** Read resolved CSS custom property values from :root */\nfunction resolveThemeColors() {\n if (typeof document === 'undefined' || typeof getComputedStyle === 'undefined') {\n return {\n primaryColor: '#4a90d9',\n primaryTextColor: '#333',\n primaryBorderColor: '#ccc',\n lineColor: '#666',\n secondaryColor: '#f5f5f5',\n tertiaryColor: '#eee',\n }\n }\n const s = getComputedStyle(document.documentElement)\n return {\n primaryColor: s.getPropertyValue('--accent-color').trim() || '#4a90d9',\n primaryTextColor: s.getPropertyValue('--text-primary').trim() || '#333',\n primaryBorderColor: s.getPropertyValue('--border-color').trim() || '#ccc',\n lineColor: s.getPropertyValue('--text-secondary').trim() || '#666',\n secondaryColor: s.getPropertyValue('--bg-secondary').trim() || '#f5f5f5',\n tertiaryColor: s.getPropertyValue('--bg-hover').trim() || '#eee',\n }\n}\n\nexport async function ensureMermaidLoaded(): Promise<void> {\n if (mermaidModule) return\n if (loadingPromise) return loadingPromise\n\n loadingPromise = (async () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mod: any = await import(/* @vite-ignore */ 'mermaid')\n mermaidModule = mod.default\n mermaidModule.initialize({\n startOnLoad: false,\n theme: isDark() ? 'dark' : 'default',\n themeVariables: resolveThemeColors(),\n })\n })()\n\n return loadingPromise\n}\n\nexport async function renderMermaid(\n code: string,\n): Promise<{ svg: string } | { error: string }> {\n await ensureMermaidLoaded()\n\n // Enqueue: wait for previous render to finish before starting this one\n const result = new Promise<{ svg: string } | { error: string }>((resolve) => {\n renderQueue = renderQueue.then(async () => {\n const id = `mermaid-${++renderCounter}`\n try {\n const { svg } = await mermaidModule.render(id, code)\n resolve({ svg })\n } catch (e) {\n resolve({ error: e instanceof Error ? e.message : 'Render failed' })\n }\n })\n })\n\n return result\n}\n\n/**\n * Re-initialize mermaid with updated theme. Called when theme changes.\n */\nexport function updateMermaidTheme(): void {\n if (!mermaidModule) return\n mermaidModule.initialize({\n startOnLoad: false,\n theme: isDark() ? 'dark' : 'default',\n themeVariables: resolveThemeColors(),\n })\n}\n","/**\n * CodeBlock NodeView — toolbar with language label, language picker, copy button,\n * mermaid preview, and renderer-plugin preview.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/plugins/code-block-view.ts`\n * with the following DI changes (v0.60.0-pre §F2.5):\n * - `RENDERER_PLUGINS` / `loadRendererPlugin` / `rendererVersions` (moraya-internal)\n * → `RendererRegistry` injected via factory parameter\n * - `editorStore.getState().currentFilePath` (used by `isFilePathRenderer`)\n * is no longer accessed here; the consumer's RendererRegistry implementation\n * closes over its own platform context and surfaces it via the renderer\n * module's `render(source, container)` call.\n * - mermaid still has a built-in special-case path (`language === 'mermaid'`),\n * using core's `plugins/mermaid-renderer.ts` (which is itself the migrated\n * version of moraya's mermaid-renderer).\n *\n * The render dispose-instance pattern from moraya (CAD viewer etc.) is\n * implemented in core via `RendererPluginModule.destroy(container)` per §3.3:\n * - On render: call `module.render(source, container, options)` (consumer\n * stores any disposable in container or via WeakMap closure).\n * - On lang change / NodeView destroy: call `module.destroy?(container)`.\n */\n\nimport type { Node as PmNode } from 'prosemirror-model'\nimport type { EditorView } from 'prosemirror-view'\nimport type { renderMermaid as RenderFn, updateMermaidTheme as UpdateThemeFn } from './mermaid-renderer'\nimport type { RendererRegistry, RendererPluginModule } from '../types'\n\n// ── Mermaid lazy-load wrapper ─────────────────────\n\ntype MermaidApi = { renderMermaid: typeof RenderFn; updateMermaidTheme: typeof UpdateThemeFn }\nlet mermaidApi: MermaidApi | null = null\nlet mermaidLoading: Promise<MermaidApi | null> | null = null\n\nfunction loadMermaidApi() {\n if (mermaidApi) return Promise.resolve(mermaidApi)\n if (mermaidLoading) return mermaidLoading\n mermaidLoading = import('./mermaid-renderer').then(mod => {\n mermaidApi = mod\n return mermaidApi\n })\n return mermaidLoading\n}\n\n// Theme change listener: re-render all mermaid previews when theme switches\nlet themeObserverInstalled = false\nconst mermaidReRenderCallbacks = new Set<() => void>()\n\nfunction installThemeObserver() {\n if (themeObserverInstalled) return\n themeObserverInstalled = true\n if (typeof document === 'undefined' || typeof MutationObserver === 'undefined') return\n const observer = new MutationObserver(() => {\n if (mermaidApi) mermaidApi.updateMermaidTheme()\n for (const cb of mermaidReRenderCallbacks) cb()\n })\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme'],\n })\n}\n\n// ── Language registry ─────────────────────────────\n\ninterface LanguageEntry {\n id: string // primary id used in node.attrs.language\n label: string // display name\n aliases: string[] // searchable aliases\n}\n\nconst POPULAR_LANGUAGES: LanguageEntry[] = [\n { id: 'javascript', label: 'JavaScript', aliases: ['js'] },\n { id: 'typescript', label: 'TypeScript', aliases: ['ts'] },\n { id: 'python', label: 'Python', aliases: ['py'] },\n { id: 'java', label: 'Java', aliases: [] },\n { id: 'go', label: 'Go', aliases: ['golang'] },\n { id: 'rust', label: 'Rust', aliases: ['rs'] },\n { id: 'c', label: 'C', aliases: [] },\n { id: 'cpp', label: 'C++', aliases: ['c++'] },\n { id: 'ruby', label: 'Ruby', aliases: ['rb'] },\n { id: 'php', label: 'PHP', aliases: [] },\n { id: 'swift', label: 'Swift', aliases: [] },\n { id: 'kotlin', label: 'Kotlin', aliases: ['kt'] },\n { id: 'sql', label: 'SQL', aliases: [] },\n { id: 'bash', label: 'Bash', aliases: ['sh', 'shell'] },\n { id: 'json', label: 'JSON', aliases: [] },\n { id: 'yaml', label: 'YAML', aliases: ['yml'] },\n { id: 'html', label: 'HTML', aliases: ['xml'] },\n { id: 'css', label: 'CSS', aliases: [] },\n { id: 'csharp', label: 'C#', aliases: ['cs'] },\n { id: 'dart', label: 'Dart', aliases: [] },\n { id: 'r', label: 'R', aliases: [] },\n { id: 'dockerfile', label: 'Dockerfile', aliases: ['docker'] },\n { id: 'graphql', label: 'GraphQL', aliases: ['gql'] },\n { id: 'markdown', label: 'Markdown', aliases: ['md'] },\n { id: 'text', label: 'Plain Text', aliases: ['plaintext', 'txt'] },\n { id: 'prompt', label: 'Prompt', aliases: ['image-prompts', 'image-prompt'] },\n { id: 'system', label: 'System Prompt', aliases: ['system-prompt'] },\n]\n\nconst BASE_OTHER_LANGUAGES: LanguageEntry[] = [\n { id: 'scss', label: 'SCSS', aliases: [] },\n { id: 'lua', label: 'Lua', aliases: [] },\n { id: 'diff', label: 'Diff', aliases: [] },\n { id: 'perl', label: 'Perl', aliases: ['pl'] },\n { id: 'scala', label: 'Scala', aliases: [] },\n { id: 'objectivec', label: 'Objective-C', aliases: ['objc'] },\n { id: 'ini', label: 'TOML / INI', aliases: ['toml'] },\n { id: 'powershell', label: 'PowerShell', aliases: ['ps', 'ps1'] },\n { id: 'makefile', label: 'Makefile', aliases: ['make'] },\n { id: 'groovy', label: 'Groovy', aliases: [] },\n { id: 'elixir', label: 'Elixir', aliases: ['ex'] },\n { id: 'haskell', label: 'Haskell', aliases: ['hs'] },\n { id: 'protobuf', label: 'Protobuf', aliases: ['proto'] },\n { id: 'latex', label: 'LaTeX', aliases: ['tex'] },\n { id: 'nginx', label: 'Nginx', aliases: ['nginxconf'] },\n { id: 'shell', label: 'Shell Session', aliases: [] },\n { id: 'mermaid', label: 'Mermaid', aliases: [] },\n]\n\nconst POPULAR_IDS = new Set(POPULAR_LANGUAGES.map(l => l.id))\n\n/** Given a renderer registry, derive the full language lists. */\nfunction buildLanguageLists(registry?: RendererRegistry): {\n popular: LanguageEntry[]\n rendererPlugins: LanguageEntry[]\n all: LanguageEntry[]\n rendererLangIds: Set<string>\n} {\n const rendererLangIds = registry\n ? new Set(Object.keys(registry.versions))\n : new Set<string>()\n const rendererPlugins: LanguageEntry[] = registry\n ? Object.keys(registry.versions).sort().map((id) => ({\n id,\n label: id.charAt(0).toUpperCase() + id.slice(1),\n aliases: [],\n }))\n : []\n const all: LanguageEntry[] = [\n ...POPULAR_LANGUAGES,\n ...BASE_OTHER_LANGUAGES,\n ...rendererPlugins,\n ].sort((a, b) => a.label.localeCompare(b.label))\n return { popular: POPULAR_LANGUAGES, rendererPlugins, all, rendererLangIds }\n}\n\nfunction findLanguageLabel(langId: string, all: LanguageEntry[]): string {\n if (!langId) return 'text'\n const entry = all.find(\n l => l.id === langId || l.aliases.includes(langId),\n )\n return entry ? entry.label : langId\n}\n\n// ── Auto-detect language via highlight.js ─────────\n\nlet hljsAutoDetect: ((code: string) => string | null) | null = null\n\nasync function getAutoDetect(): Promise<(code: string) => string | null> {\n if (hljsAutoDetect) return hljsAutoDetect\n try {\n const hljs = (await import('highlight.js/lib/core')).default\n hljsAutoDetect = (code: string) => {\n if (!code.trim() || code.length < 10) return null\n try {\n const result = hljs.highlightAuto(code)\n if (result.language && result.relevance > 5) {\n return result.language\n }\n } catch { /* ignore */ }\n return null\n }\n } catch {\n hljsAutoDetect = () => null\n }\n return hljsAutoDetect\n}\n\n// ── Language Picker ───────────────────────────────\n\nfunction createLanguagePicker(\n container: HTMLElement,\n anchor: HTMLElement,\n currentLang: string,\n codeContent: string,\n langLists: ReturnType<typeof buildLanguageLists>,\n onSelect: (lang: string) => void,\n onDismiss?: () => void,\n): { destroy: () => void } {\n const { popular, rendererPlugins, all } = langLists\n\n const picker = document.createElement('div')\n picker.className = 'code-lang-picker'\n picker.setAttribute('contenteditable', 'false')\n picker.addEventListener('mousedown', (e) => { e.stopPropagation() })\n picker.addEventListener('click', (e) => { e.stopPropagation() })\n\n const searchWrap = document.createElement('div')\n searchWrap.className = 'code-lang-search'\n const searchInput = document.createElement('input')\n searchInput.type = 'text'\n searchInput.className = 'code-lang-search-input'\n searchInput.placeholder = 'Search language...'\n searchInput.autocomplete = 'off'\n searchInput.setAttribute('autocorrect', 'off')\n searchInput.setAttribute('autocapitalize', 'off')\n searchInput.spellcheck = false\n searchWrap.appendChild(searchInput)\n picker.appendChild(searchWrap)\n\n const listEl = document.createElement('div')\n listEl.className = 'code-lang-list'\n picker.appendChild(listEl)\n\n let detectedLang: string | null = null\n\n function renderList(filter: string) {\n listEl.innerHTML = ''\n const lowerFilter = filter.toLowerCase()\n\n const matchesFilter = (entry: LanguageEntry) => {\n if (!lowerFilter) return true\n return (\n entry.id.includes(lowerFilter) ||\n entry.label.toLowerCase().includes(lowerFilter) ||\n entry.aliases.some(a => a.includes(lowerFilter))\n )\n }\n\n if (detectedLang && !lowerFilter && detectedLang !== currentLang) {\n const label = findLanguageLabel(detectedLang, all)\n const suggestEl = document.createElement('div')\n suggestEl.className = 'code-lang-suggestion'\n suggestEl.innerHTML = `<span class=\"suggestion-icon\">✦</span> ${label} <span class=\"suggestion-hint\">detected</span>`\n suggestEl.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n onSelect(detectedLang!)\n destroy()\n })\n listEl.appendChild(suggestEl)\n\n const divider = document.createElement('div')\n divider.className = 'code-lang-divider'\n listEl.appendChild(divider)\n }\n\n const popularMatches = popular.filter(matchesFilter)\n if (popularMatches.length > 0 && !lowerFilter) {\n const groupLabel = document.createElement('div')\n groupLabel.className = 'code-lang-group-label'\n groupLabel.textContent = 'Popular'\n listEl.appendChild(groupLabel)\n\n for (const lang of popularMatches) {\n listEl.appendChild(createOption(lang))\n }\n\n const rendererIds = new Set(rendererPlugins.map(l => l.id))\n const others = all.filter(\n l => !POPULAR_IDS.has(l.id) && !rendererIds.has(l.id) && matchesFilter(l),\n )\n if (others.length > 0) {\n const divider = document.createElement('div')\n divider.className = 'code-lang-divider'\n listEl.appendChild(divider)\n\n const allLabel = document.createElement('div')\n allLabel.className = 'code-lang-group-label'\n allLabel.textContent = 'All'\n listEl.appendChild(allLabel)\n for (const lang of others) {\n listEl.appendChild(createOption(lang))\n }\n }\n\n const rendererMatches = rendererPlugins.filter(matchesFilter)\n if (rendererMatches.length > 0) {\n const divider2 = document.createElement('div')\n divider2.className = 'code-lang-divider'\n listEl.appendChild(divider2)\n\n const rendererLabel = document.createElement('div')\n rendererLabel.className = 'code-lang-group-label'\n rendererLabel.textContent = 'Renderer Plugins'\n listEl.appendChild(rendererLabel)\n for (const lang of rendererMatches) {\n listEl.appendChild(createOption(lang))\n }\n }\n } else {\n const matches = all.filter(matchesFilter)\n for (const lang of matches) {\n listEl.appendChild(createOption(lang))\n }\n if (matches.length === 0) {\n const empty = document.createElement('div')\n empty.className = 'code-lang-empty'\n empty.textContent = 'No matches'\n listEl.appendChild(empty)\n }\n }\n }\n\n function createOption(lang: LanguageEntry): HTMLElement {\n const option = document.createElement('div')\n option.className = 'code-lang-option'\n if (lang.id === currentLang) option.classList.add('selected')\n option.textContent = lang.label\n option.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n onSelect(lang.id)\n destroy()\n })\n return option\n }\n\n renderList('')\n\n searchInput.addEventListener('input', () => {\n renderList(searchInput.value)\n })\n\n searchInput.addEventListener('keydown', (e) => {\n e.stopPropagation()\n if (e.key === 'Escape') {\n destroy()\n }\n })\n\n // Append OUTSIDE ProseMirror's DOM tree so the editor's domObserver won't\n // detect focus moving to the search input and steal it back.\n const pickerHost = container.closest('.editor-wrapper') ?? document.body\n pickerHost.appendChild(picker)\n\n ;(function positionPicker() {\n const rect = anchor.getBoundingClientRect()\n picker.style.position = 'fixed'\n picker.style.top = `${rect.bottom + 2}px`\n picker.style.left = `${rect.left}px`\n })()\n\n requestAnimationFrame(() => searchInput.focus())\n\n getAutoDetect().then(detect => {\n detectedLang = detect(codeContent)\n if (detectedLang && !searchInput.value) {\n renderList('')\n }\n })\n\n function handleOutsideClick(e: MouseEvent) {\n if (!picker.contains(e.target as Node) && !anchor.contains(e.target as Node)) {\n destroy()\n }\n }\n\n function handleKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n destroy()\n }\n }\n\n setTimeout(() => {\n document.addEventListener('mousedown', handleOutsideClick)\n document.addEventListener('keydown', handleKeydown, true)\n }, 0)\n\n function destroy() {\n document.removeEventListener('mousedown', handleOutsideClick)\n document.removeEventListener('keydown', handleKeydown, true)\n picker.remove()\n onDismiss?.()\n }\n\n return { destroy }\n}\n\n// ── Text escape helper ────────────────────────────\n\nfunction escapeText(str: string): string {\n const d = document.createElement('div')\n d.textContent = str\n return d.innerHTML\n}\n\n// ── Copy button helper ────────────────────────────\n\nfunction handleCopy(btn: HTMLButtonElement, codeEl: HTMLElement) {\n const text = codeEl.textContent || ''\n navigator.clipboard.writeText(text).then(() => {\n btn.classList.add('copied')\n btn.title = 'Copied!'\n setTimeout(() => {\n btn.classList.remove('copied')\n btn.title = 'Copy'\n }, 1500)\n })\n}\n\n// ── NodeView Factory ──────────────────────────────\n\nexport interface CodeBlockNodeViewOptions {\n rendererRegistry?: RendererRegistry\n}\n\n/**\n * NodeView factory builder. Returns the function to pass as\n * `nodeViews: { code_block: <returned> }` in EditorView config.\n *\n * Closes over a `RendererRegistry` so dispatched renderer plugins are\n * looked up via the consumer's injected registry rather than a Moraya-only\n * static map.\n */\nexport function createCodeBlockNodeViewFactory(opts: CodeBlockNodeViewOptions = {}) {\n const { rendererRegistry } = opts\n const langLists = buildLanguageLists(rendererRegistry)\n const { rendererLangIds, all: allLanguages } = langLists\n\n return function createCodeBlockNodeView(\n nodeArg: PmNode,\n view: EditorView,\n getPos: () => number | undefined,\n ) {\n let node = nodeArg\n // ── DOM structure ──\n const wrapper = document.createElement('div')\n wrapper.className = 'code-block-wrapper'\n\n const toolbar = document.createElement('div')\n toolbar.className = 'code-block-toolbar'\n toolbar.setAttribute('contenteditable', 'false')\n\n const langLabel = document.createElement('span')\n langLabel.className = 'code-lang-label'\n langLabel.textContent = findLanguageLabel((node.attrs.language as string) || '', allLanguages)\n langLabel.title = 'Change language'\n\n const toggleBtn = document.createElement('button')\n toggleBtn.className = 'mermaid-toggle-btn'\n toggleBtn.type = 'button'\n\n const copyBtn = document.createElement('button')\n copyBtn.className = 'code-copy-btn'\n copyBtn.title = 'Copy'\n copyBtn.type = 'button'\n copyBtn.innerHTML =\n '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">' +\n '<rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/>' +\n '<path d=\"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1\"/>' +\n '</svg>' +\n '<svg class=\"check-icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">' +\n '<path d=\"M20 6L9 17l-5-5\"/>' +\n '</svg>'\n\n const toolbarRight = document.createElement('div')\n toolbarRight.className = 'code-toolbar-right'\n toolbarRight.appendChild(toggleBtn)\n toolbarRight.appendChild(copyBtn)\n\n toolbar.appendChild(langLabel)\n toolbar.appendChild(toolbarRight)\n\n const pre = document.createElement('pre')\n pre.className = 'code-block-pre'\n const code = document.createElement('code')\n code.className = 'code-block-code'\n pre.appendChild(code)\n\n const mermaidPreview = document.createElement('div')\n mermaidPreview.className = 'mermaid-preview'\n mermaidPreview.setAttribute('contenteditable', 'false')\n mermaidPreview.style.display = 'none'\n\n const rendererPreview = document.createElement('div')\n rendererPreview.className = 'renderer-preview'\n rendererPreview.setAttribute('contenteditable', 'false')\n rendererPreview.style.display = 'none'\n\n wrapper.appendChild(toolbar)\n wrapper.appendChild(pre)\n wrapper.appendChild(mermaidPreview)\n wrapper.appendChild(rendererPreview)\n\n // ── Mermaid state ──\n let isEditing = false\n let isMermaid = (node.attrs.language === 'mermaid')\n let lastRenderedCode = ''\n let renderTimer: ReturnType<typeof setTimeout> | null = null\n\n // ── Renderer plugin state ──\n let isRenderer = rendererLangIds.has((node.attrs.language as string) || '')\n let rendererEditing = false\n let lastRendererCode = ''\n let rendererTimer: ReturnType<typeof setTimeout> | null = null\n /** Last successfully loaded renderer module — kept so destroy() can be called. */\n let currentRendererModule: RendererPluginModule | null = null\n\n function syncMermaidMode() {\n const showPreview = isMermaid && !isEditing\n pre.style.display = (showPreview || (isRenderer && !rendererEditing)) ? 'none' : ''\n mermaidPreview.style.display = showPreview ? 'flex' : 'none'\n toggleBtn.style.display = (isMermaid || isRenderer) ? 'inline-flex' : 'none'\n wrapper.classList.toggle('mermaid-preview-mode', showPreview)\n if (isMermaid) {\n toggleBtn.textContent = isEditing ? '👁 Preview' : '✏️ Edit'\n if (showPreview) triggerMermaidRender()\n }\n }\n\n function triggerMermaidRender() {\n const codeText = code.textContent || ''\n if (!codeText.trim()) {\n mermaidPreview.innerHTML = '<div class=\"mermaid-empty\">Empty diagram</div>'\n lastRenderedCode = ''\n return\n }\n if (codeText === lastRenderedCode) return\n lastRenderedCode = codeText\n\n if (renderTimer) clearTimeout(renderTimer)\n renderTimer = setTimeout(async () => {\n mermaidPreview.innerHTML = '<div class=\"mermaid-loading\"><div class=\"mermaid-spinner\"></div>Loading diagram...</div>'\n try {\n const api = await loadMermaidApi()\n if (!api) return\n const result = await api.renderMermaid(codeText)\n if (code.textContent !== codeText) return\n if ('svg' in result) {\n mermaidPreview.innerHTML = result.svg\n } else {\n mermaidPreview.innerHTML = `<div class=\"mermaid-error\">${escapeText(result.error)}</div>`\n }\n } catch {\n mermaidPreview.innerHTML = '<div class=\"mermaid-error\">Render failed</div>'\n }\n }, 150)\n }\n\n // ── Renderer plugin sync ──\n function syncRendererMode() {\n const showPreview = isRenderer && !rendererEditing\n pre.style.display = (showPreview || (isMermaid && !isEditing)) ? 'none' : ''\n rendererPreview.style.display = showPreview ? 'block' : 'none'\n toggleBtn.style.display = (isMermaid || isRenderer) ? 'inline-flex' : 'none'\n wrapper.classList.toggle('renderer-preview-mode', showPreview)\n if (isRenderer) {\n toggleBtn.textContent = rendererEditing ? '👁 Preview' : '✏️ Edit'\n if (showPreview) triggerRendererRender()\n }\n }\n\n function triggerRendererRender() {\n const source = code.textContent || ''\n const lang = (node.attrs.language as string) || ''\n if (!rendererRegistry || !rendererRegistry.has(lang)) return\n\n if (!source.trim()) {\n rendererPreview.innerHTML = '<div class=\"renderer-empty\">Empty block</div>'\n lastRendererCode = ''\n return\n }\n if (source === lastRendererCode) return\n lastRendererCode = source\n\n if (rendererTimer) clearTimeout(rendererTimer)\n rendererTimer = setTimeout(async () => {\n rendererPreview.innerHTML = '<div class=\"renderer-loading\"><div class=\"renderer-spinner\"></div>Rendering...</div>'\n try {\n const module = await rendererRegistry.load(lang)\n if (code.textContent !== source) return // source changed during load\n // Dispose previous renderer (frees canvases / observers)\n if (currentRendererModule?.destroy) {\n try { currentRendererModule.destroy(rendererPreview) } catch { /* swallow per §4.5 */ }\n }\n currentRendererModule = module\n rendererPreview.innerHTML = ''\n try {\n await module.render(source, rendererPreview)\n } catch (e) {\n // §3.3 RendererPluginModule error contract: NodeView shows\n // .renderer-error fallback; serializer keeps fenced source via\n // node.attrs (not DOM), so roundtrip is safe.\n rendererPreview.innerHTML =\n `<div class=\"renderer-error\" data-language=\"${escapeText(lang)}\" data-error=\"${escapeText(String(e))}\">[Renderer ${escapeText(lang)} failed]</div>`\n }\n } catch (e) {\n rendererPreview.innerHTML =\n `<div class=\"renderer-error\" data-language=\"${escapeText(lang)}\" data-error=\"${escapeText(String(e))}\">[Renderer ${escapeText(lang)} failed]</div>`\n }\n }, 150)\n }\n\n function onThemeChange() {\n if (isMermaid && !isEditing) {\n lastRenderedCode = ''\n triggerMermaidRender()\n }\n }\n\n if (isMermaid) {\n installThemeObserver()\n mermaidReRenderCallbacks.add(onThemeChange)\n // Defer: ProseMirror populates contentDOM AFTER NodeView factory returns\n requestAnimationFrame(() => syncMermaidMode())\n } else if (isRenderer) {\n // Hide pre and show toggle button immediately, then re-trigger after content arrives\n syncRendererMode()\n requestAnimationFrame(() => syncRendererMode())\n } else {\n syncMermaidMode()\n }\n\n // ── Language picker ──\n let activePicker: { destroy: () => void } | null = null\n\n langLabel.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n\n if (activePicker) {\n activePicker.destroy()\n activePicker = null\n wrapper.classList.remove('picker-open')\n return\n }\n\n const currentLang = (node.attrs.language as string) || ''\n const codeContent = code.textContent || ''\n wrapper.classList.add('picker-open')\n activePicker = createLanguagePicker(\n wrapper,\n langLabel,\n currentLang,\n codeContent,\n langLists,\n (newLang) => {\n activePicker = null\n wrapper.classList.remove('picker-open')\n const pos = getPos()\n if (pos === undefined) return\n view.dispatch(\n view.state.tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n language: newLang,\n }),\n )\n view.focus()\n },\n () => {\n activePicker = null\n wrapper.classList.remove('picker-open')\n },\n )\n })\n\n // ── Mermaid / Renderer toggle button ──\n toggleBtn.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n if (isMermaid) {\n isEditing = !isEditing\n syncMermaidMode()\n } else if (isRenderer) {\n rendererEditing = !rendererEditing\n syncRendererMode()\n }\n if (isEditing || rendererEditing) view.focus()\n })\n\n // Click SVG preview → enter edit mode\n mermaidPreview.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n isEditing = true\n syncMermaidMode()\n view.focus()\n })\n\n // ── Copy button ──\n copyBtn.addEventListener('mousedown', (e) => {\n e.preventDefault()\n e.stopPropagation()\n handleCopy(copyBtn, code)\n })\n\n return {\n dom: wrapper,\n contentDOM: code,\n\n stopEvent(event: Event) {\n const target = event.target as Node\n return !code.contains(target) && wrapper.contains(target) && target !== code\n },\n\n ignoreMutation(mutation: { target: Node }) {\n return !code.contains(mutation.target)\n },\n\n update(updatedNode: PmNode) {\n if (updatedNode.type.name !== 'code_block') return false\n node = updatedNode\n langLabel.textContent = findLanguageLabel((updatedNode.attrs.language as string) || '', allLanguages)\n\n const wasMermaid = isMermaid\n isMermaid = (updatedNode.attrs.language === 'mermaid')\n if (isMermaid !== wasMermaid) {\n isEditing = false\n if (isMermaid) {\n installThemeObserver()\n mermaidReRenderCallbacks.add(onThemeChange)\n } else {\n mermaidReRenderCallbacks.delete(onThemeChange)\n }\n }\n\n const wasRenderer = isRenderer\n isRenderer = rendererLangIds.has((updatedNode.attrs.language as string) || '')\n if (isRenderer !== wasRenderer) {\n rendererEditing = false\n lastRendererCode = ''\n rendererPreview.innerHTML = ''\n // Dispose old renderer module when switching away\n if (!isRenderer && currentRendererModule?.destroy) {\n try { currentRendererModule.destroy(rendererPreview) } catch { /* swallow */ }\n currentRendererModule = null\n }\n }\n\n if (isRenderer) {\n syncRendererMode()\n } else {\n rendererPreview.style.display = 'none'\n wrapper.classList.remove('renderer-preview-mode')\n syncMermaidMode()\n }\n return true\n },\n\n selectNode() {\n wrapper.classList.add('ProseMirror-selectednode')\n },\n\n deselectNode() {\n wrapper.classList.remove('ProseMirror-selectednode')\n },\n\n destroy() {\n if (activePicker) {\n activePicker.destroy()\n activePicker = null\n }\n if (renderTimer) clearTimeout(renderTimer)\n if (rendererTimer) clearTimeout(rendererTimer)\n if (currentRendererModule?.destroy) {\n try { currentRendererModule.destroy(rendererPreview) } catch { /* swallow */ }\n }\n currentRendererModule = null\n mermaidReRenderCallbacks.delete(onThemeChange)\n },\n }\n }\n}\n","/**\n * Editor lifecycle factory for `@moraya/core`.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/setup.ts`,\n * with the following DI changes (v0.60.0-pre §F2.5 / §F2.6):\n * - Schema is built per-call from a consumer-injected `MediaResolver`.\n * - `LinkOpener` / `RendererRegistry` / `Platform` are forwarded to plugins\n * that need them (RendererRegistry → Tier 1 code-block-view in next batch).\n * - All `require()` calls in the original (4 sites) are replaced with\n * top-level ESM imports (§1.1.1 Pure ESM constraint).\n *\n * Public API per §3.2:\n * - `createEditor(opts)` — returns a `MorayaEditorInstance` ready to mount\n * - `createEditorPlugins(opts)` — returns the plugin array (for consumers\n * that want full control over `EditorView` construction)\n * - `preloadEnhancementPlugins()` — warms the Tier 1 lazy-load cache\n */\n\nimport {\n AllSelection,\n EditorState,\n NodeSelection,\n Plugin,\n PluginKey,\n Selection,\n TextSelection,\n} from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\nimport { keymap } from 'prosemirror-keymap'\nimport { history, redo, undo } from 'prosemirror-history'\nimport {\n baseKeymap,\n joinForward,\n setBlockType,\n toggleMark,\n wrapIn,\n} from 'prosemirror-commands'\nimport {\n inputRules,\n textblockTypeInputRule,\n wrappingInputRule,\n InputRule,\n} from 'prosemirror-inputrules'\nimport {\n liftListItem,\n sinkListItem,\n splitListItem,\n} from 'prosemirror-schema-list'\nimport { dropCursor } from 'prosemirror-dropcursor'\nimport { columnResizing } from 'prosemirror-tables'\nimport type { Schema, Node as PmNode } from 'prosemirror-model'\n\nimport { createSchema } from './schema'\nimport { parseMarkdown, serializeMarkdown } from './markdown'\nimport { wrapInBulletList, wrapInOrderedList, wrapInTaskList } from './commands'\nimport { createDefListInputRule } from './plugins/definition-list'\nimport { createEnterHandlerPlugin } from './plugins/enter-handler'\nimport { createCursorSyntaxPlugin } from './plugins/cursor-syntax'\nimport { createLinkTextPlugin } from './plugins/link-text-plugin'\nimport { createInlineCodeConvertPlugin } from './plugins/inline-code-convert'\nimport { createEditorPropsPlugin } from './plugins/editor-props-plugin'\nimport type {\n MediaResolver,\n LinkOpener,\n RendererRegistry,\n Platform,\n SchemaConfig,\n} from './types'\nimport { createDocCache, type DocCache } from './doc-cache'\n\n// ── Tier 1: Enhancement plugins (dynamic imports, loaded in parallel) ──\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype CodeBlockNodeView = any\n\ninterface Tier1Plugins {\n highlight?: Plugin\n /** NodeView factory: `(node, view, getPos) => NodeView`. Wired into nodeViews at editor mount. */\n codeBlockView?: CodeBlockNodeView\n emoji?: Plugin\n defListInputRule?: InputRule\n}\n\ninterface Tier1CacheKey {\n schema: Schema\n rendererRegistry?: RendererRegistry\n}\n\nlet tier1Cache: { key: Tier1CacheKey; plugins: Tier1Plugins } | null = null\nlet tier1Loading: Promise<Tier1Plugins> | null = null\n\n/**\n * Preload Tier 1 enhancement plugins via dynamic `import()`.\n * Each plugin becomes a separate Vite/Rollup chunk (automatic code splitting).\n * Can be called early (e.g. in onMount) to warm the cache.\n *\n * The `defListInputRule` requires a Schema; the `codeBlockView` factory\n * closes over the consumer's `RendererRegistry`. The cache is keyed by\n * (schema, rendererRegistry) so consumers with different injection produce\n * different cached factories.\n */\nexport function preloadEnhancementPlugins(\n schema: Schema,\n rendererRegistry?: RendererRegistry,\n): Promise<Tier1Plugins> {\n if (tier1Cache &&\n tier1Cache.key.schema === schema &&\n tier1Cache.key.rendererRegistry === rendererRegistry) {\n return Promise.resolve(tier1Cache.plugins)\n }\n if (tier1Loading) return tier1Loading\n\n tier1Loading = Promise.allSettled([\n import('./plugins/highlight'),\n import('./plugins/emoji'),\n import('./plugins/code-block-view'),\n ]).then(([hl, em, cbv]) => {\n const plugins: Tier1Plugins = {}\n if (hl.status === 'fulfilled') {\n plugins.highlight = hl.value.createHighlightPlugin()\n }\n if (em.status === 'fulfilled') {\n plugins.emoji = em.value.createEmojiPlugin()\n }\n if (cbv.status === 'fulfilled') {\n plugins.codeBlockView = cbv.value.createCodeBlockNodeViewFactory({\n ...(rendererRegistry ? { rendererRegistry } : {}),\n })\n }\n plugins.defListInputRule = createDefListInputRule(schema)\n tier1Cache = { key: { schema, ...(rendererRegistry ? { rendererRegistry } : {}) }, plugins }\n tier1Loading = null\n return plugins\n })\n\n return tier1Loading\n}\n\n// ── Image Selection Highlight ───────────────────────────────────\n// When a range selection covers image nodes, add a decoration class so CSS\n// can show a blue overlay (images don't get browser text-selection highlight).\n\nfunction createImageSelectionPlugin(): Plugin {\n return new Plugin({\n key: new PluginKey('moraya-image-selection'),\n props: {\n decorations(state) {\n const { from, to } = state.selection\n if (from === to) return DecorationSet.empty // cursor, no range\n const decos: Decoration[] = []\n state.doc.nodesBetween(from, to, (node, pos) => {\n if (node.type.name === 'image') {\n decos.push(Decoration.node(pos, pos + node.nodeSize, { class: 'image-in-selection' }))\n } else if (node.type.name === 'html_inline' && /^<img\\s/i.test((node.attrs.value as string) || '')) {\n decos.push(Decoration.node(pos, pos + node.nodeSize, { class: 'image-in-selection' }))\n }\n })\n return decos.length ? DecorationSet.create(state.doc, decos) : DecorationSet.empty\n },\n },\n })\n}\n\n// ── Input Rules ─────────────────────────────────────────────────\n\nfunction buildInputRules(schema: Schema, tier1: Tier1Plugins): Plugin {\n const rules: InputRule[] = []\n const N = schema.nodes\n const M = schema.marks\n\n // Code block: ```language\n if (N.code_block) {\n rules.push(textblockTypeInputRule(\n /^```(?<language>[a-zA-Z][a-zA-Z0-9_+#.\\-]*)?[\\s\\n]$/,\n N.code_block,\n (match) => ({ language: match.groups?.language ?? '' }),\n ))\n }\n\n // Blockquote: > at start of line\n if (N.blockquote) {\n rules.push(wrappingInputRule(/^\\s*>\\s$/, N.blockquote))\n }\n\n // Bullet list: - or * at start of line\n if (N.bullet_list) {\n rules.push(wrappingInputRule(/^\\s*[-*]\\s$/, N.bullet_list))\n }\n\n // Ordered list: 1. at start of line\n if (N.ordered_list) {\n rules.push(wrappingInputRule(\n /^\\s*(\\d+)\\.\\s$/,\n N.ordered_list,\n (match) => ({ order: +(match[1] ?? '1') }),\n (match, node) => node.childCount + (node.attrs.order as number) === +(match[1] ?? '1'),\n ))\n }\n\n // Heading: # to ######\n if (N.heading) {\n for (let level = 1; level <= 6; level++) {\n const pattern = new RegExp(`^#{${level}}\\\\s$`)\n rules.push(textblockTypeInputRule(pattern, N.heading, { level }))\n }\n }\n\n // Horizontal rule: ---\n if (N.horizontal_rule) {\n rules.push(new InputRule(/^---$/, (state, _match, start, end) => {\n const hr = N.horizontal_rule!.create()\n return state.tr.replaceWith(start - 1, end, hr)\n }))\n }\n\n // Math block: $$\n if (N.math_block) {\n rules.push(new InputRule(/^\\$\\$\\s$/, (state, _match, start, end) => {\n const $start = state.doc.resolve(start)\n if (!$start.node(-1).canReplaceWith(\n $start.index(-1), $start.indexAfter(-1), N.math_block!,\n )) return null\n return state.tr.delete(start, end).setBlockType(start, start, N.math_block!)\n }))\n }\n\n // Math inline: $...$\n if (N.math_inline) {\n rules.push(new InputRule(/(?:\\$)([^$]+)(?:\\$)$/, (state, match, start, end) => {\n const content = match[1]\n if (!content) return null\n const node = N.math_inline!.create(null, schema.text(content))\n return state.tr.replaceWith(start, end, node)\n }))\n }\n\n // Strong: **text** or __text__\n if (M.strong) {\n rules.push(new InputRule(\n /(?<![\\w:/])(?:\\*\\*|__)([^*_]+?)(?:\\*\\*|__)(?![\\w/])$/,\n (state, match, start, end) => {\n const tr = state.tr\n const captured = match[1]\n if (captured) {\n const textStart = start + match[0].indexOf(captured)\n const textEnd = textStart + captured.length\n if (textEnd < end) tr.delete(textEnd, end)\n if (textStart > start) tr.delete(start, textStart)\n const markFrom = start\n const markTo = markFrom + captured.length\n tr.addMark(markFrom, markTo, M.strong!.create())\n }\n return tr\n },\n ))\n }\n\n // Emphasis: *text* or _text_\n if (M.em) {\n rules.push(new InputRule(\n /(?<![\\w:/*])(?:\\*|_)([^*_]+?)(?:\\*|_)(?![\\w/])$/,\n (state, match, start, end) => {\n const tr = state.tr\n const captured = match[1]\n if (captured) {\n const textStart = start + match[0].indexOf(captured)\n const textEnd = textStart + captured.length\n if (textEnd < end) tr.delete(textEnd, end)\n if (textStart > start) tr.delete(start, textStart)\n const markFrom = start\n const markTo = markFrom + captured.length\n tr.addMark(markFrom, markTo, M.em!.create())\n }\n return tr\n },\n ))\n }\n\n // Inline code: `text`\n if (M.code) {\n rules.push(new InputRule(\n /(?:`)([^`]+)(?:`)$/,\n (state, match, start, end) => {\n const tr = state.tr\n const captured = match[1]\n if (captured) {\n // The closing backtick is the just-typed character and is NOT in the\n // document yet (ProseMirror InputRule contract). Only text up to `end`\n // exists. Use indexOf to locate the captured text within the match,\n // then delete surrounding delimiters that ARE in the document.\n const textStart = start + match[0].indexOf(captured)\n const textEnd = textStart + captured.length\n if (textEnd < end) tr.delete(textEnd, end)\n if (textStart > start) tr.delete(start, textStart)\n const markFrom = start\n const markTo = markFrom + captured.length\n tr.addMark(markFrom, markTo, M.code!.create())\n }\n return tr\n },\n ))\n }\n\n // Strikethrough: ~~text~~\n if (M.strike_through) {\n rules.push(new InputRule(\n /~~([^~]+)~~$/,\n (state, match, start, end) => {\n const tr = state.tr\n const captured = match[1]\n if (captured) {\n const textStart = start + match[0].indexOf(captured)\n const textEnd = textStart + captured.length\n if (textEnd < end) tr.delete(textEnd, end)\n if (textStart > start) tr.delete(start, textStart)\n const markFrom = start\n const markTo = markFrom + captured.length\n tr.addMark(markFrom, markTo, M.strike_through!.create())\n }\n return tr\n },\n ))\n }\n\n // Task list: [ ] or [x] at start of list item\n rules.push(new InputRule(\n /^\\[(?<checked>\\s|x)\\]\\s$/,\n (state, match, start, end) => {\n const pos = state.doc.resolve(start)\n let depth = 0\n let node: PmNode | null = pos.node(depth)\n while (node && node.type.name !== 'list_item') {\n depth--\n try { node = pos.node(depth) } catch { node = null }\n }\n if (!node || node.attrs.checked != null) return null\n const checked = Boolean(match.groups?.checked === 'x')\n const finPos = pos.before(depth)\n return state.tr.deleteRange(start, end).setNodeMarkup(finPos, undefined, {\n ...node.attrs,\n checked,\n })\n },\n ))\n\n // Link: [text](url) — typed in visual mode becomes a proper link mark.\n // This prevents the serializer from escaping brackets (issue: []() → \\[\\]()).\n if (M.link) {\n rules.push(new InputRule(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)$/,\n (state, match, start, end) => {\n const text = match[1]\n const url = match[2]\n if (!text || !url) return null\n const linkMark = M.link!.create({ href: url })\n return state.tr.replaceWith(start, end, schema.text(text, [linkMark]))\n },\n ))\n }\n\n // Definition list input rule (Tier 1)\n if (tier1.defListInputRule) {\n rules.push(tier1.defListInputRule)\n }\n\n return inputRules({ rules })\n}\n\n// ── Keymap ──────────────────────────────────────────────────────\n\nfunction buildKeymap(schema: Schema): Plugin {\n const N = schema.nodes\n const M = schema.marks\n const listItemType = N.list_item\n\n const bindings: Record<string, import('prosemirror-state').Command> = {\n // History\n 'Mod-z': undo,\n 'Mod-y': redo,\n 'Mod-Shift-z': redo,\n\n // Marks\n ...(M.strong ? { 'Mod-b': toggleMark(M.strong) } : {}),\n ...(M.em ? { 'Mod-i': toggleMark(M.em) } : {}),\n ...(M.code ? { 'Mod-e': toggleMark(M.code) } : {}),\n ...(M.strike_through ? { 'Mod-Shift-x': toggleMark(M.strike_through) } : {}),\n }\n\n if (listItemType) {\n bindings['Enter'] = splitListItem(listItemType)\n bindings['Tab'] = (state, dispatch) => {\n // In a list → indent list item\n if (sinkListItem(listItemType)(state)) return sinkListItem(listItemType)(state, dispatch)\n // Otherwise → insert tab (4 spaces)\n if (dispatch) dispatch(state.tr.insertText(' '))\n return true\n }\n bindings['Mod-]'] = sinkListItem(listItemType)\n bindings['Shift-Tab'] = liftListItem(listItemType)\n bindings['Mod-['] = liftListItem(listItemType)\n }\n\n if (N.paragraph) bindings['Mod-Alt-0'] = setBlockType(N.paragraph)\n if (N.heading) {\n for (let level = 1; level <= 6; level++) {\n bindings[`Mod-Alt-${level}`] = setBlockType(N.heading, { level })\n }\n }\n if (N.code_block) bindings['Mod-Alt-c'] = setBlockType(N.code_block)\n if (N.blockquote) bindings['Mod-Shift-b'] = wrapIn(N.blockquote)\n\n // Select All: code block local select or whole-doc select\n bindings['Mod-a'] = (state, dispatch) => {\n const { $from } = state.selection\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'code_block') {\n if (dispatch) {\n dispatch(state.tr.setSelection(TextSelection.create(state.doc, $from.start(d), $from.end(d))))\n }\n return true\n }\n }\n if (dispatch) {\n dispatch(state.tr.setSelection(new AllSelection(state.doc)))\n }\n return true\n }\n\n // Hard break - explicitly set isInline to false for proper markdown serialization\n if (N.hardbreak) {\n bindings['Shift-Enter'] = (state, dispatch) => {\n if (dispatch) {\n dispatch(state.tr.replaceSelectionWith(N.hardbreak!.create({ isInline: false })).scrollIntoView())\n }\n return true\n }\n }\n\n // Backspace: protect block atom nodes (math_block, etc.) from deletion.\n //\n // WebKit contenteditable bug: when the caret is at the end of a textblock\n // adjacent to a contenteditable=\"false\" block (atom node), the browser's\n // native Backspace deletes that block instead of the previous character.\n // All ProseMirror built-in handlers return false for this position, so\n // native behavior runs unchecked. We must handle it ourselves.\n bindings['Backspace'] = (state, dispatch) => {\n const sel = state.selection\n\n // Case 0: Fast AllSelection / full-range deletion.\n // ProseMirror's default AllSelection delete is very slow on large docs\n // (step-by-step replacement). Replace entire content with a single empty\n // paragraph in one transaction for instant deletion.\n {\n const docSize = state.doc.content.size\n const isAllSelected =\n sel instanceof AllSelection ||\n (docSize > 0 && sel.from <= 1 && sel.to >= docSize - 1)\n if (isAllSelected && dispatch) {\n const paragraphType = state.schema.nodes.paragraph\n if (!paragraphType) return false\n const emptyParagraph = paragraphType.create()\n const tr = state.tr.replaceWith(0, docSize, emptyParagraph)\n tr.setSelection(TextSelection.create(tr.doc, 1))\n tr.setMeta('full-delete', true)\n dispatch(tr)\n return true\n }\n if (isAllSelected) return true // no dispatch but still consumed\n }\n\n // Case 1: NodeSelection on a block atom (via arrow keys) — move cursor\n // to nearest previous text position instead of deleting the atom.\n if (sel instanceof NodeSelection && sel.node.isBlock && sel.node.type.spec.atom) {\n const before = Selection.findFrom(state.doc.resolve(sel.from), -1, true)\n if (before && dispatch) {\n dispatch(state.tr.setSelection(before).scrollIntoView())\n }\n return true\n }\n\n // Remaining cases need an empty TextSelection with a cursor\n if (!sel.empty || !(sel instanceof TextSelection)) return false\n const $cursor = sel.$cursor\n if (!$cursor) return false\n const { parent, parentOffset } = $cursor\n\n // Case 2: Cursor at END of a textblock, next sibling is a block atom.\n // Main WebKit bug fix: delete the previous character via ProseMirror\n // transaction instead of letting native Backspace run.\n if (parent.isTextblock && parentOffset === parent.content.size && parent.content.size > 0) {\n const afterPos = $cursor.after()\n if (afterPos < state.doc.content.size) {\n const nextNode = state.doc.resolve(afterPos).nodeAfter\n if (nextNode && nextNode.isBlock && nextNode.type.spec.atom) {\n if (dispatch) {\n const before = $cursor.nodeBefore\n if (before) {\n const delSize = before.isText ? 1 : before.nodeSize\n dispatch(state.tr.delete(sel.from - delSize, sel.from).scrollIntoView())\n }\n }\n return true\n }\n }\n }\n\n // Case 3: Cursor at START of a textblock, previous sibling is a block atom.\n if (parent.isTextblock && parentOffset === 0) {\n const beforePos = $cursor.before()\n if (beforePos > 0) {\n const prevNode = state.doc.resolve(beforePos).nodeBefore\n if (prevNode && prevNode.isBlock && prevNode.type.spec.atom) {\n const target = Selection.findFrom(\n state.doc.resolve(beforePos - prevNode.nodeSize), -1, true,\n )\n if (target && dispatch) {\n dispatch(state.tr.setSelection(target).scrollIntoView())\n }\n return true\n }\n }\n }\n\n // Case 4: End of paragraph after an inline atom — join forward\n if (parent.type.name === 'paragraph' && parentOffset === parent.content.size) {\n const nodeBeforeAtom = $cursor.nodeBefore\n if (nodeBeforeAtom && nodeBeforeAtom.isAtom) {\n const afterPos2 = $cursor.after()\n if (afterPos2 < state.doc.content.size) {\n const nextNode2 = state.doc.resolve(afterPos2).nodeAfter\n if (nextNode2 && nextNode2.isBlock) {\n return joinForward(state, dispatch)\n }\n }\n }\n }\n\n // Case 5: Cursor at END of a textblock — delete previous char explicitly.\n // WKWebView's Selection.modify(\"move\",\"backward\",\"character\") can fail\n // at the end of a contenteditable block, causing endOfTextblock(\"backward\")\n // to incorrectly return true. This makes baseKeymap's joinBackward merge\n // the current paragraph with the next one instead of deleting a character.\n if (parent.isTextblock && parentOffset === parent.content.size && parentOffset > 0) {\n if (dispatch) {\n const nb = $cursor.nodeBefore\n if (nb && nb.isText && nb.text) {\n // Handle surrogate pairs (emoji etc.)\n const code = nb.text.charCodeAt(nb.text.length - 1)\n const delLen = (code >= 0xDC00 && code <= 0xDFFF) ? 2 : 1\n dispatch(state.tr.delete(sel.from - delLen, sel.from).scrollIntoView())\n } else if (nb) {\n dispatch(state.tr.delete(sel.from - nb.nodeSize, sel.from).scrollIntoView())\n }\n }\n return true\n }\n\n return false\n }\n\n // Delete: protect block atom nodes from deletion.\n bindings['Delete'] = (state, dispatch) => {\n const sel = state.selection\n\n if (sel instanceof NodeSelection && sel.node.isBlock && sel.node.type.spec.atom) {\n const after = Selection.findFrom(state.doc.resolve(sel.to), 1, true)\n if (after && dispatch) {\n dispatch(state.tr.setSelection(after).scrollIntoView())\n }\n return true\n }\n\n if (sel.empty && sel instanceof TextSelection && sel.$cursor) {\n const $c = sel.$cursor\n if ($c.parent.isTextblock && $c.parentOffset === $c.parent.content.size) {\n const ap = $c.after()\n if (ap < state.doc.content.size) {\n const nn = state.doc.resolve(ap).nodeAfter\n if (nn && nn.isBlock && nn.type.spec.atom) {\n return true // consume — don't delete the atom\n }\n }\n }\n }\n\n return false\n }\n\n return keymap(bindings)\n}\n\n// ── Lazy/Dirty change plugins ───────────────────────────────────\n\n/**\n * Lightweight dirty-tracking plugin: fires on every doc change with the\n * document's plain text content. No markdown serialization, no debounce —\n * runs in O(1) after each transaction.\n */\nfunction createDirtyTrackPlugin(onDocChanged: (textContent: string) => void): Plugin {\n return new Plugin({\n key: new PluginKey('moraya-dirty-track'),\n view: () => ({\n update: (view, prevState) => {\n if (!prevState || view.state.doc.eq(prevState.doc)) return\n onDocChanged(view.state.doc.textContent)\n },\n }),\n })\n}\n\n/**\n * ProseMirror plugin that defers markdown serialization. Used in split mode\n * where a SourceEditor needs periodic markdown sync. Debounce default 500ms.\n */\nfunction createLazyChangePlugin(onChange: (markdown: string) => void, debounceMs = 500): Plugin {\n let changeTimer: ReturnType<typeof setTimeout> | null = null\n\n return new Plugin({\n key: new PluginKey('moraya-lazy-change'),\n view: () => ({\n update: (view, prevState) => {\n if (!prevState || view.state.doc.eq(prevState.doc)) return\n\n if (changeTimer !== null) clearTimeout(changeTimer)\n changeTimer = setTimeout(() => {\n try {\n const markdown = serializeMarkdown(view.state.doc)\n onChange(markdown)\n } catch { /* editor might be destroyed */ }\n changeTimer = null\n }, debounceMs)\n },\n destroy: () => {\n if (changeTimer !== null) {\n clearTimeout(changeTimer)\n changeTimer = null\n }\n },\n }),\n })\n}\n\n// ── Public types ────────────────────────────────────────────────\n\nexport interface EditorPluginOptions {\n /** Render features */\n enableMath?: boolean // default true (KaTeX in toDOM, no plugin)\n enableMermaid?: boolean // default false; Moraya desktop = true (next batch)\n enableTableResize?: boolean // default true (columnResizing)\n enableImageSelection?: boolean // default true\n enableHistory?: boolean // default true; v0.72 Yjs collab consumers set false\n\n /** Dependency injection (§3.3) */\n mediaResolver: MediaResolver // required\n rendererRegistry?: RendererRegistry // optional; default = highlight.js only\n linkOpener?: LinkOpener // optional; default = window.open\n platform?: Platform // optional; default = navigator detection\n\n /** Change callbacks */\n onDocChanged?: (textContent: string) => void\n onChange?: (markdown: string) => void\n changeDebounceMs?: number // default 500\n}\n\nexport interface CreateEditorOptions extends EditorPluginOptions {\n container: HTMLElement\n initialContent?: string\n docCache?: DocCache\n onFocus?: () => void\n onBlur?: () => void\n}\n\nexport interface MorayaEditorInstance {\n view: EditorView\n getMarkdown(): string\n setContent(md: string): void\n destroy(): void\n}\n\nconst defaultPlatform = (): Platform => ({\n getCurrentFilePath: () => null,\n isMacOS:\n typeof navigator !== 'undefined' && /Mac/i.test(navigator.platform ?? ''),\n})\n\n// ── Plugin assembly ─────────────────────────────────────────────\n\n/**\n * Build the plugin array per v0.60.0-pre §4.1.\n *\n * Plugin order (with `key`s for fingerprint stability):\n * 1. listShortcutsPlugin (event.code list shortcuts; macOS Option-key safe)\n * 2. buildInputRules (must precede keymap)\n * 3. createEnterHandlerPlugin (must precede keymap so pipe-table / fence detection runs first)\n * 4. buildKeymap\n * 5. keymap(baseKeymap)\n * 6. history (skipped if enableHistory=false; for v0.72 Yjs)\n * 7. dropCursor\n * 8. columnResizing (table)\n * 9. createCursorSyntaxPlugin\n * 10. createLinkTextPlugin\n * 11. createInlineCodeConvertPlugin\n * 12. createImageSelectionPlugin\n * 13. change callback (lazy / dirty)\n * 14. Tier 1 highlight + emoji (lazy-loaded; appended to plugins array)\n *\n * NOTE: editor-props-plugin and code-block-view (RendererRegistry-coupled)\n * land in the next batch.\n */\nexport async function createEditorPlugins(\n opts: EditorPluginOptions,\n // Allow callers (e.g. createEditor) that already built a Schema to pass it\n // in to avoid double-construction. Defaults to a fresh schema from\n // createSchema(opts).\n schemaArg?: Schema,\n): Promise<Plugin[]> {\n if (!opts.mediaResolver) {\n throw new TypeError(\n '@moraya/core: createEditorPlugins() requires a MediaResolver in opts.mediaResolver',\n )\n }\n\n const platform: Platform = opts.platform ?? defaultPlatform()\n void platform // used by editor-props-plugin in the next batch\n\n const schemaConfig: SchemaConfig = {\n mediaResolver: opts.mediaResolver,\n ...(opts.rendererRegistry ? { rendererRegistry: opts.rendererRegistry } : {}),\n ...(opts.linkOpener ? { linkOpener: opts.linkOpener } : {}),\n }\n const schema = schemaArg ?? createSchema(schemaConfig)\n const linkOpener: LinkOpener = opts.linkOpener ?? {\n open(url: string) {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer')\n }\n },\n }\n\n const tier1 = await preloadEnhancementPlugins(schema, opts.rendererRegistry)\n\n const plugins: Plugin[] = [\n // List shortcuts using event.code (reliable on macOS where Option+key\n // produces special chars). Must come before keymap so this handler has\n // highest priority.\n new Plugin({\n key: new PluginKey('moraya-list-shortcuts'),\n props: {\n handleKeyDown(view, event) {\n const mod = event.metaKey || event.ctrlKey\n if (!mod || !event.altKey || event.shiftKey) return false\n if (event.code === 'KeyO') return wrapInOrderedList(view.state, view.dispatch, view)\n if (event.code === 'KeyU') return wrapInBulletList(view.state, view.dispatch, view)\n if (event.code === 'KeyX') return wrapInTaskList(view.state, view.dispatch, view)\n return false\n },\n },\n }),\n\n // Input rules (must come before keymaps)\n buildInputRules(schema, tier1),\n\n // Custom Enter handler MUST come before keymaps so pipe-table and\n // code-fence detection run before baseKeymap's splitBlock intercepts Enter.\n createEnterHandlerPlugin(),\n\n // Keymaps\n buildKeymap(schema),\n keymap(baseKeymap),\n ]\n\n if (opts.enableHistory !== false) {\n plugins.push(history())\n }\n\n plugins.push(dropCursor())\n\n // Table column resizing (skip tableEditing — its drag-to-select behavior\n // hijacks native text selection inside tables, preventing users from\n // selecting text across multiple cells).\n if (opts.enableTableResize !== false) {\n plugins.push(columnResizing())\n }\n\n // Editor props (paste handlers, link click → LinkOpener, math click fix,\n // WKWebView caret + Backspace fixes, ArrowRight ZWSP escape)\n plugins.push(createEditorPropsPlugin({ platform, linkOpener }))\n\n // Custom plugins\n plugins.push(createCursorSyntaxPlugin())\n plugins.push(createLinkTextPlugin())\n plugins.push(createInlineCodeConvertPlugin())\n\n if (opts.enableImageSelection !== false) {\n plugins.push(createImageSelectionPlugin())\n }\n\n // Change detection\n if (opts.onChange) {\n plugins.push(createLazyChangePlugin(opts.onChange, opts.changeDebounceMs))\n } else if (opts.onDocChanged) {\n plugins.push(createDirtyTrackPlugin(opts.onDocChanged))\n }\n\n // Tier 1 enhancement plugins\n if (tier1.highlight) plugins.push(tier1.highlight)\n if (tier1.emoji) plugins.push(tier1.emoji)\n\n return plugins\n}\n\n// ── Public createEditor ─────────────────────────────────────────\n\n/**\n * Create a full editor instance. Convenience wrapper that handles schema +\n * plugins + EditorState + EditorView wiring.\n */\nexport async function createEditor(opts: CreateEditorOptions): Promise<MorayaEditorInstance> {\n if (!opts.container) {\n throw new TypeError(\n '@moraya/core: createEditor() requires opts.container (HTMLElement)',\n )\n }\n if (!opts.mediaResolver) {\n throw new TypeError(\n '@moraya/core: createEditor() requires opts.mediaResolver',\n )\n }\n\n const schemaConfig: SchemaConfig = {\n mediaResolver: opts.mediaResolver,\n ...(opts.rendererRegistry ? { rendererRegistry: opts.rendererRegistry } : {}),\n ...(opts.linkOpener ? { linkOpener: opts.linkOpener } : {}),\n }\n const schema = createSchema(schemaConfig)\n const docCache = opts.docCache ?? createDocCache(10)\n void docCache // exposed for caller; not auto-applied at v0.1.0\n\n const plugins = await createEditorPlugins(opts, schema)\n\n // Tier 1 nodeViews: code_block replaced with toolbar+picker+mermaid+renderer NodeView.\n // We don't await preloadEnhancementPlugins again — createEditorPlugins already did.\n const tier1 = await preloadEnhancementPlugins(schema, opts.rendererRegistry)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nodeViews: Record<string, any> = {}\n if (tier1.codeBlockView) {\n nodeViews.code_block = tier1.codeBlockView\n }\n\n const initialDoc = opts.initialContent\n ? parseMarkdown(opts.initialContent, schema)\n : schema.topNodeType.createAndFill()!\n\n const state = EditorState.create({ schema, doc: initialDoc, plugins })\n const view = new EditorView(opts.container, {\n state,\n nodeViews,\n attributes: {\n class: 'moraya-editor',\n spellcheck: 'true',\n },\n })\n\n // Handle focus/blur events\n if (opts.onFocus || opts.onBlur) {\n const editorDom = opts.container.querySelector('.ProseMirror')\n if (editorDom) {\n if (opts.onFocus) editorDom.addEventListener('focus', opts.onFocus)\n if (opts.onBlur) editorDom.addEventListener('blur', opts.onBlur)\n }\n }\n\n return {\n view,\n getMarkdown() {\n return serializeMarkdown(view.state.doc)\n },\n setContent(md: string) {\n const newDoc = parseMarkdown(md, schema)\n const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, newDoc.content)\n view.dispatch(tr)\n },\n destroy() {\n view.destroy()\n },\n }\n}\n","/**\n * Unified ProseMirror Schema for `@moraya/core`.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/schema.ts`\n * with the following DI changes (v0.60.0-pre §F2.5):\n * - All Tauri IPC `read_file_binary` / `plugin-http` calls in image / media\n * loaders are replaced by consumer-injected `MediaResolver` methods.\n * - Schema NodeSpecs that depend on the resolver (image, html_inline) are\n * built inside `createSchema(config)` factory body, capturing `config`\n * in closures for `toDOM`. Other NodeSpecs are pure data.\n * - Module-level `documentBaseDir` + `setDocumentBaseDir` is preserved\n * (pure string state, not Tauri-coupled).\n * - Per §6.1.1: this module does NOT export the default schema. It is\n * used internally by parseMarkdown / serializeMarkdown only.\n *\n * Nodes (23): doc, text, paragraph, heading, blockquote, code_block,\n * horizontal_rule, bullet_list, ordered_list, list_item, image,\n * hardbreak, html_block, html_inline, table, table_header_row, table_row,\n * table_header, table_cell, math_inline, math_block,\n * defList, defListTerm, defListDescription\n *\n * Marks (6): html_mark, strong, em, code, link, strike_through\n */\n\nimport { Schema, Fragment } from 'prosemirror-model'\nimport type { NodeSpec, MarkSpec, Node as PmNode } from 'prosemirror-model'\nimport katex from 'katex'\nimport {\n type SchemaConfig,\n type MediaResolver,\n isNullMediaResolver,\n NULL_MEDIA_RESOLVER_SENTINEL,\n type NullMediaResolver,\n} from './types'\n\n// ── Helpers (pure DOM / string ops, no host coupling) ────────────\n\n/** Extract a quoted attribute value from an HTML tag string. */\nfunction extractHtmlAttr(html: string, name: string): string | null {\n const re = new RegExp(`${name}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, 'i')\n const m = html.match(re)\n return m ? (m[1] ?? m[2] ?? m[3] ?? null) : null\n}\n\n/** Extract all attributes from an HTML tag string as key-value pairs. */\nfunction extractAllHtmlAttrs(html: string): Record<string, string> {\n const attrs: Record<string, string> = {}\n const re = /([a-zA-Z_][\\w:.-]*)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))/gi\n let m: RegExpExecArray | null\n while ((m = re.exec(html)) !== null) {\n const name = m[1]\n if (!name) continue\n attrs[name.toLowerCase()] = m[2] ?? m[3] ?? m[4] ?? ''\n }\n return attrs\n}\n\n/** Replace element content with broken-image icon + source code display. */\nfunction showBrokenImage(container: HTMLElement, sourceText: string): void {\n container.textContent = ''\n container.className = (container.className.replace(/\\bhtml-img-wrapper\\b|\\bimage-node\\b/, '').trim()\n + ' broken-image').trim()\n const icon = document.createElement('span')\n icon.className = 'broken-image-icon'\n container.appendChild(icon)\n const code = document.createElement('code')\n code.className = 'broken-image-src'\n code.textContent = sourceText\n container.appendChild(code)\n}\n\n/** Convert HTML tag attributes to CSS inline styles for visual rendering. */\nfunction htmlTagToStyle(openTag: string): string {\n const tagMatch = openTag.match(/^<([a-zA-Z][a-zA-Z0-9]*)/)\n if (!tagMatch || !tagMatch[1]) return ''\n const tagName = tagMatch[1].toLowerCase()\n switch (tagName) {\n case 'font': {\n const parts: string[] = []\n const color = extractHtmlAttr(openTag, 'color')\n if (color) parts.push(`color: ${color}`)\n const size = extractHtmlAttr(openTag, 'size')\n if (size) {\n const sizeMap: Record<string, string> = {\n '1': '0.63em', '2': '0.82em', '3': '1em', '4': '1.13em',\n '5': '1.5em', '6': '2em', '7': '3em',\n }\n parts.push(`font-size: ${sizeMap[size] || size}`)\n }\n const face = extractHtmlAttr(openTag, 'face')\n if (face) parts.push(`font-family: ${face}`)\n return parts.join('; ')\n }\n case 'span':\n case 'div':\n return extractHtmlAttr(openTag, 'style') || ''\n default:\n return ''\n }\n}\n\n/**\n * Base directory for resolving relative image paths. Set by the consumer when\n * a document is opened so `<img src=\"./foo.png\">` can be resolved. Pure\n * string state — not Tauri-coupled.\n */\nlet documentBaseDir = ''\n\n/** Update the base directory used to resolve relative image paths. */\nexport function setDocumentBaseDir(dir: string): void {\n documentBaseDir = dir\n}\n\n/** Read the current base dir. Exposed for consumers that need to coordinate (e.g. tests). */\nexport function getDocumentBaseDir(): string {\n return documentBaseDir\n}\n\n/** Check if a path is a local file path (absolute Unix or Windows path). */\nfunction isAbsoluteFilePath(src: string): boolean {\n if (!src) return false\n if (src.startsWith('/') && !src.startsWith('//')) return true\n if (/^[A-Z]:[\\\\/]/i.test(src)) return true\n return false\n}\n\n/** Check if a src is a relative file path (not a URL scheme). */\nfunction isRelativePath(src: string): boolean {\n if (!src) return false\n if (/^(https?:|data:|blob:|javascript:|vbscript:|tauri:|\\/\\/)/i.test(src)) return false\n if (src.startsWith('/') || /^[A-Z]:[\\\\/]/i.test(src)) return false\n return true\n}\n\n/** Resolve a relative path against documentBaseDir to an absolute path. */\nfunction resolveRelativePath(src: string): string {\n if (!documentBaseDir) return src\n let rel = src.replace(/^\\.\\//, '')\n const sep = documentBaseDir.includes('\\\\') ? '\\\\' : '/'\n let base = documentBaseDir.endsWith(sep) ? documentBaseDir.slice(0, -1) : documentBaseDir\n while (rel.startsWith('../') || rel.startsWith('..\\\\')) {\n rel = rel.slice(3)\n const lastSep = base.lastIndexOf(sep)\n if (lastSep > 0) base = base.slice(0, lastSep)\n }\n return `${base}${sep}${rel}`\n}\n\n// ── Image / media DI helpers ────────────────────────────────────\n\n/**\n * Apply MediaResolver-loaded URL to an <img> element. Decodes URL-encoded\n * paths first (markdown parsers URL-encode non-ASCII; filesystem expects\n * actual Unicode characters).\n */\nfunction loadLocalImageSrc(\n img: HTMLImageElement,\n src: string,\n mediaResolver: MediaResolver\n): void {\n let path: string\n try { path = decodeURIComponent(src) } catch { path = src }\n\n mediaResolver.loadLocalImage(path).then((url) => {\n if (url) img.src = url\n else img.dispatchEvent(new Event('error'))\n }).catch(() => {\n img.dispatchEvent(new Event('error'))\n })\n}\n\n/** Apply MediaResolver-loaded URL to a <video>/<audio>/<source> element. */\nfunction setMediaSrc(\n el: HTMLMediaElement | HTMLSourceElement,\n src: string,\n mediaResolver: MediaResolver\n): void {\n if (isAbsoluteFilePath(src)) {\n mediaResolver.loadLocalMedia(src).then((url) => {\n if (!url) return\n el.src = url\n if (el instanceof HTMLMediaElement) el.load()\n }).catch(() => { /* media load failed silently */ })\n } else if (isRelativePath(src)) {\n mediaResolver.loadLocalMedia(resolveRelativePath(src)).then((url) => {\n if (!url) return\n el.src = url\n if (el instanceof HTMLMediaElement) el.load()\n }).catch(() => { /* media load failed silently */ })\n } else if (/^https?:\\/\\//i.test(src)) {\n // For <video>, set src directly so the browser can issue HTTP range requests\n // and stream playback. Tauri-HTTP-to-blob proxy used for <audio> would\n // download entire file before any frame plays — fine for a few-MB audio,\n // fatal for 10s-of-MB to GB video.\n if (el instanceof HTMLVideoElement) {\n el.src = src\n el.load()\n } else {\n mediaResolver.loadRemoteMedia(src).then((url) => {\n if (!url) return\n el.src = url\n if (el instanceof HTMLMediaElement) el.load()\n }).catch(() => { /* fetch failed */ })\n }\n } else {\n el.src = src\n }\n}\n\n/**\n * Create a <video> or <audio> element from raw HTML. Attributes from the\n * original tag are preserved. Child <source> elements are extracted.\n * Event handler attributes (on*) are stripped for XSS prevention.\n */\nfunction createMediaElement(\n tagName: 'video' | 'audio',\n value: string,\n mediaResolver: MediaResolver\n): HTMLElement {\n const wrapper = document.createElement('span')\n wrapper.dataset.type = 'html-inline'\n wrapper.dataset.value = value\n wrapper.className = 'html-media-wrapper'\n wrapper.contentEditable = 'false'\n\n const el = document.createElement(tagName)\n // Stop ProseMirror from grabbing mousedown for atom-node selection — the\n // browser's native <audio>/<video> controls (play, scrub, volume) must\n // receive events directly, otherwise clicks select the node instead of\n // triggering playback.\n const stopForControls = (ev: Event) => ev.stopPropagation()\n el.addEventListener('mousedown', stopForControls)\n el.addEventListener('click', stopForControls)\n el.addEventListener('pointerdown', stopForControls)\n\n const openTagMatch = value.match(new RegExp(`^<${tagName}\\\\b[^>]*>`, 'i'))\n const openTag = openTagMatch ? openTagMatch[0] : ''\n const attrs = extractAllHtmlAttrs(openTag)\n\n for (const [key, val] of Object.entries(attrs)) {\n if (key === 'src') continue\n if (key.startsWith('on')) continue\n el.setAttribute(key, val)\n }\n\n const strippedTag = openTag.replace(/=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/g, '')\n const boolAttrs = ['controls', 'autoplay', 'loop', 'muted', 'playsinline']\n for (const attr of boolAttrs) {\n if (!(attr in attrs) && new RegExp(`\\\\b${attr}\\\\b`, 'i').test(strippedTag)) {\n el.setAttribute(attr, '')\n }\n }\n\n if (tagName === 'audio' && !attrs.preload) {\n el.setAttribute('preload', 'auto')\n }\n\n const sourceRe = /<source\\b[^>]*\\/?>/gi\n let srcMatch: RegExpExecArray | null\n while ((srcMatch = sourceRe.exec(value)) !== null) {\n const srcAttrs = extractAllHtmlAttrs(srcMatch[0])\n if (!srcAttrs.src) continue\n const source = document.createElement('source')\n if (srcAttrs.type) source.type = srcAttrs.type\n setMediaSrc(source, srcAttrs.src, mediaResolver)\n el.appendChild(source)\n }\n\n if (attrs.src) {\n setMediaSrc(el, attrs.src, mediaResolver)\n }\n\n wrapper.appendChild(el)\n return wrapper\n}\n\n// ── Pure NodeSpecs (no MediaResolver coupling) ─────────────────\n\nconst doc: NodeSpec = {\n content: 'block+',\n}\n\nconst text: NodeSpec = { group: 'inline' }\n\nconst paragraph: NodeSpec = {\n content: 'inline*',\n group: 'block',\n parseDOM: [{ tag: 'p' }],\n toDOM() { return ['p', 0] },\n}\n\nconst heading: NodeSpec = {\n attrs: {\n id: { default: '' },\n level: { default: 1 },\n },\n content: 'inline*',\n group: 'block',\n defining: true,\n parseDOM: [1, 2, 3, 4, 5, 6].map(level => ({\n tag: `h${level}`,\n getAttrs(dom: HTMLElement) {\n return { level, id: dom.getAttribute('id') || '' }\n },\n })),\n toDOM(node) {\n const attrs: Record<string, string> = {}\n if (node.attrs.id) attrs.id = node.attrs.id as string\n return [`h${node.attrs.level as number}`, attrs, 0]\n },\n}\n\nconst blockquote: NodeSpec = {\n content: 'block+',\n group: 'block',\n defining: true,\n parseDOM: [{ tag: 'blockquote' }],\n toDOM() { return ['blockquote', 0] },\n}\n\nconst code_block: NodeSpec = {\n content: 'text*',\n group: 'block',\n marks: '',\n defining: true,\n code: true,\n attrs: {\n language: { default: 'text' },\n },\n parseDOM: [{\n tag: 'pre',\n preserveWhitespace: 'full' as const,\n getAttrs(dom: HTMLElement) {\n return { language: dom.dataset.language || 'text' }\n },\n }],\n toDOM(node) {\n return ['pre', { 'data-language': (node.attrs.language as string) || undefined }, ['code', 0]]\n },\n}\n\nconst horizontal_rule: NodeSpec = {\n group: 'block',\n parseDOM: [{ tag: 'hr' }],\n toDOM() { return ['hr'] },\n}\n\nconst bullet_list: NodeSpec = {\n content: 'list_item+',\n group: 'block',\n parseDOM: [{ tag: 'ul' }],\n toDOM() { return ['ul', 0] },\n}\n\nconst ordered_list: NodeSpec = {\n content: 'list_item+',\n group: 'block',\n attrs: {\n order: { default: 1 },\n },\n parseDOM: [{\n tag: 'ol',\n getAttrs(dom: HTMLElement) {\n return { order: dom.hasAttribute('start') ? +(dom.getAttribute('start') || 1) : 1 }\n },\n }],\n toDOM(node) {\n return node.attrs.order === 1\n ? ['ol', 0]\n : ['ol', { start: node.attrs.order as number }, 0]\n },\n}\n\nconst list_item: NodeSpec = {\n content: 'paragraph block*',\n group: 'listItem',\n defining: true,\n attrs: {\n label: { default: '•' },\n listType: { default: 'bullet' },\n spread: { default: 'true' },\n checked: { default: null },\n },\n parseDOM: [\n {\n tag: 'li[data-item-type=\"task\"]',\n getAttrs(dom: HTMLElement) {\n return {\n label: dom.dataset.label,\n listType: dom.dataset.listType,\n spread: dom.dataset.spread,\n checked: dom.dataset.checked ? dom.dataset.checked === 'true' : null,\n }\n },\n },\n {\n tag: 'li',\n getAttrs(dom: HTMLElement) {\n return {\n label: dom.dataset.label || '•',\n listType: dom.dataset.listType || 'bullet',\n spread: dom.dataset.spread || 'true',\n }\n },\n },\n ],\n toDOM(node) {\n if (node.attrs.checked != null) {\n return ['li', {\n 'data-item-type': 'task',\n 'data-label': node.attrs.label as string,\n 'data-list-type': node.attrs.listType as string,\n 'data-spread': node.attrs.spread as string,\n 'data-checked': String(node.attrs.checked),\n }, 0]\n }\n return ['li', {\n 'data-label': node.attrs.label as string,\n 'data-list-type': node.attrs.listType as string,\n 'data-spread': node.attrs.spread as string,\n }, 0]\n },\n}\n\nconst hardbreak: NodeSpec = {\n inline: true,\n group: 'inline',\n selectable: false,\n attrs: {\n isInline: { default: false },\n },\n parseDOM: [\n { tag: 'br' },\n {\n tag: 'span[data-type=\"hardbreak\"]',\n getAttrs() { return { isInline: true } },\n },\n ],\n toDOM() {\n // Always render as span with newline to maintain consistent cursor size.\n // leafText() ensures it serializes correctly.\n return ['span', { 'data-type': 'hardbreak', 'class': 'hardbreak-marker' }, '\\n']\n },\n leafText() { return '\\n' },\n}\n\nconst html_block: NodeSpec = {\n content: 'text*',\n group: 'block',\n marks: '',\n code: true,\n defining: true,\n parseDOM: [{\n tag: 'div[data-type=\"html\"]',\n preserveWhitespace: 'full' as const,\n }],\n toDOM() {\n return ['div', { 'data-type': 'html' }, ['pre', 0]]\n },\n}\n\n// ── Table NodeSpecs ─────────────────────────────────────────────\n\nconst table: NodeSpec = {\n content: 'table_header_row table_row+',\n group: 'block',\n tableRole: 'table',\n isolating: true,\n parseDOM: [{ tag: 'table' }],\n toDOM() { return ['table', ['tbody', 0]] },\n}\n\nconst table_header_row: NodeSpec = {\n content: '(table_header)*',\n tableRole: 'row',\n parseDOM: [\n { tag: 'tr[data-is-header]' },\n {\n tag: 'tr',\n getAttrs(dom: HTMLElement) {\n const hasHeader = dom.querySelector('th')\n return hasHeader ? {} : false\n },\n },\n ],\n toDOM() { return ['tr', { 'data-is-header': 'true' }, 0] },\n}\n\nconst table_row: NodeSpec = {\n content: '(table_cell)*',\n tableRole: 'row',\n parseDOM: [{ tag: 'tr' }],\n toDOM() { return ['tr', 0] },\n}\n\nconst table_header: NodeSpec = {\n content: 'paragraph+',\n tableRole: 'header_cell',\n attrs: {\n alignment: { default: 'left' },\n colspan: { default: 1 },\n rowspan: { default: 1 },\n colwidth: { default: null },\n },\n isolating: true,\n parseDOM: [{\n tag: 'th',\n getAttrs(dom: HTMLElement) {\n return {\n alignment: dom.style.textAlign || 'left',\n colspan: Number(dom.getAttribute('colspan') || 1),\n rowspan: Number(dom.getAttribute('rowspan') || 1),\n colwidth: null,\n }\n },\n }],\n toDOM(node) {\n return ['th', { style: `text-align: ${(node.attrs.alignment as string) || 'left'}` }, 0]\n },\n}\n\nconst table_cell: NodeSpec = {\n content: 'paragraph+',\n tableRole: 'cell',\n attrs: {\n alignment: { default: 'left' },\n colspan: { default: 1 },\n rowspan: { default: 1 },\n colwidth: { default: null },\n },\n isolating: true,\n parseDOM: [{\n tag: 'td',\n getAttrs(dom: HTMLElement) {\n return {\n alignment: dom.style.textAlign || 'left',\n colspan: Number(dom.getAttribute('colspan') || 1),\n rowspan: Number(dom.getAttribute('rowspan') || 1),\n colwidth: null,\n }\n },\n }],\n toDOM(node) {\n return ['td', { style: `text-align: ${(node.attrs.alignment as string) || 'left'}` }, 0]\n },\n}\n\n// ── Math NodeSpecs (KaTeX) ──────────────────────────────────────\n\nconst math_inline: NodeSpec = {\n group: 'inline',\n content: 'text*',\n inline: true,\n atom: true,\n parseDOM: [{\n tag: 'span[data-type=\"math_inline\"]',\n getContent(dom: globalThis.Node, schema: Schema) {\n if (!(dom instanceof HTMLElement)) return Fragment.empty\n const value = dom.dataset.value ?? ''\n if (!value) return Fragment.empty\n return Fragment.from(schema.text(value))\n },\n }],\n toDOM(node) {\n const code = node.textContent\n const dom = document.createElement('span')\n dom.dataset.type = 'math_inline'\n dom.dataset.value = code\n try {\n katex.render(code, dom)\n } catch {\n // §4.4 KaTeX error contract: render fallback marker; serializer reads data-tex attr.\n dom.textContent = code\n dom.classList.add('math-error')\n dom.setAttribute('data-math-type', 'inline')\n }\n return dom\n },\n}\n\nconst math_block: NodeSpec = {\n content: 'text*',\n group: 'block',\n marks: '',\n defining: true,\n atom: true,\n isolating: true,\n attrs: {\n value: { default: '' },\n },\n parseDOM: [{\n tag: 'div[data-type=\"math_block\"]',\n preserveWhitespace: 'full' as const,\n getAttrs(dom: HTMLElement) {\n return { value: dom.dataset.value ?? '' }\n },\n }],\n toDOM(node) {\n const code = node.attrs.value as string\n const dom = document.createElement('div')\n dom.dataset.type = 'math_block'\n dom.dataset.value = code\n try {\n katex.render(code, dom, { displayMode: true })\n } catch {\n dom.textContent = code\n dom.classList.add('math-error')\n dom.setAttribute('data-math-type', 'block')\n }\n return dom\n },\n}\n\n// ── Definition List NodeSpecs ───────────────────────────────────\n\nconst defList: NodeSpec = {\n content: '(defListTerm | defListDescription)+',\n group: 'block',\n defining: true,\n parseDOM: [{ tag: 'dl' }],\n toDOM() { return ['dl', { class: 'definition-list' }, 0] },\n}\n\nconst defListTerm: NodeSpec = {\n content: 'inline*',\n group: 'block',\n defining: true,\n parseDOM: [{ tag: 'dt' }],\n toDOM() { return ['dt', 0] },\n}\n\nconst defListDescription: NodeSpec = {\n content: 'block+',\n group: 'block',\n defining: true,\n parseDOM: [{ tag: 'dd' }],\n toDOM() { return ['dd', 0] },\n}\n\n// ── Marks ───────────────────────────────────────────────────────\n\nconst strong: MarkSpec = {\n parseDOM: [\n {\n tag: 'b',\n getAttrs(dom: HTMLElement) {\n return dom.style.fontWeight !== 'normal' && null\n },\n },\n { tag: 'strong' },\n {\n style: 'font-weight',\n getAttrs(value: string) {\n return /^(bold(er)?|[5-9]\\d{2,})$/.test(value) && null\n },\n },\n ],\n toDOM() { return ['strong', 0] },\n}\n\nconst em: MarkSpec = {\n parseDOM: [\n { tag: 'i' },\n { tag: 'em' },\n {\n style: 'font-style',\n getAttrs(value: string) {\n return value === 'italic' && null\n },\n },\n ],\n toDOM() { return ['em', 0] },\n}\n\nconst code: MarkSpec = {\n priority: 100,\n code: true,\n inclusive: false,\n parseDOM: [{ tag: 'code' }],\n toDOM() { return ['code', 0] },\n}\n\nconst link: MarkSpec = {\n attrs: {\n href: {},\n title: { default: null },\n },\n inclusive: false,\n parseDOM: [{\n tag: 'a[href]',\n getAttrs(dom: HTMLElement) {\n return {\n href: dom.getAttribute('href'),\n title: dom.getAttribute('title'),\n }\n },\n }],\n toDOM(mark) {\n const attrs: Record<string, string> = { href: mark.attrs.href as string }\n if (mark.attrs.title) attrs.title = mark.attrs.title as string\n return ['a', attrs, 0]\n },\n}\n\nconst strike_through: MarkSpec = {\n parseDOM: [\n { tag: 'del' },\n { tag: 's' },\n {\n style: 'text-decoration',\n getAttrs(value: string) {\n return value === 'line-through' && null\n },\n },\n ],\n toDOM() { return ['del', 0] },\n}\n\nconst html_mark: MarkSpec = {\n attrs: {\n openTag: { default: '' },\n closeTag: { default: '' },\n },\n excludes: '', // Allow nesting multiple html_marks (e.g., <font><u>text</u></font>)\n parseDOM: [{\n tag: '[data-type=\"html-mark\"]',\n getAttrs(dom: HTMLElement) {\n return {\n openTag: dom.dataset.openTag ?? '',\n closeTag: dom.dataset.closeTag ?? '',\n }\n },\n }],\n toDOM(mark) {\n const openTag = mark.attrs.openTag as string\n const tagMatch = openTag.match(/^<([a-zA-Z][a-zA-Z0-9]*)/)\n const tagName = tagMatch && tagMatch[1] ? tagMatch[1].toLowerCase() : 'span'\n\n const attrs: Record<string, string> = {\n 'data-type': 'html-mark',\n 'data-open-tag': openTag,\n 'data-close-tag': mark.attrs.closeTag as string,\n }\n\n const semanticTags = ['sub', 'sup', 'u', 'ins', 'mark', 'small', 'big', 'kbd', 'abbr']\n if (semanticTags.includes(tagName)) {\n return [tagName, attrs, 0]\n }\n\n const style = htmlTagToStyle(openTag)\n if (style) attrs.style = style\n return ['span', attrs, 0]\n },\n}\n\n// ── Resolver-coupled NodeSpec builders (image, html_inline) ─────\n\n/**\n * Build the `image` NodeSpec with a closed-over MediaResolver. Local-path\n * images are loaded via `mediaResolver.loadLocalImage`; remote URLs are\n * applied directly so the browser can stream / cache normally.\n */\nfunction buildImageNodeSpec(mediaResolver: MediaResolver): NodeSpec {\n return {\n inline: true,\n group: 'inline',\n selectable: true,\n draggable: true,\n marks: '',\n atom: true,\n defining: true,\n isolating: true,\n attrs: {\n src: { default: '' },\n alt: { default: '' },\n title: { default: '' },\n },\n parseDOM: [{\n tag: 'img[src]',\n getAttrs(dom: HTMLElement) {\n return {\n src: dom.getAttribute('src') || '',\n alt: dom.getAttribute('alt') || '',\n title: dom.getAttribute('title') || dom.getAttribute('alt') || '',\n }\n },\n }],\n toDOM(node) {\n const container = document.createElement('span')\n container.className = 'image-node'\n\n const img = document.createElement('img')\n if (node.attrs.alt) img.alt = node.attrs.alt as string\n if (node.attrs.title) img.title = node.attrs.title as string\n\n // Apply width from title attr (e.g. title=\"width=70%\")\n const titleStr = (node.attrs.title || '') as string\n const widthMatch = titleStr.match(/^width=(\\d+%?)$/)\n const widthVal = widthMatch?.[1]\n if (widthVal) {\n img.style.width = widthVal.includes('%') ? widthVal : `${widthVal}px`\n img.style.maxWidth = 'none'\n }\n\n img.onerror = () => {\n const alt = node.attrs.alt ? `![${node.attrs.alt}]` : '![]'\n const title = node.attrs.title ? ` \"${node.attrs.title}\"` : ''\n showBrokenImage(container, `${alt}(${node.attrs.src}${title})`)\n }\n\n const src = node.attrs.src as string\n if (isAbsoluteFilePath(src)) {\n loadLocalImageSrc(img, src, mediaResolver)\n } else if (isRelativePath(src)) {\n loadLocalImageSrc(img, resolveRelativePath(src), mediaResolver)\n } else {\n img.src = src\n }\n\n container.appendChild(img)\n return container\n },\n }\n}\n\n/**\n * Build the `html_inline` NodeSpec with a closed-over MediaResolver. Inline\n * <img> / <video> / <audio> tags route their src through the resolver; other\n * inline HTML (<font>, <br>, etc.) renders as a plain span carrying its\n * verbatim source for byte-stable roundtrip.\n */\nfunction buildHtmlInlineNodeSpec(mediaResolver: MediaResolver): NodeSpec {\n return {\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n value: { default: '' },\n },\n parseDOM: [{\n tag: 'span[data-type=\"html-inline\"]',\n getAttrs(dom: HTMLElement) {\n return { value: dom.dataset.value ?? '' }\n },\n }],\n toDOM(node) {\n const value = node.attrs.value as string\n\n if (/^<img\\s/i.test(value)) {\n const wrapper = document.createElement('span')\n wrapper.dataset.type = 'html-inline'\n wrapper.dataset.value = value\n wrapper.className = 'html-img-wrapper'\n\n const attrs = extractAllHtmlAttrs(value)\n const src = attrs.src || ''\n if (src) {\n const img = document.createElement('img')\n for (const [key, val] of Object.entries(attrs)) {\n if (key === 'src') continue\n if (key === 'onerror' || key === 'onload' || key.startsWith('on')) continue\n img.setAttribute(key, val)\n }\n img.onerror = () => {\n showBrokenImage(wrapper, value)\n }\n if (isAbsoluteFilePath(src)) {\n loadLocalImageSrc(img, src, mediaResolver)\n } else if (isRelativePath(src)) {\n loadLocalImageSrc(img, resolveRelativePath(src), mediaResolver)\n } else {\n img.src = src\n }\n wrapper.appendChild(img)\n } else {\n showBrokenImage(wrapper, value)\n }\n return wrapper\n }\n\n if (/^<video\\b/i.test(value)) return createMediaElement('video', value, mediaResolver)\n if (/^<audio\\b/i.test(value)) return createMediaElement('audio', value, mediaResolver)\n\n // Default: invisible span for other inline HTML (<font>, <br>, etc.)\n return ['span', { 'data-type': 'html-inline', 'data-value': value }]\n },\n }\n}\n\n// ── Schema assembly ─────────────────────────────────────────────\n\nfunction buildNodes(mediaResolver: MediaResolver): Record<string, NodeSpec> {\n return {\n doc,\n text,\n paragraph,\n heading,\n blockquote,\n code_block,\n horizontal_rule,\n bullet_list,\n ordered_list,\n list_item,\n image: buildImageNodeSpec(mediaResolver),\n hardbreak,\n html_block,\n html_inline: buildHtmlInlineNodeSpec(mediaResolver),\n table,\n table_header_row,\n table_row,\n table_header,\n table_cell,\n math_inline,\n math_block,\n defList,\n defListTerm,\n defListDescription,\n }\n}\n\nconst marks: Record<string, MarkSpec> = {\n html_mark,\n strong,\n em,\n code,\n link,\n strike_through,\n}\n\n// ── Internal default schema (parser/serializer fallback) ────────\n\nconst nullMediaResolver: NullMediaResolver = {\n [NULL_MEDIA_RESOLVER_SENTINEL]: true,\n async loadLocalImage() { return '' },\n async loadLocalMedia() { return '' },\n async loadRemoteMedia(url: string) { return url },\n}\n\n/**\n * Internal default schema (uses {@link nullMediaResolver}).\n * Used by parseMarkdown / serializeMarkdown when no real consumer schema\n * is available. Per §6.1.1 NOT exported via index.ts — consumers must call\n * createSchema(config) with a real MediaResolver.\n */\nexport const defaultSchema = new Schema({\n nodes: buildNodes(nullMediaResolver),\n marks,\n})\n\n// ── Public factory ──────────────────────────────────────────────\n\n/** Cached config-keyed schemas. Reuses Schema instances when consumers call createSchema with the same config. */\nconst schemaCache = new WeakMap<MediaResolver, Schema>()\n\n/**\n * Create a ProseMirror Schema with consumer-injected dependencies.\n *\n * @throws TypeError if `config.mediaResolver` is missing or is the internal\n * nullMediaResolver sentinel.\n */\nexport function createSchema(config: SchemaConfig): Schema {\n if (!config || typeof config !== 'object') {\n throw new TypeError('@moraya/core: createSchema() requires a config object with a MediaResolver')\n }\n if (!config.mediaResolver) {\n throw new TypeError('@moraya/core: createSchema() requires a MediaResolver')\n }\n if (isNullMediaResolver(config.mediaResolver)) {\n throw new TypeError(\n \"@moraya/core: do not pass nullMediaResolver to createSchema(). That instance is reserved for parseMarkdown/serializeMarkdown internal use only. Provide a real MediaResolver implementation (e.g. BrowserMediaResolver from '@moraya/core/adapters/browser-media-resolver').\"\n )\n }\n const cached = schemaCache.get(config.mediaResolver)\n if (cached) return cached\n const schema = new Schema({\n nodes: buildNodes(config.mediaResolver),\n marks,\n })\n schemaCache.set(config.mediaResolver, schema)\n return schema\n}\n\nexport type { SchemaConfig, PmNode }\n","/**\n * Dependency-injection interfaces for `@moraya/core`.\n *\n * These 4 interfaces are the **only** boundary between the core package\n * (host-agnostic, pure ESM) and the consumer environment (Tauri / browser /\n * mobile WebView). All Tauri / DOM-specific APIs that previously lived inside\n * the editor source are now accessed through these injected implementations.\n *\n * See iteration spec: `moraya/docs/iterations/v0.60.0-pre-shared-markdown-core.md` §3.3.\n */\n\n/**\n * Loads local / remote media as a URL usable in `img.src` / `video.src` / etc.\n * Typically returns blob: URLs for local files (cached by the implementation).\n */\nexport interface MediaResolver {\n /** Read a local image file by absolute path; return a blob: URL (implementation caches internally). */\n loadLocalImage(absolutePath: string): Promise<string>\n\n /** Read a local audio/video file by absolute path; return a blob: URL. */\n loadLocalMedia(absolutePath: string): Promise<string>\n\n /**\n * Fetch a remote media URL.\n * Browser implementations may return the original URL directly.\n * Tauri implementations proxy through plugin-http to bypass WKWebView mixed-content.\n */\n loadRemoteMedia(url: string): Promise<string>\n}\n\n/** Opens an external link (browser = `window.open`; Tauri = plugin-opener; mobile = bridge). */\nexport interface LinkOpener {\n open(url: string): void\n}\n\n/**\n * Custom code-block renderer plugin (WaveDrom / D2 / Excalidraw, etc.).\n * Loaded dynamically via {@link RendererRegistry}.\n */\nexport interface RendererPluginModule {\n /**\n * Render `source` into `container` (async supported).\n * The caller guarantees `container` is already mounted in the DOM.\n * The implementation must clear any old content of `container` before rendering.\n *\n * Error propagation: if this method throws or rejects, the core captures the error\n * inside the NodeView (no rethrow) and inserts a fallback DOM:\n * `<div class=\"renderer-error\" data-language=\"${lang}\" data-error=\"${msg}\">[Renderer ${lang} failed]</div>`\n * Roundtrip preservation: the serializer reads the original fenced source from\n * `node.attrs.source` (NOT from the fallback DOM), so the fenced code block\n * round-trips byte-stably even if rendering fails.\n */\n render(\n source: string,\n container: HTMLElement,\n options?: { theme?: string; baseUrl?: string }\n ): void | Promise<void>\n\n /**\n * Destroy the rendered content within `container` (optional).\n * Called from NodeView.destroy() to free canvas / SVG / event listeners.\n *\n * Error propagation: if this method throws, the core catches and `console.warn`s\n * (does not report to Sentry, does not rethrow). This is a cleanup path; throwing\n * here would block NodeView destruction and cause memory leaks.\n */\n destroy?(container: HTMLElement): void\n}\n\n/** Code-block custom renderer registry. Implemented by consumers (Moraya desktop / Web). */\nexport interface RendererRegistry {\n /** Whether a renderer is registered for the given language identifier. */\n has(language: string): boolean\n\n /** Asynchronously load the renderer module (consumer handles CDN / local import). */\n load(language: string): Promise<RendererPluginModule>\n\n /**\n * Snapshot of currently registered renderer versions (language → version string).\n * Used by code-block-view to invalidate cached renders when versions change.\n */\n readonly versions: Readonly<Record<string, string>>\n}\n\n/**\n * Platform behavior parameters (carries the editor-props-plugin DI from §F2.6).\n * Desktop injects Tauri / OS truth; Web uses browser detection; mobile bridges fill.\n */\nexport interface Platform {\n /**\n * Absolute path of the currently open document (used for relative-image-path\n * resolution). Returns `null` when no document is open.\n */\n getCurrentFilePath: () => string | null\n\n /**\n * Whether the user is on macOS. Affects Option-key handling, Cmd vs Ctrl,\n * emoji popup behavior, etc.\n */\n isMacOS: boolean\n}\n\n/** SchemaConfig (re-exported from schema.ts for convenience). */\nexport interface SchemaConfig {\n mediaResolver: MediaResolver\n rendererRegistry?: RendererRegistry\n linkOpener?: LinkOpener\n}\n\n// ===== Internal sentinel for misuse detection (v0.60.0-pre §6.1.1) =====\n\n/**\n * Internal symbol-tagged null MediaResolver used by core for parseMarkdown /\n * serializeMarkdown internal fallback. Consumers must NOT pass this to\n * createSchema(); doing so throws with a descriptive error.\n */\nexport const NULL_MEDIA_RESOLVER_SENTINEL = Symbol('@moraya/core:null-media-resolver')\n\nexport interface NullMediaResolver extends MediaResolver {\n readonly [NULL_MEDIA_RESOLVER_SENTINEL]: true\n}\n\nexport function isNullMediaResolver(r: MediaResolver): r is NullMediaResolver {\n return (r as NullMediaResolver)[NULL_MEDIA_RESOLVER_SENTINEL] === true\n}\n","/**\n * Markdown ↔ ProseMirror Doc roundtrip for `@moraya/core`.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/markdown.ts`.\n * Uses `prosemirror-markdown` with `markdown-it` as the tokenizer.\n *\n * Supports: CommonMark + GFM (tables, strikethrough, task lists) +\n * math (via markdown-it-texmath) + definition lists +\n * paired raw-HTML marks + frontmatter / footnote pass-through.\n *\n * Configuration matches Milkdown output conventions:\n * - bullet: '-'\n * - horizontal rule: '---'\n * - strong: '**'\n * - emphasis: '*'\n *\n * Serializer wraps `defaultSchema` (host-agnostic NullMediaResolver). The\n * schema's structural shape is identical to consumer-injected schemas\n * (same NodeSpec/MarkSpec ids), so a doc parsed against `defaultSchema`\n * round-trips through any consumer schema without rebuilding.\n */\n\nimport MarkdownIt from 'markdown-it'\nimport deflistPlugin from 'markdown-it-deflist'\nimport texmathPlugin from 'markdown-it-texmath'\nimport { MarkdownParser, MarkdownSerializer } from 'prosemirror-markdown'\nimport type { MarkdownSerializerState } from 'prosemirror-markdown'\nimport type { Node as PmNode, Mark, Schema } from 'prosemirror-model'\nimport { defaultSchema } from './schema'\n\n// ── markdown-it instance ────────────────────────────────────────\n\nconst md = new MarkdownIt({\n html: true,\n linkify: false,\n typographer: false,\n})\n .enable(['table', 'strikethrough'])\n .use(deflistPlugin)\n .use(texmathPlugin)\n\n// ── Paired HTML tag pre-processing ──────────────────────────────\n\ninterface InlineToken {\n type: string\n content: string\n children?: InlineToken[] | null\n meta?: Record<string, unknown> | null\n hidden?: boolean\n level?: number\n block?: boolean\n attrs?: unknown\n info?: string\n map?: [number, number] | null\n markup?: string\n tag?: string\n nesting?: number\n attrGet?: (name: string) => string | null\n}\n\n/**\n * Pre-scan inline tokens to identify paired HTML opening/closing tags.\n * Sets `meta.htmlPaired = true` on paired tokens so the parser converts\n * them to marks (styled rendering) instead of atom nodes (invisible).\n * Unpaired tags remain unmarked → atom nodes → exact roundtrip fidelity.\n */\nfunction tagPairedHtmlInline(tokens: InlineToken[]): void {\n const VOID_RE = /^<(?:br|hr|img|input|wbr|area|base|col|embed|link|meta|param|source|track)[\\s/>]/i\n for (const token of tokens) {\n if (token.type !== 'inline' || !token.children) continue\n const children = token.children\n const stack: { tagName: string; index: number }[] = []\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n if (!child || child.type !== 'html_inline') continue\n const content: string = child.content\n // Skip void/self-closing elements and comments\n if (VOID_RE.test(content) || /\\/>$/.test(content) || /^<!--/.test(content)) continue\n // Closing tag?\n const closeMatch = content.match(/^<\\/([a-zA-Z][a-zA-Z0-9]*)\\s*>$/)\n if (closeMatch && closeMatch[1]) {\n const tagName = closeMatch[1].toLowerCase()\n for (let j = stack.length - 1; j >= 0; j--) {\n const entry = stack[j]\n if (!entry) continue\n if (entry.tagName === tagName) {\n const opener = children[entry.index]\n if (opener) {\n opener.meta = { ...(opener.meta || {}), htmlPaired: true }\n }\n child.meta = { ...(child.meta || {}), htmlPaired: true }\n stack.splice(j, 1)\n break\n }\n }\n continue\n }\n // Opening tag?\n const openMatch = content.match(/^<([a-zA-Z][a-zA-Z0-9]*)\\b[^>]*>$/)\n if (openMatch && openMatch[1]) {\n stack.push({ tagName: openMatch[1].toLowerCase(), index: i })\n }\n }\n }\n}\n\n/**\n * Detect extra blank lines between top-level blocks and inject empty paragraph\n * tokens so ProseMirror preserves them as empty <p> nodes.\n *\n * Standard Markdown collapses consecutive blank lines into one paragraph break.\n * This post-processor restores each extra blank line as an empty paragraph,\n * giving Typora-style round-trip fidelity for multi-Enter spacing.\n */\nfunction preserveBlankLines(tokens: InlineToken[]): InlineToken[] {\n function mkToken(type: string, tag: string, nesting: number, extra?: Partial<InlineToken>): InlineToken {\n return {\n type, tag, nesting, content: '', children: null, attrs: null, info: '',\n meta: null, map: null, block: true, hidden: false, level: 0, markup: '',\n ...extra,\n }\n }\n\n const result: InlineToken[] = []\n let lastTopBlockEndLine = 0\n\n for (let i = 0; i < tokens.length; i++) {\n const tok = tokens[i]\n if (!tok) continue\n\n if (tok.map && tok.level === 0 && (tok.nesting === 1 || tok.nesting === 0)) {\n const startLine = tok.map[0] as number\n const gap = startLine - lastTopBlockEndLine\n\n if (gap > 1 && lastTopBlockEndLine > 0) {\n const extra = gap - 1\n for (let j = 0; j < extra; j++) {\n result.push(\n mkToken('paragraph_open', 'p', 1),\n mkToken('inline', '', 0, { level: 1, block: false, children: [] }),\n mkToken('paragraph_close', 'p', -1),\n )\n }\n }\n\n lastTopBlockEndLine = tok.map[1] as number\n }\n\n result.push(tok)\n }\n\n return result\n}\n\n// Patch md.parse to inject paired-tag pre-processing and blank-line preservation\n// before prosemirror-markdown processes the tokens.\nconst _origMdParse = md.parse.bind(md)\nmd.parse = function (src: string, env: unknown) {\n let tokens = _origMdParse(src, env) as unknown as InlineToken[]\n tagPairedHtmlInline(tokens)\n tokens = preserveBlankLines(tokens)\n return tokens as unknown as ReturnType<typeof _origMdParse>\n}\n\n// ── Parser ──────────────────────────────────────────────────────\n\n/**\n * Token-to-node mapping for prosemirror-markdown's MarkdownParser.\n * markdown-it token names → ProseMirror node/mark names from schema.ts\n */\nconst parserTokens: Record<string, import('prosemirror-markdown').ParseSpec> = {\n // ── Block tokens ──\n paragraph: { block: 'paragraph' },\n blockquote: { block: 'blockquote' },\n heading: {\n block: 'heading',\n getAttrs(token) {\n return { level: Number(token.tag.slice(1)) }\n },\n },\n hr: { node: 'horizontal_rule' },\n bullet_list: { block: 'bullet_list' },\n ordered_list: {\n block: 'ordered_list',\n getAttrs(token) {\n return { order: Number(token.attrGet('start') || 1) }\n },\n },\n list_item: {\n block: 'list_item',\n getAttrs(_token, tokens, index) {\n // Check for task list checkbox in the first inline child.\n // The inline content starts with [x] or [ ]\n let checked: boolean | null = null\n for (let i = index + 1; i < tokens.length; i++) {\n const t = tokens[i]\n if (!t) continue\n if (t.type === 'inline' && t.content) {\n const match = t.content.match(/^\\[( |x|X)\\]\\s?/)\n if (match) {\n checked = match[1] !== ' '\n // Strip the checkbox text from the token content\n t.content = t.content.slice(match[0].length)\n // Also update children if they exist\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const children = (t as any).children\n if (children && children.length > 0) {\n const firstChild = children[0]\n if (firstChild.type === 'text') {\n firstChild.content = firstChild.content.slice(match[0].length)\n if (!firstChild.content) {\n children.shift()\n }\n }\n }\n }\n break\n }\n if (t.type === 'list_item_close') break\n }\n return { checked }\n },\n },\n code_block: {\n block: 'code_block',\n getAttrs() {\n return { language: 'text' }\n },\n noCloseToken: true,\n },\n fence: {\n block: 'code_block',\n getAttrs(token) {\n return { language: token.info.trim() || 'text' }\n },\n noCloseToken: true,\n },\n html_block: {\n block: 'html_block',\n noCloseToken: true,\n },\n html_inline: {\n // markdown-it emits this token for inline HTML like <br>, <span>, <sup>,\n // and HTML comments <!-- ... -->. Store raw HTML in the `value` attr.\n node: 'html_inline',\n noCloseToken: true,\n getAttrs(token) {\n return { value: token.content }\n },\n },\n\n // ── Table tokens ──\n // NOTE: tr/th/td are NOT listed here — they are handled by custom tokenHandler\n // overrides in MorayaMarkdownParser below. The `block:` spec alone can't\n // handle (a) thead-row → table_header_row vs table_row dispatch, or\n // (b) wrapping inline content in the required paragraph child of each cell.\n table: { block: 'table' },\n thead: { ignore: true },\n tbody: { ignore: true },\n\n // ── Definition list tokens ──\n dl: { block: 'defList' },\n dt: { block: 'defListTerm' },\n dd: { block: 'defListDescription' },\n\n // ── Math tokens (from markdown-it-texmath) ──\n // Use block: spec (not node:) so token.content is added as text children,\n // correctly filling math_inline's `content: 'text*'`.\n math_inline: {\n block: 'math_inline',\n noCloseToken: true,\n },\n // markdown-it-texmath emits math_inline_double for $$...$$ in inline context.\n // Map to math_inline to prevent \"Token type not supported\" crash.\n math_inline_double: {\n block: 'math_inline',\n noCloseToken: true,\n },\n math_block: {\n node: 'math_block',\n noCloseToken: true,\n getAttrs(token) {\n return { value: token.content.trim() }\n },\n },\n\n // ── Inline tokens ──\n image: {\n node: 'image',\n getAttrs(token) {\n // markdown-it URL-encodes backslashes in paths (\\ → %5C),\n // which breaks Windows local paths on roundtrip.\n // Decode to preserve the original path.\n let src = token.attrGet('src') || ''\n try { src = decodeURIComponent(src) } catch { /* keep as-is */ }\n return {\n src,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n alt: ((token.children as any[]) || []).map(c => c.content).join('') || '',\n title: token.attrGet('title') || '',\n }\n },\n },\n hardbreak: { node: 'hardbreak' },\n softbreak: { node: 'hardbreak', attrs: { isInline: true } },\n\n // ── Mark tokens ──\n em: { mark: 'em' },\n strong: { mark: 'strong' },\n s: { mark: 'strike_through' },\n code_inline: { mark: 'code', noCloseToken: true },\n link: {\n mark: 'link',\n getAttrs(token) {\n let href = token.attrGet('href') || ''\n // Decode percent-encoded non-ASCII UTF-8 characters (e.g. Chinese/Japanese/Korean)\n // so URLs preserve original characters through roundtrips.\n // Only decodes multi-byte UTF-8 sequences (C2-FF start bytes + 80-BF continuations),\n // leaving ASCII encodings like %20 (space), %28/%29 (parens) intact.\n href = href.replace(\n /%[C-F][0-9A-F](?:%[89AB][0-9A-F])+/gi,\n (m) => { try { return decodeURIComponent(m) } catch { return m } },\n )\n return {\n href,\n title: token.attrGet('title') || null,\n }\n },\n },\n}\n\n/**\n * Custom MarkdownParser that correctly handles GFM table structure.\n *\n * Two problems with the default prosemirror-markdown `block:` approach for tables:\n *\n * 1. `table_header` and `table_cell` both have `content: 'paragraph+'` in our schema.\n * prosemirror-markdown opens the cell block, then adds raw inline text via addText().\n * When closeNode() calls createAndFill(attrs, [text(\"A\")]), the content match\n * for `paragraph+` cannot fit a bare text node, so createAndFill() returns null\n * and the cell (and all its content) is silently dropped → empty table.\n *\n * 2. `table: content: 'table_header_row table_row+'` requires the first child to be\n * a `table_header_row`, but the default `tr` handler always creates `table_row`.\n * ProseMirror's createAndFill() then auto-inserts an empty `table_header_row`\n * at the front, leaving the real header data in a wrongly-typed `table_row`.\n *\n * Fix: override tr/th/td tokenHandlers in the constructor.\n */\nclass MorayaMarkdownParser extends MarkdownParser {\n /**\n * The schema this parser instance is bound to. Captured for use in\n * tokenHandler overrides (tr_open / th_open / etc.) so they reference the\n * caller-provided schema rather than the module-level defaultSchema.\n */\n public readonly schema: Schema\n\n constructor(schemaArg: Schema = defaultSchema) {\n super(schemaArg, md, parserTokens)\n this.schema = schemaArg\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const h: Record<string, (state: any, tok: any, tokens: any[], i: number) => void> =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).tokenHandlers\n\n function cellAlignment(tok: { attrGet(s: string): string | null }): string {\n const style = tok.attrGet('style') || ''\n const m = style.match(/text-align:\\s*(\\w+)/)\n return m && m[1] ? m[1] : 'left'\n }\n\n // tr_open: dispatch to table_header_row or table_row based on parent context\n h['tr_open'] = (state, _tok, tokens, i) => {\n let inThead = false\n for (let j = i - 1; j >= 0; j--) {\n if (tokens[j].type === 'thead_open') { inThead = true; break }\n if (tokens[j].type === 'thead_close' || tokens[j].type === 'tbody_open') break\n }\n state.openNode(inThead ? schemaArg.nodes.table_header_row : schemaArg.nodes.table_row, null)\n }\n h['tr_close'] = (state) => state.closeNode()\n\n // th_open/close: open table_header + inner paragraph so inline text lands correctly\n h['th_open'] = (state, tok) => {\n state.openNode(schemaArg.nodes.table_header, { alignment: cellAlignment(tok) })\n state.openNode(schemaArg.nodes.paragraph, null)\n }\n h['th_close'] = (state) => {\n state.closeNode() // close paragraph\n state.closeNode() // close table_header\n }\n\n // td_open/close: open table_cell + inner paragraph\n h['td_open'] = (state, tok) => {\n state.openNode(schemaArg.nodes.table_cell, { alignment: cellAlignment(tok) })\n state.openNode(schemaArg.nodes.paragraph, null)\n }\n h['td_close'] = (state) => {\n state.closeNode() // close paragraph\n state.closeNode() // close table_cell\n }\n\n // ── Empty link preservation ────────────────────────────────────\n // When markdown-it parses `[]()` or `[](url)`, it emits link_open → link_close\n // with no text token between them. ProseMirror discards marks with no content,\n // so the link completely disappears. Fix: detect empty-text links and insert\n // the raw markdown syntax as literal text instead of creating a mark.\n const defaultLinkOpen = h['link_open']\n const defaultLinkClose = h['link_close']\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n h['link_open'] = (state: any, tok: any, tokens: any[], i: number) => {\n // Check if there's actual content between link_open and link_close\n let hasContent = false\n for (let j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'link_close') break\n if (tokens[j].type === 'text' && tokens[j].content) {\n hasContent = true\n break\n }\n if (['image', 'code_inline', 'softbreak', 'hardbreak', 'html_inline'].includes(tokens[j].type)) {\n hasContent = true\n break\n }\n }\n\n if (!hasContent) {\n // Empty-text link: insert raw markdown syntax as literal text\n let href = tok.attrGet('href') || ''\n href = href.replace(\n /%[C-F][0-9A-F](?:%[89AB][0-9A-F])+/gi,\n (m: string) => { try { return decodeURIComponent(m) } catch { return m } },\n )\n const title = tok.attrGet('title')\n let literal = `[](${href}`\n if (title) literal += ` \"${title}\"`\n literal += ')'\n state.addText(literal)\n // Mark the corresponding link_close to be skipped\n for (let j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'link_close') {\n tokens[j].meta = { ...(tokens[j].meta || {}), skipClose: true }\n break\n }\n }\n return\n }\n\n defaultLinkOpen!(state, tok, tokens, i)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n h['link_close'] = (state: any, tok: any, tokens: any[], i: number) => {\n if (tok.meta?.skipClose) return\n defaultLinkClose!(state, tok, tokens, i)\n }\n\n // ── Paired inline HTML → marks ─────────────────────────────────\n // Pre-scanned paired tags (meta.htmlPaired) become openMark/closeMark\n // so the visual editor renders them with styling. Unpaired tags stay\n // as html_inline atom nodes for exact roundtrip fidelity.\n //\n // Special case: <audio>/<video> inline tags (single-line, e.g.\n // `<audio src=\"...\" controls></audio>`) are combined into a single\n // html_inline atom node so toDOM renders them as media players.\n const defaultTextHandler = h['text']\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n h['text'] = (state: any, tok: any, toks: any[], ii: number) => {\n if (tok.meta?.mediaSkip) return\n defaultTextHandler!(state, tok, toks, ii)\n }\n\n h['html_inline'] = (state, tok, tokens, i) => {\n // Skip tokens already consumed by audio/video combination\n if (tok.meta?.mediaSkip) return\n\n const content: string = tok.content\n\n // <audio>/<video> inline: combine opening + closing into single atom.\n const mediaMatch = content.match(/^<(audio|video)\\b/i)\n if (mediaMatch && mediaMatch[1]) {\n const tagName = mediaMatch[1].toLowerCase()\n const closeRe = new RegExp(`^</${tagName}\\\\s*>$`, 'i')\n let fullHtml = content\n for (let j = i + 1; j < tokens.length; j++) {\n const t = tokens[j]\n if (t.type === 'html_inline' && closeRe.test(t.content.trim())) {\n fullHtml += t.content\n t.meta = { ...(t.meta || {}), mediaSkip: true }\n break\n }\n if (t.content) fullHtml += t.content\n t.meta = { ...(t.meta || {}), mediaSkip: true }\n }\n state.addNode(schemaArg.nodes.html_inline, { value: fullHtml })\n return\n }\n\n if (tok.meta?.htmlPaired) {\n const htmlMark = schemaArg.marks.html_mark\n if (!htmlMark) {\n // Schema lacks html_mark — fall through to atom-node fallback\n state.addNode(schemaArg.nodes.html_inline, { value: content })\n return\n }\n if (!content.startsWith('</')) {\n // Opening tag → open mark\n const tagMatch = content.match(/^<([a-zA-Z][a-zA-Z0-9]*)/)\n const tagName = tagMatch && tagMatch[1] ? tagMatch[1].toLowerCase() : ''\n state.openMark(htmlMark.create({\n openTag: content,\n closeTag: `</${tagName}>`,\n }))\n } else {\n // Closing tag → close mark\n state.closeMark(htmlMark)\n }\n return\n }\n // Not paired → atom node (preserves current behavior)\n state.addNode(schemaArg.nodes.html_inline, { value: content })\n }\n\n // ── HTML <img> / <video> / <audio> tag: block → inline promotion ──\n // markdown-it tokenizes standalone <img> as html_block (renders as code block).\n // Promote to paragraph(html_inline) so the toDOM can render it as an image.\n // Source format is preserved: html_inline serializes attrs.value (original HTML).\n const defaultHtmlBlock = h['html_block']\n h['html_block'] = (state, tok, tokens, i) => {\n const content = tok.content.trim()\n if (/^<img\\s/i.test(content)) {\n // Extract all <img> tags — put them in ONE paragraph with inline\n // hardbreaks between them, matching markdown image behavior.\n const imgPattern = /<img\\s[^>]*\\/?>/gi\n const imgs = content.match(imgPattern)\n state.openNode(schemaArg.nodes.paragraph, null)\n if (imgs && imgs.length > 0) {\n for (let j = 0; j < imgs.length; j++) {\n if (j > 0) {\n state.addNode(schemaArg.nodes.hardbreak, { isInline: true })\n }\n state.addNode(schemaArg.nodes.html_inline, { value: imgs[j] })\n }\n } else {\n state.addNode(schemaArg.nodes.html_inline, { value: content })\n }\n state.closeNode()\n } else if (/^<(video|audio)\\b/i.test(content)) {\n // Promote <video>/<audio> blocks to paragraph(html_inline) so toDOM\n // renders them as actual media players instead of code blocks.\n state.openNode(schemaArg.nodes.paragraph, null)\n state.addNode(schemaArg.nodes.html_inline, { value: content })\n state.closeNode()\n } else {\n defaultHtmlBlock!(state, tok, tokens, i)\n }\n }\n }\n}\n\n/** Default parser bound to {@link defaultSchema} (used when caller doesn't pass a schema). */\nconst defaultParser = new MorayaMarkdownParser(defaultSchema)\n\n/**\n * Cache of parsers keyed by schema identity. Rebuilding the parser per call\n * would re-construct token handlers + retype-overrides on every parseMarkdown\n * invocation; this WeakMap avoids that. The defaultSchema entry is pre-seeded.\n */\nconst parserCache = new WeakMap<Schema, MorayaMarkdownParser>()\nparserCache.set(defaultSchema, defaultParser)\n\nfunction getParserFor(schema: Schema | undefined): MorayaMarkdownParser {\n if (!schema || schema === defaultSchema) return defaultParser\n let p = parserCache.get(schema)\n if (!p) {\n p = new MorayaMarkdownParser(schema)\n parserCache.set(schema, p)\n }\n return p\n}\n\n// ── Serializer ──────────────────────────────────────────────────\n\nconst serializer = new MarkdownSerializer(\n {\n // ── Block nodes ──\n doc(state, node) {\n state.renderContent(node)\n },\n paragraph(state, node) {\n if (node.content.size === 0) {\n state.write('')\n } else {\n state.renderInline(node)\n }\n state.closeBlock(node)\n },\n heading(state, node) {\n state.write(`${'#'.repeat(node.attrs.level as number)} `)\n // fromBlockStart=false: the `## ` prefix already prevents text from being\n // parsed as list markers / blockquote, so don't escape `1.`, `-`, `>` etc.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(state.renderInline as (n: PmNode, b?: boolean) => void)(node, false)\n state.closeBlock(node)\n },\n blockquote(state, node) {\n state.wrapBlock('> ', null, node, () => state.renderContent(node))\n },\n code_block(state, node) {\n const lang = (node.attrs.language as string) || ''\n const fenceLang = lang === 'text' ? '' : lang\n state.write(`\\`\\`\\`${fenceLang}\\n`)\n state.text(node.textContent, false)\n state.ensureNewLine()\n state.write('```')\n state.closeBlock(node)\n },\n horizontal_rule(state, node) {\n state.write('---')\n state.closeBlock(node)\n },\n bullet_list(state, node) {\n state.renderList(node, ' ', () => '- ')\n },\n ordered_list(state, node) {\n const start = (node.attrs.order as number) || 1\n state.renderList(node, ' ', (i: number) => `${start + i}. `)\n },\n list_item(state, node) {\n // Task list checkbox prefix\n if (node.attrs.checked != null) {\n const checkbox = node.attrs.checked ? '[x] ' : '[ ] '\n state.write(checkbox)\n }\n state.renderContent(node)\n },\n image(state, node) {\n const alt = state.esc((node.attrs.alt as string) || '', false)\n const src = (node.attrs.src as string) || ''\n const title = node.attrs.title as string | null | undefined\n if (title) {\n state.write(`}\")`)\n } else {\n state.write(``)\n }\n },\n hardbreak(state) {\n // Always use markdown hardbreak format (two spaces + newline)\n // for consistent parsing and roundtrip fidelity\n state.write(' \\n')\n },\n html_block(state, node) {\n state.text(node.textContent, false)\n state.closeBlock(node)\n },\n html_inline(state, node) {\n // Write the raw HTML back verbatim (no escaping); value attr holds the original HTML.\n state.text(node.attrs.value as string, false)\n },\n\n // ── Table nodes ──\n table(state, node) {\n // Collect alignment from header row\n const alignments: string[] = []\n const headerRow = node.child(0)\n headerRow.forEach(cell => {\n alignments.push((cell.attrs.alignment as string) || 'left')\n })\n\n // Render header row\n renderTableRow(state, headerRow)\n\n // Render separator\n const sep = alignments.map(a => {\n switch (a) {\n case 'center': return ':---:'\n case 'right': return '---:'\n default: return '---'\n }\n })\n state.write(`| ${sep.join(' | ')} |`)\n state.ensureNewLine()\n\n // Render data rows\n for (let i = 1; i < node.childCount; i++) {\n renderTableRow(state, node.child(i))\n }\n state.closeBlock(node)\n },\n table_header_row() { /* handled by table */ },\n table_row() { /* handled by table */ },\n table_header(state, node) {\n state.renderInline(node.firstChild!)\n },\n table_cell(state, node) {\n state.renderInline(node.firstChild!)\n },\n\n // ── Math nodes ──\n math_inline(state, node) {\n state.write(`$${node.textContent}$`)\n },\n math_block(state, node) {\n state.write('$$\\n')\n state.text((node.attrs.value as string) || node.textContent, false)\n state.ensureNewLine()\n state.write('$$')\n state.closeBlock(node)\n },\n\n // ── Definition list nodes ──\n defList(state, node) {\n state.renderContent(node)\n },\n defListTerm(state, node) {\n state.renderInline(node)\n state.closeBlock(node)\n },\n defListDescription(state, node) {\n state.write(': ')\n state.renderContent(node)\n },\n\n // ── Fallback for text node (shouldn't be needed but safe) ──\n text(state, node) {\n state.text(node.text || '')\n },\n },\n {\n // ── Mark serializers ──\n strong: {\n open: '**',\n close: '**',\n mixable: true,\n expelEnclosingWhitespace: true,\n },\n em: {\n open: '*',\n close: '*',\n mixable: true,\n expelEnclosingWhitespace: true,\n },\n code: {\n open(_state: MarkdownSerializerState, mark: Mark, parent: PmNode, index: number) {\n return isPlainURL(mark, parent, index, 1) ? '' : '`'\n },\n close(_state: MarkdownSerializerState, mark: Mark, parent: PmNode, index: number) {\n return isPlainURL(mark, parent, index, -1) ? '' : '`'\n },\n escape: false,\n },\n link: {\n open(_state, mark, parent, index) {\n return isPlainURL(mark, parent, index, 1) ? '<' : '['\n },\n close(state, mark, parent, index) {\n const href = mark.attrs.href as string\n const title = mark.attrs.title as string | null | undefined\n if (isPlainURL(mark, parent, index, -1)) {\n return '>'\n }\n return title\n ? `](${href} \"${state.esc(title, false)}\")`\n : `](${href})`\n },\n mixable: false,\n },\n strike_through: {\n open: '~~',\n close: '~~',\n mixable: true,\n expelEnclosingWhitespace: true,\n },\n html_mark: {\n open(_state: MarkdownSerializerState, mark: Mark) {\n return mark.attrs.openTag as string\n },\n close(_state: MarkdownSerializerState, mark: Mark) {\n return mark.attrs.closeTag as string\n },\n },\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ({\n hardBreakNodeName: 'hardbreak',\n strict: false,\n } as any),\n)\n\n/**\n * Helper: render a table row as `| cell1 | cell2 | ... |`\n *\n * Uses ProseMirror's built-in renderInline via output-buffer capture so that\n * ALL inline content (text, marks, hard breaks, math, images, etc.) is\n * serialized correctly — the same path used for headings and paragraphs.\n */\nfunction renderTableRow(state: MarkdownSerializerState, row: PmNode) {\n const cells: string[] = []\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = state as any\n row.forEach(cell => {\n // Cells with 'paragraph+' content: each paragraph is one \"line\" in the cell.\n // GFM cells are single-line, so join multiple paragraphs with a space.\n const parts: string[] = []\n cell.forEach(para => {\n if (para.type.name !== 'paragraph') return\n // Capture renderInline output by swapping the serializer's output buffer.\n //\n // IMPORTANT: prosemirror-markdown's text() calls write() for every line,\n // and write() calls flushClose() which resets this.closed. We must save\n // and restore BOTH out AND closed so the pending block-separator (the\n // blank line between the preceding paragraph and this table) is not\n // accidentally consumed here — it must survive until state.write('| … |')\n // fires at the end of this function, where flushClose() will emit it.\n const savedOut: string = s.out\n const savedClosed = s.closed\n s.out = ''\n s.closed = null\n state.renderInline(para)\n const piece: string = (s.out as string).replace(/\\n/g, ' ').trim()\n s.out = savedOut\n s.closed = savedClosed\n parts.push(piece)\n })\n cells.push(parts.join(' '))\n })\n state.write(`| ${cells.join(' | ')} |`)\n state.ensureNewLine()\n}\n\n/**\n * Check if a link mark represents a plain URL (autolink style).\n * If so, serialize as `<url>` instead of `[text](url)`.\n */\nfunction isPlainURL(mark: Mark, parent: PmNode, index: number, side: number): boolean {\n if (mark.attrs.title || !/^\\w+:/.test(mark.attrs.href as string)) return false\n const content = parent.child(index + (side < 0 ? -1 : 0))\n if (\n !content.isText ||\n content.text !== mark.attrs.href ||\n content.marks[content.marks.length - 1] !== mark\n ) {\n return false\n }\n if (index === (side < 0 ? 1 : parent.childCount - 1)) return true\n const next = parent.child(index + (side < 0 ? -2 : 1))\n return !mark.isInSet(next.marks)\n}\n\n// ── Public API ──────────────────────────────────────────────────\n\n/**\n * Ensure display math blocks ($$…$$) are surrounded by blank lines so\n * markdown-it-texmath parses them as math_block, not math_inline_double.\n * Without blank lines, they get absorbed into the preceding paragraph as\n * inline tokens, causing wrong rendering and roundtrip corruption.\n */\nfunction normalizeMathBlocks(text: string): string {\n if (!text.includes('$$')) return text\n\n const lines = text.split('\\n')\n const result: string[] = []\n let inFence = false\n let inMathBlock = false\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? ''\n const trimmed = line.trim()\n\n // Skip fenced code blocks\n if (!inMathBlock && /^(`{3,}|~{3,})/.test(trimmed)) {\n inFence = !inFence\n result.push(line)\n continue\n }\n if (inFence) {\n result.push(line)\n continue\n }\n\n if (trimmed === '$$') {\n if (!inMathBlock) {\n // Opening $$: ensure blank line before\n const last = result[result.length - 1]\n if (result.length > 0 && last !== undefined && last.trim() !== '') {\n result.push('')\n }\n result.push(line)\n inMathBlock = true\n } else {\n // Closing $$\n result.push(line)\n inMathBlock = false\n // Ensure blank line after if next line is non-empty\n const next = lines[i + 1]\n if (next !== undefined && next.trim() !== '') {\n result.push('')\n }\n }\n } else {\n result.push(line)\n }\n }\n\n return result.join('\\n')\n}\n\n/**\n * Normalize smart/curly quotes to straight quotes in markdown syntax positions.\n * Only targets image/link title delimiters to preserve intentional smart quotes in prose.\n * Pattern: `](url \"title\")` or `](url 'title')` with curly quotes.\n */\nfunction normalizeSmartQuotes(text: string): string {\n // Quick bail: no curly quotes at all\n if (!/[“”„‟‘’‚‛]/.test(text)) return text\n\n return text\n .replace(\n /(\\]\\([^\\n)]*\\s)“([^”\\n]*)”(\\s*\\))/g,\n (_m, pre, title, post) => `${pre}\"${title}\"${post}`,\n )\n .replace(\n /(\\]\\([^\\n)]*\\s)“([^”\\n]*)”(\\s*\\))/g,\n (_m, pre, title, post) => `${pre}\"${title}\"${post}`,\n )\n // Also handle single curly quotes as title delimiters\n .replace(\n /(\\]\\([^\\n)]*\\s)‘([^’\\n]*)’(\\s*\\))/g,\n (_m, pre, title, post) => `${pre}'${title}'${post}`,\n )\n}\n\n/**\n * Parse a markdown string into a ProseMirror document node. Never throws (§4.5).\n *\n * @param markdown Source markdown string (may contain frontmatter, math, html, etc.).\n * @param schemaArg Optional consumer schema. When provided, the returned doc's\n * `node.type` references the consumer's NodeType identities,\n * allowing it to be loaded directly into an `EditorState.create`\n * built with that same schema. Defaults to {@link defaultSchema}.\n */\nexport function parseMarkdown(markdown: string, schemaArg?: Schema): PmNode {\n const p = getParserFor(schemaArg)\n try {\n return p.parse(normalizeSmartQuotes(normalizeMathBlocks(markdown)))\n } catch (err) {\n if (typeof console !== 'undefined' && console.warn) {\n console.warn('[parseMarkdown] best-effort fallback for malformed input:', err)\n }\n return p.schema.topNodeType.createAndFill()!\n }\n}\n\nconst ASYNC_PARSE_THRESHOLD = 50_000\n\n/**\n * Async version of parseMarkdown. For large files (≥50KB), yields to the\n * event loop via setTimeout(0) so the main thread stays responsive.\n * §4.5: never rejects.\n */\nexport function parseMarkdownAsync(markdown: string, schemaArg?: Schema): Promise<PmNode> {\n const p = getParserFor(schemaArg)\n const normalized = normalizeSmartQuotes(normalizeMathBlocks(markdown))\n if (normalized.length < ASYNC_PARSE_THRESHOLD) {\n return Promise.resolve(parseMarkdown(normalized, schemaArg))\n }\n return new Promise(resolve => setTimeout(() => {\n try {\n resolve(p.parse(normalized))\n } catch {\n resolve(p.schema.topNodeType.createAndFill()!)\n }\n }, 0))\n}\n\n/**\n * Serialize a ProseMirror document node to a markdown string. Never throws (§4.5).\n */\nexport function serializeMarkdown(doc: PmNode): string {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let result = serializer.serialize(doc, ({ tightLists: true } as any))\n // Un-escape markdown link syntax that the serializer's esc() over-escapes.\n result = result.replace(/\\\\\\[([^\\\\\\[\\]]*)\\\\\\]\\(([^)]*)\\)/g, '[$1]($2)')\n // Strip zero-width spaces used as cursor targets after inline code marks.\n result = result.replace(//g, '')\n return result\n}\n","import { type Command, type EditorState, type Transaction } from 'prosemirror-state'\nimport {\n toggleMark,\n setBlockType,\n wrapIn,\n lift,\n} from 'prosemirror-commands'\nimport { wrapInList, liftListItem } from 'prosemirror-schema-list'\nimport { type Node, type MarkType, type NodeType, type Attrs } from 'prosemirror-model'\nimport { defaultSchema } from './schema'\n\n/**\n * Core editing commands (§3.2).\n *\n * Pure ProseMirror Commands: `(state, dispatch?) => boolean`. No IO,\n * no async. Consumer extensions (findAndReplace / quickOpen / etc.) live\n * in their own repos and are NOT exported from this package.\n */\n\nconst schema = defaultSchema\n\nfunction markType(name: string): MarkType {\n const m = schema.marks[name]\n if (!m) throw new Error(`[@moraya/core] mark \"${name}\" not in schema`)\n return m\n}\n\nfunction nodeType(name: string): NodeType {\n const n = schema.nodes[name]\n if (!n) throw new Error(`[@moraya/core] node \"${name}\" not in schema`)\n return n\n}\n\nexport const toggleBold: Command = (state, dispatch) =>\n toggleMark(markType('strong'))(state, dispatch)\n\nexport const toggleItalic: Command = (state, dispatch) =>\n toggleMark(markType('em'))(state, dispatch)\n\nexport const toggleStrikethrough: Command = (state, dispatch) =>\n toggleMark(markType('strike_through'))(state, dispatch)\n\nexport const toggleCode: Command = (state, dispatch) =>\n toggleMark(markType('code'))(state, dispatch)\n\nexport function setHeading(level: 1 | 2 | 3 | 4 | 5 | 6): Command {\n return (state, dispatch) => setBlockType(nodeType('heading'), { level })(state, dispatch)\n}\n\nexport const toggleBlockquote: Command = (state, dispatch) => {\n // If already in blockquote, lift; else wrap.\n const $from = state.selection.$from\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'blockquote') {\n return lift(state, dispatch)\n }\n }\n return wrapIn(nodeType('blockquote'))(state, dispatch)\n}\n\nexport const toggleOrderedList: Command = (state, dispatch) =>\n wrapInList(nodeType('ordered_list'))(state, dispatch)\n\nexport const toggleBulletList: Command = (state, dispatch) =>\n wrapInList(nodeType('bullet_list'))(state, dispatch)\n\n/**\n * Toggle a list: wrap if not in this list type, lift out if already in it.\n * Schema-agnostic — uses `state.schema` rather than `defaultSchema`.\n */\nfunction makeToggleList(typeName: 'bullet_list' | 'ordered_list'): Command {\n return (state, dispatch, view) => {\n const listType = state.schema.nodes[typeName]\n const listItemType = state.schema.nodes.list_item\n if (!listType || !listItemType) return false\n const { $from } = state.selection\n for (let d = $from.depth; d >= 0; d--) {\n if ($from.node(d).type === listType) {\n return liftListItem(listItemType)(state, dispatch, view)\n }\n }\n return wrapInList(listType)(state, dispatch, view)\n }\n}\n\nexport const wrapInBulletList: Command = makeToggleList('bullet_list')\nexport const wrapInOrderedList: Command = makeToggleList('ordered_list')\n\n/**\n * Wrap current block(s) in a bullet list with task-list items (checked: false).\n * Two-step: first apply wrapInList against the bullet_list type, then\n * post-process newly-created list_item nodes within the affected range to\n * set `checked: false` so they render as task items.\n */\nexport const wrapInTaskList: Command = (state, dispatch) => {\n const bulletListType = state.schema.nodes.bullet_list\n const listItemType = state.schema.nodes.list_item\n if (!bulletListType || !listItemType) return false\n if (!wrapInList(bulletListType)(state)) return false\n if (!dispatch) return true\n\n let listTr: Transaction | undefined\n wrapInList(bulletListType)(state, (tr) => { listTr = tr })\n if (!listTr) return false\n\n const { from, to } = listTr.selection\n const updates: Array<{ pos: number; attrs: Attrs }> = []\n listTr.doc.nodesBetween(\n Math.max(0, from - 200),\n Math.min(listTr.doc.content.size, to + 200),\n (node, pos) => {\n if (node.type === listItemType && node.attrs.checked === null) {\n updates.push({ pos, attrs: { ...node.attrs, checked: false } })\n }\n },\n )\n for (let i = updates.length - 1; i >= 0; i--) {\n const u = updates[i]!\n listTr.setNodeMarkup(u.pos, undefined, u.attrs)\n }\n dispatch(listTr.scrollIntoView())\n return true\n}\n\nexport const toggleCodeBlock: Command = (state, dispatch) => {\n const cb = nodeType('code_block')\n if (state.selection.$from.parent.type === cb) {\n return setBlockType(nodeType('paragraph'))(state, dispatch)\n }\n return setBlockType(cb)(state, dispatch)\n}\n\nexport const insertHorizontalRule: Command = (state, dispatch) => {\n if (dispatch) {\n dispatch(state.tr.replaceSelectionWith(nodeType('horizontal_rule').create()))\n }\n return true\n}\n\n/**\n * Insert a 3×3 placeholder table. Note: full table support requires\n * prosemirror-tables setup at editor mount time; this command falls back\n * to inserting a markdown-style code block snippet if tables aren't\n * registered (true for this minimal v0.1.0 schema).\n */\nexport const insertTable: Command = (state, dispatch) => {\n const tableType = schema.nodes.table\n if (!tableType) {\n // Insert pipe-table markdown directly into a paragraph.\n if (dispatch) {\n const text = '\\n\\n| Col 1 | Col 2 | Col 3 |\\n|---|---|---|\\n| | | |\\n| | | |\\n\\n'\n dispatch(state.tr.insertText(text))\n }\n return true\n }\n return false\n}\n\nexport const insertMathBlock: Command = (state, dispatch) => {\n const mathBlock = schema.nodes.math_block\n if (!mathBlock) {\n if (dispatch) {\n dispatch(state.tr.insertText('\\n$$\\n\\\\\\n$$\\n'))\n }\n return true\n }\n if (dispatch) {\n const node = mathBlock.create({ value: '' })\n dispatch(state.tr.replaceSelectionWith(node))\n }\n return true\n}\n\nexport function toggleLink(href?: string): Command {\n return (state, dispatch) => {\n const link = markType('link')\n const { from, to } = state.selection\n if (state.doc.rangeHasMark(from, to, link)) {\n if (dispatch) dispatch(state.tr.removeMark(from, to, link))\n return true\n }\n if (!href) return false\n if (dispatch) {\n dispatch(state.tr.addMark(from, to, link.create({ href })))\n }\n return true\n }\n}\n\nexport function insertImage(src: string, alt?: string): Command {\n return (state, dispatch) => {\n const img = nodeType('image').create({ src, alt: alt ?? null })\n if (dispatch) {\n dispatch(state.tr.replaceSelectionWith(img))\n }\n return true\n }\n}\n\n// Re-export for ergonomic imports\nexport type { Command, EditorState, Transaction, Node }\n","/**\n * Definition list input rule.\n *\n * Typing `: ` (colon + 3 spaces) at the start of a line wraps the current\n * block in a definition description inside a definition list.\n *\n * Note: node schemas are defined in `schema.ts`, markdown parsing is handled\n * by `markdown-it-deflist` in `markdown.ts`.\n */\n\nimport { wrappingInputRule, type InputRule } from 'prosemirror-inputrules'\nimport type { Schema } from 'prosemirror-model'\n\n/**\n * Create the def-list input rule against a specific schema.\n *\n * The schema parameter is required because the rule binds to a NodeType, and\n * each consumer-injected schema (per `createSchema(config)`) is a distinct\n * Schema instance with its own NodeTypes.\n */\nexport function createDefListInputRule(schema: Schema): InputRule {\n return wrappingInputRule(\n /^:\\s{3}$/,\n schema.nodes.defListDescription!,\n )\n}\n","/**\n * Enter key handler — unified plugin for all Enter-key variants.\n *\n * In table cells:\n * - `Ctrl/Cmd+Enter` → add a new row below\n * - `Shift+Enter` → insert hard break (`<br>`)\n * - Plain `Enter` → move to same column in next row; exit table from last row\n *\n * In paragraphs:\n * - `Enter` → split the current block into a new paragraph (no `<br/>`).\n * - `Enter` after ` ``` ` or ` ```language ` → create code block.\n * - `Enter` after `| col1 | col2 |` → create GFM table with header + empty data row.\n *\n * Uses `handleKeyDown` (props-level) which has higher priority than keymaps,\n * ensuring this runs before the base keymap's hardbreak / splitBlock handlers.\n */\n\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state'\nimport type { Schema, Node as PmNode } from 'prosemirror-model'\nimport {\n splitBlock,\n chainCommands,\n newlineInCode,\n createParagraphNear,\n liftEmptyBlock,\n} from 'prosemirror-commands'\nimport { addRowAfter } from 'prosemirror-tables'\n\nconst enterHandlerKey = new PluginKey('moraya-enter-handler')\n\n/**\n * Parse a pipe-delimited table header line into cell texts.\n * Returns null if the text is not a valid table header (needs >= 2 columns,\n * must start/end with |, rejects separator-only rows like `| --- | --- |`).\n */\nfunction parsePipeTableHeader(text: string): string[] | null {\n if (!/^\\|(.+\\|)+\\s*$/.test(text)) return null\n\n const cells = text.split('|').slice(1, -1).map(s => s.trim())\n if (cells.length < 2) return null\n\n // Reject separator-only rows (e.g. | --- | :---: | ---: |)\n if (cells.every(c => /^:?-+:?$/.test(c))) return null\n\n return cells\n}\n\n/**\n * Build a GFM table node from header text values using the supplied schema.\n * Creates: header row (pre-filled) + one empty data row.\n */\nfunction buildTableFromHeaders(schema: Schema, headers: string[]): PmNode | null {\n const tableType = schema.nodes.table\n const headerRowType = schema.nodes.table_header_row\n const dataRowType = schema.nodes.table_row\n const headerCellType = schema.nodes.table_header\n const dataCellType = schema.nodes.table_cell\n const paragraphType = schema.nodes.paragraph\n\n if (!tableType || !headerRowType || !dataRowType ||\n !headerCellType || !dataCellType || !paragraphType) {\n return null\n }\n\n const headerCells = headers.map(text => {\n const para = text\n ? paragraphType.create(null, schema.text(text))\n : paragraphType.create()\n return headerCellType.create({ alignment: 'left' }, para)\n })\n\n const emptyCells = headers.map(() =>\n dataCellType.createAndFill({ alignment: 'left' })!,\n )\n\n const headerRow = headerRowType.create(null, headerCells)\n const dataRow = dataRowType.create(null, emptyCells)\n\n return tableType.create(null, [headerRow, dataRow])\n}\n\n/**\n * Enter handler plugin. Operates entirely off `view.state.schema`, so it works\n * against any consumer-injected schema produced by `createSchema(config)`.\n */\nexport function createEnterHandlerPlugin(): Plugin {\n const enterCommand = chainCommands(\n newlineInCode,\n createParagraphNear,\n liftEmptyBlock,\n splitBlock,\n )\n\n return new Plugin({\n key: enterHandlerKey,\n props: {\n handleKeyDown(view, event) {\n if (event.isComposing || event.key !== 'Enter') return false\n\n const { $from } = view.state.selection\n\n // Single depth traversal to determine context: table cell or list item\n let inTable = false\n let cellDepth = -1\n let inListItem = false\n for (let d = $from.depth; d > 0; d--) {\n const nodeName = $from.node(d).type.name\n if (nodeName === 'table_cell' || nodeName === 'table_header') {\n inTable = true\n cellDepth = d\n break\n }\n if (nodeName === 'list_item') {\n inListItem = true\n break\n }\n }\n\n // ── Table cell ──\n if (inTable) {\n // Ctrl/Cmd+Enter → add row after and move cursor there\n if ((event.ctrlKey || event.metaKey) && !event.shiftKey) {\n event.preventDefault()\n addRowAfter(view.state, view.dispatch)\n\n const { $from: $cur } = view.state.selection\n for (let d = $cur.depth; d > 0; d--) {\n const name = $cur.node(d).type.name\n if (name === 'table_row' || name === 'table_header_row') {\n try {\n const rowEnd = $cur.after(d)\n const $newRow = view.state.doc.resolve(rowEnd + 1)\n view.dispatch(\n view.state.tr.setSelection(TextSelection.near($newRow)).scrollIntoView(),\n )\n } catch { /* new row at table boundary */ }\n break\n }\n }\n return true\n }\n\n // Shift+Enter → insert hard break\n if (event.shiftKey && !event.ctrlKey && !event.metaKey) {\n event.preventDefault()\n const hardbreak = view.state.schema.nodes.hardbreak\n if (hardbreak) {\n const tr = view.state.tr.replaceSelectionWith(hardbreak.create({ isInline: false }))\n view.dispatch(tr.scrollIntoView())\n }\n return true\n }\n\n // Plain Enter → move to same column in next row; exit table from last row\n if (!event.shiftKey && !event.ctrlKey && !event.metaKey) {\n event.preventDefault()\n\n if (cellDepth < 2) return true // safety guard\n\n const rowDepth = cellDepth - 1\n const tableDepth = cellDepth - 2\n const colIndex = $from.index(rowDepth)\n const rowIndex = $from.index(tableDepth)\n const tableNode = $from.node(tableDepth)\n const tableStart = $from.start(tableDepth)\n\n if (rowIndex === tableNode.childCount - 1) {\n // Last row → exit table: move to next block, or insert paragraph\n const tableEnd = $from.after(tableDepth)\n const afterNode = view.state.doc.nodeAt(tableEnd)\n if (afterNode) {\n const $target = view.state.doc.resolve(tableEnd + 1)\n view.dispatch(view.state.tr.setSelection(TextSelection.near($target)).scrollIntoView())\n } else {\n const paragraph = view.state.schema.nodes.paragraph\n if (paragraph) {\n const tr = view.state.tr.insert(tableEnd, paragraph.create())\n const $target = tr.doc.resolve(tableEnd + 1)\n tr.setSelection(TextSelection.near($target))\n view.dispatch(tr.scrollIntoView())\n }\n }\n } else {\n // Move to same column in next row\n const nextRow = tableNode.child(rowIndex + 1)\n const safeCol = Math.min(colIndex, nextRow.childCount - 1)\n let targetPos = tableStart\n for (let r = 0; r <= rowIndex; r++) {\n targetPos += tableNode.child(r).nodeSize\n }\n targetPos += 1 // enter next row\n for (let c = 0; c < safeCol; c++) {\n targetPos += nextRow.child(c).nodeSize\n }\n targetPos += 1 // enter target cell\n const $target = view.state.doc.resolve(targetPos)\n view.dispatch(view.state.tr.setSelection(TextSelection.near($target)).scrollIntoView())\n }\n return true\n }\n\n return false\n }\n\n // ── List item: let prosemirror-schema-list keymap handle splitListItem ──\n if (inListItem) return false\n\n // ── Plain Enter (no modifiers) in non-table, non-list context ──\n if (!event.shiftKey && !event.metaKey && !event.ctrlKey) {\n // Check if current line is a code fence (```language)\n if ($from.parent.type.name === 'paragraph') {\n const text = $from.parent.textContent\n\n // ```language or bare ``` creates a code block.\n // Guard: cursor must be at end of paragraph (user finished typing the fence).\n const match = $from.parentOffset === text.length\n ? text.match(/^```(\\S*)\\s*$/)\n : null\n if (match) {\n const language = match[1] ?? ''\n const codeBlockType = view.state.schema.nodes.code_block\n if (codeBlockType) {\n const pos = $from.before()\n const end = $from.after()\n const tr = view.state.tr\n tr.replaceWith(pos, end, codeBlockType.create({ language }))\n view.dispatch(tr)\n return true\n }\n }\n\n // Pipe-separated table header: | col1 | col2 | ... |\n // Only trigger when cursor is at the END of the paragraph (same guard\n // as the code-fence check above). If the cursor is mid-line the user\n // is editing the header text, not finishing it — fall through to splitBlock.\n const headers = $from.parentOffset === text.length\n ? parsePipeTableHeader(text)\n : null\n if (headers) {\n // Ensure the parent context allows a table node (not inside blockquote/table cell)\n const $para = view.state.doc.resolve($from.before())\n const parentNode = $para.node($para.depth)\n const tableType = view.state.schema.nodes.table\n if (tableType && parentNode.type.contentMatch.matchType(tableType)) {\n const tableNode = buildTableFromHeaders(view.state.schema, headers)\n if (tableNode) {\n const pos = $from.before()\n const end = $from.after()\n const tr = view.state.tr\n tr.replaceWith(pos, end, tableNode)\n\n // Place cursor in first cell of the data row\n const inserted = tr.doc.nodeAt(pos)\n if (inserted && inserted.childCount >= 2) {\n const headerRowSize = inserted.child(0).nodeSize\n const $dataRow = tr.doc.resolve(pos + 1 + headerRowSize + 1)\n tr.setSelection(TextSelection.near($dataRow))\n }\n tr.scrollIntoView()\n view.dispatch(tr)\n return true\n }\n }\n }\n }\n return enterCommand(view.state, view.dispatch, view)\n }\n\n return false\n },\n },\n })\n}\n","/**\n * Cursor syntax plugin — Typora-style source-syntax overlay.\n *\n * Shows the source markdown delimiters (`# `, `> `, `**`, `*`, `` ` ``, `~~`)\n * around the cursor position so users see the underlying syntax while editing\n * rendered prose. Uses ProseMirror Decoration widgets with `side: ±1` so the\n * widgets sit visually adjacent to the cursor without becoming part of the\n * editable text.\n *\n * Block-level prefixes shown:\n * - heading 1-6 → `# `, `## `, ... `###### `\n * - blockquote → `> `\n *\n * Inline mark delimiters shown when cursor is inside the mark:\n * - strong → `**` ... `**`\n * - em → `*` ... `*`\n * - code → `` ` `` ... `` ` ``\n * - strike_through → `~~` ... `~~`\n *\n * Link marks are handled by `link-text-plugin` (expand/collapse pattern).\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport type { EditorState } from 'prosemirror-state'\nimport { Decoration, DecorationSet } from 'prosemirror-view'\nimport type { MarkType } from 'prosemirror-model'\n\nconst pluginKey = new PluginKey('moraya-cursor-syntax')\n\nconst HEADING_PREFIX: Record<number, string> = {\n 1: '# ',\n 2: '## ',\n 3: '### ',\n 4: '#### ',\n 5: '##### ',\n 6: '###### ',\n}\n\nconst MARK_DELIMITERS: Record<string, { open: string; close: string }> = {\n strong: { open: '**', close: '**' },\n em: { open: '*', close: '*' },\n code: { open: '`', close: '`' },\n strike_through: { open: '~~', close: '~~' },\n}\n\nfunction makeWidget(text: string, className: string): () => HTMLSpanElement {\n return () => {\n const span = document.createElement('span')\n span.className = className\n span.textContent = text\n return span\n }\n}\n\n/**\n * Find the contiguous range of `markType` in the current textblock that contains `pos`.\n * Returns absolute document positions {from, to}, or null if cursor is not inside that mark.\n */\nfunction getMarkRange(\n state: EditorState,\n pos: number,\n markType: MarkType,\n): { from: number; to: number } | null {\n const $pos = state.doc.resolve(pos)\n const parent = $pos.parent\n if (!parent.isTextblock) return null\n\n const base = $pos.start() // absolute position of parent content start\n const runs: Array<{ from: number; to: number }> = []\n let runFrom = -1\n let nodePos = base\n\n for (let i = 0; i < parent.childCount; i++) {\n const child = parent.child(i)\n const childEnd = nodePos + child.nodeSize\n\n if (markType.isInSet(child.marks)) {\n if (runFrom === -1) runFrom = nodePos\n } else {\n if (runFrom !== -1) {\n runs.push({ from: runFrom, to: nodePos })\n runFrom = -1\n }\n }\n nodePos = childEnd\n }\n if (runFrom !== -1) runs.push({ from: runFrom, to: nodePos })\n\n // Use half-open interval [from, to): include left boundary, exclude right boundary.\n // Position exactly at r.to is the \"just exited\" point — no decoration there prevents\n // the DOM-mutation-driven cursor bounce when moving from mark boundary to ZWSP position.\n return runs.find(r => pos >= r.from && pos < r.to) ?? null\n}\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const { selection } = state\n // Only show decorations when cursor is a single collapsed point (no selection)\n if (!selection.empty) return DecorationSet.empty\n\n const $from = selection.$from\n const decorations: Decoration[] = []\n const pos = $from.pos\n const depth = $from.depth\n const parent = $from.parent\n\n // 1. Block-level: heading prefix\n if (parent.type === state.schema.nodes.heading) {\n const level = parent.attrs.level as number\n const prefix = HEADING_PREFIX[level] ?? '# '\n const contentStart = $from.start(depth)\n decorations.push(\n Decoration.widget(contentStart, makeWidget(prefix, 'syntax-md-prefix'), {\n side: -1,\n key: 'heading-prefix',\n }),\n )\n }\n\n // 2. Block-level: blockquote prefix at start of current paragraph\n for (let d = depth - 1; d >= 1; d--) {\n if ($from.node(d).type === state.schema.nodes.blockquote) {\n const contentStart = $from.start(depth)\n decorations.push(\n Decoration.widget(contentStart, makeWidget('> ', 'syntax-md-prefix'), {\n side: -1,\n key: 'bq-prefix',\n }),\n )\n break\n }\n }\n\n // 3. Inline marks: strong, em, code, strike_through\n for (const [markName, delim] of Object.entries(MARK_DELIMITERS)) {\n const markType = state.schema.marks[markName]\n if (!markType) continue\n\n const range = getMarkRange(state, pos, markType)\n if (!range) continue\n\n decorations.push(\n Decoration.widget(range.from, makeWidget(delim.open, 'syntax-md-mark'), {\n side: -1,\n key: `${markName}-open`,\n }),\n Decoration.widget(range.to, makeWidget(delim.close, 'syntax-md-mark'), {\n side: 1,\n key: `${markName}-close`,\n }),\n )\n }\n\n // 4. Link marks are handled by link-text-plugin (expand/collapse)\n\n return DecorationSet.create(state.doc, decorations)\n}\n\nexport function createCursorSyntaxPlugin(): Plugin {\n return new Plugin({\n key: pluginKey,\n state: {\n init(_, state) {\n return buildDecorations(state)\n },\n apply(tr, old, _, newState) {\n // Only recompute when selection or document changes\n if (!tr.selectionSet && !tr.docChanged) return old\n return buildDecorations(newState)\n },\n },\n props: {\n decorations(state) {\n return this.getState(state)\n },\n },\n })\n}\n","/**\n * Link text plugin — Typora-style inline link editing:\n *\n * 1. **Decoration**: Scans text nodes for `[...](...)` literal patterns and\n * applies a muted CSS class so users can distinguish link syntax from text.\n *\n * 2. **Collapse**: When cursor leaves a `[text](url)` pattern (both non-empty),\n * auto-convert to a ProseMirror link mark (rendered as clickable link).\n *\n * 3. **Expand**: When cursor enters a rendered link mark, replace the mark\n * with literal text `[text](url)` so the user can edit both text and URL\n * directly inline.\n *\n * Schema-agnostic: uses `state.schema.marks.link` rather than an imported\n * singleton, so the plugin works against any consumer-injected schema.\n */\n\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state'\nimport type { EditorState } from 'prosemirror-state'\nimport { Decoration, DecorationSet } from 'prosemirror-view'\n\nconst pluginKey = new PluginKey('moraya-link-text')\n\n/** Matches [text](url) for decoration — allows empty text or url. */\nconst LINK_PATTERN_DECO = /\\[([^\\]]*)\\]\\(([^)]*)\\)/g\n\n/** Matches [text](url) for conversion — requires non-empty text AND url. */\nconst LINK_PATTERN_CONVERT = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g\n\ninterface LinkMatch {\n from: number\n to: number\n text: string\n url: string\n}\n\ninterface LinkMarkInfo {\n from: number\n to: number\n text: string\n href: string\n}\n\n/**\n * Find all [text](url) literal text patterns NOT inside a link mark.\n */\nfunction findLinkPatterns(state: EditorState, regex: RegExp): LinkMatch[] {\n const matches: LinkMatch[] = []\n const linkType = state.schema.marks.link\n\n state.doc.descendants((node, pos) => {\n if (!node.isText || !node.text) return\n if (linkType && linkType.isInSet(node.marks)) return\n\n regex.lastIndex = 0\n let m: RegExpExecArray | null\n while ((m = regex.exec(node.text)) !== null) {\n matches.push({\n from: pos + m.index,\n to: pos + m.index + m[0].length,\n text: m[1] ?? '',\n url: m[2] ?? '',\n })\n }\n })\n\n return matches\n}\n\n/**\n * Find [text](url) patterns only within the textblock containing `pos`.\n * Much cheaper than full-doc scan for appendTransaction checks.\n */\nfunction findLinkPatternsInBlock(state: EditorState, pos: number, regex: RegExp): LinkMatch[] {\n const matches: LinkMatch[] = []\n const linkType = state.schema.marks.link\n let resolved\n try { resolved = state.doc.resolve(pos) } catch { return matches }\n const parent = resolved.parent\n if (!parent.isTextblock) return matches\n\n const base = resolved.start()\n let nodePos = base\n for (let i = 0; i < parent.childCount; i++) {\n const child = parent.child(i)\n if (child.isText && child.text && !(linkType && linkType.isInSet(child.marks))) {\n regex.lastIndex = 0\n let m: RegExpExecArray | null\n while ((m = regex.exec(child.text)) !== null) {\n matches.push({\n from: nodePos + m.index,\n to: nodePos + m.index + m[0].length,\n text: m[1] ?? '',\n url: m[2] ?? '',\n })\n }\n }\n nodePos += child.nodeSize\n }\n return matches\n}\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const matches = findLinkPatterns(state, LINK_PATTERN_DECO)\n if (matches.length === 0) return DecorationSet.empty\n\n const decorations = matches.map((m) =>\n Decoration.inline(m.from, m.to, { class: 'link-text-syntax' }),\n )\n return DecorationSet.create(state.doc, decorations)\n}\n\nfunction cursorInsidePattern(pos: number, matches: LinkMatch[]): boolean {\n return matches.some((m) => pos >= m.from && pos <= m.to)\n}\n\n/**\n * Find link mark range containing `pos`. Returns mark info or null.\n */\nfunction findLinkMarkAtPos(state: EditorState, pos: number): LinkMarkInfo | null {\n const linkType = state.schema.marks.link\n if (!linkType) return null\n\n let resolved\n try { resolved = state.doc.resolve(pos) } catch { return null }\n const parent = resolved.parent\n if (!parent.isTextblock) return null\n\n const base = resolved.start()\n let runFrom = -1\n let runTo = -1\n let href = ''\n const textParts: string[] = []\n let nodePos = base\n\n for (let i = 0; i < parent.childCount; i++) {\n const child = parent.child(i)\n const childEnd = nodePos + child.nodeSize\n const lm = linkType.isInSet(child.marks)\n\n if (lm) {\n if (runFrom === -1) {\n runFrom = nodePos\n href = (lm.attrs.href as string) || ''\n textParts.length = 0\n }\n textParts.push(child.text || '')\n runTo = childEnd\n } else {\n if (runFrom !== -1 && pos >= runFrom && pos <= runTo) {\n return { from: runFrom, to: runTo, text: textParts.join(''), href }\n }\n runFrom = -1\n runTo = -1\n href = ''\n textParts.length = 0\n }\n nodePos = childEnd\n }\n\n if (runFrom !== -1 && pos >= runFrom && pos <= runTo) {\n return { from: runFrom, to: runTo, text: textParts.join(''), href }\n }\n return null\n}\n\nexport function createLinkTextPlugin(): Plugin {\n return new Plugin({\n key: pluginKey,\n\n state: {\n init(_, state) { return buildDecorations(state) },\n apply(tr, old, _, newState) {\n // Decorations depend only on document content, not cursor position.\n // Selection-only changes can reuse existing decorations via mapping.\n if (!tr.docChanged) return old\n // Full-delete: new doc is tiny, rebuild directly (skip mapping old decos)\n if (tr.getMeta('full-delete')) return DecorationSet.empty\n return buildDecorations(newState)\n },\n },\n\n props: {\n decorations(state) { return this.getState(state) },\n },\n\n appendTransaction(transactions, oldState, newState) {\n // Skip if this plugin already produced a transaction in this batch\n if (transactions.some((tr) => tr.getMeta(pluginKey))) return null\n\n // Skip for full-delete transactions (entire document replaced)\n if (transactions.some((tr) => tr.getMeta('full-delete'))) return null\n\n const selChanged = transactions.some((tr) => tr.selectionSet)\n const docChanged = transactions.some((tr) => tr.docChanged)\n if (!selChanged && !docChanged) return null\n\n const linkType = newState.schema.marks.link\n if (!linkType) return null\n if (!newState.selection.empty) return null\n\n const newPos = newState.selection.from\n const oldPos = oldState.selection.from\n\n // ── EXPAND: cursor just entered a link mark ──\n const linkInfo = findLinkMarkAtPos(newState, newPos)\n if (linkInfo) {\n // Only expand if cursor was NOT in a link mark in old state\n const oldLinkInfo = findLinkMarkAtPos(oldState, oldPos)\n if (!oldLinkInfo) {\n const { from, to, text, href } = linkInfo\n const literal = `[${text}](${href})`\n const textNode = newState.schema.text(literal)\n const tr = newState.tr.replaceWith(from, to, textNode)\n tr.setMeta(pluginKey, 'expand')\n tr.setMeta('addToHistory', false)\n\n // Place cursor at same relative offset within text portion\n const relPos = Math.max(0, Math.min(newPos - from, text.length))\n const cursorPos = from + 1 + relPos // +1 for the `[`\n try {\n tr.setSelection(TextSelection.create(tr.doc, cursorPos))\n } catch { /* ignore */ }\n return tr\n }\n return null\n }\n\n // ── COLLAPSE: cursor left a [text](url) pattern ──\n // Use block-local scan instead of full-doc scan for performance.\n const oldBlockMatches = findLinkPatternsInBlock(oldState, oldPos, LINK_PATTERN_CONVERT)\n if (oldBlockMatches.length === 0) return null\n\n const wasIn = oldBlockMatches.find((m) => oldPos >= m.from && oldPos <= m.to)\n if (!wasIn) return null\n\n // Find the pattern in the new state (scan only the affected block)\n let target: LinkMatch | undefined\n if (docChanged) {\n let mappedFrom = wasIn.from\n for (const t of transactions) {\n mappedFrom = t.mapping.map(mappedFrom)\n }\n // After large deletes, the mapped position may be invalid — bail out\n if (mappedFrom < 0 || mappedFrom > newState.doc.content.size) return null\n const newBlockMatches = findLinkPatternsInBlock(newState, mappedFrom, LINK_PATTERN_CONVERT)\n if (cursorInsidePattern(newPos, newBlockMatches)) return null\n target = newBlockMatches.find((m) => Math.abs(m.from - mappedFrom) < 3)\n } else {\n const newBlockMatches = findLinkPatternsInBlock(newState, wasIn.from, LINK_PATTERN_CONVERT)\n if (cursorInsidePattern(newPos, newBlockMatches)) return null\n target = newBlockMatches.find((m) => m.from === wasIn.from && m.to === wasIn.to)\n }\n\n if (!target || !target.text || !target.url) return null\n\n const mark = linkType.create({ href: target.url })\n const linkNode = newState.schema.text(target.text, [mark])\n const tr = newState.tr.replaceWith(target.from, target.to, linkNode)\n tr.setMeta(pluginKey, 'collapse')\n tr.setMeta('addToHistory', false)\n return tr\n },\n })\n}\n","/**\n * Inline mark convert plugin — three responsibilities:\n *\n * 1. **Backtick collapse**: Auto-converts `` `text` `` patterns to code marks\n * when the cursor leaves the backtick pair. Handles the workflow where the\n * user types two backticks first, moves the cursor between them, types\n * content, then leaves.\n *\n * 2. **Cursor target**: Inserts a zero-width space (U+200B) after formatting\n * marks (`code`, `strong`, `em`, `strike_through`) at the end of textblocks.\n * WebKit can't position the caret after certain inline elements when there\n * is no subsequent text node, so the ZWSP provides a DOM target for both\n * keyboard navigation and mouse clicks.\n *\n * 3. **Stored marks at code–ZWSP boundary**: code is `inclusive: false` so\n * `marks()` at the boundary excludes it. The plugin proactively sets stored\n * marks so typing at the boundary still extends code. ArrowRight clears the\n * stored marks (handled in `editor-props-plugin.ts` `'code-escape'` meta).\n * `strong` / `em` / `strike_through` are `inclusive: true` so `marks()`\n * already includes them at the boundary — no `storedMarks` manipulation\n * needed for those.\n *\n * The U+200B is stripped during markdown serialization (see `serializeMarkdown`).\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport type { EditorState } from 'prosemirror-state'\n\nconst pluginKey = new PluginKey('moraya-inline-code-convert')\n\n/** Zero-width space used as cursor anchor after trailing formatting marks. */\nexport const ZWSP = ''\n\n/**\n * Marks that get a ZWSP cursor target when they are the last content in a\n * textblock. Includes non-inclusive marks (code) and inclusive formatting\n * marks (strong, em, strike_through) — all need an escape position at end\n * of paragraph so ArrowRight doesn't jump straight to the next block.\n */\nconst ZWSP_MARK_NAMES = ['code', 'strong', 'em', 'strike_through'] as const\n\nfunction hasZwspTargetMark(\n marks: readonly import('prosemirror-model').Mark[],\n state: EditorState,\n): boolean {\n return ZWSP_MARK_NAMES.some(name => {\n const mt = state.schema.marks[name]\n return mt && mt.isInSet(marks)\n })\n}\n\n/** Matches `` `text` `` (backtick-delimited) for conversion — requires non-empty content. */\nconst CODE_PATTERN = /`([^`]+)`/g\n\ninterface CodeMatch {\n from: number\n to: number\n content: string\n}\n\n/**\n * Find `` `text` `` patterns in the textblock containing `pos`.\n * Only scans unmarked text nodes (skips text already marked as code).\n */\nfunction findCodePatternsInBlock(state: EditorState, pos: number): CodeMatch[] {\n const matches: CodeMatch[] = []\n const codeType = state.schema.marks.code\n\n let resolved\n try { resolved = state.doc.resolve(pos) } catch { return matches }\n const parent = resolved.parent\n if (!parent.isTextblock) return matches\n\n // Skip code blocks — backticks are literal there\n if (parent.type.spec.code) return matches\n\n const base = resolved.start()\n let nodePos = base\n for (let i = 0; i < parent.childCount; i++) {\n const child = parent.child(i)\n if (child.isText && child.text && !(codeType && codeType.isInSet(child.marks))) {\n CODE_PATTERN.lastIndex = 0\n let m: RegExpExecArray | null\n while ((m = CODE_PATTERN.exec(child.text)) !== null) {\n matches.push({\n from: nodePos + m.index,\n to: nodePos + m.index + m[0].length,\n content: m[1] ?? '',\n })\n }\n }\n nodePos += child.nodeSize\n }\n return matches\n}\n\n/**\n * Check if a textblock's last content is a formatting mark that needs a\n * trailing cursor target (U+200B). Returns the insert position, or -1.\n */\nfunction needsCursorTarget(state: EditorState): number {\n const { $head } = state.selection\n if (!$head) return -1\n const parent = $head.parent\n if (!parent.isTextblock || parent.type.spec.code || parent.childCount === 0) return -1\n\n const lastChild = parent.lastChild\n if (!lastChild?.isText) return -1\n\n // Already has a trailing ZWSP without any target mark — no action needed\n if (!hasZwspTargetMark(lastChild.marks, state) && lastChild.text?.endsWith(ZWSP)) return -1\n\n // Walk backwards skipping existing ZWSP-only unmarked nodes.\n // If the last meaningful child has a target mark → insert ZWSP at end.\n for (let i = parent.childCount - 1; i >= 0; i--) {\n const child = parent.child(i)\n if (child.isText && !hasZwspTargetMark(child.marks, state) && child.text === ZWSP) continue\n if (child.isText && hasZwspTargetMark(child.marks, state)) {\n return $head.start() + parent.content.size // insert at end of textblock content\n }\n break // non-target-mark, non-ZWSP content found — no target needed\n }\n return -1\n}\n\nexport function createInlineCodeConvertPlugin(): Plugin {\n return new Plugin({\n key: pluginKey,\n\n appendTransaction(transactions, oldState, newState) {\n // Skip if this plugin already produced a transaction\n if (transactions.some((tr) => tr.getMeta(pluginKey))) return null\n if (transactions.some((tr) => tr.getMeta('full-delete'))) return null\n\n const selChanged = transactions.some((tr) => tr.selectionSet)\n const docChanged = transactions.some((tr) => tr.docChanged)\n if (!selChanged && !docChanged) return null\n if (!newState.selection.empty) return null\n\n const newPos = newState.selection.from\n const oldPos = oldState.selection.from\n const codeType = newState.schema.marks.code\n\n // ── 1. Backtick pair collapse ──\n const oldMatches = findCodePatternsInBlock(oldState, oldPos)\n const wasIn = oldMatches.find((m) => oldPos > m.from && oldPos < m.to)\n if (wasIn && codeType) {\n let mappedFrom = wasIn.from\n if (docChanged) {\n for (const t of transactions) {\n mappedFrom = t.mapping.map(mappedFrom)\n }\n if (mappedFrom < 0 || mappedFrom > newState.doc.content.size) return null\n }\n\n const newMatches = findCodePatternsInBlock(newState, mappedFrom)\n const isStillIn = newMatches.find((m) => newPos > m.from && newPos < m.to)\n if (!isStillIn) {\n const target = newMatches.find(\n (m) => Math.abs(m.from - mappedFrom) < 3,\n )\n if (target?.content) {\n const codeNode = newState.schema.text(target.content, [codeType.create()])\n const tr = newState.tr.replaceWith(target.from, target.to, codeNode)\n tr.setMeta(pluginKey, 'collapse')\n tr.setMeta('addToHistory', false)\n return tr\n }\n }\n }\n\n // ── 2. Cursor target: ensure U+200B after trailing formatting marks ──\n const insertPos = needsCursorTarget(newState)\n if (insertPos >= 0) {\n const tr = newState.tr.insertText(ZWSP, insertPos)\n tr.setMeta(pluginKey, 'cursor-target')\n tr.setMeta('addToHistory', false)\n\n // For inclusive marks (strong/em/strike_through): if cursor is exactly at\n // the insertion point (the right boundary of the mark), clear those marks\n // from storedMarks so that typing immediately after the input rule produces\n // plain text (Typora-style: completing **bold** exits bold).\n if (newState.selection.from === insertPos) {\n const { $head: $h } = newState.selection\n if ($h?.nodeBefore) {\n const hasInclusive = ZWSP_MARK_NAMES\n .filter((n) => n !== 'code')\n .some((name) => {\n const mt = newState.schema.marks[name]\n return mt && $h.nodeBefore!.marks.some((m) => m.type === mt)\n })\n if (hasInclusive) {\n const filtered = $h.marks().filter((m) =>\n !ZWSP_MARK_NAMES.filter((n) => n !== 'code').some((name) => {\n const mt = newState.schema.marks[name]\n return mt && m.type === mt\n }),\n )\n tr.setStoredMarks(filtered)\n }\n }\n }\n\n return tr\n }\n\n // ── 3. Stored marks at code–ZWSP boundary ──\n // With inclusive:false, marks() at the right boundary of code excludes\n // the code mark. But the user expects typing at the end of code text to\n // extend the code (they visually see the cursor inside the gray background).\n // Proactively set stored marks to include code at this position.\n // ArrowRight handler sets 'code-escape' meta to opt out.\n if (transactions.some((tr) => tr.getMeta('code-escape'))) return null\n\n const { $head } = newState.selection\n if ($head && newState.selection.empty && codeType) {\n const nodeBefore = $head.nodeBefore\n const nodeAfter = $head.nodeAfter\n\n if (\n nodeBefore?.marks.some((m) => m.type === codeType) &&\n nodeAfter?.isText &&\n !codeType.isInSet(nodeAfter.marks) &&\n nodeAfter.text?.startsWith(ZWSP)\n ) {\n // Already has code in stored marks — nothing to do\n const stored = newState.storedMarks\n if (stored && stored.some((m) => m.type === codeType)) return null\n\n const marks = [...$head.marks(), codeType.create()]\n const tr = newState.tr.setStoredMarks(marks)\n tr.setMeta(pluginKey, 'boundary-marks')\n tr.setMeta('addToHistory', false)\n return tr\n }\n\n // ── 3b. Clear inclusive marks at mark–ZWSP boundary ──\n // strong/em/strike_through are inclusive:true, so marks() at the right\n // boundary includes them. When cursor navigates here (via ← or click),\n // clear those marks from storedMarks so typing is plain text.\n const inclusiveMarkNames = ZWSP_MARK_NAMES.filter((n) => n !== 'code')\n const hasInclusiveBefore = nodeBefore != null && inclusiveMarkNames.some((name) => {\n const mt = newState.schema.marks[name]\n return mt && nodeBefore.marks.some((m) => m.type === mt)\n })\n if (hasInclusiveBefore && nodeAfter?.isText && nodeAfter.text?.startsWith(ZWSP)) {\n // If storedMarks is already null or already excludes inclusive marks, bail\n const stored = newState.storedMarks\n const storedHasInclusive = stored?.some((m) =>\n inclusiveMarkNames.some((name) => {\n const mt = newState.schema.marks[name]\n return mt && m.type === mt\n }),\n )\n if (stored !== null && !storedHasInclusive) return null\n\n const filtered = $head.marks().filter((m) =>\n !inclusiveMarkNames.some((name) => {\n const mt = newState.schema.marks[name]\n return mt && m.type === mt\n }),\n )\n const tr = newState.tr.setStoredMarks(filtered)\n tr.setMeta(pluginKey, 'boundary-marks-inclusive')\n tr.setMeta('addToHistory', false)\n return tr\n }\n }\n\n return null\n },\n })\n}\n","/**\n * Unified editor props plugin — merges 5 separate ProseMirror plugins into one.\n *\n * Faithful 1:1 migration from Moraya desktop `src/lib/editor/plugins/editor-props-plugin.ts`\n * with the following DI changes (v0.60.0-pre §F2.6):\n * - `editorStore.getState().currentFilePath` → `platform.getCurrentFilePath()`\n * - `isMacOS` from `$lib/utils/platform` → `platform.isMacOS`\n * - `import('@tauri-apps/plugin-opener').{openPath,openUrl}` → `linkOpener.open(href)`\n * (the consumer's LinkOpener implementation routes to the right platform API)\n *\n * Consolidated props:\n * - `clipboardTextParser`: parse pasted plain text as Markdown (render instead of escape)\n * - `transformPastedHTML`: paste language fix (copy `class=\"language-xxx\"` → `data-language`)\n * - `handleDOMEvents.mousedown`: math_block click → prevent WebKit broken selection;\n * Cmd/Ctrl+click on links → open externally via LinkOpener\n * - `handleDOMEvents.keydown/keyup`: toggle link-hover cursor class on Cmd/Ctrl;\n * fast AllSelection delete; WKWebView end-of-textblock Backspace fix\n * - `handleClick`: click below content → append paragraph + place cursor\n * - `handleClickOn`: image click → TextSelection (prevent NodeSelection blue highlight)\n * - `handleKeyDown`: ArrowRight escape; fast AllSelection delete (fallback)\n * - `decorations`: WKWebView caret fix for empty paragraphs (macOS only)\n * - `view` lifecycle: scroll-after-paste; empty-doc focus recovery\n *\n * Reducing 5 plugin instances to 1 saves ~4 apply() traversals per transaction.\n */\n\nimport { Fragment, Slice } from 'prosemirror-model'\nimport { AllSelection, Plugin, PluginKey, TextSelection } from 'prosemirror-state'\nimport { Decoration, DecorationSet } from 'prosemirror-view'\nimport { parseMarkdown } from '../markdown'\nimport type { LinkOpener, Platform } from '../types'\n\nconst editorPropsKey = new PluginKey('moraya-editor-props')\n\n/** Detect whether a URL is a local file path (absolute or relative). */\nfunction isLocalFilePath(href: string): boolean {\n // Absolute Unix/macOS paths\n if (href.startsWith('/')) return true\n // Relative paths\n if (href.startsWith('./') || href.startsWith('../')) return true\n // Windows absolute paths\n if (/^[A-Za-z]:[/\\\\]/.test(href)) return true\n // file:// protocol\n if (href.startsWith('file://')) return true\n return false\n}\n\n/** Resolve a local-path href against the platform's current file directory. */\nfunction resolveLocalPath(href: string, platform: Platform): string {\n // Strip file:// protocol and decode URL-encoded characters\n let path = href\n if (path.startsWith('file:///')) {\n path = path.slice(7) // file:///path → /path\n try { path = decodeURIComponent(path) } catch { /* keep as-is */ }\n } else if (path.startsWith('file://')) {\n path = path.slice(5) // file://path → //path (UNC)\n try { path = decodeURIComponent(path) } catch { /* keep as-is */ }\n }\n\n // Already absolute\n if (path.startsWith('/') || /^[A-Za-z]:[/\\\\]/.test(path)) return path\n\n // Relative path: resolve against current file's directory\n const currentFile = platform.getCurrentFilePath()\n if (currentFile) {\n const dir = currentFile.replace(/[/\\\\][^/\\\\]*$/, '')\n return dir + '/' + path\n }\n return path\n}\n\nexport interface EditorPropsPluginOptions {\n platform: Platform\n linkOpener: LinkOpener\n}\n\nexport function createEditorPropsPlugin(opts: EditorPropsPluginOptions): Plugin {\n const { platform, linkOpener } = opts\n const isMacOS = platform.isMacOS\n\n // scroll-after-paste state\n let pendingPaste = false\n\n return new Plugin({\n key: editorPropsKey,\n\n props: {\n /**\n * Parse pasted plain text as Markdown so syntax renders instead of\n * being inserted as escaped literal text.\n */\n clipboardTextParser(text, $context, plain) {\n if (plain || $context.parent.type.spec.code) return undefined!\n const doc = parseMarkdown(text)\n // If markdown parse produced a single empty paragraph, fall back to\n // literal text insertion to avoid replacing the current selection.\n if (doc.textContent.length === 0 && doc.content.size <= 2) return undefined!\n const content = doc.content\n // Single paragraph → extract inline content so it merges into current text\n if (content.childCount === 1 && content.firstChild!.type.name === 'paragraph') {\n return new Slice(content.firstChild!.content, 0, 0)\n }\n return new Slice(content, 0, 0)\n },\n\n /**\n * Safety net for degenerate pastes (empty markdown link, empty <a>, etc.).\n * Also routes pasted markdown image syntax through the markdown parser.\n */\n handlePaste(view, event, slice) {\n const plain = event.clipboardData?.getData('text/plain')\n if (!plain) return false\n\n // Markdown image syntax — parse so the image renders instead of being escaped\n const trimmed = plain.trim()\n if (/^!\\[/.test(trimmed)) {\n const doc = parseMarkdown(trimmed)\n if (doc.content.size > 2) {\n const content = doc.content\n const inner = (content.childCount === 1 && content.firstChild!.type.name === 'paragraph')\n ? content.firstChild!.content\n : content\n view.dispatch(\n view.state.tr.replaceSelection(new Slice(inner, 0, 0)),\n )\n pendingPaste = true\n return true\n }\n }\n\n // Link pattern with empty text or empty URL\n const linkMatch = /^\\[([^\\]]*)\\]\\(([^)]*)\\)$/.exec(trimmed)\n if (linkMatch && (!linkMatch[1] || !linkMatch[2])) {\n const textNode = view.state.schema.text(plain)\n view.dispatch(\n view.state.tr.replaceSelection(new Slice(Fragment.from(textNode), 0, 0)),\n )\n pendingPaste = true\n return true\n }\n\n // Degenerate slice (e.g. empty <a> tag from HTML clipboard)\n try {\n const sliceText = slice.content.textBetween(0, slice.content.size, '', '')\n if (sliceText.trim().length === 0 && trimmed.length > 0) {\n const textNode = view.state.schema.text(plain)\n view.dispatch(\n view.state.tr.replaceSelection(new Slice(Fragment.from(textNode), 0, 0)),\n )\n pendingPaste = true\n return true\n }\n } catch { /* malformed slice — fall through */ }\n\n return false\n },\n\n /**\n * Paste language normalization:\n * Copy class=\"language-xxx\" from <code> to data-language on parent <pre>.\n */\n transformPastedHTML(html) {\n if (!html.includes('language-')) return html\n try {\n const template = document.createElement('template')\n template.innerHTML = html\n const fragment = template.content\n for (const pre of fragment.querySelectorAll('pre')) {\n if (pre.dataset.language) continue\n const code = pre.querySelector('code')\n if (!code) continue\n const match = code.className.match(/(?:language|lang)-(\\S+)/)\n if (match && match[1]) {\n pre.dataset.language = match[1]\n }\n }\n return template.innerHTML\n } catch {\n return html\n }\n },\n\n handleDOMEvents: {\n /**\n * Safety: prevent WebView navigation on any remaining <a> clicks.\n * (Most <a> tags get expanded to literal text on mousedown, but this\n * is a fallback in case the click fires before the expand.)\n */\n click(_view, event) {\n const me = event as MouseEvent\n const target = me.target as HTMLElement | null\n if (!target) return false\n const anchor = target.closest('a[href]') as HTMLAnchorElement | null\n if (anchor) {\n me.preventDefault()\n }\n return false\n },\n\n mousedown(view, event) {\n const me = event as MouseEvent\n if (me.button !== 0) return false\n const target = me.target as HTMLElement | null\n if (!target) return false\n\n // ── Cmd/Ctrl+click on links → open externally via LinkOpener ──\n // Must be handled in mousedown BEFORE ProseMirror places cursor,\n // because link-text-plugin's appendTransaction expands link marks\n // to literal text on cursor entry, removing <a> from DOM before\n // the click event fires.\n if (me.metaKey || me.ctrlKey) {\n const anchor = target.closest('a[href]') as HTMLAnchorElement | null\n if (anchor) {\n const href = anchor.getAttribute('href')\n if (href) {\n me.preventDefault()\n const targetHref = isLocalFilePath(href)\n ? resolveLocalPath(href, platform)\n : href\n try {\n linkOpener.open(targetHref)\n } catch (e) {\n console.warn('[opener] failed:', targetHref, e)\n }\n return true // consume — don't place cursor or expand\n }\n }\n }\n\n // ── Math block click fix ──\n const mathBlock = target.closest('div[data-type=\"math_block\"]')\n if (!mathBlock) return false\n\n // Prevent WebKit from creating the broken range selection\n me.preventDefault()\n\n try {\n const pos = view.posAtDOM(mathBlock, 0)\n const $pos = view.state.doc.resolve(pos)\n\n // Walk up to find the math_block node and get its before-position\n let beforePos = pos\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'math_block') {\n beforePos = $pos.before(d)\n break\n }\n }\n const $before = view.state.doc.resolve(beforePos)\n if (!$before.nodeAfter || $before.nodeAfter.type.name !== 'math_block') {\n if ($pos.nodeAfter?.type.name === 'math_block') {\n beforePos = pos\n }\n }\n\n const sel = TextSelection.near(view.state.doc.resolve(beforePos), -1)\n view.dispatch(view.state.tr.setSelection(sel))\n } catch { /* ignore — focus below is the fallback */ }\n\n view.focus()\n return true\n },\n\n /**\n * Cmd/Ctrl held → add 'link-hover' class for pointer cursor on links.\n * Also handles fast AllSelection delete + WKWebView end-of-textblock\n * Backspace fix at the highest priority interception point.\n */\n keydown(view, event) {\n if (event.isComposing) return false\n\n if (event.key === 'Meta' || event.key === 'Control') {\n view.dom.classList.add('link-hover')\n }\n\n // handleDOMEvents.keydown fires BEFORE handleKeyDown and captureKeyDown\n if ((event.key === 'Backspace' || event.key === 'Delete') &&\n !event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey) {\n // Fast AllSelection / full-range deletion\n // On macOS Cmd+A is handled by native PredefinedMenuItem::select_all\n // which changes the DOM selection but ProseMirror's selectionchange\n // observer may NOT have synced yet. Force flush + DOM Range comparison.\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(view as any).domObserver?.flush?.()\n } catch { /* internal API */ }\n\n const docSize = view.state.doc.content.size\n let isAllSelected = false\n\n // Check 1: ProseMirror's internal selection\n const sel = view.state.selection\n if (sel instanceof AllSelection ||\n (docSize > 0 && sel.from <= 1 && sel.to >= docSize - 1)) {\n isAllSelected = true\n }\n\n // Check 2: DOM Range comparison\n if (!isAllSelected && docSize > 0) {\n try {\n const domSel = window.getSelection()\n if (domSel && !domSel.isCollapsed && domSel.rangeCount > 0) {\n const range = domSel.getRangeAt(0)\n const editorRange = document.createRange()\n editorRange.selectNodeContents(view.dom)\n if (range.compareBoundaryPoints(Range.START_TO_START, editorRange) <= 0 &&\n range.compareBoundaryPoints(Range.END_TO_END, editorRange) >= 0) {\n isAllSelected = true\n }\n }\n } catch { /* Range API edge cases */ }\n }\n\n // Check 3: Text content length comparison (last resort)\n if (!isAllSelected && docSize > 0) {\n try {\n const domSel = window.getSelection()\n if (domSel && !domSel.isCollapsed) {\n const selectedText = domSel.toString()\n const fullText = view.dom.textContent || ''\n if (selectedText.length > 0 && fullText.length > 0 &&\n selectedText.length >= fullText.length * 0.9) {\n isAllSelected = true\n }\n }\n } catch { /* ignore */ }\n }\n\n if (isAllSelected) {\n event.preventDefault()\n const paragraphType = view.state.schema.nodes.paragraph\n if (!paragraphType) return false\n const emptyParagraph = paragraphType.create()\n const tr = view.state.tr.replaceWith(0, docSize, emptyParagraph)\n tr.setSelection(TextSelection.create(tr.doc, 1))\n tr.setMeta('full-delete', true)\n view.dispatch(tr)\n return true\n }\n\n // ── WKWebView end-of-textblock Backspace fix ──\n // ProseMirror's captureKeyDown → stopNativeHorizontalDelete uses\n // view.endOfTextblock(\"backward\") which relies on WebKit's\n // Selection.modify(). In WKWebView this can return incorrect\n // results at paragraph boundaries, causing joinBackward to merge\n // paragraphs instead of deleting the character before the cursor.\n if (event.key === 'Backspace') {\n if (sel instanceof TextSelection && sel.empty && sel.$cursor) {\n const { parent, parentOffset } = sel.$cursor\n if (parent.isTextblock && parentOffset === parent.content.size && parentOffset > 0) {\n const nb = sel.$cursor.nodeBefore\n if (nb) {\n event.preventDefault()\n if (nb.isText && nb.text) {\n const code = nb.text.charCodeAt(nb.text.length - 1)\n const delLen = (code >= 0xDC00 && code <= 0xDFFF) ? 2 : 1\n view.dispatch(view.state.tr.delete(sel.from - delLen, sel.from).scrollIntoView())\n } else {\n view.dispatch(view.state.tr.delete(sel.from - nb.nodeSize, sel.from).scrollIntoView())\n }\n return true\n }\n }\n }\n }\n }\n\n return false\n },\n keyup(view, event) {\n if (event.key === 'Meta' || event.key === 'Control') {\n view.dom.classList.remove('link-hover')\n }\n return false\n },\n },\n\n /**\n * Click below content: append a paragraph and place cursor there when\n * the last node is a code_block / table / etc. and user clicks below it.\n */\n handleClick(view, _pos, event) {\n if (event.button !== 0) return false\n const { doc } = view.state\n const lastNode = doc.lastChild\n if (!lastNode || lastNode.type.name === 'paragraph') return false\n const lastNodePos = doc.content.size - lastNode.nodeSize\n const lastDOM = view.nodeDOM(lastNodePos) as HTMLElement | null\n if (!lastDOM) return false\n\n // Only trigger when clicking BELOW the last block's bottom edge.\n const rect = lastDOM.getBoundingClientRect()\n if (event.clientY <= rect.bottom) return false\n\n const paragraphType = view.state.schema.nodes.paragraph\n if (!paragraphType) return false\n const endPos = doc.content.size\n const paragraph = paragraphType.create()\n const tr = view.state.tr.insert(endPos, paragraph)\n tr.setSelection(TextSelection.create(tr.doc, endPos + 1))\n view.dispatch(tr)\n view.focus()\n return true\n },\n\n /**\n * Image click: prevent NodeSelection blue highlight, place TextSelection\n * after the image instead. (math_block is handled in mousedown above.)\n */\n handleClickOn(view, _pos, node, nodePos, event) {\n if (node.type.name !== 'image') return false\n if (event.button !== 0) return false\n\n const $pos = view.state.doc.resolve(nodePos + node.nodeSize)\n const sel = TextSelection.near($pos)\n view.dispatch(view.state.tr.setSelection(sel))\n return true\n },\n\n /**\n * Keyboard shortcuts (after keymap plugins):\n * - ArrowRight: escape formatting mark boundary\n * - Backspace/Delete on AllSelection: fast full-doc deletion\n */\n handleKeyDown(view, event) {\n if (event.isComposing) return false\n\n // ArrowRight: escape formatting mark at right boundary\n if (event.key === 'ArrowRight' &&\n !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey) {\n const sel = view.state.selection\n if (sel.empty && sel instanceof TextSelection && sel.$cursor) {\n const $cursor = sel.$cursor\n const ZWSP_MARK_NAMES = ['code', 'strong', 'em', 'strike_through']\n const nodeBefore = $cursor.nodeBefore\n const nodeAfter = $cursor.nodeAfter\n const hasTargetMarkBefore = nodeBefore != null && ZWSP_MARK_NAMES.some(name => {\n const mt = view.state.schema.marks[name]\n return mt && nodeBefore.marks.some(m => m.type === mt)\n })\n if (hasTargetMarkBefore && nodeAfter?.isText &&\n nodeAfter.text?.startsWith('')) {\n const nextPos = $cursor.pos + nodeAfter.nodeSize\n const $next = view.state.doc.resolve(Math.min(nextPos, view.state.doc.content.size))\n const nextSel = TextSelection.near($next, 1)\n const tr = view.state.tr.setSelection(nextSel)\n tr.setStoredMarks([])\n tr.setMeta('code-escape', true)\n tr.scrollIntoView()\n view.dispatch(tr)\n return true\n }\n }\n }\n\n // Fast AllSelection / full-range deletion\n if (event.key === 'Backspace' || event.key === 'Delete') {\n const sel = view.state.selection\n const docSize = view.state.doc.content.size\n const isAllSelected =\n sel instanceof AllSelection ||\n (docSize > 0 && sel.from <= 1 && sel.to >= docSize - 1)\n if (isAllSelected) {\n event.preventDefault()\n const paragraphType = view.state.schema.nodes.paragraph\n if (!paragraphType) return false\n const emptyParagraph = paragraphType.create()\n const tr = view.state.tr.replaceWith(0, docSize, emptyParagraph)\n tr.setSelection(TextSelection.create(tr.doc, 1))\n tr.setMeta('full-delete', true)\n view.dispatch(tr)\n return true\n }\n }\n\n return false\n },\n\n /**\n * WKWebView caret fix: add 'caret-empty-para' decoration to empty\n * paragraph under cursor on macOS.\n */\n decorations(state) {\n if (!isMacOS) return DecorationSet.empty\n const { selection } = state\n if (!selection.empty) return DecorationSet.empty\n\n const { $from } = selection\n const parent = $from.parent\n if (parent.type.name === 'paragraph' && parent.content.size === 0) {\n const pos = $from.before()\n return DecorationSet.create(state.doc, [\n Decoration.node(pos, pos + parent.nodeSize, { class: 'caret-empty-para' }),\n ])\n }\n return DecorationSet.empty\n },\n },\n\n /**\n * Scroll-after-paste + empty-doc focus recovery.\n */\n view(editorView) {\n function onPaste() { pendingPaste = true }\n editorView.dom.addEventListener('paste', onPaste, true)\n\n // Remove link-hover class when window loses focus (Cmd/Ctrl release won't fire)\n function onBlur() { editorView.dom.classList.remove('link-hover') }\n window.addEventListener('blur', onBlur)\n\n return {\n update(view, prevState) {\n // WKWebView empty-doc focus recovery\n if (isMacOS && view.state.doc !== prevState.doc) {\n const docSize = view.state.doc.content.size\n const prevDocSize = prevState.doc.content.size\n if (docSize <= 4 && prevDocSize > 4) {\n requestAnimationFrame(() => {\n try {\n if (!view.hasFocus()) view.focus()\n } catch { /* ignore */ }\n })\n }\n }\n\n if (!pendingPaste || view.state.doc.eq(prevState.doc)) return\n pendingPaste = false\n requestAnimationFrame(() => {\n try {\n const { from } = view.state.selection\n const coords = view.coordsAtPos(from)\n const wrapper = view.dom.closest('.editor-wrapper') as HTMLElement | null\n if (!wrapper) return\n const rect = wrapper.getBoundingClientRect()\n if (coords.top < rect.top || coords.bottom > rect.bottom) {\n wrapper.scrollTop += coords.top - rect.top - rect.height / 2\n }\n } catch { /* ignore */ }\n })\n },\n destroy() {\n editorView.dom.removeEventListener('paste', onPaste, true)\n window.removeEventListener('blur', onBlur)\n editorView.dom.classList.remove('link-hover')\n },\n }\n },\n })\n}\n","import type { Node } from 'prosemirror-model'\n\n/**\n * ProseMirror Doc LRU cache (v0.19.0 perf optimization, ported here).\n *\n * Per v0.60.0-pre §3 file tree note:\n * - Factory `createDocCache(maxEntries?)` (no module-level singleton)\n * - Consumers inject via `createEditor(opts.docCache)`; default = createDocCache(10)\n * - Moraya desktop multi-tab: one app-level instance keyed by filePath hash\n * - Moraya Web note list: shared app-level instance with createDocCache(50)\n */\n\nexport interface DocCache {\n get(hash: number): Node | undefined\n set(hash: number, doc: Node): void\n clear(): void\n /** Current entry count (read-only). */\n readonly size: number\n}\n\nclass LRUDocCache implements DocCache {\n private readonly map = new Map<number, Node>()\n constructor(private readonly maxEntries: number) {\n if (maxEntries < 1) throw new RangeError('docCache maxEntries must be ≥ 1')\n }\n\n get size(): number {\n return this.map.size\n }\n\n get(hash: number): Node | undefined {\n const v = this.map.get(hash)\n if (v !== undefined) {\n // LRU touch: re-insert to mark as most-recently-used\n this.map.delete(hash)\n this.map.set(hash, v)\n }\n return v\n }\n\n set(hash: number, doc: Node): void {\n if (this.map.has(hash)) {\n this.map.delete(hash)\n }\n this.map.set(hash, doc)\n if (this.map.size > this.maxEntries) {\n // Evict oldest\n const firstKey = this.map.keys().next().value\n if (firstKey !== undefined) {\n this.map.delete(firstKey)\n }\n }\n }\n\n clear(): void {\n this.map.clear()\n }\n}\n\n/**\n * Create an LRU-bounded ProseMirror Doc cache.\n *\n * @param maxEntries Max docs to retain. Default 10 (matches Moraya desktop's\n * per-Editor instance size; Moraya Web with note list typically uses 50).\n */\nexport function createDocCache(maxEntries = 10): DocCache {\n return new LRUDocCache(maxEntries)\n}\n\n/** djb2 hash (matches Moraya desktop's existing hash to keep cache key compat). */\nexport function djb2Hash(str: string): number {\n let hash = 5381\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 33) ^ str.charCodeAt(i)\n }\n return hash >>> 0\n}\n"],"mappings":"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","names":["Plugin","PluginKey","Decoration","DecorationSet","code","doc","Plugin","PluginKey","text","code","hljs","code","text","AllSelection","Plugin","PluginKey","TextSelection","Decoration","DecorationSet","setBlockType","toggleMark","wrapIn","wrappingInputRule","liftListItem","r","code","code","c","text","markdown","doc","text","c","hardbreak","paragraph","r","Plugin","PluginKey","text","r","Plugin","PluginKey","TextSelection","Decoration","DecorationSet","pluginKey","buildDecorations","tr","text","Plugin","PluginKey","pluginKey","marks","Fragment","Plugin","PluginKey","TextSelection","Decoration","DecorationSet","PluginKey","Plugin","text","doc","Fragment","code","TextSelection","paragraph","ZWSP_MARK_NAMES","DecorationSet","Decoration","doc","em","Plugin","PluginKey","DecorationSet","Decoration","wrappingInputRule","text","toggleMark","liftListItem","setBlockType","wrapIn","TextSelection","AllSelection","code","markdown","md"]}
|