@sendbird/actionbook-core 0.10.7 → 0.10.8

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/schema.ts","../../src/ui/plugin/registry.ts","../../src/ui/components/ActionbookRenderer.tsx","../../src/jinja/conditionHighlighter.ts","../../src/ui/components/icons.tsx","../../src/ui/components/EditorShell.tsx","../../src/ui/nodeView/ReactNodeView.ts","../../src/ui/hooks/useEditorView.ts","../../src/ast/types.ts","../../src/compat/prosemirror.ts","../../src/markdown/serializer.ts","../../node_modules/devlop/lib/default.js","../../node_modules/micromark-util-normalize-identifier/index.js","../../node_modules/mdast-util-gfm-footnote/lib/index.js","../../node_modules/mdast-util-gfm-strikethrough/lib/index.js","../../node_modules/markdown-table/index.js","../../node_modules/mdast-util-gfm-table/lib/index.js","../../node_modules/mdast-util-gfm-task-list-item/lib/index.js","../../src/markdown/plugins/resourceTag.ts","../../src/markdown/plugins/jumpPoint.ts","../../src/markdown/mdastAdapter.ts","../../src/ui/bridge/toProseMirrorJSON.ts","../../src/ui/styles/editorTextStyles.ts","../../src/ui/plugin/inputRulesPlugin.ts","../../src/ui/plugin/slashCommandPlugin.ts","../../src/ui/plugin/historyPlugin.ts","../../src/ui/plugin/keymapPlugin.ts","../../src/ui/plugin/noteBlockPlugin.tsx","../../src/ui/plugin/markdownClipboard.ts","../../src/ast/traverse.ts","../../src/markdown/parser.ts","../../node_modules/micromark-util-chunked/index.js","../../node_modules/micromark-util-combine-extensions/index.js","../../node_modules/micromark-util-classify-character/index.js","../../node_modules/micromark-util-resolve-all/index.js","../../node_modules/micromark-factory-space/index.js","../../node_modules/micromark-core-commonmark/lib/blank-line.js","../../node_modules/micromark-extension-gfm-footnote/lib/syntax.js","../../node_modules/micromark-extension-gfm-strikethrough/lib/syntax.js","../../node_modules/micromark-extension-gfm-table/lib/syntax.js","../../node_modules/micromark-extension-gfm-table/lib/edit-map.js","../../node_modules/micromark-extension-gfm-table/lib/infer.js","../../node_modules/micromark-extension-gfm-task-list-item/lib/syntax.js","../../src/markdown/plugins/jinjaBlock.ts","../../src/markdown/fragment.ts","../../src/jinja/scanner.ts","../../src/jinja/structurer.ts","../../src/jinja/analyzer.ts","../../src/jinja/evaluator.ts","../../src/tree/documentTree.ts","../../src/ui/plugin/jumpPointPlugin.ts","../../src/ui/plugin/jumpPointNodeViewPlugin.tsx","../../src/ui/plugin/jumpPointValidationPlugin.ts","../../src/ui/plugin/inlineToolTagNodeViewPlugin.tsx","../../src/ui/plugin/jinjaDecoration.ts","../../src/ui/plugin/jinjaIfBlockPlugin.tsx","../../src/ui/plugin/linkPlugin.ts","../../src/ui/plugin/dragHandlePlugin.ts","../../src/ui/plugin/todoNodeViewPlugin.tsx","../../src/ui/plugin/placeholderPlugin.ts","../../src/ui/components/SlashCommandMenu.tsx","../../src/ui/components/JinjaTreeView.tsx","../../src/ui/components/DocumentTreeView.tsx","../../src/ui/components/FloatingMenu.tsx","../../src/ui/plugin/inlineSuggestPlugin.ts","../../src/ui/bridge/jinjaValidation.ts"],"sourcesContent":["import { Schema } from 'prosemirror-model';\n\n/**\n * ProseMirror Schema for Actionbook documents.\n */\nexport const actionbookSchema = new Schema({\n nodes: {\n doc: {\n content: 'block*',\n },\n\n paragraph: {\n content: 'inline*',\n group: 'block',\n parseDOM: [{ tag: 'p' }],\n toDOM() {\n return ['p', 0];\n },\n },\n\n heading: {\n content: '(text | jumpPoint | hardBreak)*',\n group: 'block',\n attrs: { level: { default: 1 } },\n parseDOM: [\n { tag: 'h1', attrs: { level: 1 } },\n { tag: 'h2', attrs: { level: 2 } },\n { tag: 'h3', attrs: { level: 3 } },\n { tag: 'h4', attrs: { level: 4 } },\n { tag: 'h5', attrs: { level: 5 } },\n { tag: 'h6', attrs: { level: 6 } },\n ],\n toDOM(node) {\n return [`h${node.attrs.level}`, 0];\n },\n },\n\n bulletList: {\n content: 'listItem+',\n group: 'block',\n parseDOM: [{ tag: 'ul' }],\n toDOM() {\n return ['ul', 0];\n },\n },\n\n orderedList: {\n content: 'listItem+',\n group: 'block',\n attrs: { start: { default: 1 } },\n parseDOM: [\n {\n tag: 'ol',\n getAttrs(dom) {\n return { start: (dom as HTMLOListElement).start || 1 };\n },\n },\n ],\n toDOM(node) {\n return node.attrs.start === 1 ? ['ol', 0] : ['ol', { start: node.attrs.start }, 0];\n },\n },\n\n listItem: {\n content: 'block+',\n attrs: { checked: { default: null }, value: { default: null } },\n parseDOM: [\n {\n tag: 'li',\n getAttrs(dom) {\n const el = dom as HTMLLIElement;\n const checkbox = el.querySelector('input[type=\"checkbox\"]');\n if (checkbox) {\n return { checked: (checkbox as HTMLInputElement).checked, value: el.value || null };\n }\n if (el.dataset.checked != null) {\n return { checked: el.dataset.checked === 'true', value: el.value || null };\n }\n return { checked: null, value: el.value || null };\n },\n },\n ],\n toDOM(node) {\n const liAttrs: Record<string, string> = {};\n if (node.attrs.checked != null) {\n liAttrs.class = 'todo-item';\n liAttrs['data-checked'] = String(node.attrs.checked);\n }\n if (node.attrs.value != null) {\n liAttrs.value = String(node.attrs.value);\n }\n return Object.keys(liAttrs).length > 0 ? ['li', liAttrs, 0] : ['li', 0];\n },\n defining: true,\n },\n\n blockquote: {\n content: 'block+',\n group: 'block',\n parseDOM: [{ tag: 'blockquote' }],\n toDOM() {\n return ['blockquote', 0];\n },\n defining: true,\n },\n\n codeBlock: {\n content: 'text*',\n group: 'block',\n code: true,\n defining: true,\n marks: '',\n attrs: { language: { default: null } },\n parseDOM: [{\n tag: 'pre',\n preserveWhitespace: 'full' as const,\n getAttrs(dom) {\n return { language: (dom as HTMLElement).getAttribute('data-language') || null };\n },\n }],\n toDOM(node) {\n return ['pre', { 'data-language': node.attrs.language || undefined }, ['code', 0]];\n },\n },\n\n horizontalRule: {\n group: 'block',\n parseDOM: [{ tag: 'hr' }],\n toDOM() {\n return ['hr'];\n },\n },\n\n // ── Jinja conditional block ──\n\n jinjaIfBlock: {\n content: 'jinjaIfBranch+',\n group: 'block',\n isolating: true,\n defining: true,\n parseDOM: [{ tag: 'div[data-jinja-if-block]' }],\n toDOM() {\n return ['div', { 'data-jinja-if-block': '', class: 'jinja-if-block' }, 0];\n },\n },\n\n jinjaIfBranch: {\n content: 'block+',\n isolating: true,\n defining: true,\n attrs: {\n branchType: { default: 'if' }, // 'if' | 'elif' | 'else'\n condition: { default: '' },\n },\n parseDOM: [\n {\n tag: 'div[data-jinja-branch]',\n getAttrs(dom) {\n const el = dom as HTMLElement;\n return {\n branchType: el.getAttribute('data-branch-type') || 'if',\n condition: el.getAttribute('data-condition') || '',\n };\n },\n },\n ],\n toDOM(node) {\n return [\n 'div',\n {\n 'data-jinja-branch': '',\n 'data-branch-type': node.attrs.branchType,\n 'data-condition': node.attrs.condition,\n class: `jinja-branch jinja-branch-${node.attrs.branchType}`,\n },\n 0,\n ];\n },\n },\n\n noteBlock: {\n content: 'block+',\n group: 'block',\n defining: true,\n isolating: true,\n parseDOM: [{ tag: 'div[data-note-block]' }],\n toDOM() {\n return ['div', { 'data-note-block': '', class: 'ab-note-block' }, 0];\n },\n },\n // ── Table nodes ──\n\n table: {\n content: 'tableRow+',\n group: 'block',\n tableRole: 'table',\n isolating: true,\n parseDOM: [{ tag: 'table' }],\n toDOM() {\n return ['table', ['tbody', 0]];\n },\n },\n\n tableRow: {\n content: '(tableCell | tableHeader)+',\n tableRole: 'row',\n parseDOM: [{ tag: 'tr' }],\n toDOM() {\n return ['tr', 0];\n },\n },\n\n tableCell: {\n content: 'inline*',\n tableRole: 'cell',\n attrs: {\n colspan: { default: 1 },\n rowspan: { default: 1 },\n },\n isolating: true,\n parseDOM: [\n {\n tag: 'td',\n getAttrs(dom) {\n const el = dom as HTMLTableCellElement;\n return {\n colspan: el.colSpan || 1,\n rowspan: el.rowSpan || 1,\n };\n },\n },\n ],\n toDOM(node) {\n const attrs: Record<string, string | number> = {};\n if (node.attrs.colspan !== 1) attrs.colspan = node.attrs.colspan;\n if (node.attrs.rowspan !== 1) attrs.rowspan = node.attrs.rowspan;\n return ['td', attrs, 0];\n },\n },\n\n tableHeader: {\n content: 'inline*',\n tableRole: 'header_cell',\n attrs: {\n colspan: { default: 1 },\n rowspan: { default: 1 },\n },\n isolating: true,\n parseDOM: [\n {\n tag: 'th',\n getAttrs(dom) {\n const el = dom as HTMLTableCellElement;\n return {\n colspan: el.colSpan || 1,\n rowspan: el.rowSpan || 1,\n };\n },\n },\n ],\n toDOM(node) {\n const attrs: Record<string, string | number> = {};\n if (node.attrs.colspan !== 1) attrs.colspan = node.attrs.colspan;\n if (node.attrs.rowspan !== 1) attrs.rowspan = node.attrs.rowspan;\n return ['th', attrs, 0];\n },\n },\n\n text: {\n group: 'inline',\n },\n\n inlineToolTag: {\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n type: { default: 'tool' },\n resourceId: { default: '' },\n text: { default: '' },\n },\n toDOM(node) {\n return [\n 'span',\n {\n class: 'inline-tool-tag',\n 'data-type': node.attrs.type,\n 'data-resource-id': node.attrs.resourceId,\n },\n node.attrs.text,\n ];\n },\n parseDOM: [\n {\n tag: 'span.inline-tool-tag',\n getAttrs(dom) {\n const el = dom as HTMLElement;\n return {\n type: el.getAttribute('data-type') || 'tool',\n resourceId: el.getAttribute('data-resource-id') || '',\n text: el.textContent || '',\n };\n },\n },\n ],\n },\n\n jumpPoint: {\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n id: { default: '' },\n },\n toDOM(node) {\n return [\n 'span',\n {\n class: 'jump-point',\n 'data-jump-point-id': node.attrs.id,\n },\n `^${node.attrs.id}^`,\n ];\n },\n parseDOM: [\n {\n tag: 'span.jump-point',\n getAttrs(dom) {\n return {\n id: (dom as HTMLElement).getAttribute('data-jump-point-id') || '',\n };\n },\n },\n ],\n },\n\n hardBreak: {\n group: 'inline',\n inline: true,\n selectable: false,\n parseDOM: [{ tag: 'br' }],\n toDOM() {\n return ['br'];\n },\n },\n },\n\n marks: {\n bold: {\n parseDOM: [\n { tag: 'strong' },\n { tag: 'b', getAttrs: (node) => (node as HTMLElement).style.fontWeight !== 'normal' && null },\n {\n style: 'font-weight',\n getAttrs: (value) => /^(bold(er)?|[5-9]\\d{2,})$/.test(value as string) && null,\n },\n ],\n toDOM() {\n return ['strong', 0];\n },\n },\n\n italic: {\n parseDOM: [\n { tag: 'em' },\n { tag: 'i', getAttrs: (node) => (node as HTMLElement).style.fontStyle !== 'normal' && null },\n {\n style: 'font-style',\n getAttrs: (value) => (value as string) === 'italic' && null,\n },\n ],\n toDOM() {\n return ['em', 0];\n },\n },\n\n underline: {\n parseDOM: [\n { tag: 'u' },\n {\n style: 'text-decoration',\n getAttrs: (value) => (value as string).includes('underline') && null,\n },\n ],\n toDOM() {\n return ['u', 0];\n },\n },\n\n strikethrough: {\n parseDOM: [\n { tag: 's' },\n { tag: 'del' },\n { tag: 'strike' },\n {\n style: 'text-decoration',\n getAttrs: (value) => (value as string).includes('line-through') && null,\n },\n ],\n toDOM() {\n return ['s', 0];\n },\n },\n\n code: {\n parseDOM: [{ tag: 'code' }],\n toDOM() {\n return ['code', 0];\n },\n },\n\n link: {\n attrs: {\n href: { default: '' },\n title: { default: null },\n },\n inclusive: false,\n parseDOM: [\n {\n tag: 'a[href]',\n getAttrs(dom) {\n return {\n href: (dom as HTMLElement).getAttribute('href'),\n title: (dom as HTMLElement).getAttribute('title'),\n };\n },\n },\n ],\n toDOM(node) {\n const { href, title } = node.attrs;\n return ['a', { href, title, rel: 'noopener noreferrer nofollow' }, 0];\n },\n },\n\n diffMark: {\n attrs: {\n type: { default: 'added' },\n },\n parseDOM: [\n {\n tag: 'span[data-diff-type]',\n getAttrs(dom) {\n return { type: (dom as HTMLElement).getAttribute('data-diff-type') || 'added' };\n },\n },\n ],\n toDOM(node) {\n return ['span', { 'data-diff-type': node.attrs.type, class: `diff-${node.attrs.type}` }, 0];\n },\n },\n },\n});\n","import { Plugin } from 'prosemirror-state';\nimport { keymap } from 'prosemirror-keymap';\nimport { inputRules } from 'prosemirror-inputrules';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\n/**\n * Converts ActionbookPlugin[] into a flat array of PM Plugins.\n * Merges inputRules and keymaps from all plugins.\n *\n * Priority order (ProseMirror tries plugins in array order — first wins):\n * 1. Merged inputRules — highest priority for text-input transforms\n * 2. Merged keymap — custom handlers (e.g. splitListItem on Enter)\n * 3. Raw PM plugins — baseline behaviors (history, baseKeymap, etc.)\n *\n * Putting the merged keymap BEFORE raw plugins ensures that handlers like\n * `splitListItem` on Enter take priority over `baseKeymap`'s `splitBlock`.\n */\nexport function createPluginArray(plugins: ActionbookPlugin[]): {\n pmPlugins: Plugin[];\n nodeViews: Record<string, NodeViewFactory>;\n} {\n const rawPlugins: Plugin[] = [];\n const allNodeViews: Record<string, NodeViewFactory> = {};\n const allInputRules: import('prosemirror-inputrules').InputRule[] = [];\n const allKeymaps: Record<string, import('prosemirror-state').Command> = {};\n\n for (const plugin of plugins) {\n if (plugin.plugins) {\n rawPlugins.push(...plugin.plugins());\n }\n if (plugin.inputRules) {\n allInputRules.push(...plugin.inputRules());\n }\n if (plugin.keymap) {\n for (const [key, handler] of Object.entries(plugin.keymap())) {\n const prev = allKeymaps[key];\n // Chain: if an earlier plugin already claimed this key, run it first;\n // fall through to the new handler only if the earlier one returns false.\n allKeymaps[key] = prev\n ? (state, dispatch, view) => prev(state, dispatch, view) || handler(state, dispatch, view)\n : handler;\n }\n }\n if (plugin.nodeViews) {\n Object.assign(allNodeViews, plugin.nodeViews());\n }\n }\n\n const pmPlugins: Plugin[] = [];\n\n // 1. Input rules first (text-input events, no conflict with keydown)\n if (allInputRules.length > 0) {\n pmPlugins.push(inputRules({ rules: allInputRules }));\n }\n\n // 2. Merged keymap before raw plugins so custom handlers win on key conflicts\n if (Object.keys(allKeymaps).length > 0) {\n pmPlugins.push(keymap(allKeymaps));\n }\n\n // 3. Raw PM plugins (history, baseKeymap, etc.) as fallback\n pmPlugins.push(...rawPlugins);\n\n return { pmPlugins, nodeViews: allNodeViews };\n}\n","import React, { type ReactElement } from 'react';\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n AstNode,\n Mark,\n JinjaIfBranch,\n} from '../../ast/types';\nimport { tokenizeCondition } from '../../jinja/conditionHighlighter';\nimport {\n IconAnchor,\n IconHandoff,\n IconManual,\n IconMessageTemplate,\n IconTimeDiff,\n IconTool,\n} from './icons';\n\nexport interface ActionbookRendererProps {\n doc: DocumentNode;\n className?: string;\n /** Custom node renderer for extension points */\n renderNode?: (node: AstNode, defaultRender: () => ReactElement) => ReactElement;\n}\n\n// Color values matching Feather design tokens used in sbdashboard.\nconst RESOURCE_TAG_COLORS: Record<string, string> = {\n tool: '#027D69', // green-6\n manual: '#5959D3', // blue-6\n agent_message_template: '#8012B3', // violet-6\n handoff: '#D25309', // orange-6\n time_diff: '#FB6B6B', // data-viz-4 (red-4)\n};\nconst DEFAULT_RESOURCE_TAG_COLOR = '#027D69';\n\ntype IconComponent = typeof IconTool;\nconst RESOURCE_TAG_ICONS: Record<string, IconComponent> = {\n tool: IconTool,\n manual: IconManual,\n agent_message_template: IconMessageTemplate,\n handoff: IconHandoff,\n time_diff: IconTimeDiff,\n};\nconst DEFAULT_RESOURCE_TAG_ICON = IconTool;\n\nfunction renderMark(mark: Mark, children: ReactElement, key: string): ReactElement {\n switch (mark.type) {\n case 'bold':\n return <strong key={key}>{children}</strong>;\n case 'italic':\n return <em key={key}>{children}</em>;\n case 'underline':\n return <u key={key}>{children}</u>;\n case 'strikethrough':\n return <s key={key}>{children}</s>;\n case 'code':\n return <code key={key}>{children}</code>;\n case 'link':\n return (\n <a key={key} href={mark.href} title={mark.title} rel=\"noopener noreferrer nofollow\">\n {children}\n </a>\n );\n }\n}\n\nfunction wrapWithMarks(text: string, marks: readonly Mark[] | undefined, key: string): ReactElement {\n let element: ReactElement = <React.Fragment key={key}>{text}</React.Fragment>;\n if (!marks || marks.length === 0) return element;\n for (let i = 0; i < marks.length; i++) {\n element = renderMark(marks[i], element, `${key}-m${i}`);\n }\n return element;\n}\n\nfunction renderInline(\n node: InlineNode,\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const defaultRender = (): ReactElement => {\n switch (node.type) {\n case 'text':\n return wrapWithMarks(node.text, node.marks, key);\n case 'resourceTag': {\n const color = RESOURCE_TAG_COLORS[node.tagType] ?? DEFAULT_RESOURCE_TAG_COLOR;\n const Icon = RESOURCE_TAG_ICONS[node.tagType] ?? DEFAULT_RESOURCE_TAG_ICON;\n return (\n <span\n key={key}\n className=\"inline-tool-tag\"\n data-type={node.tagType}\n data-resource-id={node.resourceId}\n style={{\n display: 'inline-flex',\n height: '20px',\n padding: '1px',\n border: '1px solid #CCCCCC',\n borderRadius: '2px',\n alignItems: 'center',\n backgroundColor: 'white',\n verticalAlign: 'middle',\n userSelect: 'none',\n }}\n >\n <span\n style={{\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '16px',\n height: '16px',\n backgroundColor: color,\n borderRadius: '2px',\n flexShrink: 0,\n }}\n >\n <Icon size={9} fill=\"white\" />\n </span>\n <span\n style={{\n padding: '0 4px',\n color,\n fontSize: '11px',\n lineHeight: 1,\n userSelect: 'none',\n }}\n >\n {node.text}\n </span>\n </span>\n );\n }\n case 'jumpPoint':\n return (\n <span\n key={key}\n className=\"jump-point\"\n data-jump-point-id={node.id}\n id={`jp-${node.id}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: '#FFF2B6',\n border: '1px solid #FFC233',\n color: '#AA5D04',\n borderRadius: '4px',\n height: 'max(20px, 1em)',\n padding: '0 max(0.3em, 2px)',\n fontSize: 'max(0.9em, 14px)',\n lineHeight: '0.9em',\n verticalAlign: 'middle',\n userSelect: 'none',\n }}\n >\n <IconAnchor\n size={12}\n fill=\"#AA5D04\"\n style={{ marginRight: 'max(0.15em, 2px)', flexShrink: 0 }}\n />\n {node.id}\n </span>\n );\n case 'hardBreak':\n return <br key={key} />;\n default:\n return <span key={key} />;\n }\n };\n\n if (renderNode) return renderNode(node, defaultRender);\n return defaultRender();\n}\n\nfunction renderInlineContent(\n content: readonly InlineNode[],\n keyPrefix: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement[] {\n return content.map((node, i) => renderInline(node, `${keyPrefix}-${i}`, renderNode));\n}\n\n// --- Jinja If Block rendering (read-only) ---\n\nconst JINJA_RENDERER_STYLE_ID = 'ab-renderer-jinja-styles';\n\nconst JINJA_RENDERER_STYLES = `\n.ab-r-jinja-block {\n margin: 8px 0;\n}\n\n.ab-r-jinja-branch {\n position: relative;\n}\n\n.ab-r-jinja-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px;\n border: 1px solid #E0E0E0;\n border-radius: 4px;\n background: #FFFFFF;\n}\n\n.ab-r-jinja-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 32px;\n padding: 0 8px;\n border-radius: 4px;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n font-weight: 700;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.ab-r-jinja-badge-if,\n.ab-r-jinja-badge-elif {\n background: #E7F1FF;\n color: #0D0D0D;\n}\n\n.ab-r-jinja-badge-else {\n background: #F7F7F7;\n color: #424242;\n}\n\n.ab-r-jinja-condition {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n color: #0D0D0D;\n}\n\n.ab-r-jinja-otherwise {\n flex: 1;\n color: #858585;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.ab-r-jinja-body {\n display: flex;\n gap: 12px;\n padding: 0 8px;\n min-height: 32px;\n}\n\n.ab-r-jinja-divider-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n justify-content: center;\n}\n\n.ab-r-jinja-divider {\n width: 1px;\n background: #E0E0E0;\n}\n\n.ab-r-jinja-branch-last .ab-r-jinja-divider-col {\n align-items: flex-start;\n padding-left: 16px;\n}\n\n.ab-r-jinja-branch-last .ab-r-jinja-divider {\n width: 16px;\n height: 28px;\n background: none;\n border-left: 1px solid #E0E0E0;\n border-bottom: 1px solid #E0E0E0;\n border-bottom-left-radius: 8px;\n}\n\n.ab-r-jinja-content {\n flex: 1;\n min-width: 0;\n padding: 12px 0;\n}\n\n.ab-r-jinja-token-variable { color: #4141B2; }\n.ab-r-jinja-token-operator { color: #858585; }\n.ab-r-jinja-token-value { color: #0D0D0D; }\n.ab-r-jinja-token-punctuation { color: #858585; }\n`;\n\nlet jinjaRendererStyleRefCount = 0;\nlet jinjaRendererStyleEl: HTMLStyleElement | null = null;\n\nfunction ensureJinjaRendererStyles(): void {\n if (jinjaRendererStyleRefCount++ > 0) return;\n if (typeof document === 'undefined') return;\n const existing = document.getElementById(JINJA_RENDERER_STYLE_ID);\n if (existing instanceof HTMLStyleElement) {\n jinjaRendererStyleEl = existing;\n return;\n }\n jinjaRendererStyleEl = document.createElement('style');\n jinjaRendererStyleEl.id = JINJA_RENDERER_STYLE_ID;\n jinjaRendererStyleEl.textContent = JINJA_RENDERER_STYLES;\n document.head.appendChild(jinjaRendererStyleEl);\n}\n\nfunction renderConditionTokens(condition: string): ReactElement[] {\n const tokens = tokenizeCondition(condition);\n return tokens.map((token, i) => (\n <span key={`t-${i}-${token.start}`} className={`ab-r-jinja-token-${token.category}`}>\n {token.text}\n </span>\n ));\n}\n\nfunction renderJinjaBranch(\n branch: JinjaIfBranch<BlockNode>,\n key: string,\n isLast: boolean,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const branchType = branch.branchType;\n const badgeLabel = branchType === 'elif' ? 'ELSE IF' : branchType.toUpperCase();\n\n return (\n <div\n key={key}\n className={`ab-r-jinja-branch${isLast ? ' ab-r-jinja-branch-last' : ''}`}\n >\n <div className=\"ab-r-jinja-header\">\n <span className={`ab-r-jinja-badge ab-r-jinja-badge-${branchType}`}>\n {badgeLabel}\n </span>\n {branchType === 'else' ? (\n <span className=\"ab-r-jinja-otherwise\">otherwise</span>\n ) : (\n <span className=\"ab-r-jinja-condition\">\n {branch.condition ? renderConditionTokens(branch.condition) : null}\n </span>\n )}\n </div>\n <div className=\"ab-r-jinja-body\">\n <div className=\"ab-r-jinja-divider-col\">\n <div className=\"ab-r-jinja-divider\" />\n </div>\n <div className=\"ab-r-jinja-content\">\n {branch.content.map((child, i) => renderBlock(child, `${key}-c${i}`, renderNode))}\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderJinjaIfBlock(\n node: { readonly type: 'jinjaIfBlock'; readonly branches: readonly JinjaIfBranch<BlockNode>[] },\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n ensureJinjaRendererStyles();\n\n return (\n <div key={key} className=\"ab-r-jinja-block\">\n {node.branches.map((branch, i) =>\n renderJinjaBranch(\n branch,\n `${key}-b${i}`,\n i === node.branches.length - 1,\n renderNode,\n ),\n )}\n </div>\n );\n}\n\n// --- End Jinja If Block rendering ---\n\nfunction renderBlock(\n node: BlockNode,\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const defaultRender = (): ReactElement => {\n switch (node.type) {\n case 'paragraph':\n return <p key={key}>{renderInlineContent(node.content, key, renderNode)}</p>;\n case 'heading': {\n const Tag = `h${node.level}` as keyof JSX.IntrinsicElements;\n return <Tag key={key}>{renderInlineContent(node.content, key, renderNode)}</Tag>;\n }\n case 'bulletList':\n return (\n <ul key={key}>\n {node.content.map((item, i) => renderBlock(item, `${key}-${i}`, renderNode))}\n </ul>\n );\n case 'orderedList':\n return (\n <ol key={key} start={node.start !== 1 ? node.start : undefined}>\n {node.content.map((item, i) => renderBlock(item, `${key}-${i}`, renderNode))}\n </ol>\n );\n case 'listItem':\n if (node.checked != null) {\n return (\n <li key={key} style={{ display: 'flex', alignItems: 'flex-start', listStyle: 'none' }}>\n <input\n type=\"checkbox\"\n checked={node.checked}\n readOnly\n style={{ marginRight: 6, marginTop: 4, flexShrink: 0 }}\n />\n <div style={node.checked ? { textDecoration: 'line-through', opacity: 0.6 } : undefined}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </div>\n </li>\n );\n }\n return (\n <li key={key}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </li>\n );\n case 'blockquote':\n return (\n <blockquote key={key}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </blockquote>\n );\n case 'jinjaIfBlock':\n return renderJinjaIfBlock(node, key, renderNode);\n case 'horizontalRule':\n return <hr key={key} />;\n case 'table':\n return (\n <table key={key}>\n <tbody>\n {node.content.map((row, ri) => (\n <tr key={`${key}-r${ri}`}>\n {row.content.map((cell, ci) => {\n const CellTag = cell.header ? 'th' : 'td';\n return (\n <CellTag key={`${key}-r${ri}-c${ci}`}>\n {renderInlineContent(cell.content, `${key}-r${ri}-c${ci}`, renderNode)}\n </CellTag>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n );\n default:\n return <div key={key} />;\n }\n };\n\n if (renderNode) return renderNode(node, defaultRender);\n return defaultRender();\n}\n\nexport function ActionbookRenderer({ doc, className, renderNode }: ActionbookRendererProps): ReactElement {\n return (\n <div className={className}>\n {doc.content.map((node, i) => renderBlock(node, `ab-${i}`, renderNode))}\n </div>\n );\n}\n","type TokenType =\n | 'STRING'\n | 'NUMBER'\n | 'BOOL'\n | 'NONE'\n | 'IDENT'\n | 'AND'\n | 'OR'\n | 'NOT'\n | 'IN'\n | 'IS'\n | 'EQ'\n | 'NEQ'\n | 'LT'\n | 'GT'\n | 'LTE'\n | 'GTE'\n | 'LPAREN'\n | 'RPAREN';\n\nexport type HighlightCategory = 'variable' | 'operator' | 'value' | 'punctuation';\n\nexport interface ConditionToken {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n readonly category: HighlightCategory;\n}\n\ninterface RawToken {\n readonly type: TokenType;\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst KEYWORDS: Readonly<Record<string, TokenType>> = {\n and: 'AND',\n or: 'OR',\n not: 'NOT',\n in: 'IN',\n is: 'IS',\n True: 'BOOL',\n False: 'BOOL',\n true: 'BOOL',\n false: 'BOOL',\n None: 'NONE',\n null: 'NONE',\n};\n\nconst CATEGORY_BY_TYPE: Readonly<Record<TokenType, HighlightCategory>> = {\n STRING: 'value',\n NUMBER: 'value',\n BOOL: 'value',\n NONE: 'value',\n IDENT: 'variable',\n AND: 'operator',\n OR: 'operator',\n NOT: 'operator',\n IN: 'operator',\n IS: 'operator',\n EQ: 'operator',\n NEQ: 'operator',\n LT: 'operator',\n GT: 'operator',\n LTE: 'operator',\n GTE: 'operator',\n LPAREN: 'punctuation',\n RPAREN: 'punctuation',\n};\n\nconst NEGATIVE_NUMBER_PRECEDERS = new Set<TokenType>([\n 'AND',\n 'OR',\n 'NOT',\n 'IN',\n 'IS',\n 'EQ',\n 'NEQ',\n 'LT',\n 'GT',\n 'LTE',\n 'GTE',\n 'LPAREN',\n]);\n\nfunction canStartNegativeNumber(tokens: readonly RawToken[]): boolean {\n if (tokens.length === 0) {\n return true;\n }\n\n const previous = tokens[tokens.length - 1];\n return NEGATIVE_NUMBER_PRECEDERS.has(previous.type);\n}\n\nfunction finalizeTokens(input: string, rawTokens: readonly RawToken[]): ConditionToken[] {\n const highlighted: ConditionToken[] = [];\n\n for (let i = 0; i < rawTokens.length; i++) {\n const token = rawTokens[i];\n const next = rawTokens[i + 1];\n\n if (token.type === 'IS' && next?.type === 'NOT') {\n highlighted.push({\n text: input.slice(token.start, next.end),\n start: token.start,\n end: next.end,\n category: 'operator',\n });\n i++;\n continue;\n }\n\n highlighted.push({\n text: token.text,\n start: token.start,\n end: token.end,\n category: CATEGORY_BY_TYPE[token.type],\n });\n }\n\n return highlighted;\n}\n\nexport function tokenizeCondition(input: string): ConditionToken[] {\n const rawTokens: RawToken[] = [];\n let i = 0;\n\n while (i < input.length) {\n const char = input[i];\n\n if (/\\s/.test(char)) {\n i++;\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n const start = i;\n const quote = char;\n i++;\n\n while (i < input.length) {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i += 2;\n continue;\n }\n\n if (input[i] === quote) {\n i++;\n rawTokens.push({\n type: 'STRING',\n text: input.slice(start, i),\n start,\n end: i,\n });\n break;\n }\n\n i++;\n }\n\n if (rawTokens[rawTokens.length - 1]?.start !== start) {\n return finalizeTokens(input, rawTokens);\n }\n\n continue;\n }\n\n if (/[0-9]/.test(char) || (char === '-' && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && canStartNegativeNumber(rawTokens))) {\n const start = i;\n\n if (input[i] === '-') {\n i++;\n }\n\n while (i < input.length && /[0-9]/.test(input[i])) {\n i++;\n }\n\n if (i < input.length && input[i] === '.') {\n i++;\n while (i < input.length && /[0-9]/.test(input[i])) {\n i++;\n }\n }\n\n rawTokens.push({\n type: 'NUMBER',\n text: input.slice(start, i),\n start,\n end: i,\n });\n continue;\n }\n\n if (/[a-zA-Z_]/.test(char)) {\n const start = i;\n i++;\n\n while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {\n i++;\n }\n\n const text = input.slice(start, i);\n rawTokens.push({\n type: KEYWORDS[text] ?? 'IDENT',\n text,\n start,\n end: i,\n });\n continue;\n }\n\n if (i + 1 < input.length) {\n const twoChar = input.slice(i, i + 2);\n\n if (twoChar === '==') {\n rawTokens.push({ type: 'EQ', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '!=') {\n rawTokens.push({ type: 'NEQ', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '<=') {\n rawTokens.push({ type: 'LTE', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '>=') {\n rawTokens.push({ type: 'GTE', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n }\n\n if (char === '<') {\n rawTokens.push({ type: 'LT', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === '>') {\n rawTokens.push({ type: 'GT', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === '(') {\n rawTokens.push({ type: 'LPAREN', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === ')') {\n rawTokens.push({ type: 'RPAREN', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n return finalizeTokens(input, rawTokens);\n }\n\n return finalizeTokens(input, rawTokens);\n}\n","/**\n * Inline SVG icons copied from sbdashboard/app/feather/components/icons/svg/.\n * Intentionally minimal — no external icon library required.\n */\nimport React from 'react';\n\ninterface IconProps {\n size?: number;\n fill?: string;\n style?: React.CSSProperties;\n}\n\n/** SBiDeveloperResources — used for \"tool\" resource tags */\nexport function IconTool({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path d=\"m14.064 3.649-6 16 1.873.702 6-16-1.873-.702ZM6.293 5.793.086 12l6.207 6.207 1.414-1.414L2.914 12l4.793-4.793-1.414-1.414ZM17.707 5.793 23.914 12l-6.207 6.207-1.414-1.414L21.086 12l-4.793-4.793 1.414-1.414Z\" />\n </svg>\n );\n}\n\n/** SBiDivide — used for \"manual\" resource tags */\nexport function IconManual({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M18.5 4C19.3284 4 20 4.67157 20 5.5C20 6.32843 19.3284 7 18.5 7C17.6716 7 17 6.32843 17 5.5C17 4.67157 17.6716 4 18.5 4ZM18.5 2C16.9145 2 15.5752 3.05426 15.1449 4.5H10.5V11H8.91946C8.57612 9.42741 7.17556 8.25 5.5 8.25C3.567 8.25 2 9.817 2 11.75C2 13.683 3.567 15.25 5.5 15.25C6.9926 15.25 8.26697 14.3157 8.77019 13H10.5V19.5H15.1449C15.5752 20.9457 16.9145 22 18.5 22C20.433 22 22 20.433 22 18.5C22 16.567 20.433 15 18.5 15C16.9145 15 15.5752 16.0543 15.1449 17.5H12.5V13V11V6.5H15.1449C15.5752 7.94574 16.9145 9 18.5 9C20.433 9 22 7.433 22 5.5C22 3.567 20.433 2 18.5 2ZM17 18.5C17 17.6716 17.6716 17 18.5 17C19.3284 17 20 17.6716 20 18.5C20 19.3284 19.3284 20 18.5 20C17.6716 20 17 19.3284 17 18.5ZM5.5 10.25C6.32843 10.25 7 10.9216 7 11.75C7 12.5784 6.32843 13.25 5.5 13.25C4.67157 13.25 4 12.5784 4 11.75C4 10.9216 4.67157 10.25 5.5 10.25Z\"\n />\n </svg>\n );\n}\n\n/** SBiReplyTemplate — used for \"agent_message_template\" resource tags */\nexport function IconMessageTemplate({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M2 4.5A2.5 2.5 0 0 1 4.5 2h15A2.5 2.5 0 0 1 22 4.5v11a2.5 2.5 0 0 1-2.5 2.5H6l-4 4V4.5Zm2 12.672L5.172 16H19.5a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15a.5.5 0 0 0-.5.5v12.672Z\"\n />\n <path d=\"m12 12.404 2.781 1.687-.738-3.179L16.5 8.774l-3.236-.276L12 5.5l-1.264 2.998-3.236.276 2.457 2.138-.738 3.179L12 12.404Z\" />\n </svg>\n );\n}\n\n/** SBiAgents — used for \"handoff\" resource tags */\nexport function IconHandoff({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M12 4a8 8 0 0 0-8 8v4a3 3 0 1 1 6 0v3a3 3 0 1 1-6 0v-.5H2V12C2 6.477 6.477 2 12 2s10 4.477 10 10v6.5h-2v.5a3 3 0 1 1-6 0v-3a3 3 0 1 1 6 0v-4a8 8 0 0 0-8-8ZM8 16v3a1 1 0 1 1-2 0v-3a1 1 0 1 1 2 0Zm10 3v-3a1 1 0 1 0-2 0v3a1 1 0 1 0 2 0Z\"\n />\n </svg>\n );\n}\n\n/** SBiTime — used for \"time_diff\" resource tags */\nexport function IconTimeDiff({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path d=\"M12.485 6.244h-2v6.618l4.553 2.277.895-1.79-3.448-1.723V6.244Z\" />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm8-10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Z\"\n />\n </svg>\n );\n}\n\n/** SBiAnchor — used for jump points */\nexport function IconStop({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 8 8\" width={size} height={size} fill=\"none\" style={style}>\n <path d=\"M5.4375 3.375L2.0625 3.375V4.125L5.4375 4.125V3.375Z\" fill={fill} />\n <path fillRule=\"evenodd\" clipRule=\"evenodd\" d=\"M3.75 7.5C5.82107 7.5 7.5 5.82107 7.5 3.75C7.5 1.67893 5.82107 0 3.75 0C1.67893 0 0 1.67893 0 3.75C0 5.82107 1.67893 7.5 3.75 7.5ZM6.75 3.75C6.75 5.40685 5.40685 6.75 3.75 6.75C2.09315 6.75 0.75 5.40685 0.75 3.75C0.75 2.09315 2.09315 0.75 3.75 0.75C5.40685 0.75 6.75 2.09315 6.75 3.75Z\" fill={fill} />\n </svg>\n );\n}\n\nexport function IconAnchor({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 16 16\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <g fillRule=\"evenodd\" clipPath=\"url(#anchor-clip)\" clipRule=\"evenodd\">\n <path d=\"M8 5.333a2.667 2.667 0 1 1 0 5.333 2.667 2.667 0 0 1 0-5.333Zm0 1.333a1.333 1.333 0 1 0 0 2.667 1.333 1.333 0 0 0 0-2.667Z\" />\n <path d=\"M8.667 2.037a6 6 0 0 1 5.295 5.296h1.371v1.333h-1.37a6 6 0 0 1-5.296 5.295v1.372H7.333V13.96a6 6 0 0 1-5.295-5.295H.667V7.333h1.37a6 6 0 0 1 5.296-5.296V.666h1.334v1.371ZM8 3.333a4.667 4.667 0 1 0 0 9.333 4.667 4.667 0 0 0 0-9.333Z\" />\n </g>\n <defs>\n <clipPath id=\"anchor-clip\">\n <path d=\"M0 0H16V16H0z\" transform=\"translate(0 -.001)\" />\n </clipPath>\n </defs>\n </svg>\n );\n}\n","import React, { forwardRef } from 'react';\n\nexport interface EditorShellProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Contenteditable container for ProseMirror EditorView.\n * Pass the ref from `useEditorView().viewRef` to mount the editor.\n */\nexport const EditorShell = forwardRef<HTMLDivElement, EditorShellProps>(function EditorShell(\n { className, style },\n ref,\n) {\n return <div ref={ref} className={className} style={style} />;\n});\n","import { createElement } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport type { Decoration, DecorationSource, EditorView, NodeView } from 'prosemirror-view';\nimport type { NodeViewFactory } from '../plugin/types';\n\nexport interface ReactNodeViewProps {\n node: PMNode;\n view: EditorView;\n getPos: () => number | undefined;\n selected: boolean;\n /** Outer node decorations currently applied to this node. */\n decorations: readonly Decoration[];\n}\n\nexport interface ReactNodeViewOptions {\n /** The React component to render */\n component: React.ComponentType<ReactNodeViewProps>;\n /** Container tag name (default: 'span' for inline, 'div' for block) */\n as?: string;\n /** CSS class name for the container */\n className?: string;\n /** Whether this is an inline node (default: true) */\n inline?: boolean;\n /**\n * Optional wrapper component that provides context (Router, QueryClient, etc.)\n * around every NodeView React root. Receives `children` as its only prop.\n */\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n}\n\nclass ReactNodeViewImpl implements NodeView {\n dom: HTMLElement;\n private root: Root;\n private component: React.ComponentType<ReactNodeViewProps>;\n private wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n private _node: PMNode;\n private _view: EditorView;\n private _getPos: () => number | undefined;\n private _selected = false;\n private _decorations: readonly Decoration[] = [];\n\n constructor(\n node: PMNode,\n view: EditorView,\n getPos: () => number | undefined,\n decorations: readonly Decoration[],\n options: ReactNodeViewOptions,\n ) {\n this._node = node;\n this._view = view;\n this._getPos = getPos;\n this._decorations = decorations;\n this.component = options.component;\n this.wrapper = options.wrapper;\n\n const tag = options.as ?? (options.inline !== false ? 'span' : 'div');\n this.dom = document.createElement(tag);\n if (options.inline !== false) {\n this.dom.style.display = 'inline';\n this.dom.style.verticalAlign = 'baseline';\n }\n if (options.className) {\n this.dom.className = options.className;\n }\n\n this.root = createRoot(this.dom);\n this.render();\n }\n\n private render() {\n const element = createElement(this.component, {\n node: this._node,\n view: this._view,\n getPos: this._getPos,\n selected: this._selected,\n decorations: this._decorations,\n });\n this.root.render(\n this.wrapper ? createElement(this.wrapper, null, element) : element,\n );\n }\n\n update(node: PMNode, decorations: readonly Decoration[], _innerDecorations: DecorationSource): boolean {\n if (node.type !== this._node.type) return false;\n this._node = node;\n this._decorations = decorations;\n this.render();\n return true;\n }\n\n selectNode() {\n this._selected = true;\n this.render();\n }\n\n deselectNode() {\n this._selected = false;\n this.render();\n }\n\n destroy() {\n // Defer unmount to avoid flushSync warnings in React 18\n setTimeout(() => this.root.unmount(), 0);\n }\n\n stopEvent() {\n return false;\n }\n\n ignoreMutation() {\n return true;\n }\n}\n\n/**\n * Creates a NodeViewFactory that renders a React component as a PM NodeView.\n *\n * Usage:\n * ```ts\n * const jumpPointPlugin: ActionbookPlugin = {\n * name: 'jumpPoint',\n * nodeViews: () => ({\n * jumpPoint: createReactNodeView({ component: JumpPointView }),\n * }),\n * };\n * ```\n */\nexport function createReactNodeView(options: ReactNodeViewOptions): NodeViewFactory {\n return (node, view, getPos, decorations) => new ReactNodeViewImpl(node, view, getPos, decorations, options);\n}\n","import { useRef, useEffect, useCallback, useState, type RefCallback } from 'react';\nimport { EditorState, type Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { Node as PMNode } from 'prosemirror-model';\nimport type { DocumentNode } from '../../ast/types';\nimport type { LlmCompletionEndpoint } from '../../lint/types';\nimport { fromProseMirrorJSON, type JSONContent } from '../../compat/prosemirror';\nimport { serializeToMarkdown } from '../../markdown/serializer';\nimport { actionbookSchema } from '../schema';\nimport { createPluginArray } from '../plugin/registry';\nimport { toProseMirrorJSON } from '../bridge/toProseMirrorJSON';\nimport { EDITOR_TEXT_STYLES } from '../styles/editorTextStyles';\nimport type { ActionbookPlugin } from '../plugin/types';\n\nconst TEXT_STYLE_ID = 'ab-editor-text-styles';\nlet textStyleRefCount = 0;\n\nfunction acquireTextStyles(): void {\n if (textStyleRefCount++ > 0) return;\n if (document.getElementById(TEXT_STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = TEXT_STYLE_ID;\n el.textContent = EDITOR_TEXT_STYLES;\n document.head.appendChild(el);\n}\n\nfunction releaseTextStyles(): void {\n if (--textStyleRefCount > 0) return;\n document.getElementById(TEXT_STYLE_ID)?.remove();\n}\n\nexport interface EditorViewConfig {\n plugins?: ActionbookPlugin[];\n content?: DocumentNode | null;\n editable?: boolean;\n onTransaction?: (state: EditorState) => void;\n onContentChange?: (doc: DocumentNode) => void;\n /**\n * Optional LLM completion endpoint for LLM-based lint rules.\n * When provided, the editor can run async lint rules that leverage LLM analysis.\n * Accepts any backend: OpenAI, Anthropic, Gemini Nano, custom proxy, etc.\n */\n llmCompletionEndpoint?: LlmCompletionEndpoint;\n}\n\nexport interface EditorViewHandle {\n viewRef: RefCallback<HTMLDivElement>;\n view: EditorView | null;\n /** Always returns the current EditorView (not a stale snapshot). */\n getView: () => EditorView | null;\n getAST: () => DocumentNode | null;\n getMarkdown: () => string;\n setContent: (doc: DocumentNode) => void;\n focus: () => void;\n destroy: () => void;\n}\n\nfunction docToState(doc: DocumentNode | null | undefined, plugins: import('prosemirror-state').Plugin[]): EditorState {\n const pmJSON = doc ? toProseMirrorJSON(doc) : { type: 'doc', content: [{ type: 'paragraph' }] };\n const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);\n return EditorState.create({ doc: pmDoc, plugins });\n}\n\nfunction pmDocToAST(pmDoc: PMNode): DocumentNode {\n const json = pmDoc.toJSON() as JSONContent;\n return fromProseMirrorJSON(json);\n}\n\nexport function useEditorView(config: EditorViewConfig): EditorViewHandle {\n const viewInstanceRef = useRef<EditorView | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [, forceUpdate] = useState(0);\n\n // Stable refs for callbacks\n const configRef = useRef(config);\n configRef.current = config;\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n viewInstanceRef.current?.destroy();\n viewInstanceRef.current = null;\n };\n }, []);\n\n // When `editable` changes, dispatch a no-op transaction so ProseMirror plugins\n // (e.g. editableWatcher in jinjaIfBlockPlugin) can detect the change and\n // re-render NodeViews that show/hide edit-only controls.\n const prevEditableRef = useRef(config.editable);\n useEffect(() => {\n if (prevEditableRef.current !== config.editable) {\n prevEditableRef.current = config.editable;\n const view = viewInstanceRef.current;\n if (view) {\n const tr = view.state.tr;\n tr.setMeta('editableChanged', true);\n view.dispatch(tr);\n }\n }\n }, [config.editable]);\n\n // Ref callback: create EditorView when DOM element appears, destroy when removed\n const viewRef: RefCallback<HTMLDivElement> = useCallback((container: HTMLDivElement | null) => {\n // Same element — nothing to do\n if (container === containerRef.current) return;\n\n // Previous container removed — destroy old view\n if (viewInstanceRef.current) {\n viewInstanceRef.current.destroy();\n viewInstanceRef.current = null;\n releaseTextStyles();\n }\n\n containerRef.current = container;\n if (!container) {\n forceUpdate((n) => n + 1);\n return;\n }\n\n acquireTextStyles();\n const { pmPlugins, nodeViews } = createPluginArray(configRef.current.plugins ?? []);\n const state = docToState(configRef.current.content, pmPlugins);\n\n const view = new EditorView(container, {\n state,\n nodeViews,\n attributes: { spellcheck: 'false' },\n editable: () => configRef.current.editable === true,\n dispatchTransaction(tr: Transaction) {\n const newState = view.state.apply(tr);\n view.updateState(newState);\n configRef.current.onTransaction?.(newState);\n if (tr.docChanged) {\n const ast = pmDocToAST(newState.doc);\n configRef.current.onContentChange?.(ast);\n }\n },\n });\n\n viewInstanceRef.current = view;\n forceUpdate((n) => n + 1);\n }, []);\n\n const getAST = useCallback((): DocumentNode | null => {\n const view = viewInstanceRef.current;\n if (!view) return null;\n return pmDocToAST(view.state.doc);\n }, []);\n\n const getMarkdown = useCallback((): string => {\n const ast = getAST();\n if (!ast) return '';\n return serializeToMarkdown(ast);\n }, [getAST]);\n\n const setContent = useCallback((doc: DocumentNode) => {\n const view = viewInstanceRef.current;\n if (!view) return;\n const pmJSON = toProseMirrorJSON(doc);\n const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);\n const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, pmDoc.content);\n // Don't record initial content load in undo history\n tr.setMeta('addToHistory', false);\n view.dispatch(tr);\n }, []);\n\n const focus = useCallback(() => {\n viewInstanceRef.current?.focus();\n }, []);\n\n const destroy = useCallback(() => {\n if (viewInstanceRef.current) {\n viewInstanceRef.current.destroy();\n viewInstanceRef.current = null;\n releaseTextStyles();\n }\n }, []);\n\n const getView = useCallback(() => viewInstanceRef.current, []);\n\n return {\n viewRef,\n view: viewInstanceRef.current,\n getView,\n getAST,\n getMarkdown,\n setContent,\n focus,\n destroy,\n };\n}\n","// === Marks (인라인 서식) ===\nexport type BoldMark = { readonly type: 'bold' };\nexport type ItalicMark = { readonly type: 'italic' };\nexport type UnderlineMark = { readonly type: 'underline' };\nexport type StrikethroughMark = { readonly type: 'strikethrough' };\nexport type CodeMark = { readonly type: 'code' };\nexport type LinkMark = { readonly type: 'link'; readonly href: string; readonly title?: string };\nexport type Mark = BoldMark | ItalicMark | UnderlineMark | StrikethroughMark | CodeMark | LinkMark;\n\n// === Resource tag type values ===\nexport const RESOURCE_TAG_TYPES = ['tool', 'manual', 'agent_message_template', 'handoff', 'time_diff', 'time_difference'] as const;\nexport type ResourceTagType = (typeof RESOURCE_TAG_TYPES)[number];\n\n// === Inline Nodes ===\nexport type TextNode = {\n readonly type: 'text';\n readonly text: string;\n readonly marks?: readonly Mark[];\n};\n\nexport type ResourceTagNode = {\n readonly type: 'resourceTag';\n readonly tagType: ResourceTagType;\n readonly resourceId: string;\n readonly text: string;\n};\n\nexport type JumpPointNode = {\n readonly type: 'jumpPoint';\n readonly id: string; // /^[\\p{L}\\p{N}_-]+$/u\n};\n\nexport type HardBreakNode = { readonly type: 'hardBreak' };\n\n// === Jinja If (Inline) ===\nexport type JinjaIfBranch<T> = {\n readonly branchType: 'if' | 'elif' | 'else';\n readonly condition?: string;\n readonly content: readonly T[];\n};\n\nexport type JinjaIfInlineNode = {\n readonly type: 'jinjaIfInline';\n readonly branches: readonly JinjaIfBranch<InlineNode>[];\n};\n\nexport type InlineNode = TextNode | ResourceTagNode | JumpPointNode | HardBreakNode | JinjaIfInlineNode;\n\n// === Block Nodes ===\nexport type ParagraphNode = {\n readonly type: 'paragraph';\n readonly content: readonly InlineNode[];\n};\n\nexport type HeadingNode = {\n readonly type: 'heading';\n readonly level: 1 | 2 | 3 | 4 | 5 | 6;\n readonly content: readonly InlineNode[];\n};\n\nexport type ListItemNode = {\n readonly type: 'listItem';\n readonly checked?: boolean | null;\n readonly value?: number | null;\n readonly spread?: boolean;\n readonly content: readonly BlockNode[];\n};\n\nexport type BulletListNode = {\n readonly type: 'bulletList';\n readonly spread?: boolean;\n readonly content: readonly ListItemNode[];\n};\n\nexport type OrderedListNode = {\n readonly type: 'orderedList';\n readonly start: number;\n readonly spread?: boolean;\n readonly content: readonly ListItemNode[];\n};\n\nexport type BlockquoteNode = {\n readonly type: 'blockquote';\n readonly content: readonly BlockNode[];\n};\n\nexport type HorizontalRuleNode = { readonly type: 'horizontalRule' };\n\nexport type CodeBlockNode = {\n readonly type: 'codeBlock';\n readonly language?: string;\n readonly content: string;\n};\n\nexport type TableCellNode = {\n readonly type: 'tableCell';\n readonly header?: boolean;\n readonly content: readonly InlineNode[];\n};\n\nexport type TableRowNode = {\n readonly type: 'tableRow';\n readonly content: readonly TableCellNode[];\n};\n\nexport type TableNode = {\n readonly type: 'table';\n readonly content: readonly TableRowNode[];\n};\n\n// === Jinja If (Block) ===\nexport type JinjaIfBlockNode = {\n readonly type: 'jinjaIfBlock';\n readonly branches: readonly JinjaIfBranch<BlockNode>[];\n};\n\n// === Note Block (editor-only, not serialized to markdown) ===\nexport type NoteBlockNode = {\n readonly type: 'noteBlock';\n readonly content: readonly BlockNode[];\n};\n\nexport type BlockNode =\n | ParagraphNode\n | HeadingNode\n | BulletListNode\n | OrderedListNode\n | ListItemNode\n | BlockquoteNode\n | HorizontalRuleNode\n | CodeBlockNode\n | TableNode\n | JinjaIfBlockNode\n | NoteBlockNode;\n\n// === Document Root ===\nexport type DocumentNode = {\n readonly type: 'doc';\n readonly content: readonly BlockNode[];\n};\n\n// === Union ===\nexport type AstNode = DocumentNode | BlockNode | InlineNode | TableRowNode | TableCellNode;\n\n// === Node Path (향후 CRDT/undo-redo 지원) ===\nexport type NodePath = readonly number[];\n\n// === Jump point ID validation ===\nexport const JUMP_POINT_ID_PATTERN = /^[\\p{L}\\p{N}_-]+$/u;\n","/**\n * Convert ProseMirror/Tiptap JSONContent to ActionbookAST.\n *\n * This handles the legacy editor_data format stored in LogicV2.\n */\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n Mark,\n ResourceTagType,\n TableNode,\n TableRowNode,\n TableCellNode,\n JinjaIfBranch,\n} from '../ast/types';\nimport { RESOURCE_TAG_TYPES } from '../ast/types';\n\nconst MAX_DEPTH = 128;\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nconst LIST_TYPES = new Set(['bulletList', 'orderedList']);\n\n/**\n * A list is \"loose\" (spread) if any item has multiple non-list block children.\n * Nested sub-lists don't count — a listItem with [paragraph, bulletList] is still tight.\n */\nfunction isLooseList(items: { content: BlockNode[] }[]): boolean {\n return items.some((li) => {\n const nonListBlocks = li.content.filter((b) => !LIST_TYPES.has(b.type));\n return nonListBlocks.length > 1;\n });\n}\n\n// Minimal JSONContent type (compatible with @tiptap/core)\nexport type JSONContent = {\n type?: string;\n attrs?: Record<string, unknown>;\n content?: JSONContent[];\n marks?: { type: string; attrs?: Record<string, unknown> }[];\n text?: string;\n};\n\nfunction convertPMMark(mark: { type: string; attrs?: Record<string, unknown> }): Mark | null {\n switch (mark.type) {\n case 'bold':\n return { type: 'bold' };\n case 'italic':\n return { type: 'italic' };\n case 'underline':\n return { type: 'underline' };\n case 'strikethrough':\n return { type: 'strikethrough' };\n case 'code':\n return { type: 'code' };\n case 'link': {\n const rawHref = (mark.attrs?.href as string) ?? '';\n // Strip dangerous URL protocols\n if (!ALLOWED_URL_PROTOCOLS.test(rawHref)) return null;\n const title = mark.attrs?.title as string | undefined;\n return title ? { type: 'link', href: rawHref, title } : { type: 'link', href: rawHref };\n }\n // Ignored marks (UI-only or unused)\n case 'diffMark':\n case 'inlineResource':\n case 'textStyle':\n return null;\n default:\n return null;\n }\n}\n\nfunction convertPMInline(node: JSONContent, depth: number): InlineNode[] {\n if (depth > MAX_DEPTH) return [];\n const type = node.type ?? '';\n\n switch (type) {\n case 'text': {\n const marks = (node.marks ?? []).map(convertPMMark).filter((m): m is Mark => m !== null);\n const textNode = node.text ?? '';\n return marks.length > 0 ? [{ type: 'text', text: textNode, marks }] : [{ type: 'text', text: textNode }];\n }\n\n case 'inlineToolTag': {\n const attrs = node.attrs ?? {};\n const tagType = (attrs.type as string) ?? 'tool';\n const text = (attrs.text as string) ?? '';\n // Fallback: unknown tag types become plain text to avoid validation failure\n if (!(RESOURCE_TAG_TYPES as readonly string[]).includes(tagType)) {\n return text ? [{ type: 'text', text }] : [];\n }\n return [\n {\n type: 'resourceTag',\n tagType: tagType as ResourceTagType,\n resourceId: (attrs.resourceId as string) ?? '',\n text,\n },\n ];\n }\n\n case 'jumpPoint': {\n const id = (node.attrs?.id as string) ?? '';\n return [{ type: 'jumpPoint', id }];\n }\n\n case 'hardBreak':\n return [{ type: 'hardBreak' }];\n\n default:\n if (node.text) {\n return [{ type: 'text', text: node.text }];\n }\n if (node.content) {\n return node.content.flatMap((c) => convertPMInline(c, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertPMBlock(node: JSONContent, depth: number = 0): BlockNode[] {\n if (depth > MAX_DEPTH) return [];\n const type = node.type ?? '';\n const children = node.content ?? [];\n\n switch (type) {\n case 'paragraph':\n return [{ type: 'paragraph', content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];\n\n case 'heading': {\n const level = ((node.attrs?.level as number) ?? 1) as 1 | 2 | 3 | 4 | 5 | 6;\n return [{ type: 'heading', level, content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];\n }\n\n case 'bulletList': {\n const items = children.map((c) => convertPMListItem(c, depth + 1));\n const spread = isLooseList(items);\n return [\n {\n type: 'bulletList',\n ...(spread ? { spread: true } : {}),\n content: items.map((li) => spread ? { ...li, spread: true } : li),\n },\n ];\n }\n\n case 'orderedList': {\n const start = (node.attrs?.start as number) ?? 1;\n const items = children.map((c) => convertPMListItem(c, depth + 1));\n const spread = isLooseList(items);\n return [\n {\n type: 'orderedList',\n start,\n ...(spread ? { spread: true } : {}),\n content: items.map((li) => spread ? { ...li, spread: true } : li),\n },\n ];\n }\n\n case 'listItem': {\n return [convertPMListItem(node, depth)];\n }\n\n case 'blockquote':\n return [{ type: 'blockquote', content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];\n\n case 'horizontalRule':\n return [{ type: 'horizontalRule' }];\n\n case 'codeBlock': {\n const textContent = children.map(c => (c as any).text ?? '').join('');\n return [{ type: 'codeBlock', content: textContent, ...(node.attrs?.language ? { language: node.attrs.language } : {}) } as BlockNode];\n }\n\n case 'noteBlock':\n return [{ type: 'noteBlock', content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];\n\n case 'table': {\n const rows: TableRowNode[] = children.map((rowNode) => {\n const cells: TableCellNode[] = (rowNode.content ?? []).map((cellNode) => {\n const cellType = cellNode.type ?? '';\n const isHeader = cellType === 'tableHeader';\n const inlines = (cellNode.content ?? []).flatMap((c) => convertPMInline(c, depth + 3));\n return {\n type: 'tableCell' as const,\n ...(isHeader ? { header: true } : {}),\n content: inlines,\n };\n });\n return { type: 'tableRow' as const, content: cells };\n });\n return [{ type: 'table', content: rows }];\n }\n\n case 'jinjaIfBlock': {\n const branches: JinjaIfBranch<BlockNode>[] = children.map((branchNode) => {\n const branchType = (branchNode.attrs?.branchType ?? 'if') as 'if' | 'elif' | 'else';\n const condition = branchNode.attrs?.condition as string | undefined;\n const branchContent = (branchNode.content ?? []).flatMap((c) => convertPMBlock(c, depth + 2));\n return {\n branchType,\n ...(branchType !== 'else' && condition ? { condition } : {}),\n content: branchContent,\n };\n });\n if (branches.length === 0) return [];\n return [{ type: 'jinjaIfBlock', branches } as BlockNode];\n }\n\n case 'jinjaIfBranch':\n // Standalone jinjaIfBranch outside a jinjaIfBlock — flatten content\n return children.flatMap((c) => convertPMBlock(c, depth + 1));\n\n default:\n if (children.length > 0) {\n return children.flatMap((c) => convertPMBlock(c, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertPMListItem(node: JSONContent, depth: number = 0): { type: 'listItem'; checked?: boolean | null; spread?: boolean; content: BlockNode[] } {\n if (depth > MAX_DEPTH) return { type: 'listItem', content: [{ type: 'paragraph', content: [] }] };\n const children = node.content ?? [];\n const content = children.flatMap((c) => convertPMBlock(c, depth + 1));\n const base: { type: 'listItem'; checked?: boolean | null; spread?: boolean; content: BlockNode[] } = {\n type: 'listItem',\n content: content.length > 0 ? content : [{ type: 'paragraph', content: [] }],\n };\n const checked = node.attrs?.checked as boolean | null | undefined;\n if (typeof checked === 'boolean') {\n base.checked = checked;\n }\n const value = node.attrs?.value as number | null | undefined;\n if (value != null) {\n (base as any).value = value;\n }\n return base;\n}\n\nexport function fromProseMirrorJSON(pmJSON: JSONContent): DocumentNode {\n if (pmJSON.type !== 'doc') {\n const blocks = convertPMBlock(pmJSON, 0);\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n }\n\n const children = pmJSON.content ?? [];\n const blocks = children.flatMap((c) => convertPMBlock(c, 0));\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n}\n","import type { Link, List, ListItem, Parents, Text } from 'mdast';\nimport { defaultHandlers, toMarkdown } from 'mdast-util-to-markdown';\nimport type { Handle, Info, Options, State } from 'mdast-util-to-markdown';\nimport { gfmFootnoteToMarkdown } from 'mdast-util-gfm-footnote';\nimport { gfmStrikethroughToMarkdown } from 'mdast-util-gfm-strikethrough';\nimport { gfmTableToMarkdown } from 'mdast-util-gfm-table';\nimport { gfmTaskListItemToMarkdown } from 'mdast-util-gfm-task-list-item';\nimport { resourceTagToMarkdown } from './plugins/resourceTag';\nimport { jumpPointToMarkdown } from './plugins/jumpPoint';\nimport { toMdast } from './mdastAdapter';\nimport type { DocumentNode } from '../ast/types';\n\n// GFM without autolink literal — see parser.ts for rationale.\nconst gfmNoAutolinkToMarkdown = () => ({\n extensions: [\n gfmFootnoteToMarkdown(),\n gfmStrikethroughToMarkdown(),\n gfmTableToMarkdown(),\n gfmTaskListItemToMarkdown(),\n ],\n});\n\nfunction isEmptyParagraph(node: Parents | { type: string; children?: unknown[] }): boolean {\n return node.type === 'paragraph' && (!('children' in node) || !node.children || node.children.length === 0);\n}\n\nconst JINJA_TAG_RE = /^\\{%\\s*(if|elif|else|endif)\\b/;\n\nfunction isJinjaTagParagraph(node: { type: string; children?: unknown[] }): boolean {\n if (node.type !== 'paragraph') return false;\n const children = (node as Parents).children;\n if (!children || children.length !== 1) return false;\n const child = children[0] as { type: string; value?: string };\n return child.type === 'text' && typeof child.value === 'string' && JINJA_TAG_RE.test(child.value);\n}\n\n/**\n * Custom text handler that prevents unnecessary `_` escaping in inline text.\n *\n * mdast-util-to-markdown's default unsafe rules include\n * `{character: '_', inConstruct: 'phrasing'}`, which escapes every underscore\n * in paragraph/heading text (e.g. `ENUM_VALUE` → `ENUM\\_VALUE`). Since we\n * generate emphasis and strong with `*`, underscores in plain text are never\n * interpreted as emphasis markers and do not need escaping.\n *\n * The `unsafe` option in `toMarkdown` is ADDITIVE (it pushes into the default\n * list, never replaces it), so we cannot override this via options alone.\n * Instead, we temporarily remove the phrasing-`_` rule from `state.unsafe`\n * before delegating to the default text handler.\n */\nfunction textHandler(node: Text, parent: Parents | undefined, state: State, info: Info): string {\n const originalUnsafe = state.unsafe;\n state.unsafe = originalUnsafe.filter((p) => !(p.character === '_' && !p.atBreak));\n const result = (defaultHandlers.text as Options['handlers'] & ((n: Text, p: Parents | undefined, s: State, i: Info) => string))(node, parent, state, info);\n state.unsafe = originalUnsafe;\n return result;\n}\n\n/**\n * Custom link handler — emits `[text](url)` without angle brackets, even when\n * the URL contains spaces. tiptap-markdown uses this form; CommonMark would\n * require `<>` but micromark accepts both.\n */\nfunction linkHandler(node: Link, parent: Parents | undefined, state: State, info: Info): string {\n const childrenText = state.containerPhrasing(node, { ...info, before: '[', after: ']' });\n const url = node.url ?? '';\n const title = node.title;\n const titlePart = title ? ` \"${title.replace(/\"/g, '\\\\\"')}\"` : '';\n return `[${childrenText}](${url}${titlePart})`;\n}\n\n/**\n * Custom listItem handler that uses `_ordinalValue` (set by mdastAdapter)\n * to output the correct per-item number with \".\" marker.\n */\n/**\n * Custom listItem handler that uses `_ordinalValue` (set by mdastAdapter)\n * to output the correct per-item number with \".\" marker.\n * Patches `state.bulletLastUsed` / `state.options.bulletOrdered` temporarily\n * so the default handler emits \"N.\" with the right number.\n */\nfunction listItemHandler(node: ListItem, parent: Parents | undefined, state: State, info: Info): string {\n const value = (node as any)._ordinalValue as number | undefined;\n if (value != null && parent && (parent as List).ordered) {\n // Temporarily override the list start so the default handler uses our number\n const list = parent as List;\n const savedStart = list.start;\n const idx = list.children.indexOf(node);\n // The default handler computes: start + index. We want: value.\n // So set start = value - index.\n list.start = value - idx;\n const result = defaultHandlers.listItem(node, parent, state, info);\n list.start = savedStart;\n return result;\n }\n return defaultHandlers.listItem(node, parent, state, info);\n}\n\nexport function serializeToMarkdown(doc: DocumentNode): string {\n const mdastTree = toMdast(doc);\n\n const raw = toMarkdown(mdastTree, {\n bullet: '-',\n bulletOrdered: '.',\n rule: '-',\n listItemIndent: 'one',\n incrementListMarker: true,\n emphasis: '*',\n strong: '*',\n resourceLink: true,\n join: [\n // Empty paragraphs represent blank-line spacers.\n // Reduce the separator after an empty paragraph from \\n\\n to \\n\n // so that 1 empty paragraph = 1 extra blank line in the output.\n (left) => (isEmptyParagraph(left) ? 0 : null),\n ],\n handlers: {\n text: textHandler as Handle,\n link: linkHandler as Handle,\n listItem: listItemHandler as Handle,\n ...resourceTagToMarkdown().handlers,\n ...jumpPointToMarkdown().handlers,\n },\n extensions: [gfmNoAutolinkToMarkdown()],\n });\n\n // Post-process to match tiptap-markdown's serialization conventions:\n // 1. `\\>` at break positions → `&gt;` (entity-based escaping)\n // 2. Bare `>` in text (non-blockquote) → `&gt;` (tiptap encodes all `>`)\n // 3. `]` after `\\[` patterns → `\\]` (tiptap escapes both brackets)\n // 4. `&#x20;` → plain space (remark encodes leading spaces to prevent\n // markdown interpretation, but downstream consumers expect plain spaces)\n let result = raw\n .replace(/^(\\s*)\\\\>/gm, '$1&gt;')\n .replace(/(\\S) *>/g, (match, pre) => `${pre} &gt;`)\n .replace(/\\\\\\[([^\\]]*)\\]/g, '\\\\[$1\\\\]')\n .replace(/&#x20;/g, ' ');\n\n return result;\n}\n","export function deprecate(fn) {\n return fn\n}\n\nexport function equal() {}\n\nexport function ok() {}\n\nexport function unreachable() {}\n","/**\n * Normalize an identifier (as found in references, definitions).\n *\n * Collapses markdown whitespace, trim, and then lower- and uppercase.\n *\n * Some characters are considered “uppercase”, such as U+03F4 (`ϴ`), but if their\n * lowercase counterpart (U+03B8 (`θ`)) is uppercased will result in a different\n * uppercase character (U+0398 (`Θ`)).\n * So, to get a canonical form, we perform both lower- and uppercase.\n *\n * Using uppercase last makes sure keys will never interact with default\n * prototypal values (such as `constructor`): nothing in the prototype of\n * `Object` is uppercase.\n *\n * @param {string} value\n * Identifier to normalize.\n * @returns {string}\n * Normalized identifier.\n */\nexport function normalizeIdentifier(value) {\n return value\n // Collapse markdown whitespace.\n .replace(/[\\t\\n\\r ]+/g, \" \")\n // Trim.\n .replace(/^ | $/g, '')\n // Some characters are considered “uppercase”, but if their lowercase\n // counterpart is uppercased will result in a different uppercase\n // character.\n // Hence, to get that form, we perform both lower- and uppercase.\n // Upper case makes sure keys will not interact with default prototypal\n // methods: no method is uppercase.\n .toLowerCase().toUpperCase();\n}","/**\n * @import {\n * CompileContext,\n * Extension as FromMarkdownExtension,\n * Handle as FromMarkdownHandle\n * } from 'mdast-util-from-markdown'\n * @import {ToMarkdownOptions} from 'mdast-util-gfm-footnote'\n * @import {\n * Handle as ToMarkdownHandle,\n * Map,\n * Options as ToMarkdownExtension\n * } from 'mdast-util-to-markdown'\n * @import {FootnoteDefinition, FootnoteReference} from 'mdast'\n */\n\nimport {ok as assert} from 'devlop'\nimport {normalizeIdentifier} from 'micromark-util-normalize-identifier'\n\nfootnoteReference.peek = footnoteReferencePeek\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteCallString() {\n this.buffer()\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteCall(token) {\n this.enter({type: 'footnoteReference', identifier: '', label: ''}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteDefinitionLabelString() {\n this.buffer()\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteDefinition(token) {\n this.enter(\n {type: 'footnoteDefinition', identifier: '', label: '', children: []},\n token\n )\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteCallString(token) {\n const label = this.resume()\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'footnoteReference')\n node.identifier = normalizeIdentifier(\n this.sliceSerialize(token)\n ).toLowerCase()\n node.label = label\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteCall(token) {\n this.exit(token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteDefinitionLabelString(token) {\n const label = this.resume()\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'footnoteDefinition')\n node.identifier = normalizeIdentifier(\n this.sliceSerialize(token)\n ).toLowerCase()\n node.label = label\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteDefinition(token) {\n this.exit(token)\n}\n\n/** @type {ToMarkdownHandle} */\nfunction footnoteReferencePeek() {\n return '['\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {FootnoteReference} node\n */\nfunction footnoteReference(node, _, state, info) {\n const tracker = state.createTracker(info)\n let value = tracker.move('[^')\n const exit = state.enter('footnoteReference')\n const subexit = state.enter('reference')\n value += tracker.move(\n state.safe(state.associationId(node), {after: ']', before: value})\n )\n subexit()\n exit()\n value += tracker.move(']')\n return value\n}\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM footnotes\n * in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown`.\n */\nexport function gfmFootnoteFromMarkdown() {\n return {\n enter: {\n gfmFootnoteCallString: enterFootnoteCallString,\n gfmFootnoteCall: enterFootnoteCall,\n gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString,\n gfmFootnoteDefinition: enterFootnoteDefinition\n },\n exit: {\n gfmFootnoteCallString: exitFootnoteCallString,\n gfmFootnoteCall: exitFootnoteCall,\n gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString,\n gfmFootnoteDefinition: exitFootnoteDefinition\n }\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM footnotes\n * in markdown.\n *\n * @param {ToMarkdownOptions | null | undefined} [options]\n * Configuration (optional).\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown`.\n */\nexport function gfmFootnoteToMarkdown(options) {\n // To do: next major: change default.\n let firstLineBlank = false\n\n if (options && options.firstLineBlank) {\n firstLineBlank = true\n }\n\n return {\n handlers: {footnoteDefinition, footnoteReference},\n // This is on by default already.\n unsafe: [{character: '[', inConstruct: ['label', 'phrasing', 'reference']}]\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {FootnoteDefinition} node\n */\n function footnoteDefinition(node, _, state, info) {\n const tracker = state.createTracker(info)\n let value = tracker.move('[^')\n const exit = state.enter('footnoteDefinition')\n const subexit = state.enter('label')\n value += tracker.move(\n state.safe(state.associationId(node), {before: value, after: ']'})\n )\n subexit()\n\n value += tracker.move(']:')\n\n if (node.children && node.children.length > 0) {\n tracker.shift(4)\n\n value += tracker.move(\n (firstLineBlank ? '\\n' : ' ') +\n state.indentLines(\n state.containerFlow(node, tracker.current()),\n firstLineBlank ? mapAll : mapExceptFirst\n )\n )\n }\n\n exit()\n\n return value\n }\n}\n\n/** @type {Map} */\nfunction mapExceptFirst(line, index, blank) {\n return index === 0 ? line : mapAll(line, index, blank)\n}\n\n/** @type {Map} */\nfunction mapAll(line, index, blank) {\n return (blank ? '' : ' ') + line\n}\n","/**\n * @typedef {import('mdast').Delete} Delete\n *\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n *\n * @typedef {import('mdast-util-to-markdown').ConstructName} ConstructName\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n */\n\n/**\n * List of constructs that occur in phrasing (paragraphs, headings), but cannot\n * contain strikethrough.\n * So they sort of cancel each other out.\n * Note: could use a better name.\n *\n * Note: keep in sync with: <https://github.com/syntax-tree/mdast-util-to-markdown/blob/8ce8dbf/lib/unsafe.js#L14>\n *\n * @type {Array<ConstructName>}\n */\nconst constructsWithoutStrikethrough = [\n 'autolink',\n 'destinationLiteral',\n 'destinationRaw',\n 'reference',\n 'titleQuote',\n 'titleApostrophe'\n]\n\nhandleDelete.peek = peekDelete\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM\n * strikethrough in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM strikethrough.\n */\nexport function gfmStrikethroughFromMarkdown() {\n return {\n canContainEols: ['delete'],\n enter: {strikethrough: enterStrikethrough},\n exit: {strikethrough: exitStrikethrough}\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM\n * strikethrough in markdown.\n *\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM strikethrough.\n */\nexport function gfmStrikethroughToMarkdown() {\n return {\n unsafe: [\n {\n character: '~',\n inConstruct: 'phrasing',\n notInConstruct: constructsWithoutStrikethrough\n }\n ],\n handlers: {delete: handleDelete}\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterStrikethrough(token) {\n this.enter({type: 'delete', children: []}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitStrikethrough(token) {\n this.exit(token)\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {Delete} node\n */\nfunction handleDelete(node, _, state, info) {\n const tracker = state.createTracker(info)\n const exit = state.enter('strikethrough')\n let value = tracker.move('~~')\n value += state.containerPhrasing(node, {\n ...tracker.current(),\n before: value,\n after: '~'\n })\n value += tracker.move('~~')\n exit()\n return value\n}\n\n/** @type {ToMarkdownHandle} */\nfunction peekDelete() {\n return '~'\n}\n","// To do: next major: remove.\n/**\n * @typedef {Options} MarkdownTableOptions\n * Configuration.\n */\n\n/**\n * @typedef Options\n * Configuration.\n * @property {boolean | null | undefined} [alignDelimiters=true]\n * Whether to align the delimiters (default: `true`);\n * they are aligned by default:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * Pass `false` to make them staggered:\n *\n * ```markdown\n * | Alpha | B |\n * | - | - |\n * | C | Delta |\n * ```\n * @property {ReadonlyArray<string | null | undefined> | string | null | undefined} [align]\n * How to align columns (default: `''`);\n * one style for all columns or styles for their respective columns;\n * each style is either `'l'` (left), `'r'` (right), or `'c'` (center);\n * other values are treated as `''`, which doesn’t place the colon in the\n * alignment row but does align left;\n * *only the lowercased first character is used, so `Right` is fine.*\n * @property {boolean | null | undefined} [delimiterEnd=true]\n * Whether to end each row with the delimiter (default: `true`).\n *\n * > 👉 **Note**: please don’t use this: it could create fragile structures\n * > that aren’t understandable to some markdown parsers.\n *\n * When `true`, there are ending delimiters:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there are no ending delimiters:\n *\n * ```markdown\n * | Alpha | B\n * | ----- | -----\n * | C | Delta\n * ```\n * @property {boolean | null | undefined} [delimiterStart=true]\n * Whether to begin each row with the delimiter (default: `true`).\n *\n * > 👉 **Note**: please don’t use this: it could create fragile structures\n * > that aren’t understandable to some markdown parsers.\n *\n * When `true`, there are starting delimiters:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there are no starting delimiters:\n *\n * ```markdown\n * Alpha | B |\n * ----- | ----- |\n * C | Delta |\n * ```\n * @property {boolean | null | undefined} [padding=true]\n * Whether to add a space of padding between delimiters and cells\n * (default: `true`).\n *\n * When `true`, there is padding:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there is no padding:\n *\n * ```markdown\n * |Alpha|B |\n * |-----|-----|\n * |C |Delta|\n * ```\n * @property {((value: string) => number) | null | undefined} [stringLength]\n * Function to detect the length of table cell content (optional);\n * this is used when aligning the delimiters (`|`) between table cells;\n * full-width characters and emoji mess up delimiter alignment when viewing\n * the markdown source;\n * to fix this, you can pass this function,\n * which receives the cell content and returns its “visible” size;\n * note that what is and isn’t visible depends on where the text is displayed.\n *\n * Without such a function, the following:\n *\n * ```js\n * markdownTable([\n * ['Alpha', 'Bravo'],\n * ['中文', 'Charlie'],\n * ['👩‍❤️‍👩', 'Delta']\n * ])\n * ```\n *\n * Yields:\n *\n * ```markdown\n * | Alpha | Bravo |\n * | - | - |\n * | 中文 | Charlie |\n * | 👩‍❤️‍👩 | Delta |\n * ```\n *\n * With [`string-width`](https://github.com/sindresorhus/string-width):\n *\n * ```js\n * import stringWidth from 'string-width'\n *\n * markdownTable(\n * [\n * ['Alpha', 'Bravo'],\n * ['中文', 'Charlie'],\n * ['👩‍❤️‍👩', 'Delta']\n * ],\n * {stringLength: stringWidth}\n * )\n * ```\n *\n * Yields:\n *\n * ```markdown\n * | Alpha | Bravo |\n * | ----- | ------- |\n * | 中文 | Charlie |\n * | 👩‍❤️‍👩 | Delta |\n * ```\n */\n\n/**\n * @param {string} value\n * Cell value.\n * @returns {number}\n * Cell size.\n */\nfunction defaultStringLength(value) {\n return value.length\n}\n\n/**\n * Generate a markdown\n * ([GFM](https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables))\n * table.\n *\n * @param {ReadonlyArray<ReadonlyArray<string | null | undefined>>} table\n * Table data (matrix of strings).\n * @param {Readonly<Options> | null | undefined} [options]\n * Configuration (optional).\n * @returns {string}\n * Result.\n */\nexport function markdownTable(table, options) {\n const settings = options || {}\n // To do: next major: change to spread.\n const align = (settings.align || []).concat()\n const stringLength = settings.stringLength || defaultStringLength\n /** @type {Array<number>} Character codes as symbols for alignment per column. */\n const alignments = []\n /** @type {Array<Array<string>>} Cells per row. */\n const cellMatrix = []\n /** @type {Array<Array<number>>} Sizes of each cell per row. */\n const sizeMatrix = []\n /** @type {Array<number>} */\n const longestCellByColumn = []\n let mostCellsPerRow = 0\n let rowIndex = -1\n\n // This is a superfluous loop if we don’t align delimiters, but otherwise we’d\n // do superfluous work when aligning, so optimize for aligning.\n while (++rowIndex < table.length) {\n /** @type {Array<string>} */\n const row = []\n /** @type {Array<number>} */\n const sizes = []\n let columnIndex = -1\n\n if (table[rowIndex].length > mostCellsPerRow) {\n mostCellsPerRow = table[rowIndex].length\n }\n\n while (++columnIndex < table[rowIndex].length) {\n const cell = serialize(table[rowIndex][columnIndex])\n\n if (settings.alignDelimiters !== false) {\n const size = stringLength(cell)\n sizes[columnIndex] = size\n\n if (\n longestCellByColumn[columnIndex] === undefined ||\n size > longestCellByColumn[columnIndex]\n ) {\n longestCellByColumn[columnIndex] = size\n }\n }\n\n row.push(cell)\n }\n\n cellMatrix[rowIndex] = row\n sizeMatrix[rowIndex] = sizes\n }\n\n // Figure out which alignments to use.\n let columnIndex = -1\n\n if (typeof align === 'object' && 'length' in align) {\n while (++columnIndex < mostCellsPerRow) {\n alignments[columnIndex] = toAlignment(align[columnIndex])\n }\n } else {\n const code = toAlignment(align)\n\n while (++columnIndex < mostCellsPerRow) {\n alignments[columnIndex] = code\n }\n }\n\n // Inject the alignment row.\n columnIndex = -1\n /** @type {Array<string>} */\n const row = []\n /** @type {Array<number>} */\n const sizes = []\n\n while (++columnIndex < mostCellsPerRow) {\n const code = alignments[columnIndex]\n let before = ''\n let after = ''\n\n if (code === 99 /* `c` */) {\n before = ':'\n after = ':'\n } else if (code === 108 /* `l` */) {\n before = ':'\n } else if (code === 114 /* `r` */) {\n after = ':'\n }\n\n // There *must* be at least one hyphen-minus in each alignment cell.\n let size =\n settings.alignDelimiters === false\n ? 1\n : Math.max(\n 1,\n longestCellByColumn[columnIndex] - before.length - after.length\n )\n\n const cell = before + '-'.repeat(size) + after\n\n if (settings.alignDelimiters !== false) {\n size = before.length + size + after.length\n\n if (size > longestCellByColumn[columnIndex]) {\n longestCellByColumn[columnIndex] = size\n }\n\n sizes[columnIndex] = size\n }\n\n row[columnIndex] = cell\n }\n\n // Inject the alignment row.\n cellMatrix.splice(1, 0, row)\n sizeMatrix.splice(1, 0, sizes)\n\n rowIndex = -1\n /** @type {Array<string>} */\n const lines = []\n\n while (++rowIndex < cellMatrix.length) {\n const row = cellMatrix[rowIndex]\n const sizes = sizeMatrix[rowIndex]\n columnIndex = -1\n /** @type {Array<string>} */\n const line = []\n\n while (++columnIndex < mostCellsPerRow) {\n const cell = row[columnIndex] || ''\n let before = ''\n let after = ''\n\n if (settings.alignDelimiters !== false) {\n const size =\n longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0)\n const code = alignments[columnIndex]\n\n if (code === 114 /* `r` */) {\n before = ' '.repeat(size)\n } else if (code === 99 /* `c` */) {\n if (size % 2) {\n before = ' '.repeat(size / 2 + 0.5)\n after = ' '.repeat(size / 2 - 0.5)\n } else {\n before = ' '.repeat(size / 2)\n after = before\n }\n } else {\n after = ' '.repeat(size)\n }\n }\n\n if (settings.delimiterStart !== false && !columnIndex) {\n line.push('|')\n }\n\n if (\n settings.padding !== false &&\n // Don’t add the opening space if we’re not aligning and the cell is\n // empty: there will be a closing space.\n !(settings.alignDelimiters === false && cell === '') &&\n (settings.delimiterStart !== false || columnIndex)\n ) {\n line.push(' ')\n }\n\n if (settings.alignDelimiters !== false) {\n line.push(before)\n }\n\n line.push(cell)\n\n if (settings.alignDelimiters !== false) {\n line.push(after)\n }\n\n if (settings.padding !== false) {\n line.push(' ')\n }\n\n if (\n settings.delimiterEnd !== false ||\n columnIndex !== mostCellsPerRow - 1\n ) {\n line.push('|')\n }\n }\n\n lines.push(\n settings.delimiterEnd === false\n ? line.join('').replace(/ +$/, '')\n : line.join('')\n )\n }\n\n return lines.join('\\n')\n}\n\n/**\n * @param {string | null | undefined} [value]\n * Value to serialize.\n * @returns {string}\n * Result.\n */\nfunction serialize(value) {\n return value === null || value === undefined ? '' : String(value)\n}\n\n/**\n * @param {string | null | undefined} value\n * Value.\n * @returns {number}\n * Alignment.\n */\nfunction toAlignment(value) {\n const code = typeof value === 'string' ? value.codePointAt(0) : 0\n\n return code === 67 /* `C` */ || code === 99 /* `c` */\n ? 99 /* `c` */\n : code === 76 /* `L` */ || code === 108 /* `l` */\n ? 108 /* `l` */\n : code === 82 /* `R` */ || code === 114 /* `r` */\n ? 114 /* `r` */\n : 0\n}\n","/**\n * @typedef {import('mdast').InlineCode} InlineCode\n * @typedef {import('mdast').Table} Table\n * @typedef {import('mdast').TableCell} TableCell\n * @typedef {import('mdast').TableRow} TableRow\n *\n * @typedef {import('markdown-table').Options} MarkdownTableOptions\n *\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n *\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').State} State\n * @typedef {import('mdast-util-to-markdown').Info} Info\n */\n\n/**\n * @typedef Options\n * Configuration.\n * @property {boolean | null | undefined} [tableCellPadding=true]\n * Whether to add a space of padding between delimiters and cells (default:\n * `true`).\n * @property {boolean | null | undefined} [tablePipeAlign=true]\n * Whether to align the delimiters (default: `true`).\n * @property {MarkdownTableOptions['stringLength'] | null | undefined} [stringLength]\n * Function to detect the length of table cell content, used when aligning\n * the delimiters between cells (optional).\n */\n\nimport {ok as assert} from 'devlop'\nimport {markdownTable} from 'markdown-table'\nimport {defaultHandlers} from 'mdast-util-to-markdown'\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM tables in\n * markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM tables.\n */\nexport function gfmTableFromMarkdown() {\n return {\n enter: {\n table: enterTable,\n tableData: enterCell,\n tableHeader: enterCell,\n tableRow: enterRow\n },\n exit: {\n codeText: exitCodeText,\n table: exitTable,\n tableData: exit,\n tableHeader: exit,\n tableRow: exit\n }\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterTable(token) {\n const align = token._align\n assert(align, 'expected `_align` on table')\n this.enter(\n {\n type: 'table',\n align: align.map(function (d) {\n return d === 'none' ? null : d\n }),\n children: []\n },\n token\n )\n this.data.inTable = true\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitTable(token) {\n this.exit(token)\n this.data.inTable = undefined\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterRow(token) {\n this.enter({type: 'tableRow', children: []}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exit(token) {\n this.exit(token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterCell(token) {\n this.enter({type: 'tableCell', children: []}, token)\n}\n\n// Overwrite the default code text data handler to unescape escaped pipes when\n// they are in tables.\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitCodeText(token) {\n let value = this.resume()\n\n if (this.data.inTable) {\n value = value.replace(/\\\\([\\\\|])/g, replace)\n }\n\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'inlineCode')\n node.value = value\n this.exit(token)\n}\n\n/**\n * @param {string} $0\n * @param {string} $1\n * @returns {string}\n */\nfunction replace($0, $1) {\n // Pipes work, backslashes don’t (but can’t escape pipes).\n return $1 === '|' ? $1 : $0\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM tables in\n * markdown.\n *\n * @param {Options | null | undefined} [options]\n * Configuration.\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM tables.\n */\nexport function gfmTableToMarkdown(options) {\n const settings = options || {}\n const padding = settings.tableCellPadding\n const alignDelimiters = settings.tablePipeAlign\n const stringLength = settings.stringLength\n const around = padding ? ' ' : '|'\n\n return {\n unsafe: [\n {character: '\\r', inConstruct: 'tableCell'},\n {character: '\\n', inConstruct: 'tableCell'},\n // A pipe, when followed by a tab or space (padding), or a dash or colon\n // (unpadded delimiter row), could result in a table.\n {atBreak: true, character: '|', after: '[\\t :-]'},\n // A pipe in a cell must be encoded.\n {character: '|', inConstruct: 'tableCell'},\n // A colon must be followed by a dash, in which case it could start a\n // delimiter row.\n {atBreak: true, character: ':', after: '-'},\n // A delimiter row can also start with a dash, when followed by more\n // dashes, a colon, or a pipe.\n // This is a stricter version than the built in check for lists, thematic\n // breaks, and setex heading underlines though:\n // <https://github.com/syntax-tree/mdast-util-to-markdown/blob/51a2038/lib/unsafe.js#L57>\n {atBreak: true, character: '-', after: '[:|-]'}\n ],\n handlers: {\n inlineCode: inlineCodeWithTable,\n table: handleTable,\n tableCell: handleTableCell,\n tableRow: handleTableRow\n }\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {Table} node\n */\n function handleTable(node, _, state, info) {\n return serializeData(handleTableAsData(node, state, info), node.align)\n }\n\n /**\n * This function isn’t really used normally, because we handle rows at the\n * table level.\n * But, if someone passes in a table row, this ensures we make somewhat sense.\n *\n * @type {ToMarkdownHandle}\n * @param {TableRow} node\n */\n function handleTableRow(node, _, state, info) {\n const row = handleTableRowAsData(node, state, info)\n const value = serializeData([row])\n // `markdown-table` will always add an align row\n return value.slice(0, value.indexOf('\\n'))\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {TableCell} node\n */\n function handleTableCell(node, _, state, info) {\n const exit = state.enter('tableCell')\n const subexit = state.enter('phrasing')\n const value = state.containerPhrasing(node, {\n ...info,\n before: around,\n after: around\n })\n subexit()\n exit()\n return value\n }\n\n /**\n * @param {Array<Array<string>>} matrix\n * @param {Array<string | null | undefined> | null | undefined} [align]\n */\n function serializeData(matrix, align) {\n return markdownTable(matrix, {\n align,\n // @ts-expect-error: `markdown-table` types should support `null`.\n alignDelimiters,\n // @ts-expect-error: `markdown-table` types should support `null`.\n padding,\n // @ts-expect-error: `markdown-table` types should support `null`.\n stringLength\n })\n }\n\n /**\n * @param {Table} node\n * @param {State} state\n * @param {Info} info\n */\n function handleTableAsData(node, state, info) {\n const children = node.children\n let index = -1\n /** @type {Array<Array<string>>} */\n const result = []\n const subexit = state.enter('table')\n\n while (++index < children.length) {\n result[index] = handleTableRowAsData(children[index], state, info)\n }\n\n subexit()\n\n return result\n }\n\n /**\n * @param {TableRow} node\n * @param {State} state\n * @param {Info} info\n */\n function handleTableRowAsData(node, state, info) {\n const children = node.children\n let index = -1\n /** @type {Array<string>} */\n const result = []\n const subexit = state.enter('tableRow')\n\n while (++index < children.length) {\n // Note: the positional info as used here is incorrect.\n // Making it correct would be impossible due to aligning cells?\n // And it would need copy/pasting `markdown-table` into this project.\n result[index] = handleTableCell(children[index], node, state, info)\n }\n\n subexit()\n\n return result\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {InlineCode} node\n */\n function inlineCodeWithTable(node, parent, state) {\n let value = defaultHandlers.inlineCode(node, parent, state)\n\n if (state.stack.includes('tableCell')) {\n value = value.replace(/\\|/g, '\\\\$&')\n }\n\n return value\n }\n}\n","/**\n * @typedef {import('mdast').ListItem} ListItem\n * @typedef {import('mdast').Paragraph} Paragraph\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n */\n\nimport {ok as assert} from 'devlop'\nimport {defaultHandlers} from 'mdast-util-to-markdown'\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM task\n * list items in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM task list items.\n */\nexport function gfmTaskListItemFromMarkdown() {\n return {\n exit: {\n taskListCheckValueChecked: exitCheck,\n taskListCheckValueUnchecked: exitCheck,\n paragraph: exitParagraphWithTaskListItem\n }\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM task list\n * items in markdown.\n *\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM task list items.\n */\nexport function gfmTaskListItemToMarkdown() {\n return {\n unsafe: [{atBreak: true, character: '-', after: '[:|-]'}],\n handlers: {listItem: listItemWithTaskListItem}\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitCheck(token) {\n // We’re always in a paragraph, in a list item.\n const node = this.stack[this.stack.length - 2]\n assert(node.type === 'listItem')\n node.checked = token.type === 'taskListCheckValueChecked'\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitParagraphWithTaskListItem(token) {\n const parent = this.stack[this.stack.length - 2]\n\n if (\n parent &&\n parent.type === 'listItem' &&\n typeof parent.checked === 'boolean'\n ) {\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'paragraph')\n const head = node.children[0]\n\n if (head && head.type === 'text') {\n const siblings = parent.children\n let index = -1\n /** @type {Paragraph | undefined} */\n let firstParaghraph\n\n while (++index < siblings.length) {\n const sibling = siblings[index]\n if (sibling.type === 'paragraph') {\n firstParaghraph = sibling\n break\n }\n }\n\n if (firstParaghraph === node) {\n // Must start with a space or a tab.\n head.value = head.value.slice(1)\n\n if (head.value.length === 0) {\n node.children.shift()\n } else if (\n node.position &&\n head.position &&\n typeof head.position.start.offset === 'number'\n ) {\n head.position.start.column++\n head.position.start.offset++\n node.position.start = Object.assign({}, head.position.start)\n }\n }\n }\n }\n\n this.exit(token)\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {ListItem} node\n */\nfunction listItemWithTaskListItem(node, parent, state, info) {\n const head = node.children[0]\n const checkable =\n typeof node.checked === 'boolean' && head && head.type === 'paragraph'\n const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '\n const tracker = state.createTracker(info)\n\n if (checkable) {\n tracker.move(checkbox)\n }\n\n let value = defaultHandlers.listItem(node, parent, state, {\n ...info,\n ...tracker.current()\n })\n\n if (checkable) {\n value = value.replace(/^(?:[*+-]|\\d+\\.)([\\r\\n]| {1,3})/, check)\n }\n\n return value\n\n /**\n * @param {string} $0\n * @returns {string}\n */\n function check($0) {\n return $0 + checkbox\n }\n}\n","/**\n * Micromark syntax extension + mdast extension for resource tags: {{type:resourceId:text}}\n *\n * Instead of a full micromark extension (which requires complex token/state handling),\n * we use mdast-util-from-markdown's transform hook to post-process text nodes.\n * This is simpler and matches the existing regex approach.\n */\nimport type { Root, PhrasingContent, Text } from 'mdast';\n\nconst RESOURCE_TAG_RE = /\\{\\{([^:}]+):([^:}]*):([^}]+)\\}\\}/g;\nconst VALID_TYPES = new Set(['tool', 'manual', 'agent_message_template', 'handoff', 'end_call', 'time_diff']);\nconst MAX_DEPTH = 128;\n\nexport type ResourceTagMdastNode = {\n type: 'resourceTagMdast';\n data: {\n tagType: string;\n resourceId: string;\n };\n value: string;\n};\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n resourceTagMdast: ResourceTagMdastNode;\n }\n\n interface RootContentMap {\n resourceTagMdast: ResourceTagMdastNode;\n }\n}\n\nfunction splitTextWithResourceTags(text: string): (Text | ResourceTagMdastNode)[] {\n const results: (Text | ResourceTagMdastNode)[] = [];\n let lastIndex = 0;\n\n RESOURCE_TAG_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = RESOURCE_TAG_RE.exec(text)) !== null) {\n const [full, tagType, resourceId, displayText] = match;\n if (!VALID_TYPES.has(tagType)) continue;\n\n if (match.index > lastIndex) {\n results.push({ type: 'text', value: text.slice(lastIndex, match.index) });\n }\n results.push({\n type: 'resourceTagMdast',\n data: { tagType, resourceId },\n value: displayText,\n });\n lastIndex = match.index + full.length;\n }\n\n if (lastIndex < text.length) {\n results.push({ type: 'text', value: text.slice(lastIndex) });\n }\n\n return results;\n}\n\nfunction visitNode(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n visitNode(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n if ((child as { type: string }).type === 'text') {\n const parts = splitTextWithResourceTags((child as Text).value);\n newChildren.push(...parts);\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function resourceTagFromMarkdown() {\n return (tree: Root) => {\n visitNode(tree as unknown as { children?: unknown[] }, 0);\n };\n}\n\n/**\n * Exported for use in combined single-pass transform.\n * Returns the per-node text splitter without constructing a full plugin.\n */\nexport { splitTextWithResourceTags };\n\nexport function resourceTagToMarkdown() {\n return {\n handlers: {\n resourceTagMdast(node: ResourceTagMdastNode): string {\n return `{{${node.data.tagType}:${node.data.resourceId}:${node.value}}}`;\n },\n },\n };\n}\n","/**\n * mdast transform for jump points: ^id^\n * id must match /^[\\p{L}\\p{N}_-]+$/u\n */\nimport type { Root, Text, PhrasingContent } from 'mdast';\n\nconst JUMP_POINT_RE = /\\^([\\p{L}\\p{N}_-]+)\\^/gu;\nconst MAX_DEPTH = 128;\n\nexport type JumpPointMdastNode = {\n type: 'jumpPointMdast';\n data: {\n id: string;\n };\n value: string;\n};\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n jumpPointMdast: JumpPointMdastNode;\n }\n\n interface RootContentMap {\n jumpPointMdast: JumpPointMdastNode;\n }\n}\n\nfunction splitTextWithJumpPoints(text: string): (Text | JumpPointMdastNode)[] {\n const results: (Text | JumpPointMdastNode)[] = [];\n let lastIndex = 0;\n\n JUMP_POINT_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = JUMP_POINT_RE.exec(text)) !== null) {\n const [full, id] = match;\n\n if (match.index > lastIndex) {\n results.push({ type: 'text', value: text.slice(lastIndex, match.index) });\n }\n results.push({\n type: 'jumpPointMdast',\n data: { id },\n value: id,\n });\n lastIndex = match.index + full.length;\n }\n\n if (lastIndex < text.length) {\n results.push({ type: 'text', value: text.slice(lastIndex) });\n }\n\n return results;\n}\n\nfunction visitNode(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n visitNode(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n if ((child as { type: string }).type === 'text') {\n const parts = splitTextWithJumpPoints((child as Text).value);\n newChildren.push(...parts);\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function jumpPointFromMarkdown() {\n return (tree: Root) => {\n visitNode(tree as unknown as { children?: unknown[] }, 0);\n };\n}\n\n/**\n * Exported for use in combined single-pass transform.\n * Returns the per-node text splitter without constructing a full plugin.\n */\nexport { splitTextWithJumpPoints };\n\nexport function jumpPointToMarkdown() {\n return {\n handlers: {\n jumpPointMdast(node: JumpPointMdastNode): string {\n return `^${node.data.id}^`;\n },\n },\n };\n}\n","/**\n * Bidirectional conversion between mdast and ActionbookAST.\n */\nimport type { Root, RootContent, PhrasingContent, List, ListItem, Paragraph, Heading, Blockquote, ThematicBreak, Text as MdastText, Strong, Emphasis, InlineCode, Link, Break, Delete } from 'mdast';\nimport type { ResourceTagMdastNode } from './plugins/resourceTag';\nimport type { JumpPointMdastNode } from './plugins/jumpPoint';\nimport type { JinjaIfBlockMdastNode, JinjaIfInlineMdastNode, JinjaBranchMdast } from './plugins/jinjaBlock';\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n Mark,\n TextNode,\n ParagraphNode,\n HeadingNode,\n BulletListNode,\n OrderedListNode,\n ListItemNode,\n BlockquoteNode,\n HorizontalRuleNode,\n ResourceTagNode,\n JumpPointNode,\n HardBreakNode,\n TableNode,\n TableRowNode,\n TableCellNode,\n JinjaIfBlockNode,\n JinjaIfInlineNode,\n JinjaIfBranch,\n} from '../ast/types';\n\nconst MAX_DEPTH = 128;\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nfunction sanitizeUrl(url: string): string {\n if (ALLOWED_URL_PROTOCOLS.test(url)) return url;\n // Strip dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '';\n}\n\nclass DepthError extends Error {\n constructor(depth: number) {\n super(`Maximum mdast conversion depth (${MAX_DEPTH}) exceeded at depth ${depth}`);\n this.name = 'DepthError';\n }\n}\n\n// === mdast → ActionbookAST ===\n\nfunction convertInline(node: PhrasingContent, marks: Mark[] = [], depth: number = 0): InlineNode[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'text':\n return [marks.length > 0 ? { type: 'text', text: node.value, marks } : { type: 'text', text: node.value }];\n\n case 'strong': {\n const childMarks: Mark[] = [...marks, { type: 'bold' }];\n return (node as Strong).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'emphasis': {\n const childMarks: Mark[] = [...marks, { type: 'italic' }];\n return (node as Emphasis).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'delete': {\n const childMarks: Mark[] = [...marks, { type: 'strikethrough' }];\n return (node as Delete).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'inlineCode':\n return [\n marks.length > 0\n ? { type: 'text', text: (node as InlineCode).value, marks: [...marks, { type: 'code' }] }\n : { type: 'text', text: (node as InlineCode).value, marks: [{ type: 'code' }] },\n ];\n\n case 'link': {\n const href = sanitizeUrl((node as Link).url);\n if (!href) {\n // Dangerous URL protocol → strip the link, keep children as plain text\n return (node as Link).children.flatMap((child) => convertInline(child as PhrasingContent, marks, depth + 1));\n }\n const linkMark: Mark = { type: 'link', href, ...((node as Link).title ? { title: (node as Link).title! } : {}) };\n const childMarks: Mark[] = [...marks, linkMark];\n return (node as Link).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'break':\n return [{ type: 'hardBreak' }];\n\n case 'resourceTagMdast' as string: {\n const rtNode = node as unknown as ResourceTagMdastNode;\n return [\n {\n type: 'resourceTag',\n tagType: rtNode.data.tagType as ResourceTagNode['tagType'],\n resourceId: rtNode.data.resourceId,\n text: rtNode.value,\n },\n ];\n }\n\n case 'jumpPointMdast' as string: {\n const jpNode = node as unknown as JumpPointMdastNode;\n return [{ type: 'jumpPoint', id: jpNode.data.id }];\n }\n\n case 'jinjaIfInlineMdast' as string: {\n const jNode = node as unknown as JinjaIfInlineMdastNode;\n const branches: JinjaIfBranch<InlineNode>[] = jNode.branches.map(b => ({\n branchType: b.branchType,\n ...(b.condition ? { condition: b.condition } : {}),\n content: (b.content as PhrasingContent[]).flatMap(c => convertInline(c, [], depth + 1)),\n }));\n return [{ type: 'jinjaIfInline', branches } as InlineNode];\n }\n\n default:\n if ('value' in node && typeof (node as { value: unknown }).value === 'string') {\n return [{ type: 'text', text: (node as { value: string }).value }];\n }\n if ('children' in node && Array.isArray((node as { children: unknown[] }).children)) {\n return (node as { children: PhrasingContent[] }).children.flatMap((child) => convertInline(child, marks, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertBlock(node: RootContent, depth: number = 0): BlockNode[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'paragraph': {\n const para = node as Paragraph;\n const content = para.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 1));\n return [{ type: 'paragraph', content }];\n }\n\n case 'heading': {\n const h = node as Heading;\n const content = h.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 1));\n return [{ type: 'heading', level: h.depth as HeadingNode['level'], content }];\n }\n\n case 'list': {\n const list = node as List;\n const items = list.children.map((li) => convertListItem(li, depth + 1));\n const spread = list.spread ?? false;\n if (list.ordered) {\n return [{ type: 'orderedList', start: list.start ?? 1, spread, content: items }];\n }\n return [{ type: 'bulletList', spread, content: items }];\n }\n\n case 'blockquote': {\n const bq = node as Blockquote;\n const content = bq.children.flatMap((child) => convertBlock(child, depth + 1));\n return [{ type: 'blockquote', content }];\n }\n\n case 'thematicBreak':\n return [{ type: 'horizontalRule' }];\n\n case 'code': {\n const codeNode = node as import('mdast').Code;\n return [{ type: 'codeBlock', content: codeNode.value, ...(codeNode.lang ? { language: codeNode.lang } : {}) } as BlockNode];\n }\n\n case 'jinjaIfBlockMdast' as string: {\n const jNode = node as unknown as JinjaIfBlockMdastNode;\n const branches: JinjaIfBranch<BlockNode>[] = jNode.branches.map(b => ({\n branchType: b.branchType,\n ...(b.condition ? { condition: b.condition } : {}),\n content: (b.content as RootContent[]).flatMap(c => convertBlock(c, depth + 1)),\n }));\n return [{ type: 'jinjaIfBlock', branches } as BlockNode];\n }\n\n case 'table': {\n const tbl = node as { type: 'table'; children: Array<{ type: 'tableRow'; children: Array<{ type: 'tableCell'; children: PhrasingContent[] }> }>; align?: (string | null)[] };\n const rows: TableRowNode[] = tbl.children.map((row, rowIdx) => {\n const cells: TableCellNode[] = row.children.map((cell) => {\n const content = cell.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 2));\n return {\n type: 'tableCell' as const,\n ...(rowIdx === 0 ? { header: true } : {}),\n content,\n };\n });\n return { type: 'tableRow' as const, content: cells };\n });\n return [{ type: 'table', content: rows }];\n }\n\n default:\n if ('children' in node && Array.isArray((node as { children: unknown[] }).children)) {\n const inlines = (node as { children: PhrasingContent[] }).children.flatMap((child) =>\n convertInline(child as PhrasingContent, [], depth + 1),\n );\n if (inlines.length > 0) return [{ type: 'paragraph', content: inlines }];\n }\n if ('value' in node && typeof (node as { value: unknown }).value === 'string') {\n return [{ type: 'paragraph', content: [{ type: 'text', text: (node as { value: string }).value }] }];\n }\n return [];\n }\n}\n\nfunction convertListItem(node: ListItem, depth: number = 0): ListItemNode {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n const content = node.children.flatMap((child) => convertBlock(child as RootContent, depth + 1));\n const base: ListItemNode = {\n type: 'listItem',\n spread: node.spread ?? false,\n content: content.length > 0 ? content : [{ type: 'paragraph', content: [] }],\n };\n if (typeof node.checked === 'boolean') {\n return { ...base, checked: node.checked };\n }\n return base;\n}\n\nexport function fromMdast(root: Root): DocumentNode {\n const blocks: BlockNode[] = [];\n\n for (let i = 0; i < root.children.length; i++) {\n // Detect extra blank lines between consecutive blocks and restore as empty paragraphs.\n // Standard markdown block separation = 1 blank line. Each additional blank line\n // maps to one empty paragraph (1:1), matching the serializer's join function\n // that outputs \\n (instead of \\n\\n) after empty paragraphs.\n if (i > 0) {\n const prev = root.children[i - 1] as { position?: { end?: { line?: number } } };\n const curr = root.children[i] as { position?: { start?: { line?: number } } };\n const prevEndLine = prev.position?.end?.line ?? 0;\n const currStartLine = curr.position?.start?.line ?? 0;\n const emptyCount = currStartLine - prevEndLine - 2;\n for (let j = 0; j < emptyCount; j++) {\n blocks.push({ type: 'paragraph', content: [] });\n }\n }\n\n blocks.push(...convertBlock(root.children[i], 0));\n }\n\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n}\n\n// === ActionbookAST → mdast ===\n\nfunction inlineToMdast(node: InlineNode, depth: number = 0): PhrasingContent[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'text': {\n const marks = node.marks ?? [];\n let result: PhrasingContent[] = [{ type: 'text', value: node.text } as MdastText];\n\n for (const mark of marks) {\n switch (mark.type) {\n case 'bold':\n result = [{ type: 'strong', children: result as Strong['children'] }];\n break;\n case 'italic':\n result = [{ type: 'emphasis', children: result as Emphasis['children'] }];\n break;\n case 'strikethrough':\n result = [{ type: 'delete', children: result as Delete['children'] }];\n break;\n case 'underline':\n // Underline has no markdown representation; mark is lost on serialization\n break;\n case 'code':\n result = [{ type: 'inlineCode', value: node.text }];\n break;\n case 'link':\n result = [\n {\n type: 'link',\n url: mark.href,\n ...(mark.title ? { title: mark.title } : {}),\n children: result as Link['children'],\n },\n ];\n break;\n }\n }\n return result;\n }\n\n case 'resourceTag':\n return [\n {\n type: 'resourceTagMdast',\n data: { tagType: node.tagType, resourceId: node.resourceId },\n value: node.text,\n } as unknown as PhrasingContent,\n ];\n\n case 'jumpPoint':\n return [\n {\n type: 'jumpPointMdast',\n data: { id: node.id },\n value: node.id,\n } as unknown as PhrasingContent,\n ];\n\n case 'hardBreak':\n return [{ type: 'break' } as Break];\n\n case 'jinjaIfInline': {\n const jNode = node as JinjaIfInlineNode;\n const result: PhrasingContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'text', value: tagText } as MdastText);\n for (const child of branch.content) {\n result.push(...inlineToMdast(child, depth + 1));\n }\n }\n result.push({ type: 'text', value: '{% endif %}' } as MdastText);\n return result;\n }\n }\n}\n\nfunction blockToMdast(node: BlockNode, depth: number = 0): RootContent[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'paragraph':\n return [{ type: 'paragraph', children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];\n\n case 'heading':\n return [{ type: 'heading', depth: node.level, children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];\n\n case 'bulletList': {\n const items = node.content.map((li) => listItemToMdast(li, depth + 1));\n return [\n {\n type: 'list',\n ordered: false,\n spread: node.spread ?? false,\n children: items,\n },\n ];\n }\n\n case 'orderedList': {\n const spread = node.spread ?? false;\n let counter = node.start;\n const items = node.content.map((li) => {\n const mdastLi = listItemToMdast(li, depth + 1);\n if (li.value != null) counter = li.value;\n // Store the effective number on the mdast node for the serializer\n (mdastLi as any)._ordinalValue = counter;\n counter++;\n return mdastLi;\n });\n return [\n {\n type: 'list',\n ordered: true,\n start: node.content[0]?.value ?? node.start,\n spread,\n children: items,\n },\n ];\n }\n\n case 'listItem':\n return listItemToMdast(node, depth).children.flatMap((child) => [child as RootContent]);\n\n case 'blockquote':\n return [{ type: 'blockquote', children: node.content.flatMap((c) => blockToMdast(c, depth + 1)) as Blockquote['children'] }];\n\n case 'horizontalRule':\n return [{ type: 'thematicBreak' }];\n\n case 'codeBlock': {\n const cb = node as import('../ast/types').CodeBlockNode;\n return [{ type: 'code', value: cb.content, ...(cb.language ? { lang: cb.language } : {}) } as RootContent];\n }\n\n case 'jinjaIfBlock': {\n const jNode = node as JinjaIfBlockNode;\n const result: RootContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', children: [{ type: 'text', value: tagText } as MdastText] } as Paragraph);\n for (const child of branch.content) {\n result.push(...blockToMdast(child, depth + 1));\n }\n }\n result.push({ type: 'paragraph', children: [{ type: 'text', value: '{% endif %}' } as MdastText] } as Paragraph);\n return result;\n }\n\n case 'table': {\n const rows = node.content.map((row) => ({\n type: 'tableRow' as const,\n children: row.content.map((cell) => ({\n type: 'tableCell' as const,\n children: cell.content.flatMap((c) => inlineToMdast(c, depth + 2)) as PhrasingContent[],\n })),\n }));\n return [{ type: 'table', children: rows } as unknown as RootContent];\n }\n\n case 'noteBlock':\n // Note blocks are editor-only — not serialized to markdown\n return [];\n }\n}\n\nfunction listItemToMdast(node: ListItemNode, depth: number = 0): ListItem {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n const children = node.content.flatMap((child) => blockToMdast(child, depth + 1)) as ListItem['children'];\n // A list item is \"loose\" (spread) when it has nested lists or multiple\n // block-level children beyond a single paragraph. This matches the blank\n // lines that tiptap-markdown inserts in the original instruction text.\n const isSpread = node.spread ?? false;\n const result: ListItem = {\n type: 'listItem',\n spread: isSpread,\n children,\n };\n if (typeof node.checked === 'boolean') {\n result.checked = node.checked;\n }\n return result;\n}\n\nexport function toMdast(doc: DocumentNode): Root {\n return {\n type: 'root',\n children: doc.content.flatMap((c) => blockToMdast(c, 0)),\n };\n}\n","/**\n * Convert ActionbookAST → ProseMirror JSONContent.\n */\nimport type { BlockNode, DocumentNode, InlineNode, JinjaIfBlockNode, JinjaIfInlineNode, Mark } from '../../ast/types';\nimport type { JSONContent } from '../../compat/prosemirror';\n\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nfunction assertNever(value: never): never {\n throw new Error(`Unexpected AST node: ${JSON.stringify(value)}`);\n}\n\nfunction convertMark(mark: Mark): NonNullable<JSONContent['marks']>[number] {\n switch (mark.type) {\n case 'bold':\n return { type: 'bold' };\n case 'italic':\n return { type: 'italic' };\n case 'underline':\n return { type: 'underline' };\n case 'strikethrough':\n return { type: 'strikethrough' };\n case 'code':\n return { type: 'code' };\n case 'link': {\n const href = ALLOWED_URL_PROTOCOLS.test(mark.href) ? mark.href : '';\n return mark.title ? { type: 'link', attrs: { href, title: mark.title } } : { type: 'link', attrs: { href } };\n }\n default:\n return assertNever(mark);\n }\n}\n\nfunction convertInlineToArray(node: InlineNode): JSONContent[] {\n switch (node.type) {\n case 'jinjaIfInline': {\n const jNode = node as JinjaIfInlineNode;\n const parts: JSONContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n parts.push({ type: 'text', text: tagText });\n for (const child of branch.content) {\n parts.push(...convertInlineToArray(child));\n }\n }\n parts.push({ type: 'text', text: '{% endif %}' });\n return parts;\n }\n default:\n return [convertInline(node)];\n }\n}\n\nexport function convertInline(node: InlineNode): JSONContent {\n switch (node.type) {\n case 'text': {\n const result: JSONContent = { type: 'text', text: node.text };\n if (node.marks && node.marks.length > 0) {\n result.marks = node.marks.map(convertMark);\n }\n return result;\n }\n case 'resourceTag':\n return {\n type: 'inlineToolTag',\n attrs: {\n type: node.tagType,\n resourceId: node.resourceId,\n text: node.text,\n },\n };\n case 'jumpPoint':\n return {\n type: 'jumpPoint',\n attrs: { id: node.id },\n };\n case 'hardBreak':\n return { type: 'hardBreak' };\n case 'jinjaIfInline': {\n // Flatten to single text node for PM\n const parts = convertInlineToArray(node);\n const fullText = parts.map(p => p.text ?? '').join('');\n return { type: 'text', text: fullText };\n }\n default:\n return assertNever(node as never);\n }\n}\n\nfunction convertBlockToArray(node: BlockNode): JSONContent[] {\n if (node.type === 'jinjaIfBlock') {\n return [convertJinjaIfBlock(node as JinjaIfBlockNode)];\n }\n return [convertBlock(node)];\n}\n\nfunction convertJinjaIfBlock(node: JinjaIfBlockNode): JSONContent {\n return {\n type: 'jinjaIfBlock',\n content: node.branches.map((branch) => ({\n type: 'jinjaIfBranch',\n attrs: {\n branchType: branch.branchType,\n condition: branch.condition ?? '',\n },\n content: branch.content.length > 0\n ? branch.content.flatMap(convertBlockToArray)\n : [{ type: 'paragraph', content: [] }],\n })),\n };\n}\n\n/**\n * Flatten jinjaIfBlock to text paragraphs (legacy format for editors without structured jinja support).\n */\nfunction convertJinjaIfBlockFlat(node: JinjaIfBlockNode): JSONContent[] {\n const result: JSONContent[] = [];\n for (const branch of node.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', content: [{ type: 'text', text: tagText }] });\n for (const child of branch.content) {\n result.push(...convertBlockToArray(child));\n }\n }\n result.push({ type: 'paragraph', content: [{ type: 'text', text: '{% endif %}' }] });\n return result;\n}\n\nexport function convertBlock(node: BlockNode): JSONContent {\n switch (node.type) {\n case 'paragraph':\n return {\n type: 'paragraph',\n content: node.content.flatMap(convertInlineToArray),\n };\n case 'heading':\n return {\n type: 'heading',\n attrs: { level: node.level },\n content: node.content.flatMap(convertInlineToArray),\n };\n case 'bulletList':\n return {\n type: 'bulletList',\n content: node.content.map(convertBlock),\n };\n case 'orderedList':\n return {\n type: 'orderedList',\n attrs: { start: node.start },\n content: node.content.map(convertBlock),\n };\n case 'listItem': {\n const result: JSONContent = {\n type: 'listItem',\n content: node.content.flatMap(convertBlockToArray),\n };\n if (node.checked != null || node.value != null) {\n result.attrs = {\n ...(node.checked != null ? { checked: node.checked } : {}),\n ...(node.value != null ? { value: node.value } : {}),\n };\n }\n return result;\n }\n case 'blockquote':\n return {\n type: 'blockquote',\n content: node.content.flatMap(convertBlockToArray),\n };\n case 'horizontalRule':\n return { type: 'horizontalRule' };\n case 'codeBlock': {\n const cb = node as import('../../ast/types').CodeBlockNode;\n return {\n type: 'codeBlock',\n attrs: { language: cb.language ?? null },\n content: cb.content ? [{ type: 'text', text: cb.content }] : undefined,\n };\n }\n case 'noteBlock':\n return {\n type: 'noteBlock',\n content: node.content.flatMap(convertBlockToArray),\n };\n case 'table':\n return {\n type: 'table',\n content: node.content.map((row) => ({\n type: 'tableRow',\n content: row.content.map((cell) => ({\n type: cell.header ? 'tableHeader' : 'tableCell',\n content: cell.content.flatMap(convertInlineToArray),\n })),\n })),\n };\n case 'jinjaIfBlock':\n return convertJinjaIfBlock(node as JinjaIfBlockNode);\n default:\n return assertNever(node as never);\n }\n}\n\nexport function toProseMirrorJSON(doc: DocumentNode): JSONContent {\n return {\n type: 'doc',\n content: doc.content.flatMap(convertBlockToArray),\n };\n}\n\n/**\n * Convert parseFragment() output (InlineNode[] | BlockNode[]) to PM JSONContent[].\n * If nodes are inline, wraps them in a single paragraph.\n */\nexport function astNodesToJSONContent(nodes: (InlineNode | BlockNode)[]): JSONContent[] {\n if (nodes.length === 0) return [];\n\n const firstType = nodes[0].type;\n const isInlineFragment =\n firstType === 'text' || firstType === 'resourceTag' || firstType === 'jumpPoint' || firstType === 'hardBreak';\n\n if (isInlineFragment) {\n return [{ type: 'paragraph', content: (nodes as InlineNode[]).flatMap(convertInlineToArray) }];\n }\n\n return (nodes as BlockNode[]).flatMap(convertBlockToArray);\n}\n","/**\n * CSS custom properties for editor text styles.\n *\n * Consumers can override any `--ab-*` variable on the `.ProseMirror` element\n * or a wrapper to customize fonts, sizes, colors, etc.\n *\n * Usage in consumer CSS:\n * .ProseMirror {\n * --ab-font-heading: 'Gellix', sans-serif;\n * --ab-font-body: 'SF Pro Text', -apple-system, sans-serif;\n * --ab-font-code: 'Roboto Mono', monospace;\n * --ab-color-body: #0d0d0d;\n * }\n */\nexport const EDITOR_TEXT_STYLES = `\n/* ── CSS custom properties (override on .ProseMirror to customize) ── */\n.ProseMirror {\n /* Font families */\n --ab-font-heading: 'Gellix', sans-serif;\n --ab-font-body: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n --ab-font-code: 'Roboto Mono', monospace;\n\n /* Body text */\n --ab-body-size: 14px;\n --ab-body-weight: 400;\n --ab-body-line-height: 20px;\n --ab-body-letter-spacing: -0.1px;\n --ab-color-body: #0d0d0d;\n\n /* H1 */\n --ab-h1-size: 24px;\n --ab-h1-weight: 700;\n --ab-h1-line-height: 32px;\n --ab-h1-letter-spacing: -0.25px;\n\n /* H2 */\n --ab-h2-size: 20px;\n --ab-h2-weight: 700;\n --ab-h2-line-height: 24px;\n --ab-h2-letter-spacing: -0.25px;\n\n /* H3 */\n --ab-h3-size: 18px;\n --ab-h3-weight: 700;\n --ab-h3-line-height: 24px;\n --ab-h3-letter-spacing: -0.25px;\n\n /* Inline code */\n --ab-code-size: 13px;\n --ab-code-weight: 400;\n --ab-code-line-height: 20px;\n --ab-code-letter-spacing: -0.3px;\n --ab-code-bg: #ececec;\n --ab-code-padding: 0 8px;\n --ab-code-radius: 2px;\n\n /* Code block */\n --ab-pre-bg: #ececec;\n --ab-pre-radius: 4px;\n --ab-pre-padding: 16px 8px 16px 24px;\n\n /* Link */\n --ab-link-color: #6210cc;\n --ab-link-weight: 500;\n\n /* Blockquote */\n --ab-blockquote-border-color: #0d0d0d;\n\n /* HR */\n --ab-hr-color: #e0e0e0;\n\n /* Block spacing */\n --ab-block-gap: 16px;\n}\n\n/* ── Base text ── */\n.ProseMirror {\n font-family: var(--ab-font-body);\n font-size: var(--ab-body-size);\n font-weight: var(--ab-body-weight);\n line-height: var(--ab-body-line-height);\n letter-spacing: var(--ab-body-letter-spacing);\n color: var(--ab-color-body);\n}\n\n.ProseMirror > * + * {\n margin-top: var(--ab-block-gap);\n}\n\n/* ── Headings ── */\n.ProseMirror h1 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h1-size);\n font-weight: var(--ab-h1-weight);\n line-height: var(--ab-h1-line-height);\n letter-spacing: var(--ab-h1-letter-spacing);\n}\n\n.ProseMirror h2 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h2-size);\n font-weight: var(--ab-h2-weight);\n line-height: var(--ab-h2-line-height);\n letter-spacing: var(--ab-h2-letter-spacing);\n}\n\n.ProseMirror h3 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h3-size);\n font-weight: var(--ab-h3-weight);\n line-height: var(--ab-h3-line-height);\n letter-spacing: var(--ab-h3-letter-spacing);\n}\n\n/* ── Inline code ── */\n.ProseMirror code {\n font-family: var(--ab-font-code);\n font-size: var(--ab-code-size);\n font-weight: var(--ab-code-weight);\n line-height: var(--ab-code-line-height);\n letter-spacing: var(--ab-code-letter-spacing);\n background: var(--ab-code-bg);\n padding: var(--ab-code-padding);\n border-radius: var(--ab-code-radius);\n}\n\n/* ── Code block ── */\n.ProseMirror pre {\n font-family: var(--ab-font-code);\n font-size: var(--ab-code-size);\n font-weight: var(--ab-code-weight);\n line-height: var(--ab-code-line-height);\n letter-spacing: var(--ab-code-letter-spacing);\n color: var(--ab-color-body);\n background: var(--ab-pre-bg);\n border-radius: var(--ab-pre-radius);\n padding: var(--ab-pre-padding);\n overflow-x: auto;\n white-space: pre;\n}\n\n.ProseMirror pre code {\n background: transparent;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n}\n\n/* ── Link ── */\n.ProseMirror a {\n color: var(--ab-link-color);\n font-weight: var(--ab-link-weight);\n text-decoration: none;\n}\n\n.ProseMirror a:hover {\n text-decoration: none;\n}\n\n/* ── Blockquote ── */\n.ProseMirror blockquote {\n border-left: 2px solid var(--ab-blockquote-border-color);\n border-radius: 0;\n padding-left: 20px;\n color: var(--ab-color-body);\n}\n\n/* ── HR ── */\n.ProseMirror hr {\n border: none;\n height: 1px;\n background: var(--ab-hr-color);\n margin: 8px 0;\n}\n`;\n","/**\n * Input rules for markdown-style text formatting.\n *\n * Provides real-time conversion of typed markdown syntax into ProseMirror nodes/marks:\n *\n * \"# \" ~ \"###### \" → heading (h1–h6)\n * \"> \" → blockquote\n * \"```lang\" → codeBlock (with optional language)\n * \"---\" / \"***\" / \"___\" → horizontalRule\n * \"- \" or \"* \" → bulletList\n * \"1. \" → orderedList\n * \"- [ ] \" / \"- [x] \" → bulletList with todo item\n * \"^id^\" → jumpPoint (duplicate IDs are rejected)\n * **text** → bold\n * *text* → italic\n * ~~text~~ → strikethrough\n * `text` → inline code\n */\nimport { InputRule, textblockTypeInputRule, wrappingInputRule } from 'prosemirror-inputrules';\nimport type { MarkType, NodeType } from 'prosemirror-model';\nimport type { EditorState } from 'prosemirror-state';\nimport { TextSelection } from 'prosemirror-state';\nimport { actionbookSchema } from '../schema';\nimport { slashCommandKey } from './slashCommandPlugin';\nimport type { ActionbookPlugin } from './types';\n\n// Block-level patterns\nconst HEADING_RE = /^(#{1,6})\\s$/;\nconst BLOCKQUOTE_RE = /^\\s*>\\s$/;\nconst CODE_BLOCK_RE = /^```([a-zA-Z0-9]*)$/;\nconst HR_RE = /^([-*_])\\1{2,}$/;\n\nconst BULLET_LIST_RE = /^\\s*([-*])\\s$/;\nconst ORDERED_LIST_RE = /^(\\d+)\\.\\s$/;\nconst JUMP_POINT_RE = /\\^([\\p{L}\\p{N}_-]+)\\^$/u;\n\n// Inline mark autoformat patterns\n// **text** → bold\nconst BOLD_RE = /(?:^|[^*])\\*\\*([^*]+)\\*\\*$/;\n// __text__ → italic\nconst ITALIC_RE = /(?:^|[^_])__([^_]+)__$/;\n// ~~text~~ → strikethrough\nconst STRIKE_RE = /(?:^|[^~])~~([^~]+)~~$/;\n// `text` → inline code\nconst CODE_RE = /(?:^|[^`])`([^`]+)`$/;\n\n/**\n * Find the nearest ancestor list node around the cursor.\n * Returns { depth, node } or null if not inside a list.\n */\nfunction findParentList(state: EditorState, pos: number): { depth: number; node: any } | null {\n const $pos = state.doc.resolve(pos);\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d);\n const name = node.type.name;\n if (name === 'bulletList' || name === 'orderedList') {\n return { depth: d, node: node as any };\n }\n }\n return null;\n}\n\n/** Check if position is inside a listItem. */\nfunction isInsideList(state: EditorState, pos: number): boolean {\n const $pos = state.doc.resolve(pos);\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'listItem') return true;\n }\n return false;\n}\n\n/** Sentinel value: same list type detected → no-op (distinct from null = \"not in a list\") */\nconst NOOP = Symbol('noop');\n\n/**\n * Smart list input rule handler:\n * - Inside SAME list type + empty → update orderedList start attr (or NOOP for bullet)\n * - Inside SAME list type + content → NOOP (prevent nesting)\n * - Inside DIFFERENT list type + empty content → convert ONLY this item to target type\n * - Inside DIFFERENT list type + content → NOOP (prevent nesting)\n * - Not in a list → null (let wrappingInputRule handle new list creation)\n */\nfunction handleListInputRule(\n state: EditorState,\n start: number,\n end: number,\n listType: NodeType,\n attrs?: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): any {\n // Resolve from inside the matched text (not at the boundary which may be outside paragraph)\n const resolvePos = Math.max(start, end - 1);\n const parentList = findParentList(state, resolvePos);\n if (!parentList) return null; // not in a list — return null to fall through\n\n const $from = state.doc.resolve(resolvePos);\n const { depth: listDepth, node: listNode } = parentList;\n\n const paraContentSize = $from.parent.content.size;\n const matchedLen = end - start;\n const isMarkerOnly = paraContentSize === matchedLen;\n\n if (listNode.type.name === listType.name) {\n // Same orderedList → set this item's value attr (per-item numbering)\n if (listType.name === 'orderedList' && attrs?.start != null) {\n const newValue = attrs.start as number;\n // Find the listItem depth and compute natural number\n let liDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'listItem') { liDepth = d; break; }\n }\n if (liDepth > 0) {\n const liIndex = $from.index(listDepth);\n const listStartNum = (listNode.attrs.start as number) ?? 1;\n const naturalNumber = listStartNum + liIndex;\n const currentValue = ($from.node(liDepth).attrs.value as number | null);\n if (currentValue === newValue || (currentValue == null && newValue === naturalNumber)) {\n // Same number — just consume the typed marker so it doesn't stay as text\n const tr = state.tr.delete(start, end);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n // Delete the typed marker, then re-resolve to find the listItem safely\n const tr = state.tr.delete(start, end);\n const $afterDelete = tr.doc.resolve(tr.mapping.map(resolvePos));\n for (let d = $afterDelete.depth; d > 0; d--) {\n if ($afterDelete.node(d).type.name === 'listItem') {\n const pos = $afterDelete.before(d);\n const node = $afterDelete.node(d);\n tr.setNodeMarkup(pos, undefined, { ...node.attrs, value: newValue });\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n }\n }\n }\n return NOOP;\n }\n\n // Different type → split list, convert only this item\n const tr = state.tr.delete(start, end);\n const $pos = tr.doc.resolve(tr.mapping.map(resolvePos));\n\n // Find the listItem containing the cursor\n let liDepth = -1;\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'listItem') { liDepth = d; break; }\n }\n if (liDepth < 0) return null;\n\n const parentListAfterDelete = $pos.node(liDepth - 1);\n const liIndex = $pos.index(liDepth - 1);\n const liNode = parentListAfterDelete.child(liIndex);\n const parentListStart = $pos.before(liDepth - 1);\n const parentListEnd = $pos.after(liDepth - 1);\n\n // Build replacement fragments: [before items in original type] + [this item in new type] + [after items in original type]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fragments: any[] = [];\n\n // Before items (keep in original list type)\n if (liIndex > 0) {\n const beforeItems = [];\n for (let i = 0; i < liIndex; i++) beforeItems.push(parentListAfterDelete.child(i));\n fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, beforeItems));\n }\n\n // This item in new list type\n fragments.push(listType.create(attrs ?? null, liNode));\n\n // After items (keep in original list type)\n if (liIndex < parentListAfterDelete.childCount - 1) {\n const afterItems = [];\n for (let i = liIndex + 1; i < parentListAfterDelete.childCount; i++) {\n afterItems.push(parentListAfterDelete.child(i));\n }\n fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, afterItems));\n }\n\n tr.replaceWith(parentListStart, parentListEnd, fragments);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n}\n\nfunction markInputRule(pattern: RegExp, markType: MarkType, markerLen: number): InputRule {\n return new InputRule(pattern, (state, match, start, end) => {\n // Suppress mark input rules while slash command menu is active.\n // e.g. typing /anchor_point:_test_ should not italicize \"_test_\".\n const slashState = slashCommandKey.getState(state);\n if (slashState?.active) return null;\n\n const textContent = match[1];\n // ProseMirror provides `start` as the position where the full match begins\n // and `end` as the position where it ends (after the just-typed character).\n // The regex (?:^|[^x]) may match one extra char before the opening marker.\n // We need to only delete the marker+content portion, not the preceding char.\n const fullMatch = match[0];\n const markedLength = markerLen * 2 + textContent.length;\n // How many prefix chars before the actual marker (0 if matched at ^, 1 otherwise)\n const prefixLen = fullMatch.length - markedLength;\n const deleteFrom = start + prefixLen;\n\n const tr = state.tr;\n tr.delete(deleteFrom, end);\n const textNode = state.schema.text(textContent, [markType.create()]);\n tr.insert(deleteFrom, textNode);\n // Remove stored marks so subsequent typing is not marked\n tr.removeStoredMark(markType);\n return tr;\n });\n}\n\nexport function createInputRulesPlugin(): ActionbookPlugin {\n return {\n name: 'inputRules',\n inputRules: () => {\n const rules: InputRule[] = [];\n\n // \"# \" through \"###### \" → heading (h1–h6)\n rules.push(\n textblockTypeInputRule(HEADING_RE, actionbookSchema.nodes.heading, (match) => ({\n level: match[1].length,\n })),\n );\n\n // \"> \" → blockquote (not inside lists)\n rules.push(\n new InputRule(BLOCKQUOTE_RE, (state, match, start, end) => {\n if (isInsideList(state, start)) return null;\n const fallback = wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote);\n return (fallback as any).handler(state, match, start, end);\n }),\n );\n\n // \"```lang\" → codeBlock (not inside lists)\n rules.push(\n new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {\n if (isInsideList(state, start)) return null;\n const language = match[1] || null;\n const $start = state.doc.resolve(start);\n const blockStart = $start.before($start.depth);\n const blockEnd = $start.after($start.depth);\n const tr = state.tr;\n tr.replaceWith(\n blockStart,\n blockEnd,\n actionbookSchema.nodes.codeBlock.create({ language }),\n );\n return tr;\n }),\n );\n\n // \"---\" / \"***\" / \"___\" → horizontalRule (not inside lists)\n rules.push(\n new InputRule(HR_RE, (state, _match, start, end) => {\n if (isInsideList(state, start)) return null;\n const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;\n const $start = state.doc.resolve(start);\n // Find the parent paragraph boundaries\n const blockStart = $start.before($start.depth);\n const blockEnd = $start.after($start.depth);\n const tr = state.tr;\n // Replace the entire paragraph with hr + empty paragraph\n tr.replaceWith(blockStart, blockEnd, [hrType.create(), pType.create()]);\n // Place cursor in the new paragraph\n tr.setSelection(\n TextSelection.near(tr.doc.resolve(blockStart + hrType.createAndFill()!.nodeSize + 1)),\n );\n return tr;\n }),\n );\n\n // \"- [ ] \" or \"- [x] \" → bulletList with checked listItem\n // MUST be before bullet/ordered rules so the more specific pattern matches first\n rules.push(\n new InputRule(/^\\s*[-*]\\s\\[([ xX])\\]\\s$/, (state, match, start, end) => {\n const checked = match[1] !== ' ';\n const { bulletList: blType, listItem: liType } = actionbookSchema.nodes;\n const li = liType.create({ checked }, state.schema.nodes.paragraph.create());\n const list = blType.create(null, li);\n return state.tr.delete(start, end).insert(start, list);\n }),\n );\n\n // \"- \" or \"* \" → bulletList (with toggle/convert behavior inside existing lists)\n {\n const blType = actionbookSchema.nodes.bulletList;\n const fallback = wrappingInputRule(BULLET_LIST_RE, blType);\n rules.push(\n new InputRule(BULLET_LIST_RE, (state, match, start, end) => {\n const result = handleListInputRule(state, start, end, blType);\n if (result === NOOP) return null; // same type → let text be typed as-is\n if (result) return result;\n // Not in a list — delegate to standard wrapping behavior\n const handler = (fallback as any).handler;\n return handler(state, match, start, end);\n }),\n );\n }\n\n // \"1. \" → orderedList (with toggle/convert behavior inside existing lists)\n {\n const olType = actionbookSchema.nodes.orderedList;\n const fallback = wrappingInputRule(ORDERED_LIST_RE, olType, (m) => ({ start: +m[1] }));\n rules.push(\n new InputRule(ORDERED_LIST_RE, (state, match, start, end) => {\n const typedNumber = +match[1];\n\n // Check if we're inside an existing list\n const resolvePos = Math.max(start, end - 1);\n const parentList = findParentList(state, resolvePos);\n if (parentList) {\n const { node: listNode } = parentList;\n\n // Inside an orderedList → change this item's number\n if (listNode.type.name === 'orderedList') {\n const tr = state.tr.delete(start, end);\n const $after = tr.doc.resolve(tr.mapping.map(resolvePos));\n for (let d = $after.depth; d > 0; d--) {\n if ($after.node(d).type.name === 'listItem') {\n const liPos = $after.before(d);\n const liNode = $after.node(d);\n tr.setNodeMarkup(liPos, undefined, { ...liNode.attrs, value: typedNumber });\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n }\n return null;\n }\n\n // Inside a bulletList → convert (only if empty item)\n const result = handleListInputRule(state, start, end, olType, { start: typedNumber });\n if (result === NOOP) return null;\n if (result) return result;\n }\n\n // Not in a list — create new orderedList\n const handler = (fallback as any).handler;\n return handler(state, match, start, end);\n }),\n );\n }\n\n // \"^id^\" → jumpPoint (duplicates allowed — validation plugin shows error state)\n const jumpPointType = actionbookSchema.nodes.jumpPoint;\n rules.push(\n new InputRule(JUMP_POINT_RE, (state, match, start, end) => {\n const id = match[1];\n const tr = state.tr.delete(start, end).insert(start, jumpPointType.create({ id }));\n // Insert trailing space so the jump point exits adjacent/edit state\n const afterAtom = start + 1; // atom nodeSize = 1\n tr.insertText(' ', afterAtom);\n // Place cursor after the space\n const cursorPos = afterAtom + 1;\n tr.setSelection(TextSelection.near(tr.doc.resolve(Math.min(cursorPos, tr.doc.content.size))));\n return tr;\n }),\n );\n\n // Inline mark input rules\n rules.push(markInputRule(BOLD_RE, actionbookSchema.marks.bold, 2));\n rules.push(markInputRule(ITALIC_RE, actionbookSchema.marks.italic, 2));\n rules.push(markInputRule(STRIKE_RE, actionbookSchema.marks.strikethrough, 2));\n rules.push(markInputRule(CODE_RE, actionbookSchema.marks.code, 1));\n\n return rules;\n },\n };\n}\n","/**\n * Slash-command trigger plugin.\n *\n * Tracks whether the cursor is inside a `/query` pattern and exposes the\n * active range + query string via `slashCommandKey` so that the\n * `SlashCommandMenu` React component can read it and render the popup.\n *\n * The plugin also handles:\n * - Escape → dismisses the menu (sets dismissed state so the same `/`\n * position doesn't re-trigger until the user moves away and types `/` again)\n * - ArrowUp / ArrowDown / Enter → consumed by the React component through\n * a capture-phase keydown listener; the plugin just marks them as handled\n * when the menu is active so ProseMirror doesn't move the cursor.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\n// ── Public types ──────────────────────────────────────────\n\nexport interface SlashCommandState {\n /** Whether a slash trigger is currently active. */\n active: boolean;\n /** Document positions of the full `/query` text (inclusive). */\n range: { from: number; to: number } | null;\n /** Text typed after `/`, not including the slash itself. */\n query: string;\n /** The parent node type name where the slash trigger is active (e.g. 'paragraph', 'heading'). */\n parentType: string;\n}\n\n// ── Plugin key (exported so SlashCommandMenu can read state) ──\n\nexport const slashCommandKey = new PluginKey<SlashCommandState>('slashCommand');\n\n// ── Internal helpers ──────────────────────────────────────\n\n/**\n * Regex matching `/` followed by zero-or-more non-whitespace chars at the\n * end of the current paragraph text up to the cursor.\n *\n * Allows the trigger at the very start of the line or after whitespace,\n * but not inside a word (e.g. `foo/bar` should NOT trigger).\n */\nconst TRIGGER_RE = /(?:^|\\s)(\\/[^\\s]*)$/;\n\n/** Derive slash-command state purely from editor state + dismissed position. */\nfunction deriveState(\n state: EditorState,\n dismissedFrom: number | null,\n): SlashCommandState {\n const inactive: SlashCommandState = { active: false, range: null, query: '', parentType: '' };\n const { selection } = state;\n if (!selection.empty) return inactive;\n\n const { $from } = selection;\n const parentType = $from.parent.type.name;\n\n // Don't trigger inside noteBlock\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'noteBlock') return inactive;\n }\n\n const textBefore = $from.parent.textBetween(0, $from.parentOffset, '\\n', '\\0');\n const match = TRIGGER_RE.exec(textBefore);\n if (!match) return inactive;\n\n const slashText = match[1]; // e.g. '/foo'\n const slashStartInParent = textBefore.lastIndexOf(slashText);\n const from = $from.start() + slashStartInParent;\n const to = $from.pos;\n\n // If the user dismissed at this exact slash position, stay inactive\n if (dismissedFrom === from) return inactive;\n\n return {\n active: true,\n range: { from, to },\n query: slashText.slice(1),\n parentType,\n };\n}\n\n// ── Meta shape ────────────────────────────────────────────\n\ninterface SlashMeta {\n /** Position of the slash that was dismissed (Escape key). */\n dismiss?: number;\n}\n\n// ── Internal plugin state (extends public state with dismiss tracking) ──\n\ninterface InternalState extends SlashCommandState {\n _dismissedFrom: number | null;\n}\n\n// ── Factory ───────────────────────────────────────────────\n\nexport function createSlashCommandPlugin(): ActionbookPlugin {\n const plugin = new Plugin<InternalState>({\n key: slashCommandKey as unknown as PluginKey<InternalState>,\n\n state: {\n init(_, state): InternalState {\n const derived = deriveState(state, null);\n return { ...derived, _dismissedFrom: null };\n },\n\n apply(tr: Transaction, prev: InternalState, _old, newState: EditorState): InternalState {\n const meta = tr.getMeta(slashCommandKey) as SlashMeta | undefined;\n\n let dismissedFrom = prev._dismissedFrom;\n\n if (meta?.dismiss !== undefined) {\n dismissedFrom = meta.dismiss;\n } else if (dismissedFrom !== null) {\n // Clear dismiss if the user typed a new `/` somewhere else\n const derived = deriveState(newState, null);\n if (derived.active && derived.range && derived.range.from !== dismissedFrom) {\n dismissedFrom = null;\n }\n }\n\n const derived = deriveState(newState, dismissedFrom);\n return { ...derived, _dismissedFrom: dismissedFrom };\n },\n },\n\n props: {\n decorations(state) {\n const s = plugin.getState(state);\n if (!s?.active || !s.range) return DecorationSet.empty;\n\n const decos: Decoration[] = [\n // Inline highlight for the slash command text\n Decoration.inline(s.range.from, s.range.to, {\n class: 'ab-slash-trigger',\n }),\n ];\n\n // Placeholder widget at cursor when query ends with \":\" and nothing after\n if (s.query.endsWith(':')) {\n decos.push(\n Decoration.widget(s.range.to, () => {\n const span = document.createElement('span');\n span.className = 'ab-slash-trigger-placeholder';\n span.textContent = 'Type a name';\n return span;\n }, { side: 1 }),\n );\n }\n\n return DecorationSet.create(state.doc, decos);\n },\n },\n });\n\n return {\n name: 'slashCommand',\n plugins: () => [plugin],\n\n keymap: () => ({\n Escape: (state, dispatch) => {\n const s = slashCommandKey.getState(state) as InternalState | undefined;\n if (!s?.active || !s.range) return false;\n\n // Dismiss: store the slash position so it won't re-trigger\n if (dispatch) {\n const tr = state.tr;\n tr.setMeta(slashCommandKey, { dismiss: s.range.from } satisfies SlashMeta);\n dispatch(tr);\n }\n return true;\n },\n }),\n };\n}\n","/**\n * History (undo/redo) plugin for the Actionbook editor.\n *\n * Wraps prosemirror-history with standard Mod-z / Mod-Shift-z / Mod-y keybindings.\n */\nimport { history, undo, redo } from 'prosemirror-history';\nimport { keymap } from 'prosemirror-keymap';\nimport type { ActionbookPlugin } from './types';\n\nexport function createHistoryPlugin(): ActionbookPlugin {\n return {\n name: 'history',\n plugins: () => [\n history(),\n keymap({ 'Mod-z': undo, 'Mod-Shift-z': redo, 'Mod-y': redo }),\n ],\n };\n}\n","/**\n * Keymap plugin for the Actionbook editor.\n *\n * Provides keyboard shortcuts matching the sbdashboard Tiptap editor:\n *\n * Backspace — lift list item out one depth when cursor is at start\n * — delete horizontalRule when in empty paragraph after it\n * — joinBackward fallback (heading/blockquote/codeBlock join)\n * Tab — sink (indent) list item, or insert tab char\n * Shift-Tab — lift (outdent) list item, or delete tab char\n * Enter — split list item; lift empty list item out of list\n * Shift-Enter — insert hardBreak\n * Mod-Shift-7 — wrap selection in bulletList\n * Mod-Shift-8 — wrap selection in orderedList\n */\nimport { baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark, setBlockType, joinBackward } from 'prosemirror-commands';\nimport { AllSelection, Plugin, TextSelection } from 'prosemirror-state';\nimport { keymap } from 'prosemirror-keymap';\nimport { liftListItem, sinkListItem, splitListItem, wrapInList } from 'prosemirror-schema-list';\nimport type { Command } from 'prosemirror-state';\nimport { actionbookSchema } from '../schema';\nimport { exitNoteBlockOnEnter } from './noteBlockPlugin';\nimport type { ActionbookPlugin } from './types';\n\nconst TAB_CHAR = '\\u0009';\n\nconst { listItem, bulletList, orderedList, hardBreak, heading, paragraph, horizontalRule, blockquote } = actionbookSchema.nodes;\n\n/** Check if a node is effectively empty (no content, or only whitespace text) */\nfunction isEffectivelyEmpty(node: import('prosemirror-model').Node): boolean {\n if (node.content.size === 0) return true;\n return node.textContent.trim().length === 0 && !node.firstChild?.isAtom;\n}\nconst { bold: boldMark, italic: italicMark, underline: underlineMark, strikethrough: strikethroughMark, code: codeMark } = actionbookSchema.marks;\n\n/**\n * Returns true only when the cursor's block is the direct child of a listItem.\n * Using `depth - 1` instead of walking all ancestors avoids false positives\n * when a listItem is a distant ancestor (e.g. cursor in a blockquote inside a\n * listItem) — those cases should fall through to the default Backspace handler.\n */\nfunction cursorDirectlyInListItem(state: Parameters<Command>[0]): boolean {\n const { $from } = state.selection;\n return $from.depth >= 2 && $from.node($from.depth - 1).type === listItem;\n}\n\n/**\n * Backspace at the start of an empty paragraph right after a list →\n * delete the paragraph and move cursor to end of the last list item.\n *\n * Spec: \"리스트 아이템 다음 빈 paragraph에서 backspace → paragraph 삭제, 커서가 리스트 아이템 끝으로\"\n */\nconst backspaceAfterList: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n\n // Must be in a paragraph at the top-level or inside a block container\n if ($from.parent.type !== paragraph) return false;\n\n // The paragraph must be empty (whitespace-only counts as empty)\n if (!isEffectivelyEmpty($from.parent)) return false;\n\n // Look at the previous sibling — it must be a list\n const parentDepth = $from.depth - 1;\n if (parentDepth < 0) return false;\n const indexInParent = $from.index(parentDepth);\n if (indexInParent === 0) return false;\n\n const prevNode = $from.node(parentDepth).child(indexInParent - 1);\n const isList = prevNode.type === bulletList || prevNode.type === orderedList;\n if (!isList) return false;\n\n if (dispatch) {\n // Delete the empty paragraph\n const from = $from.before($from.depth);\n const to = $from.after($from.depth);\n const tr = state.tr.delete(from, to);\n // Cursor lands at the position just before the deleted paragraph,\n // which is the end of the last list item\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\n/**\n * Backspace at the start of an empty paragraph that follows a leaf block\n * (horizontalRule) → delete the leaf block, keep the paragraph.\n */\nconst backspaceAfterLeafBlock: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parent.type !== paragraph) return false;\n if (!isEffectivelyEmpty($from.parent)) return false;\n\n const parentDepth = $from.depth - 1;\n if (parentDepth < 0) return false;\n const indexInParent = $from.index(parentDepth);\n if (indexInParent === 0) return false;\n\n const prevNode = $from.node(parentDepth).child(indexInParent - 1);\n if (prevNode.type !== horizontalRule) return false;\n\n if (dispatch) {\n const hrPos = $from.posAtIndex(indexInParent - 1, parentDepth);\n dispatch(state.tr.delete(hrPos, hrPos + prevNode.nodeSize).scrollIntoView());\n }\n return true;\n};\n\n/**\n * Backspace at the start of a list item → lift one depth out.\n * Prevents the default join-backward behaviour and acts like Shift-Tab.\n * Falls back to joinBackward for remaining cases (e.g. empty para after\n * heading/blockquote/codeBlock).\n */\n/** Backspace in an empty block (jinja/note/blockquote) → delete the entire block */\nconst backspaceDeleteEmptyBlock: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parent.type !== paragraph || !isEffectivelyEmpty($from.parent)) return false;\n\n const deletableTypes = new Set(['jinjaIfBlock', 'jinjaIfBranch', 'noteBlock', 'blockquote']);\n\n for (let d = $from.depth - 1; d > 0; d--) {\n const ancestor = $from.node(d);\n if (!deletableTypes.has(ancestor.type.name)) continue;\n\n // For jinjaIfBranch, check if the branch content is just this empty paragraph\n if (ancestor.type.name === 'jinjaIfBranch' && ancestor.childCount === 1 && ancestor.child(0).content.size === 0) {\n // Go up to jinjaIfBlock\n for (let dd = d - 1; dd > 0; dd--) {\n if ($from.node(dd).type.name === 'jinjaIfBlock') {\n d = dd;\n break;\n }\n }\n }\n\n // Only delete if the block has no meaningful content\n const blockNode = $from.node(d);\n const blockText = blockNode.textContent.trim();\n if (blockText.length > 0) return false;\n\n if (dispatch) {\n const blockStart = $from.before(d);\n const blockEnd = $from.after(d);\n const tr = state.tr.replaceWith(blockStart, blockEnd, paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockStart)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n return false;\n};\n\n/**\n * Backspace at the start of a list item's first paragraph:\n *\n * Case A: First item, block above list exists → join with block above\n * Case B: First item, nothing above → lift out of list\n * Case C: Non-first item → join with previous item's last paragraph\n * (nested content moves to previous item as children)\n */\nconst joinListItemBackward: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parentOffset !== 0) return false;\n if (!cursorDirectlyInListItem(state)) return false;\n // Must be in the FIRST child (paragraph) of the listItem\n if ($from.index($from.depth - 1) !== 0) return false;\n\n const liDepth = $from.depth - 1; // listItem depth\n const listDepth = liDepth - 1; // bulletList/orderedList depth\n if (listDepth < 0) return false;\n\n const listNode = $from.node(listDepth);\n if (listNode.type !== bulletList && listNode.type !== orderedList) return false;\n\n const liIndex = $from.index(listDepth); // index of this item in the list\n\n if (liIndex > 0) {\n // Case C: Non-first item → join with previous item's last paragraph\n // Two joins needed:\n // 1. Join list items (merges children into one item)\n // 2. Join the adjacent paragraphs inside the merged item\n if (dispatch) {\n const joinPos = $from.before(liDepth); // boundary between prev and current listItem\n const tr = state.tr.join(joinPos);\n // After list item join, the two paragraphs are now adjacent inside one item.\n // Join them at the mapped position (same pos, now between paragraphs).\n const mappedPos = tr.mapping.map(joinPos);\n if (tr.doc.resolve(mappedPos).nodeBefore?.isTextblock && tr.doc.resolve(mappedPos).nodeAfter?.isTextblock) {\n tr.join(mappedPos);\n }\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n\n // First item — check what's above the list\n const listStart = $from.before(listDepth);\n const parentOfList = $from.node(listDepth - 1);\n const listIndexInParent = $from.index(listDepth - 1);\n\n if (listIndexInParent > 0) {\n // Case A: There's a block above the list → join first item with it\n const prevBlock = parentOfList.child(listIndexInParent - 1);\n\n // Only join if the previous block is a textblock (paragraph, heading, etc.)\n if (prevBlock.isTextblock) {\n if (dispatch) {\n const liNode = listNode.child(0);\n const firstPara = liNode.firstChild!;\n\n // Build the transaction:\n // 1. Delete the first list item from the list\n const liStart = $from.before(liDepth);\n const liEnd = $from.after(liDepth);\n const tr = state.tr;\n\n if (listNode.childCount === 1) {\n // Only item in list → delete entire list, append content to prev block\n tr.delete(listStart, $from.after(listDepth));\n } else {\n // Multiple items → delete just the first item\n tr.delete(liStart, liEnd);\n }\n\n // 2. Append the first paragraph's content to the previous block\n const prevBlockEnd = tr.mapping.map(listStart) - 1; // end of previous block's content\n if (firstPara.content.size > 0) {\n tr.insert(prevBlockEnd, firstPara.content);\n }\n\n // 3. If the list item had nested content (sub-lists etc.), insert after prev block\n if (liNode.childCount > 1) {\n const nestedContent = [];\n for (let i = 1; i < liNode.childCount; i++) {\n nestedContent.push(liNode.child(i));\n }\n const insertPos = tr.mapping.map(listStart);\n for (const node of nestedContent) {\n tr.insert(insertPos, node);\n }\n }\n\n tr.setSelection(TextSelection.near(tr.doc.resolve(prevBlockEnd)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n }\n\n // Case B: Nothing above (or prev block not textblock) → lift\n return liftListItem(listItem)(state, dispatch);\n};\n\nconst backspaceCommand: Command = chainCommands(\n backspaceDeleteEmptyBlock,\n backspaceAfterList,\n backspaceAfterLeafBlock,\n (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parentOffset !== 0) return false;\n\n // At start of a heading → convert to paragraph\n if ($from.parent.type === heading) {\n return setBlockType(paragraph)(state, dispatch);\n }\n\n return false;\n },\n joinListItemBackward,\n (state, dispatch) => {\n // Fallback: lift list item if joinListItemBackward didn't handle it\n if (!cursorDirectlyInListItem(state)) return false;\n const { $from } = state.selection;\n if ($from.parentOffset !== 0) return false;\n if ($from.index($from.depth - 1) !== 0) return false;\n return liftListItem(listItem)(state, dispatch);\n },\n joinBackward,\n);\n\nconst tabCommand: Command = (state, dispatch) => {\n const { $from } = state.selection;\n // In list items: try to indent regardless of cursor position\n if (cursorDirectlyInListItem(state)) {\n if (sinkListItem(listItem)(state, dispatch)) return true;\n // If sink fails (e.g. already max depth), swallow the Tab — don't insert tab char\n return true;\n }\n if (dispatch) dispatch(state.tr.insertText(TAB_CHAR));\n return true;\n};\n\nconst shiftTabCommand: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (cursorDirectlyInListItem(state) && $from.parentOffset === 0) {\n return liftListItem(listItem)(state, dispatch);\n }\n const pos = $from.pos;\n if (state.doc.textBetween(pos - 1, pos) === TAB_CHAR) {\n if (dispatch) dispatch(state.tr.delete(pos - 1, pos));\n return true;\n }\n return true;\n};\n\n// ── Double-enter exit for blockquote and jinjaIfBranch ────\n// On 2nd consecutive Enter in an empty paragraph inside these blocks,\n// exit the block and create a new paragraph after it.\nlet blockExitEnterCount = 0;\nlet blockExitLastTime = 0;\nconst BLOCK_EXIT_TYPES = new Set(['blockquote', 'jinjaIfBranch']);\n\nconst exitBlockOnDoubleEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n\n // Find qualifying ancestor block\n let blockDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if (BLOCK_EXIT_TYPES.has($from.node(d).type.name)) {\n blockDepth = d;\n break;\n }\n }\n if (blockDepth < 0) {\n blockExitEnterCount = 0;\n return false;\n }\n\n // Must be in an empty paragraph\n if ($from.parent.type.name !== 'paragraph' || $from.parent.content.size !== 0) {\n blockExitEnterCount = 0;\n return false;\n }\n\n const now = Date.now();\n if (now - blockExitLastTime > 2000) blockExitEnterCount = 0;\n blockExitLastTime = now;\n blockExitEnterCount++;\n\n if (blockExitEnterCount < 2) return false;\n blockExitEnterCount = 0;\n\n if (!dispatch) return true;\n\n // Delete current empty paragraph\n const paraStart = $from.before($from.depth);\n const paraEnd = $from.after($from.depth);\n const tr = state.tr.delete(paraStart, paraEnd);\n\n // Delete previous empty paragraph (from first Enter)\n const mapped = tr.mapping.map($from.before($from.depth));\n const $m = tr.doc.resolve(Math.min(mapped, tr.doc.content.size));\n for (let d = $m.depth; d > 0; d--) {\n if (BLOCK_EXIT_TYPES.has($m.node(d).type.name)) {\n const last = $m.node(d).lastChild;\n if (last?.type.name === 'paragraph' && last.content.size === 0) {\n const lastPos = $m.end(d) - last.nodeSize;\n tr.delete(lastPos, lastPos + last.nodeSize);\n }\n break;\n }\n }\n\n // For jinjaIfBranch, exit the parent jinjaIfBlock (not just the branch)\n let exitDepth = blockDepth;\n const blockTypeName = $from.node(blockDepth).type.name;\n if (blockTypeName === 'jinjaIfBranch') {\n // Go up one more level to exit jinjaIfBlock\n for (let d = blockDepth - 1; d > 0; d--) {\n if ($from.node(d).type.name === 'jinjaIfBlock') {\n exitDepth = d;\n break;\n }\n }\n }\n\n // Insert new paragraph after the block\n const blockEnd = tr.mapping.map($from.after(exitDepth));\n const newPara = paragraph.create();\n tr.insert(blockEnd, newPara);\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockEnd + 1)));\n\n dispatch(tr.scrollIntoView());\n return true;\n};\n\n/**\n * Enter at the end of a codeBlock when the last line is empty →\n * remove the trailing newline and create a new paragraph after the block.\n */\nconst exitCodeBlockOnEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if ($from.parent.type.name !== 'codeBlock') return false;\n\n const codeBlock = $from.parent;\n const text = codeBlock.textContent;\n\n // Only exit if cursor is at the end AND text ends with a newline (empty last line)\n if ($from.parentOffset !== text.length) return false;\n if (!text.endsWith('\\n')) return false;\n\n if (dispatch) {\n const codeBlockPos = $from.before($from.depth);\n // Remove trailing newline\n const tr = state.tr.delete($from.pos - 1, $from.pos);\n // Insert new paragraph after the codeBlock\n const blockEnd = tr.mapping.map(codeBlockPos + codeBlock.nodeSize);\n tr.insert(blockEnd, paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockEnd + 1)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\nconst enterCommand: Command = chainCommands(\n exitNoteBlockOnEnter,\n exitBlockOnDoubleEnter,\n exitCodeBlockOnEnter,\n newlineInCode,\n // Split list item on Enter; lift empty list item out of list\n splitListItem(listItem),\n createParagraphNear,\n liftEmptyBlock,\n splitBlock,\n);\n\nconst shiftEnterCommand: Command = (state, dispatch) => {\n if (dispatch) {\n const { from, to, $from } = state.selection;\n const tr = state.tr;\n // Delete selection range first (if non-empty).\n if (from !== to) tr.delete(from, to);\n const insertPos = tr.mapping.map(from);\n const marks = $from.marks();\n\n // Insert hardBreak followed by a zero-width space (U+200B).\n // Without the ZWS, browsers merge typed text into the text node BEFORE\n // the <br> (contenteditable treats the cursor position between two <br>\n // elements as \"end of preceding text node\"). The ZWS creates a separate\n // text node after the <br> that anchors the cursor. ProseMirror will\n // absorb it into the next typed character automatically.\n tr.insert(insertPos, hardBreak.create());\n const afterBr = insertPos + 1;\n tr.insertText('\\u200B', afterBr);\n // Place cursor AFTER the ZWS (it will be replaced by the first typed char)\n const cursorPos = afterBr + 1;\n if (cursorPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.create(tr.doc, cursorPos));\n }\n if (marks.length > 0) tr.setStoredMarks(marks);\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\n/**\n * When the document is reduced to a single empty non-paragraph block\n * (e.g. Cmd+A → Delete leaves an empty heading), auto-convert it to a\n * paragraph so the user can continue typing normally.\n */\nfunction createEmptyDocGuardPlugin(): Plugin {\n return new Plugin({\n appendTransaction(_, __, newState) {\n const { doc } = newState;\n if (doc.childCount !== 1) return null;\n const only = doc.child(0);\n if (only.type === paragraph) return null;\n if (only.content.size !== 0) return null;\n\n // Single empty non-paragraph block → convert to paragraph\n return newState.tr.setNodeMarkup(0, paragraph);\n },\n });\n}\n\n/**\n * Smart Cmd+A: first press selects current top-level block,\n * second press (when block is already fully selected) selects entire document.\n */\nconst selectAllCommand: Command = (state, dispatch) => {\n const { $from, from, to } = state.selection;\n\n // Find the top-level block containing the cursor\n const depth = Math.min($from.depth, 1); // top-level = depth 1\n const blockStart = $from.start(depth);\n const blockEnd = $from.end(depth);\n\n // If the current block is already fully selected, select entire document\n const blockFullySelected = from <= blockStart && to >= blockEnd;\n if (blockFullySelected) {\n if (dispatch) dispatch(state.tr.setSelection(new AllSelection(state.doc)));\n return true;\n }\n\n // Otherwise, select the entire current block content\n if (dispatch) dispatch(state.tr.setSelection(TextSelection.create(state.doc, blockStart, blockEnd)));\n return true;\n};\n\nexport function createKeymapPlugin(): ActionbookPlugin {\n return {\n name: 'keymapPlugin',\n keymap: () => ({\n Backspace: backspaceCommand,\n Tab: tabCommand,\n 'Shift-Tab': shiftTabCommand,\n Enter: enterCommand,\n 'Shift-Enter': shiftEnterCommand,\n 'Mod-a': selectAllCommand,\n 'Mod-b': toggleMark(boldMark),\n 'Mod-i': toggleMark(italicMark),\n 'Mod-u': toggleMark(underlineMark),\n 'Mod-Shift-s': toggleMark(strikethroughMark),\n 'Mod-e': toggleMark(codeMark),\n 'Mod-Shift-7': wrapInList(bulletList),\n 'Mod-Shift-8': wrapInList(orderedList),\n }),\n plugins: () => [keymap(baseKeymap), createEmptyDocGuardPlugin()],\n };\n}\n","/**\n * NodeView plugin for noteBlock — editor-only content not sent to LLM.\n * Renders with a \"Note\" label chip, gray italic text, and a dashed border.\n *\n * Design tokens (from Figma):\n * Block: bg #FFF, border 1px dashed #CCC, radius 4px, padding 16px 24px\n * Label: bg #F7F7F7, border 1px solid #E0E0E0, radius 4px, padding 2px 4px\n * font 12px/16px Regular #858585\n * Body: font 14px/20px Regular Italic #858585, letter-spacing -0.1px\n * Gap: 4px between label and body\n */\nimport type { NodeView, EditorView } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Selection } from 'prosemirror-state';\nimport type { Command } from 'prosemirror-state';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\nclass NoteBlockView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n constructor(\n _node: PMNode,\n _view: EditorView,\n _getPos: () => number | undefined,\n ) {\n // Outer wrapper — dashed border box\n this.dom = document.createElement('div');\n this.dom.setAttribute('data-note-block', '');\n this.dom.className = 'ab-note-block';\n this.dom.style.cssText = [\n 'position: relative',\n 'margin: 8px 0',\n 'padding: 16px 24px',\n 'background: #fff',\n 'border: 1px dashed #ccc',\n 'border-radius: 4px',\n 'display: flex',\n 'flex-direction: column',\n 'gap: 4px',\n ].join(';');\n\n // Label chip\n const label = document.createElement('span');\n label.contentEditable = 'false';\n label.textContent = 'Note';\n label.style.cssText = [\n 'font-family: SF Pro Text, -apple-system, BlinkMacSystemFont, sans-serif',\n 'display: inline-flex',\n 'align-items: center',\n 'justify-content: center',\n 'align-self: flex-start',\n 'font-size: 12px',\n 'font-weight: 400',\n 'font-style: normal',\n 'line-height: 16px',\n 'color: #858585',\n 'background: #f7f7f7',\n 'border: 1px solid #e0e0e0',\n 'border-radius: 4px',\n 'padding: 2px 4px',\n 'user-select: none',\n 'height: 20px',\n ].join(';');\n this.dom.appendChild(label);\n\n // Content area — italic gray text\n this.contentDOM = document.createElement('div');\n this.contentDOM.className = 'ab-note-block-content';\n this.contentDOM.style.cssText = [\n 'font-size: 14px',\n 'font-style: italic',\n 'font-weight: 400',\n 'line-height: 20px',\n 'letter-spacing: -0.1px',\n 'color: #858585',\n ].join(';');\n this.dom.appendChild(this.contentDOM);\n }\n}\n\n/**\n * Exit noteBlock on Enter in an empty paragraph.\n * Deletes the empty paragraph and creates a new paragraph after the noteBlock.\n */\nconst exitNoteBlockOnEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n\n // Find noteBlock ancestor\n let noteBlockDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'noteBlock') {\n noteBlockDepth = d;\n break;\n }\n }\n if (noteBlockDepth < 0) return false;\n\n // Must be in an empty paragraph\n const parentNode = $from.parent;\n if (parentNode.type.name !== 'paragraph' || parentNode.content.size !== 0) {\n return false;\n }\n\n if (!dispatch) return true;\n\n // Delete the current empty paragraph\n const paragraphStart = $from.before($from.depth);\n const paragraphEnd = $from.after($from.depth);\n const tr = state.tr.delete(paragraphStart, paragraphEnd);\n\n // Insert new paragraph after the noteBlock\n const noteBlockEnd = tr.mapping.map($from.after(noteBlockDepth));\n const newParagraph = state.schema.nodes.paragraph.create();\n tr.insert(noteBlockEnd, newParagraph);\n\n // Move cursor into the new paragraph\n tr.setSelection(Selection.near(tr.doc.resolve(noteBlockEnd + 1)));\n\n dispatch(tr.scrollIntoView());\n return true;\n};\n\n/** Exported so keymapPlugin can include it in the Enter chain with correct priority. */\nexport { exitNoteBlockOnEnter };\n\nexport function createNoteBlockPlugin(): ActionbookPlugin {\n return {\n name: 'noteBlockNodeView',\n nodeViews: (): Record<string, NodeViewFactory> => ({\n noteBlock: (node, view, getPos) => new NoteBlockView(node, view, getPos),\n }),\n };\n}\n","/**\n * Clipboard plugin: paste plain-text / markdown → ProseMirror nodes,\n * copy ProseMirror nodes → markdown text.\n *\n * Mirrors the MarkdownClipboardManager from sbdashboard, using\n * actionbook-core's own parseFragment / serializeFragment / fromProseMirrorJSON.\n *\n * Jump-point deduplication: if a pasted `^id^` already exists in the doc,\n * the caret `^...^` markers are stripped so the text is kept as plain text\n * rather than creating a duplicate node.\n */\nimport { DOMParser as ProseMirrorDOMParser, Fragment, Slice } from 'prosemirror-model';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorView } from 'prosemirror-view';\nimport { parseFragment, serializeFragment, fromProseMirrorJSON } from '../../index';\nimport { astNodesToJSONContent } from '../bridge/toProseMirrorJSON';\nimport { actionbookSchema } from '../schema';\nimport type { ActionbookPlugin } from './types';\n\nconst key = new PluginKey('markdownClipboard');\n\n/**\n * Maximum list nesting depth allowed on paste.\n * Lists deeper than this are flattened to this depth.\n */\nconst MAX_PASTE_LIST_DEPTH = 15;\n\n/**\n * Flatten deeply nested lists in a ProseMirror node tree.\n * Lists beyond MAX_PASTE_LIST_DEPTH have their nested sublists removed —\n * only the direct paragraph content of list items is kept.\n */\nconst MAX_FLATTEN_DEPTH = 128;\n\nfunction flattenDeepLists(node: PMNode, listDepth: number = 0, _recurseDepth: number = 0): PMNode {\n if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;\n const isList = node.type.name === 'bulletList' || node.type.name === 'orderedList';\n const currentDepth = isList ? listDepth + 1 : listDepth;\n\n if (isList && currentDepth >= MAX_PASTE_LIST_DEPTH) {\n // At max depth: strip any nested lists from list items, keep only blocks\n const flatItems: PMNode[] = [];\n node.forEach((li) => {\n const nonListBlocks: PMNode[] = [];\n li.forEach((block) => {\n if (block.type.name !== 'bulletList' && block.type.name !== 'orderedList') {\n nonListBlocks.push(block);\n }\n // Nested lists are dropped — their content is already too deep\n });\n if (nonListBlocks.length > 0) {\n flatItems.push(li.type.create(li.attrs, nonListBlocks));\n }\n });\n if (flatItems.length === 0) return node;\n return node.copy(Fragment.fromArray(flatItems));\n }\n\n // Recurse into children\n const children: PMNode[] = [];\n let changed = false;\n node.forEach((child) => {\n const flattened = flattenDeepLists(child, currentDepth, _recurseDepth + 1);\n if (flattened !== child) changed = true;\n children.push(flattened);\n });\n\n if (!changed) return node;\n return node.copy(Fragment.fromArray(children));\n}\n\n/**\n * Parse HTML clipboard content through ProseMirror's DOMParser,\n * then flatten deep lists to prevent Chrome hangs.\n *\n * Uses ProseMirror's DOMParser which only creates nodes allowed by the schema,\n * effectively sanitizing the HTML through the schema whitelist.\n */\nfunction htmlToSlice(html: string): Slice | null {\n if (typeof document === 'undefined') return null;\n try {\n // Parse HTML into DOM using the browser's safe HTML parser\n const domParser = new DOMParser();\n const parsed = domParser.parseFromString(html, 'text/html');\n const body = parsed.body;\n if (!body || !body.childNodes.length) return null;\n\n // Use ProseMirror's schema-aware DOMParser to convert to PM nodes\n const pmParser = ProseMirrorDOMParser.fromSchema(actionbookSchema);\n const doc = pmParser.parse(body);\n\n // Flatten deep lists to prevent hanging\n const flattened = flattenDeepLists(doc);\n const content = flattened.content;\n\n // Skip if we only got empty paragraphs\n let hasContent = false;\n content.forEach((node) => {\n if (node.type.name !== 'paragraph' || node.content.size > 0) {\n hasContent = true;\n }\n });\n if (!hasContent) return null;\n\n const openDepth = content.childCount === 1 && content.firstChild?.type.name === 'paragraph' ? 1 : 0;\n return new Slice(content, openDepth, openDepth);\n } catch {\n return null;\n }\n}\n\nfunction textToSlice(text: string, view: EditorView): Slice | null {\n try {\n const existingIds = new Set<string>();\n view.state.doc.descendants((node) => {\n if (node.type.name === 'jumpPoint') existingIds.add(node.attrs.id as string);\n });\n\n // Strip duplicate jump-point markers\n const deduped = text.replace(/\\^([\\p{L}\\p{N}_-]+)\\^/gmu, (match, id) => {\n if (existingIds.has(id)) return id; // keep as plain text\n existingIds.add(id);\n return match;\n });\n\n const astNodes = parseFragment(deduped);\n const pmJSONNodes = astNodesToJSONContent(astNodes);\n const pmNodes = pmJSONNodes.map((json) => actionbookSchema.nodeFromJSON(json));\n const fragment = Fragment.fromArray(pmNodes);\n // Single paragraph → inline paste (openDepth 1); otherwise block paste\n const openDepth = pmJSONNodes.length === 1 && pmJSONNodes[0].type === 'paragraph' ? 1 : 0;\n return new Slice(fragment, openDepth, openDepth);\n } catch {\n return null;\n }\n}\n\n/** Check if text is a plain URL (http/https) */\nconst URL_RE = /^https?:\\/\\/[^\\s]+$/i;\n\nlet shiftHeld = false;\n\nfunction createPlugin(): Plugin {\n return new Plugin({\n key,\n props: {\n handleDOMEvents: {\n keydown(_view, event) {\n shiftHeld = event.shiftKey;\n return false;\n },\n keyup() {\n shiftHeld = false;\n return false;\n },\n paste(view, event) {\n if (shiftHeld) return false;\n const clipboardData = (event as ClipboardEvent).clipboardData;\n const text = clipboardData?.getData('text/plain');\n if (!text || !URL_RE.test(text.trim())) return false;\n const { from, to } = view.state.selection;\n if (from >= to) return false;\n const selectedText = view.state.doc.textBetween(from, to);\n if (!selectedText) return false;\n // Selected text + URL paste → wrap text as link label\n event.preventDefault();\n const linkType = view.state.schema.marks.link;\n if (!linkType) return false;\n const linkMark = linkType.create({ href: text.trim() });\n view.dispatch(view.state.tr.addMark(from, to, linkMark));\n return true;\n },\n },\n handlePaste(view: EditorView, event: ClipboardEvent) {\n const text = event.clipboardData?.getData('text/plain');\n\n // Cmd+Shift+V (or Ctrl+Shift+V) → paste without formatting\n if (shiftHeld) {\n if (!text) return false;\n const textNode = actionbookSchema.text(text);\n const slice = new Slice(Fragment.from(textNode), 0, 0);\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n }\n\n const html = event.clipboardData?.getData('text/html');\n\n // Try HTML first (preserves formatting from Google Docs, Confluence, etc.)\n if (html) {\n const htmlSlice = htmlToSlice(html);\n if (htmlSlice) {\n view.dispatch(view.state.tr.replaceSelection(htmlSlice));\n return true;\n }\n }\n\n // Plain URL (no selection) → insert as link\n if (text && URL_RE.test(text.trim())) {\n const url = text.trim();\n const linkMark = actionbookSchema.marks.link.create({ href: url });\n const textNode = actionbookSchema.text(url, [linkMark]);\n const slice = new Slice(Fragment.from(textNode), 0, 0);\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n }\n\n // Fall back to plain text / markdown\n if (!text) return false;\n const slice = textToSlice(text, view);\n if (!slice) return false;\n\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n },\n\n clipboardTextParser(text: string, _$context, _plain, view) {\n if (!text) return Slice.empty;\n const slice = textToSlice(text, view!);\n if (!slice) {\n const textNode = actionbookSchema.text(text);\n return new Slice(Fragment.from(textNode), 0, 0);\n }\n return slice;\n },\n\n // Transform pasted HTML: keep structure but flatten deep lists\n // to prevent Chrome contentEditable hanging\n transformPasted(slice: Slice) {\n const nodes: PMNode[] = [];\n slice.content.forEach((node) => {\n nodes.push(flattenDeepLists(node));\n });\n return new Slice(Fragment.fromArray(nodes), slice.openStart, slice.openEnd);\n },\n\n clipboardTextSerializer(slice: Slice) {\n try {\n const jsonNodes: Record<string, unknown>[] = [];\n slice.content.forEach((node) => jsonNodes.push(node.toJSON()));\n const doc = fromProseMirrorJSON({ type: 'doc', content: jsonNodes });\n return serializeFragment(doc.content as Parameters<typeof serializeFragment>[0]);\n } catch {\n return '';\n }\n },\n },\n });\n}\n\nexport function createMarkdownClipboardPlugin(): ActionbookPlugin {\n return {\n name: 'markdownClipboard',\n plugins: () => [createPlugin()],\n };\n}\n","import type { AstNode, BlockNode, DocumentNode, InlineNode, JinjaIfBlockNode, JinjaIfInlineNode, NodePath } from './types';\n\n/**\n * Maximum recursion depth for all tree traversal functions.\n * Prevents stack overflow from maliciously deep or malformed input.\n */\nexport const MAX_DEPTH = 128;\n\nexport class TraversalDepthError extends Error {\n constructor(depth: number) {\n super(`Maximum traversal depth (${MAX_DEPTH}) exceeded at depth ${depth}`);\n this.name = 'TraversalDepthError';\n }\n}\n\nfunction getChildren(node: AstNode): readonly AstNode[] {\n switch (node.type) {\n case 'doc':\n case 'blockquote':\n case 'listItem':\n case 'noteBlock':\n return node.content;\n case 'paragraph':\n case 'heading':\n return node.content;\n case 'bulletList':\n case 'orderedList':\n return node.content;\n case 'jinjaIfBlock':\n return node.branches.flatMap(b => b.content as readonly AstNode[]);\n case 'jinjaIfInline':\n return node.branches.flatMap(b => b.content as readonly AstNode[]);\n default:\n return [];\n }\n}\n\n// Internal recursive implementation shared by visit()\nfunction visitInternal(\n node: AstNode,\n callback: (node: AstNode, parent?: AstNode, path?: NodePath) => void,\n parent: AstNode | undefined,\n path: NodePath,\n depth: number,\n trackPath: boolean,\n): void {\n if (depth > MAX_DEPTH) {\n throw new TraversalDepthError(depth);\n }\n callback(node, parent, trackPath ? path : undefined);\n const children = getChildren(node);\n for (let i = 0; i < children.length; i++) {\n const nextPath = trackPath ? [...path, i] : path;\n visitInternal(children[i], callback, node, nextPath, depth + 1, trackPath);\n }\n}\n\nexport interface VisitOptions {\n /**\n * Whether to compute and pass a NodePath to each callback invocation.\n * Defaults to true for backward compatibility.\n * Set to false for performance-critical traversals that don't need path info.\n */\n trackPath?: boolean;\n}\n\nexport function visit(\n node: AstNode,\n callback: (node: AstNode, parent?: AstNode, path?: NodePath) => void,\n options?: VisitOptions,\n): void {\n visitInternal(node, callback, undefined, [], 0, options?.trackPath ?? true);\n}\n\nexport function map(node: AstNode, fn: (node: AstNode) => AstNode, _depth: number = 0): AstNode {\n if (_depth > MAX_DEPTH) {\n throw new TraversalDepthError(_depth);\n }\n const mapped = fn(node);\n const children = getChildren(mapped);\n if (children.length === 0) return mapped;\n\n const newChildren = children.map((child) => map(child, fn, _depth + 1));\n const changed = newChildren.some((c, i) => c !== children[i]);\n if (!changed) return mapped;\n\n switch (mapped.type) {\n case 'doc':\n return { ...mapped, content: newChildren as BlockNode[] };\n case 'blockquote':\n case 'listItem':\n case 'noteBlock':\n return { ...mapped, content: newChildren as BlockNode[] };\n case 'paragraph':\n case 'heading':\n return { ...mapped, content: newChildren as InlineNode[] };\n case 'bulletList':\n return { ...mapped, content: newChildren as typeof mapped.content };\n case 'orderedList':\n return { ...mapped, content: newChildren as typeof mapped.content };\n case 'jinjaIfBlock': {\n const jNode = mapped as JinjaIfBlockNode;\n let offset = 0;\n const newBranches = jNode.branches.map(b => {\n const slice = newChildren.slice(offset, offset + b.content.length) as BlockNode[];\n offset += b.content.length;\n return { ...b, content: slice };\n });\n return { ...jNode, branches: newBranches };\n }\n case 'jinjaIfInline': {\n const jNode = mapped as JinjaIfInlineNode;\n let offset = 0;\n const newBranches = jNode.branches.map(b => {\n const slice = newChildren.slice(offset, offset + b.content.length) as InlineNode[];\n offset += b.content.length;\n return { ...b, content: slice };\n });\n return { ...jNode, branches: newBranches };\n }\n default:\n return mapped;\n }\n}\n\nexport function textContent(node: AstNode, _depth: number = 0): string {\n if (_depth > MAX_DEPTH) {\n throw new TraversalDepthError(_depth);\n }\n switch (node.type) {\n case 'text':\n return node.text;\n case 'resourceTag':\n return node.text;\n case 'jumpPoint':\n return `^${node.id}^`;\n case 'hardBreak':\n return '\\n';\n case 'jinjaIfInline': {\n // Reconstruct original {% %} text for analyzer compatibility\n let out = '';\n for (const branch of node.branches) {\n if (branch.branchType === 'if') out += `{% if ${branch.condition} %}`;\n else if (branch.branchType === 'elif') out += `{% elif ${branch.condition} %}`;\n else out += '{% else %}';\n for (const child of branch.content) out += textContent(child, _depth + 1);\n }\n out += '{% endif %}';\n return out;\n }\n case 'horizontalRule':\n return '';\n default: {\n const children = getChildren(node);\n let out = '';\n for (const child of children) out += textContent(child, _depth + 1);\n return out;\n }\n }\n}\n\nexport function findAll(node: AstNode, predicate: (n: AstNode) => boolean): AstNode[] {\n const results: AstNode[] = [];\n visit(node, (n) => {\n if (predicate(n)) results.push(n);\n }, { trackPath: false });\n return results;\n}\n\nexport function nodeAtPath(root: DocumentNode, path: NodePath): AstNode | undefined {\n if (path.length > MAX_DEPTH) {\n throw new TraversalDepthError(path.length);\n }\n let current: AstNode = root;\n for (const index of path) {\n const children = getChildren(current);\n if (index < 0 || index >= children.length) return undefined;\n current = children[index];\n }\n return current;\n}\n","import { fromMarkdown } from 'mdast-util-from-markdown';\nimport { combineExtensions } from 'micromark-util-combine-extensions';\nimport { gfmFootnote } from 'micromark-extension-gfm-footnote';\nimport { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough';\nimport { gfmTable } from 'micromark-extension-gfm-table';\nimport { gfmTaskListItem } from 'micromark-extension-gfm-task-list-item';\nimport { gfmFootnoteFromMarkdown } from 'mdast-util-gfm-footnote';\nimport { gfmStrikethroughFromMarkdown } from 'mdast-util-gfm-strikethrough';\nimport { gfmTableFromMarkdown } from 'mdast-util-gfm-table';\nimport { gfmTaskListItemFromMarkdown } from 'mdast-util-gfm-task-list-item';\nimport { splitTextWithResourceTags } from './plugins/resourceTag';\nimport { splitTextWithJumpPoints } from './plugins/jumpPoint';\nimport type { ResourceTagMdastNode } from './plugins/resourceTag';\nimport type { JumpPointMdastNode } from './plugins/jumpPoint';\nimport { fromMdast } from './mdastAdapter';\nimport { jinjaBlockTransform } from './plugins/jinjaBlock';\nimport type { DocumentNode } from '../ast/types';\nimport type { Link, Root, Text } from 'mdast';\n\nexport interface ParseMarkdownOptions {\n jinjaNodes?: boolean;\n}\n\n// GFM without autolink literal — autolink literal converts escaped emails/URLs\n// (e.g. bookings\\@flynorse.com) into link nodes during the mdast transform pass,\n// which then serialize as <bookings@flynorse.com> instead of preserving the\n// original backslash escaping.\nconst gfmNoAutolink = () =>\n combineExtensions([gfmFootnote(), gfmStrikethrough(), gfmTable(), gfmTaskListItem()]);\n\nconst gfmNoAutolinkFromMarkdown = () => [\n gfmFootnoteFromMarkdown(),\n gfmStrikethroughFromMarkdown(),\n gfmTableFromMarkdown(),\n gfmTaskListItemFromMarkdown(),\n];\n\nconst MAX_DEPTH = 128;\n\ntype CustomNode = ResourceTagMdastNode | JumpPointMdastNode;\n\n/**\n * Recover markdown links that micromark failed to parse because the URL\n * contains spaces (e.g. `[Go to #Wrap up](#Wrap up)`). CommonMark requires\n * `<>` around such URLs, but tiptap-markdown emits the bare form.\n */\nconst BRACKET_LINK_RE = /\\[([^\\]]+)\\]\\(([^)]*\\s[^)]*)\\)/g;\n\nfunction splitTextWithBracketLinks(value: string): Array<Text | Link> {\n const results: Array<Text | Link> = [];\n let lastIndex = 0;\n for (const m of value.matchAll(BRACKET_LINK_RE)) {\n const idx = m.index!;\n if (idx > lastIndex) results.push({ type: 'text', value: value.slice(lastIndex, idx) } as Text);\n results.push({\n type: 'link',\n url: m[2],\n children: [{ type: 'text', value: m[1] } as Text],\n } as Link);\n lastIndex = idx + m[0].length;\n }\n if (lastIndex < value.length) results.push({ type: 'text', value: value.slice(lastIndex) } as Text);\n return results;\n}\n\n/**\n * Combined single-pass transform for resource tags and jump points.\n * Each text node is scanned for both patterns in one iteration,\n * avoiding two separate full-tree traversals.\n */\nfunction combinedTokensFromMarkdown(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n combinedTokensFromMarkdown(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n const c = child as { type: string };\n if (c.type === 'text') {\n // Split pipeline: bracket links → resource tags → jump points\n const afterLinks = splitTextWithBracketLinks((child as Text).value);\n for (const linkPart of afterLinks) {\n if (linkPart.type !== 'text') { newChildren.push(linkPart); continue; }\n const afterResourceTags = splitTextWithResourceTags(linkPart.value);\n for (const part of afterResourceTags) {\n if (part.type === 'text') {\n const afterJumpPoints = splitTextWithJumpPoints(part.value);\n newChildren.push(...afterJumpPoints);\n } else {\n newChildren.push(part as unknown as CustomNode);\n }\n }\n }\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function parseMarkdown(markdown: string, options?: ParseMarkdownOptions): DocumentNode {\n const tree = fromMarkdown(markdown, {\n extensions: [gfmNoAutolink()],\n mdastExtensions: [gfmNoAutolinkFromMarkdown()],\n });\n\n // Single combined pass for resource tags and jump points\n combinedTokensFromMarkdown(tree as unknown as { children?: unknown[] });\n\n // Optional: transform Jinja tags into structured mdast nodes\n if (options?.jinjaNodes) {\n jinjaBlockTransform(tree as unknown as { type: string; children?: unknown[] });\n }\n\n return fromMdast(tree);\n}\n","/**\n * Like `Array#splice`, but smarter for giant arrays.\n *\n * `Array#splice` takes all items to be inserted as individual argument which\n * causes a stack overflow in V8 when trying to insert 100k items for instance.\n *\n * Otherwise, this does not return the removed items, and takes `items` as an\n * array instead of rest parameters.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array<T>} list\n * List to operate on.\n * @param {number} start\n * Index to remove/insert at (can be negative).\n * @param {number} remove\n * Number of items to remove.\n * @param {Array<T>} items\n * Items to inject into `list`.\n * @returns {undefined}\n * Nothing.\n */\nexport function splice(list, start, remove, items) {\n const end = list.length;\n let chunkStart = 0;\n /** @type {Array<unknown>} */\n let parameters;\n\n // Make start between zero and `end` (included).\n if (start < 0) {\n start = -start > end ? 0 : end + start;\n } else {\n start = start > end ? end : start;\n }\n remove = remove > 0 ? remove : 0;\n\n // No need to chunk the items if there’s only a couple (10k) items.\n if (items.length < 10000) {\n parameters = Array.from(items);\n parameters.unshift(start, remove);\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters);\n } else {\n // Delete `remove` items starting from `start`\n if (remove) list.splice(start, remove);\n\n // Insert the items in chunks to not cause stack overflows.\n while (chunkStart < items.length) {\n parameters = items.slice(chunkStart, chunkStart + 10000);\n parameters.unshift(start, 0);\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters);\n chunkStart += 10000;\n start += 10000;\n }\n }\n}\n\n/**\n * Append `items` (an array) at the end of `list` (another array).\n * When `list` was empty, returns `items` instead.\n *\n * This prevents a potentially expensive operation when `list` is empty,\n * and adds items in batches to prevent V8 from hanging.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array<T>} list\n * List to operate on.\n * @param {Array<T>} items\n * Items to add to `list`.\n * @returns {Array<T>}\n * Either `list` or `items`.\n */\nexport function push(list, items) {\n if (list.length > 0) {\n splice(list, list.length, 0, items);\n return list;\n }\n return items;\n}","/**\n * @import {\n * Extension,\n * Handles,\n * HtmlExtension,\n * NormalizedExtension\n * } from 'micromark-util-types'\n */\n\nimport {splice} from 'micromark-util-chunked'\n\nconst hasOwnProperty = {}.hasOwnProperty\n\n/**\n * Combine multiple syntax extensions into one.\n *\n * @param {ReadonlyArray<Extension>} extensions\n * List of syntax extensions.\n * @returns {NormalizedExtension}\n * A single combined extension.\n */\nexport function combineExtensions(extensions) {\n /** @type {NormalizedExtension} */\n const all = {}\n let index = -1\n\n while (++index < extensions.length) {\n syntaxExtension(all, extensions[index])\n }\n\n return all\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {NormalizedExtension} all\n * Extension to merge into.\n * @param {Extension} extension\n * Extension to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction syntaxExtension(all, extension) {\n /** @type {keyof Extension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n /** @type {Record<string, unknown>} */\n const left = maybe || (all[hook] = {})\n /** @type {Record<string, unknown> | undefined} */\n const right = extension[hook]\n /** @type {string} */\n let code\n\n if (right) {\n for (code in right) {\n if (!hasOwnProperty.call(left, code)) left[code] = []\n const value = right[code]\n constructs(\n // @ts-expect-error Looks like a list.\n left[code],\n Array.isArray(value) ? value : value ? [value] : []\n )\n }\n }\n }\n}\n\n/**\n * Merge `list` into `existing` (both lists of constructs).\n * Mutates `existing`.\n *\n * @param {Array<unknown>} existing\n * List of constructs to merge into.\n * @param {Array<unknown>} list\n * List of constructs to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction constructs(existing, list) {\n let index = -1\n /** @type {Array<unknown>} */\n const before = []\n\n while (++index < list.length) {\n // @ts-expect-error Looks like an object.\n ;(list[index].add === 'after' ? existing : before).push(list[index])\n }\n\n splice(existing, 0, 0, before)\n}\n\n/**\n * Combine multiple HTML extensions into one.\n *\n * @param {ReadonlyArray<HtmlExtension>} htmlExtensions\n * List of HTML extensions.\n * @returns {HtmlExtension}\n * Single combined HTML extension.\n */\nexport function combineHtmlExtensions(htmlExtensions) {\n /** @type {HtmlExtension} */\n const handlers = {}\n let index = -1\n\n while (++index < htmlExtensions.length) {\n htmlExtension(handlers, htmlExtensions[index])\n }\n\n return handlers\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {HtmlExtension} all\n * Extension to merge into.\n * @param {HtmlExtension} extension\n * Extension to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction htmlExtension(all, extension) {\n /** @type {keyof HtmlExtension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n const left = maybe || (all[hook] = {})\n const right = extension[hook]\n /** @type {keyof Handles} */\n let type\n\n if (right) {\n for (type in right) {\n // @ts-expect-error assume document vs regular handler are managed correctly.\n left[type] = right[type]\n }\n }\n }\n}\n","/**\n * @import {Code} from 'micromark-util-types'\n */\n\nimport { markdownLineEndingOrSpace, unicodePunctuation, unicodeWhitespace } from 'micromark-util-character';\n/**\n * Classify whether a code represents whitespace, punctuation, or something\n * else.\n *\n * Used for attention (emphasis, strong), whose sequences can open or close\n * based on the class of surrounding characters.\n *\n * > 👉 **Note**: eof (`null`) is seen as whitespace.\n *\n * @param {Code} code\n * Code.\n * @returns {typeof constants.characterGroupWhitespace | typeof constants.characterGroupPunctuation | undefined}\n * Group.\n */\nexport function classifyCharacter(code) {\n if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) {\n return 1;\n }\n if (unicodePunctuation(code)) {\n return 2;\n }\n}","/**\n * @import {Event, Resolver, TokenizeContext} from 'micromark-util-types'\n */\n\n/**\n * Call all `resolveAll`s.\n *\n * @param {ReadonlyArray<{resolveAll?: Resolver | undefined}>} constructs\n * List of constructs, optionally with `resolveAll`s.\n * @param {Array<Event>} events\n * List of events.\n * @param {TokenizeContext} context\n * Context used by `tokenize`.\n * @returns {Array<Event>}\n * Changed events.\n */\nexport function resolveAll(constructs, events, context) {\n /** @type {Array<Resolver>} */\n const called = []\n let index = -1\n\n while (++index < constructs.length) {\n const resolve = constructs[index].resolveAll\n\n if (resolve && !called.includes(resolve)) {\n events = resolve(events, context)\n called.push(resolve)\n }\n }\n\n return events\n}\n","/**\n * @import {Effects, State, TokenType} from 'micromark-util-types'\n */\n\nimport { markdownSpace } from 'micromark-util-character';\n\n// To do: implement `spaceOrTab`, `spaceOrTabMinMax`, `spaceOrTabWithOptions`.\n\n/**\n * Parse spaces and tabs.\n *\n * There is no `nok` parameter:\n *\n * * spaces in markdown are often optional, in which case this factory can be\n * used and `ok` will be switched to whether spaces were found or not\n * * one line ending or space can be detected with `markdownSpace(code)` right\n * before using `factorySpace`\n *\n * ###### Examples\n *\n * Where `␉` represents a tab (plus how much it expands) and `␠` represents a\n * single space.\n *\n * ```markdown\n * ␉\n * ␠␠␠␠\n * ␉␠\n * ```\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {TokenType} type\n * Type (`' \\t'`).\n * @param {number | undefined} [max=Infinity]\n * Max (exclusive).\n * @returns {State}\n * Start state.\n */\nexport function factorySpace(effects, ok, type, max) {\n const limit = max ? max - 1 : Number.POSITIVE_INFINITY;\n let size = 0;\n return start;\n\n /** @type {State} */\n function start(code) {\n if (markdownSpace(code)) {\n effects.enter(type);\n return prefix(code);\n }\n return ok(code);\n }\n\n /** @type {State} */\n function prefix(code) {\n if (markdownSpace(code) && size++ < limit) {\n effects.consume(code);\n return prefix;\n }\n effects.exit(type);\n return ok(code);\n }\n}","/**\n * @import {\n * Construct,\n * State,\n * TokenizeContext,\n * Tokenizer\n * } from 'micromark-util-types'\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownSpace } from 'micromark-util-character';\n/** @type {Construct} */\nexport const blankLine = {\n partial: true,\n tokenize: tokenizeBlankLine\n};\n\n/**\n * @this {TokenizeContext}\n * Context.\n * @type {Tokenizer}\n */\nfunction tokenizeBlankLine(effects, ok, nok) {\n return start;\n\n /**\n * Start of blank line.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n return markdownSpace(code) ? factorySpace(effects, after, \"linePrefix\")(code) : after(code);\n }\n\n /**\n * At eof/eol, after optional whitespace.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n return code === null || markdownLineEnding(code) ? ok(code) : nok(code);\n }\n}","/**\n * @import {Event, Exiter, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { blankLine } from 'micromark-core-commonmark';\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEndingOrSpace } from 'micromark-util-character';\nimport { normalizeIdentifier } from 'micromark-util-normalize-identifier';\nconst indent = {\n tokenize: tokenizeIndent,\n partial: true\n};\n\n// To do: micromark should support a `_hiddenGfmFootnoteSupport`, which only\n// affects label start (image).\n// That will let us drop `tokenizePotentialGfmFootnote*`.\n// It currently has a `_hiddenFootnoteSupport`, which affects that and more.\n// That can be removed when `micromark-extension-footnote` is archived.\n\n/**\n * Create an extension for `micromark` to enable GFM footnote syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions` to\n * enable GFM footnote syntax.\n */\nexport function gfmFootnote() {\n /** @type {Extension} */\n return {\n document: {\n [91]: {\n name: 'gfmFootnoteDefinition',\n tokenize: tokenizeDefinitionStart,\n continuation: {\n tokenize: tokenizeDefinitionContinuation\n },\n exit: gfmFootnoteDefinitionEnd\n }\n },\n text: {\n [91]: {\n name: 'gfmFootnoteCall',\n tokenize: tokenizeGfmFootnoteCall\n },\n [93]: {\n name: 'gfmPotentialFootnoteCall',\n add: 'after',\n tokenize: tokenizePotentialGfmFootnoteCall,\n resolveTo: resolveToPotentialGfmFootnoteCall\n }\n }\n };\n}\n\n// To do: remove after micromark update.\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizePotentialGfmFootnoteCall(effects, ok, nok) {\n const self = this;\n let index = self.events.length;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n /** @type {Token} */\n let labelStart;\n\n // Find an opening.\n while (index--) {\n const token = self.events[index][1];\n if (token.type === \"labelImage\") {\n labelStart = token;\n break;\n }\n\n // Exit if we’ve walked far enough.\n if (token.type === 'gfmFootnoteCall' || token.type === \"labelLink\" || token.type === \"label\" || token.type === \"image\" || token.type === \"link\") {\n break;\n }\n }\n return start;\n\n /**\n * @type {State}\n */\n function start(code) {\n if (!labelStart || !labelStart._balanced) {\n return nok(code);\n }\n const id = normalizeIdentifier(self.sliceSerialize({\n start: labelStart.end,\n end: self.now()\n }));\n if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) {\n return nok(code);\n }\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n return ok(code);\n }\n}\n\n// To do: remove after micromark update.\n/** @type {Resolver} */\nfunction resolveToPotentialGfmFootnoteCall(events, context) {\n let index = events.length;\n /** @type {Token | undefined} */\n let labelStart;\n\n // Find an opening.\n while (index--) {\n if (events[index][1].type === \"labelImage\" && events[index][0] === 'enter') {\n labelStart = events[index][1];\n break;\n }\n }\n // Change the `labelImageMarker` to a `data`.\n events[index + 1][1].type = \"data\";\n events[index + 3][1].type = 'gfmFootnoteCallLabelMarker';\n\n // The whole (without `!`):\n /** @type {Token} */\n const call = {\n type: 'gfmFootnoteCall',\n start: Object.assign({}, events[index + 3][1].start),\n end: Object.assign({}, events[events.length - 1][1].end)\n };\n // The `^` marker\n /** @type {Token} */\n const marker = {\n type: 'gfmFootnoteCallMarker',\n start: Object.assign({}, events[index + 3][1].end),\n end: Object.assign({}, events[index + 3][1].end)\n };\n // Increment the end 1 character.\n marker.end.column++;\n marker.end.offset++;\n marker.end._bufferIndex++;\n /** @type {Token} */\n const string = {\n type: 'gfmFootnoteCallString',\n start: Object.assign({}, marker.end),\n end: Object.assign({}, events[events.length - 1][1].start)\n };\n /** @type {Token} */\n const chunk = {\n type: \"chunkString\",\n contentType: 'string',\n start: Object.assign({}, string.start),\n end: Object.assign({}, string.end)\n };\n\n /** @type {Array<Event>} */\n const replacement = [\n // Take the `labelImageMarker` (now `data`, the `!`)\n events[index + 1], events[index + 2], ['enter', call, context],\n // The `[`\n events[index + 3], events[index + 4],\n // The `^`.\n ['enter', marker, context], ['exit', marker, context],\n // Everything in between.\n ['enter', string, context], ['enter', chunk, context], ['exit', chunk, context], ['exit', string, context],\n // The ending (`]`, properly parsed and labelled).\n events[events.length - 2], events[events.length - 1], ['exit', call, context]];\n events.splice(index, events.length - index + 1, ...replacement);\n return events;\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeGfmFootnoteCall(effects, ok, nok) {\n const self = this;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n let size = 0;\n /** @type {boolean} */\n let data;\n\n // Note: the implementation of `markdown-rs` is different, because it houses\n // core *and* extensions in one project.\n // Therefore, it can include footnote logic inside `label-end`.\n // We can’t do that, but luckily, we can parse footnotes in a simpler way than\n // needed for labels.\n return start;\n\n /**\n * Start of footnote label.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n effects.enter('gfmFootnoteCall');\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n return callStart;\n }\n\n /**\n * After `[`, at `^`.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function callStart(code) {\n if (code !== 94) return nok(code);\n effects.enter('gfmFootnoteCallMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallMarker');\n effects.enter('gfmFootnoteCallString');\n effects.enter('chunkString').contentType = 'string';\n return callData;\n }\n\n /**\n * In label.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function callData(code) {\n if (\n // Too long.\n size > 999 ||\n // Closing brace with nothing.\n code === 93 && !data ||\n // Space or tab is not supported by GFM for some reason.\n // `\\n` and `[` not being supported makes sense.\n code === null || code === 91 || markdownLineEndingOrSpace(code)) {\n return nok(code);\n }\n if (code === 93) {\n effects.exit('chunkString');\n const token = effects.exit('gfmFootnoteCallString');\n if (!defined.includes(normalizeIdentifier(self.sliceSerialize(token)))) {\n return nok(code);\n }\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n effects.exit('gfmFootnoteCall');\n return ok;\n }\n if (!markdownLineEndingOrSpace(code)) {\n data = true;\n }\n size++;\n effects.consume(code);\n return code === 92 ? callEscape : callData;\n }\n\n /**\n * On character after escape.\n *\n * ```markdown\n * > | a [^b\\c] d\n * ^\n * ```\n *\n * @type {State}\n */\n function callEscape(code) {\n if (code === 91 || code === 92 || code === 93) {\n effects.consume(code);\n size++;\n return callData;\n }\n return callData(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeDefinitionStart(effects, ok, nok) {\n const self = this;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n /** @type {string} */\n let identifier;\n let size = 0;\n /** @type {boolean | undefined} */\n let data;\n return start;\n\n /**\n * Start of GFM footnote definition.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n effects.enter('gfmFootnoteDefinition')._container = true;\n effects.enter('gfmFootnoteDefinitionLabel');\n effects.enter('gfmFootnoteDefinitionLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionLabelMarker');\n return labelAtMarker;\n }\n\n /**\n * In label, at caret.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelAtMarker(code) {\n if (code === 94) {\n effects.enter('gfmFootnoteDefinitionMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionMarker');\n effects.enter('gfmFootnoteDefinitionLabelString');\n effects.enter('chunkString').contentType = 'string';\n return labelInside;\n }\n return nok(code);\n }\n\n /**\n * In label.\n *\n * > 👉 **Note**: `cmark-gfm` prevents whitespace from occurring in footnote\n * > definition labels.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelInside(code) {\n if (\n // Too long.\n size > 999 ||\n // Closing brace with nothing.\n code === 93 && !data ||\n // Space or tab is not supported by GFM for some reason.\n // `\\n` and `[` not being supported makes sense.\n code === null || code === 91 || markdownLineEndingOrSpace(code)) {\n return nok(code);\n }\n if (code === 93) {\n effects.exit('chunkString');\n const token = effects.exit('gfmFootnoteDefinitionLabelString');\n identifier = normalizeIdentifier(self.sliceSerialize(token));\n effects.enter('gfmFootnoteDefinitionLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionLabelMarker');\n effects.exit('gfmFootnoteDefinitionLabel');\n return labelAfter;\n }\n if (!markdownLineEndingOrSpace(code)) {\n data = true;\n }\n size++;\n effects.consume(code);\n return code === 92 ? labelEscape : labelInside;\n }\n\n /**\n * After `\\`, at a special character.\n *\n * > 👉 **Note**: `cmark-gfm` currently does not support escaped brackets:\n * > <https://github.com/github/cmark-gfm/issues/240>\n *\n * ```markdown\n * > | [^a\\*b]: c\n * ^\n * ```\n *\n * @type {State}\n */\n function labelEscape(code) {\n if (code === 91 || code === 92 || code === 93) {\n effects.consume(code);\n size++;\n return labelInside;\n }\n return labelInside(code);\n }\n\n /**\n * After definition label.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelAfter(code) {\n if (code === 58) {\n effects.enter('definitionMarker');\n effects.consume(code);\n effects.exit('definitionMarker');\n if (!defined.includes(identifier)) {\n defined.push(identifier);\n }\n\n // Any whitespace after the marker is eaten, forming indented code\n // is not possible.\n // No space is also fine, just like a block quote marker.\n return factorySpace(effects, whitespaceAfter, 'gfmFootnoteDefinitionWhitespace');\n }\n return nok(code);\n }\n\n /**\n * After definition prefix.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function whitespaceAfter(code) {\n // `markdown-rs` has a wrapping token for the prefix that is closed here.\n return ok(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeDefinitionContinuation(effects, ok, nok) {\n /// Start of footnote definition continuation.\n ///\n /// ```markdown\n /// | [^a]: b\n /// > | c\n /// ^\n /// ```\n //\n // Either a blank line, which is okay, or an indented thing.\n return effects.check(blankLine, ok, effects.attempt(indent, ok, nok));\n}\n\n/** @type {Exiter} */\nfunction gfmFootnoteDefinitionEnd(effects) {\n effects.exit('gfmFootnoteDefinition');\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeIndent(effects, ok, nok) {\n const self = this;\n return factorySpace(effects, afterPrefix, 'gfmFootnoteDefinitionIndent', 4 + 1);\n\n /**\n * @type {State}\n */\n function afterPrefix(code) {\n const tail = self.events[self.events.length - 1];\n return tail && tail[1].type === 'gfmFootnoteDefinitionIndent' && tail[2].sliceSerialize(tail[1], true).length === 4 ? ok(code) : nok(code);\n }\n}","/**\n * @import {Options} from 'micromark-extension-gfm-strikethrough'\n * @import {Event, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { splice } from 'micromark-util-chunked';\nimport { classifyCharacter } from 'micromark-util-classify-character';\nimport { resolveAll } from 'micromark-util-resolve-all';\n/**\n * Create an extension for `micromark` to enable GFM strikethrough syntax.\n *\n * @param {Options | null | undefined} [options={}]\n * Configuration.\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions`, to\n * enable GFM strikethrough syntax.\n */\nexport function gfmStrikethrough(options) {\n const options_ = options || {};\n let single = options_.singleTilde;\n const tokenizer = {\n name: 'strikethrough',\n tokenize: tokenizeStrikethrough,\n resolveAll: resolveAllStrikethrough\n };\n if (single === null || single === undefined) {\n single = true;\n }\n return {\n text: {\n [126]: tokenizer\n },\n insideSpan: {\n null: [tokenizer]\n },\n attentionMarkers: {\n null: [126]\n }\n };\n\n /**\n * Take events and resolve strikethrough.\n *\n * @type {Resolver}\n */\n function resolveAllStrikethrough(events, context) {\n let index = -1;\n\n // Walk through all events.\n while (++index < events.length) {\n // Find a token that can close.\n if (events[index][0] === 'enter' && events[index][1].type === 'strikethroughSequenceTemporary' && events[index][1]._close) {\n let open = index;\n\n // Now walk back to find an opener.\n while (open--) {\n // Find a token that can open the closer.\n if (events[open][0] === 'exit' && events[open][1].type === 'strikethroughSequenceTemporary' && events[open][1]._open &&\n // If the sizes are the same:\n events[index][1].end.offset - events[index][1].start.offset === events[open][1].end.offset - events[open][1].start.offset) {\n events[index][1].type = 'strikethroughSequence';\n events[open][1].type = 'strikethroughSequence';\n\n /** @type {Token} */\n const strikethrough = {\n type: 'strikethrough',\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[index][1].end)\n };\n\n /** @type {Token} */\n const text = {\n type: 'strikethroughText',\n start: Object.assign({}, events[open][1].end),\n end: Object.assign({}, events[index][1].start)\n };\n\n // Opening.\n /** @type {Array<Event>} */\n const nextEvents = [['enter', strikethrough, context], ['enter', events[open][1], context], ['exit', events[open][1], context], ['enter', text, context]];\n const insideSpan = context.parser.constructs.insideSpan.null;\n if (insideSpan) {\n // Between.\n splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));\n }\n\n // Closing.\n splice(nextEvents, nextEvents.length, 0, [['exit', text, context], ['enter', events[index][1], context], ['exit', events[index][1], context], ['exit', strikethrough, context]]);\n splice(events, open - 1, index - open + 3, nextEvents);\n index = open + nextEvents.length - 2;\n break;\n }\n }\n }\n }\n index = -1;\n while (++index < events.length) {\n if (events[index][1].type === 'strikethroughSequenceTemporary') {\n events[index][1].type = \"data\";\n }\n }\n return events;\n }\n\n /**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\n function tokenizeStrikethrough(effects, ok, nok) {\n const previous = this.previous;\n const events = this.events;\n let size = 0;\n return start;\n\n /** @type {State} */\n function start(code) {\n if (previous === 126 && events[events.length - 1][1].type !== \"characterEscape\") {\n return nok(code);\n }\n effects.enter('strikethroughSequenceTemporary');\n return more(code);\n }\n\n /** @type {State} */\n function more(code) {\n const before = classifyCharacter(previous);\n if (code === 126) {\n // If this is the third marker, exit.\n if (size > 1) return nok(code);\n effects.consume(code);\n size++;\n return more;\n }\n if (size < 2 && !single) return nok(code);\n const token = effects.exit('strikethroughSequenceTemporary');\n const after = classifyCharacter(code);\n token._open = !after || after === 2 && Boolean(before);\n token._close = !before || before === 2 && Boolean(after);\n return ok(code);\n }\n }\n}","/**\n * @import {Event, Extension, Point, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\n/**\n * @typedef {[number, number, number, number]} Range\n * Cell info.\n *\n * @typedef {0 | 1 | 2 | 3} RowKind\n * Where we are: `1` for head row, `2` for delimiter row, `3` for body row.\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace } from 'micromark-util-character';\nimport { EditMap } from './edit-map.js';\nimport { gfmTableAlign } from './infer.js';\n\n/**\n * Create an HTML extension for `micromark` to support GitHub tables syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions` to enable GFM\n * table syntax.\n */\nexport function gfmTable() {\n return {\n flow: {\n null: {\n name: 'table',\n tokenize: tokenizeTable,\n resolveAll: resolveTable\n }\n }\n };\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeTable(effects, ok, nok) {\n const self = this;\n let size = 0;\n let sizeB = 0;\n /** @type {boolean | undefined} */\n let seen;\n return start;\n\n /**\n * Start of a GFM table.\n *\n * If there is a valid table row or table head before, then we try to parse\n * another row.\n * Otherwise, we try to parse a head.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * > | | b |\n * ^\n * ```\n * @type {State}\n */\n function start(code) {\n let index = self.events.length - 1;\n while (index > -1) {\n const type = self.events[index][1].type;\n if (type === \"lineEnding\" ||\n // Note: markdown-rs uses `whitespace` instead of `linePrefix`\n type === \"linePrefix\") index--;else break;\n }\n const tail = index > -1 ? self.events[index][1].type : null;\n const next = tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore;\n\n // Don’t allow lazy body rows.\n if (next === bodyRowStart && self.parser.lazy[self.now().line]) {\n return nok(code);\n }\n return next(code);\n }\n\n /**\n * Before table head row.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowBefore(code) {\n effects.enter('tableHead');\n effects.enter('tableRow');\n return headRowStart(code);\n }\n\n /**\n * Before table head row, after whitespace.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowStart(code) {\n if (code === 124) {\n return headRowBreak(code);\n }\n\n // To do: micromark-js should let us parse our own whitespace in extensions,\n // like `markdown-rs`:\n //\n // ```js\n // // 4+ spaces.\n // if (markdownSpace(code)) {\n // return nok(code)\n // }\n // ```\n\n seen = true;\n // Count the first character, that isn’t a pipe, double.\n sizeB += 1;\n return headRowBreak(code);\n }\n\n /**\n * At break in table head row.\n *\n * ```markdown\n * > | | a |\n * ^\n * ^\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowBreak(code) {\n if (code === null) {\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n if (markdownLineEnding(code)) {\n // If anything other than one pipe (ignoring whitespace) was used, it’s fine.\n if (sizeB > 1) {\n sizeB = 0;\n // To do: check if this works.\n // Feel free to interrupt:\n self.interrupt = true;\n effects.exit('tableRow');\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return headDelimiterStart;\n }\n\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n if (markdownSpace(code)) {\n // To do: check if this is fine.\n // effects.attempt(State::Next(StateName::GfmTableHeadRowBreak), State::Nok)\n // State::Retry(space_or_tab(tokenizer))\n return factorySpace(effects, headRowBreak, \"whitespace\")(code);\n }\n sizeB += 1;\n if (seen) {\n seen = false;\n // Header cell count.\n size += 1;\n }\n if (code === 124) {\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n // Whether a delimiter was seen.\n seen = true;\n return headRowBreak;\n }\n\n // Anything else is cell data.\n effects.enter(\"data\");\n return headRowData(code);\n }\n\n /**\n * In table head row data.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowData(code) {\n if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {\n effects.exit(\"data\");\n return headRowBreak(code);\n }\n effects.consume(code);\n return code === 92 ? headRowEscape : headRowData;\n }\n\n /**\n * In table head row escape.\n *\n * ```markdown\n * > | | a\\-b |\n * ^\n * | | ---- |\n * | | c |\n * ```\n *\n * @type {State}\n */\n function headRowEscape(code) {\n if (code === 92 || code === 124) {\n effects.consume(code);\n return headRowData;\n }\n return headRowData(code);\n }\n\n /**\n * Before delimiter row.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headDelimiterStart(code) {\n // Reset `interrupt`.\n self.interrupt = false;\n\n // Note: in `markdown-rs`, we need to handle piercing here too.\n if (self.parser.lazy[self.now().line]) {\n return nok(code);\n }\n effects.enter('tableDelimiterRow');\n // Track if we’ve seen a `:` or `|`.\n seen = false;\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterBefore, \"linePrefix\", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code);\n }\n return headDelimiterBefore(code);\n }\n\n /**\n * Before delimiter row, after optional whitespace.\n *\n * Reused when a `|` is found later, to parse another cell.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headDelimiterBefore(code) {\n if (code === 45 || code === 58) {\n return headDelimiterValueBefore(code);\n }\n if (code === 124) {\n seen = true;\n // If we start with a pipe, we open a cell marker.\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n return headDelimiterCellBefore;\n }\n\n // More whitespace / empty row not allowed at start.\n return headDelimiterNok(code);\n }\n\n /**\n * After `|`, before delimiter cell.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterCellBefore(code) {\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterValueBefore, \"whitespace\")(code);\n }\n return headDelimiterValueBefore(code);\n }\n\n /**\n * Before delimiter cell value.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterValueBefore(code) {\n // Align: left.\n if (code === 58) {\n sizeB += 1;\n seen = true;\n effects.enter('tableDelimiterMarker');\n effects.consume(code);\n effects.exit('tableDelimiterMarker');\n return headDelimiterLeftAlignmentAfter;\n }\n\n // Align: none.\n if (code === 45) {\n sizeB += 1;\n // To do: seems weird that this *isn’t* left aligned, but that state is used?\n return headDelimiterLeftAlignmentAfter(code);\n }\n if (code === null || markdownLineEnding(code)) {\n return headDelimiterCellAfter(code);\n }\n return headDelimiterNok(code);\n }\n\n /**\n * After delimiter cell left alignment marker.\n *\n * ```markdown\n * | | a |\n * > | | :- |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterLeftAlignmentAfter(code) {\n if (code === 45) {\n effects.enter('tableDelimiterFiller');\n return headDelimiterFiller(code);\n }\n\n // Anything else is not ok after the left-align colon.\n return headDelimiterNok(code);\n }\n\n /**\n * In delimiter cell filler.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterFiller(code) {\n if (code === 45) {\n effects.consume(code);\n return headDelimiterFiller;\n }\n\n // Align is `center` if it was `left`, `right` otherwise.\n if (code === 58) {\n seen = true;\n effects.exit('tableDelimiterFiller');\n effects.enter('tableDelimiterMarker');\n effects.consume(code);\n effects.exit('tableDelimiterMarker');\n return headDelimiterRightAlignmentAfter;\n }\n effects.exit('tableDelimiterFiller');\n return headDelimiterRightAlignmentAfter(code);\n }\n\n /**\n * After delimiter cell right alignment marker.\n *\n * ```markdown\n * | | a |\n * > | | -: |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterRightAlignmentAfter(code) {\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterCellAfter, \"whitespace\")(code);\n }\n return headDelimiterCellAfter(code);\n }\n\n /**\n * After delimiter cell.\n *\n * ```markdown\n * | | a |\n * > | | -: |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterCellAfter(code) {\n if (code === 124) {\n return headDelimiterBefore(code);\n }\n if (code === null || markdownLineEnding(code)) {\n // Exit when:\n // * there was no `:` or `|` at all (it’s a thematic break or setext\n // underline instead)\n // * the header cell count is not the delimiter cell count\n if (!seen || size !== sizeB) {\n return headDelimiterNok(code);\n }\n\n // Note: in markdown-rs`, a reset is needed here.\n effects.exit('tableDelimiterRow');\n effects.exit('tableHead');\n // To do: in `markdown-rs`, resolvers need to be registered manually.\n // effects.register_resolver(ResolveName::GfmTable)\n return ok(code);\n }\n return headDelimiterNok(code);\n }\n\n /**\n * In delimiter row, at a disallowed byte.\n *\n * ```markdown\n * | | a |\n * > | | x |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterNok(code) {\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n\n /**\n * Before table body row.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowStart(code) {\n // Note: in `markdown-rs` we need to manually take care of a prefix,\n // but in `micromark-js` that is done for us, so if we’re here, we’re\n // never at whitespace.\n effects.enter('tableRow');\n return bodyRowBreak(code);\n }\n\n /**\n * At break in table body row.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ^\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowBreak(code) {\n if (code === 124) {\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n return bodyRowBreak;\n }\n if (code === null || markdownLineEnding(code)) {\n effects.exit('tableRow');\n return ok(code);\n }\n if (markdownSpace(code)) {\n return factorySpace(effects, bodyRowBreak, \"whitespace\")(code);\n }\n\n // Anything else is cell content.\n effects.enter(\"data\");\n return bodyRowData(code);\n }\n\n /**\n * In table body row data.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowData(code) {\n if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {\n effects.exit(\"data\");\n return bodyRowBreak(code);\n }\n effects.consume(code);\n return code === 92 ? bodyRowEscape : bodyRowData;\n }\n\n /**\n * In table body row escape.\n *\n * ```markdown\n * | | a |\n * | | ---- |\n * > | | b\\-c |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowEscape(code) {\n if (code === 92 || code === 124) {\n effects.consume(code);\n return bodyRowData;\n }\n return bodyRowData(code);\n }\n}\n\n/** @type {Resolver} */\n\nfunction resolveTable(events, context) {\n let index = -1;\n let inFirstCellAwaitingPipe = true;\n /** @type {RowKind} */\n let rowKind = 0;\n /** @type {Range} */\n let lastCell = [0, 0, 0, 0];\n /** @type {Range} */\n let cell = [0, 0, 0, 0];\n let afterHeadAwaitingFirstBodyRow = false;\n let lastTableEnd = 0;\n /** @type {Token | undefined} */\n let currentTable;\n /** @type {Token | undefined} */\n let currentBody;\n /** @type {Token | undefined} */\n let currentCell;\n const map = new EditMap();\n while (++index < events.length) {\n const event = events[index];\n const token = event[1];\n if (event[0] === 'enter') {\n // Start of head.\n if (token.type === 'tableHead') {\n afterHeadAwaitingFirstBodyRow = false;\n\n // Inject previous (body end and) table end.\n if (lastTableEnd !== 0) {\n flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);\n currentBody = undefined;\n lastTableEnd = 0;\n }\n\n // Inject table start.\n currentTable = {\n type: 'table',\n start: Object.assign({}, token.start),\n // Note: correct end is set later.\n end: Object.assign({}, token.end)\n };\n map.add(index, 0, [['enter', currentTable, context]]);\n } else if (token.type === 'tableRow' || token.type === 'tableDelimiterRow') {\n inFirstCellAwaitingPipe = true;\n currentCell = undefined;\n lastCell = [0, 0, 0, 0];\n cell = [0, index + 1, 0, 0];\n\n // Inject table body start.\n if (afterHeadAwaitingFirstBodyRow) {\n afterHeadAwaitingFirstBodyRow = false;\n currentBody = {\n type: 'tableBody',\n start: Object.assign({}, token.start),\n // Note: correct end is set later.\n end: Object.assign({}, token.end)\n };\n map.add(index, 0, [['enter', currentBody, context]]);\n }\n rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1;\n }\n // Cell data.\n else if (rowKind && (token.type === \"data\" || token.type === 'tableDelimiterMarker' || token.type === 'tableDelimiterFiller')) {\n inFirstCellAwaitingPipe = false;\n\n // First value in cell.\n if (cell[2] === 0) {\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, undefined, currentCell);\n lastCell = [0, 0, 0, 0];\n }\n cell[2] = index;\n }\n } else if (token.type === 'tableCellDivider') {\n if (inFirstCellAwaitingPipe) {\n inFirstCellAwaitingPipe = false;\n } else {\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, undefined, currentCell);\n }\n lastCell = cell;\n cell = [lastCell[1], index, 0, 0];\n }\n }\n }\n // Exit events.\n else if (token.type === 'tableHead') {\n afterHeadAwaitingFirstBodyRow = true;\n lastTableEnd = index;\n } else if (token.type === 'tableRow' || token.type === 'tableDelimiterRow') {\n lastTableEnd = index;\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, index, currentCell);\n } else if (cell[1] !== 0) {\n currentCell = flushCell(map, context, cell, rowKind, index, currentCell);\n }\n rowKind = 0;\n } else if (rowKind && (token.type === \"data\" || token.type === 'tableDelimiterMarker' || token.type === 'tableDelimiterFiller')) {\n cell[3] = index;\n }\n }\n if (lastTableEnd !== 0) {\n flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);\n }\n map.consume(context.events);\n\n // To do: move this into `html`, when events are exposed there.\n // That’s what `markdown-rs` does.\n // That needs updates to `mdast-util-gfm-table`.\n index = -1;\n while (++index < context.events.length) {\n const event = context.events[index];\n if (event[0] === 'enter' && event[1].type === 'table') {\n event[1]._align = gfmTableAlign(context.events, index);\n }\n }\n return events;\n}\n\n/**\n * Generate a cell.\n *\n * @param {EditMap} map\n * @param {Readonly<TokenizeContext>} context\n * @param {Readonly<Range>} range\n * @param {RowKind} rowKind\n * @param {number | undefined} rowEnd\n * @param {Token | undefined} previousCell\n * @returns {Token | undefined}\n */\n// eslint-disable-next-line max-params\nfunction flushCell(map, context, range, rowKind, rowEnd, previousCell) {\n // `markdown-rs` uses:\n // rowKind === 2 ? 'tableDelimiterCell' : 'tableCell'\n const groupName = rowKind === 1 ? 'tableHeader' : rowKind === 2 ? 'tableDelimiter' : 'tableData';\n // `markdown-rs` uses:\n // rowKind === 2 ? 'tableDelimiterCellValue' : 'tableCellText'\n const valueName = 'tableContent';\n\n // Insert an exit for the previous cell, if there is one.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- exit\n // ^^^^-- this cell\n // ```\n if (range[0] !== 0) {\n previousCell.end = Object.assign({}, getPoint(context.events, range[0]));\n map.add(range[0], 0, [['exit', previousCell, context]]);\n }\n\n // Insert enter of this cell.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- enter\n // ^^^^-- this cell\n // ```\n const now = getPoint(context.events, range[1]);\n previousCell = {\n type: groupName,\n start: Object.assign({}, now),\n // Note: correct end is set later.\n end: Object.assign({}, now)\n };\n map.add(range[1], 0, [['enter', previousCell, context]]);\n\n // Insert text start at first data start and end at last data end, and\n // remove events between.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- enter\n // ^-- exit\n // ^^^^-- this cell\n // ```\n if (range[2] !== 0) {\n const relatedStart = getPoint(context.events, range[2]);\n const relatedEnd = getPoint(context.events, range[3]);\n /** @type {Token} */\n const valueToken = {\n type: valueName,\n start: Object.assign({}, relatedStart),\n end: Object.assign({}, relatedEnd)\n };\n map.add(range[2], 0, [['enter', valueToken, context]]);\n if (rowKind !== 2) {\n // Fix positional info on remaining events\n const start = context.events[range[2]];\n const end = context.events[range[3]];\n start[1].end = Object.assign({}, end[1].end);\n start[1].type = \"chunkText\";\n start[1].contentType = \"text\";\n\n // Remove if needed.\n if (range[3] > range[2] + 1) {\n const a = range[2] + 1;\n const b = range[3] - range[2] - 1;\n map.add(a, b, []);\n }\n }\n map.add(range[3] + 1, 0, [['exit', valueToken, context]]);\n }\n\n // Insert an exit for the last cell, if at the row end.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- exit\n // ^^^^^^-- this cell (the last one contains two “between” parts)\n // ```\n if (rowEnd !== undefined) {\n previousCell.end = Object.assign({}, getPoint(context.events, rowEnd));\n map.add(rowEnd, 0, [['exit', previousCell, context]]);\n previousCell = undefined;\n }\n return previousCell;\n}\n\n/**\n * Generate table end (and table body end).\n *\n * @param {Readonly<EditMap>} map\n * @param {Readonly<TokenizeContext>} context\n * @param {number} index\n * @param {Token} table\n * @param {Token | undefined} tableBody\n */\n// eslint-disable-next-line max-params\nfunction flushTableEnd(map, context, index, table, tableBody) {\n /** @type {Array<Event>} */\n const exits = [];\n const related = getPoint(context.events, index);\n if (tableBody) {\n tableBody.end = Object.assign({}, related);\n exits.push(['exit', tableBody, context]);\n }\n table.end = Object.assign({}, related);\n exits.push(['exit', table, context]);\n map.add(index + 1, 0, exits);\n}\n\n/**\n * @param {Readonly<Array<Event>>} events\n * @param {number} index\n * @returns {Readonly<Point>}\n */\nfunction getPoint(events, index) {\n const event = events[index];\n const side = event[0] === 'enter' ? 'start' : 'end';\n return event[1][side];\n}","/**\n * @import {Event} from 'micromark-util-types'\n */\n\n// Port of `edit_map.rs` from `markdown-rs`.\n// This should move to `markdown-js` later.\n\n// Deal with several changes in events, batching them together.\n//\n// Preferably, changes should be kept to a minimum.\n// Sometimes, it’s needed to change the list of events, because parsing can be\n// messy, and it helps to expose a cleaner interface of events to the compiler\n// and other users.\n// It can also help to merge many adjacent similar events.\n// And, in other cases, it’s needed to parse subcontent: pass some events\n// through another tokenizer and inject the result.\n\n/**\n * @typedef {[number, number, Array<Event>]} Change\n * @typedef {[number, number, number]} Jump\n */\n\n/**\n * Tracks a bunch of edits.\n */\nexport class EditMap {\n /**\n * Create a new edit map.\n */\n constructor() {\n /**\n * Record of changes.\n *\n * @type {Array<Change>}\n */\n this.map = [];\n }\n\n /**\n * Create an edit: a remove and/or add at a certain place.\n *\n * @param {number} index\n * @param {number} remove\n * @param {Array<Event>} add\n * @returns {undefined}\n */\n add(index, remove, add) {\n addImplementation(this, index, remove, add);\n }\n\n // To do: add this when moving to `micromark`.\n // /**\n // * Create an edit: but insert `add` before existing additions.\n // *\n // * @param {number} index\n // * @param {number} remove\n // * @param {Array<Event>} add\n // * @returns {undefined}\n // */\n // addBefore(index, remove, add) {\n // addImplementation(this, index, remove, add, true)\n // }\n\n /**\n * Done, change the events.\n *\n * @param {Array<Event>} events\n * @returns {undefined}\n */\n consume(events) {\n this.map.sort(function (a, b) {\n return a[0] - b[0];\n });\n\n /* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */\n if (this.map.length === 0) {\n return;\n }\n\n // To do: if links are added in events, like they are in `markdown-rs`,\n // this is needed.\n // // Calculate jumps: where items in the current list move to.\n // /** @type {Array<Jump>} */\n // const jumps = []\n // let index = 0\n // let addAcc = 0\n // let removeAcc = 0\n // while (index < this.map.length) {\n // const [at, remove, add] = this.map[index]\n // removeAcc += remove\n // addAcc += add.length\n // jumps.push([at, removeAcc, addAcc])\n // index += 1\n // }\n //\n // . shiftLinks(events, jumps)\n\n let index = this.map.length;\n /** @type {Array<Array<Event>>} */\n const vecs = [];\n while (index > 0) {\n index -= 1;\n vecs.push(events.slice(this.map[index][0] + this.map[index][1]), this.map[index][2]);\n\n // Truncate rest.\n events.length = this.map[index][0];\n }\n vecs.push(events.slice());\n events.length = 0;\n let slice = vecs.pop();\n while (slice) {\n for (const element of slice) {\n events.push(element);\n }\n slice = vecs.pop();\n }\n\n // Truncate everything.\n this.map.length = 0;\n }\n}\n\n/**\n * Create an edit.\n *\n * @param {EditMap} editMap\n * @param {number} at\n * @param {number} remove\n * @param {Array<Event>} add\n * @returns {undefined}\n */\nfunction addImplementation(editMap, at, remove, add) {\n let index = 0;\n\n /* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */\n if (remove === 0 && add.length === 0) {\n return;\n }\n while (index < editMap.map.length) {\n if (editMap.map[index][0] === at) {\n editMap.map[index][1] += remove;\n\n // To do: before not used by tables, use when moving to micromark.\n // if (before) {\n // add.push(...editMap.map[index][2])\n // editMap.map[index][2] = add\n // } else {\n editMap.map[index][2].push(...add);\n // }\n\n return;\n }\n index += 1;\n }\n editMap.map.push([at, remove, add]);\n}\n\n// /**\n// * Shift `previous` and `next` links according to `jumps`.\n// *\n// * This fixes links in case there are events removed or added between them.\n// *\n// * @param {Array<Event>} events\n// * @param {Array<Jump>} jumps\n// */\n// function shiftLinks(events, jumps) {\n// let jumpIndex = 0\n// let index = 0\n// let add = 0\n// let rm = 0\n\n// while (index < events.length) {\n// const rmCurr = rm\n\n// while (jumpIndex < jumps.length && jumps[jumpIndex][0] <= index) {\n// add = jumps[jumpIndex][2]\n// rm = jumps[jumpIndex][1]\n// jumpIndex += 1\n// }\n\n// // Ignore items that will be removed.\n// if (rm > rmCurr) {\n// index += rm - rmCurr\n// } else {\n// // ?\n// // if let Some(link) = &events[index].link {\n// // if let Some(next) = link.next {\n// // events[next].link.as_mut().unwrap().previous = Some(index + add - rm);\n// // while jumpIndex < jumps.len() && jumps[jumpIndex].0 <= next {\n// // add = jumps[jumpIndex].2;\n// // rm = jumps[jumpIndex].1;\n// // jumpIndex += 1;\n// // }\n// // events[index].link.as_mut().unwrap().next = Some(next + add - rm);\n// // index = next;\n// // continue;\n// // }\n// // }\n// index += 1\n// }\n// }\n// }","/**\n * @import {Event} from 'micromark-util-types'\n */\n\n/**\n * @typedef {'center' | 'left' | 'none' | 'right'} Align\n */\n\n/**\n * Figure out the alignment of a GFM table.\n *\n * @param {Readonly<Array<Event>>} events\n * List of events.\n * @param {number} index\n * Table enter event.\n * @returns {Array<Align>}\n * List of aligns.\n */\nexport function gfmTableAlign(events, index) {\n let inDelimiterRow = false;\n /** @type {Array<Align>} */\n const align = [];\n while (index < events.length) {\n const event = events[index];\n if (inDelimiterRow) {\n if (event[0] === 'enter') {\n // Start of alignment value: set a new column.\n // To do: `markdown-rs` uses `tableDelimiterCellValue`.\n if (event[1].type === 'tableContent') {\n align.push(events[index + 1][1].type === 'tableDelimiterMarker' ? 'left' : 'none');\n }\n }\n // Exits:\n // End of alignment value: change the column.\n // To do: `markdown-rs` uses `tableDelimiterCellValue`.\n else if (event[1].type === 'tableContent') {\n if (events[index - 1][1].type === 'tableDelimiterMarker') {\n const alignIndex = align.length - 1;\n align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right';\n }\n }\n // Done!\n else if (event[1].type === 'tableDelimiterRow') {\n break;\n }\n } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') {\n inDelimiterRow = true;\n }\n index += 1;\n }\n return align;\n}","/**\n * @import {Extension, State, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace } from 'micromark-util-character';\nconst tasklistCheck = {\n name: 'tasklistCheck',\n tokenize: tokenizeTasklistCheck\n};\n\n/**\n * Create an HTML extension for `micromark` to support GFM task list items\n * syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `htmlExtensions` to\n * support GFM task list items when serializing to HTML.\n */\nexport function gfmTaskListItem() {\n return {\n text: {\n [91]: tasklistCheck\n }\n };\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeTasklistCheck(effects, ok, nok) {\n const self = this;\n return open;\n\n /**\n * At start of task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (\n // Exit if there’s stuff before.\n self.previous !== null ||\n // Exit if not in the first content that is the first child of a list\n // item.\n !self._gfmTasklistFirstContentOfListItem) {\n return nok(code);\n }\n effects.enter('taskListCheck');\n effects.enter('taskListCheckMarker');\n effects.consume(code);\n effects.exit('taskListCheckMarker');\n return inside;\n }\n\n /**\n * In task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n // Currently we match how GH works in files.\n // To match how GH works in comments, use `markdownSpace` (`[\\t ]`) instead\n // of `markdownLineEndingOrSpace` (`[\\t\\n\\r ]`).\n if (markdownLineEndingOrSpace(code)) {\n effects.enter('taskListCheckValueUnchecked');\n effects.consume(code);\n effects.exit('taskListCheckValueUnchecked');\n return close;\n }\n if (code === 88 || code === 120) {\n effects.enter('taskListCheckValueChecked');\n effects.consume(code);\n effects.exit('taskListCheckValueChecked');\n return close;\n }\n return nok(code);\n }\n\n /**\n * At close of task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function close(code) {\n if (code === 93) {\n effects.enter('taskListCheckMarker');\n effects.consume(code);\n effects.exit('taskListCheckMarker');\n effects.exit('taskListCheck');\n return after;\n }\n return nok(code);\n }\n\n /**\n * @type {State}\n */\n function after(code) {\n // EOL in paragraph means there must be something else after it.\n if (markdownLineEnding(code)) {\n return ok(code);\n }\n\n // Space or tab?\n // Check what comes after.\n if (markdownSpace(code)) {\n return effects.check({\n tokenize: spaceThenNonSpace\n }, ok, nok)(code);\n }\n\n // EOF, or non-whitespace, both wrong.\n return nok(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction spaceThenNonSpace(effects, ok, nok) {\n return factorySpace(effects, after, \"whitespace\");\n\n /**\n * After whitespace, after task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n // EOF means there was nothing, so bad.\n // EOL means there’s content after it, so good.\n // Impossible to have more spaces.\n // Anything else is good.\n return code === null ? nok(code) : ok(code);\n }\n}","/**\n * mdast transform plugin for Jinja if/elif/else/endif blocks.\n *\n * Three passes:\n * Pass 1 — Extract Jinja tags absorbed into list item text (Case B)\n * Pass 2 — Group standalone Jinja-tag paragraphs into jinjaIfBlockMdast nodes (Case A)\n * Pass 3 — Structure inline Jinja tags into jinjaIfInlineMdast nodes\n */\n\nconst MAX_DEPTH = 128;\n\n// Regex for a standalone Jinja tag paragraph (entire paragraph is one tag)\nconst JINJA_BLOCK_RE = /^\\s*\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}\\s*$/;\n\n// Regex for Jinja tags at line boundaries inside list item text\nconst JINJA_LINE_END_RE = /\\n\\s*(\\{%\\s*(?:if|elif|else|endif)\\s*[^%]*?\\s*%\\})\\s*$/;\nconst JINJA_LINE_START_RE = /^(\\{%\\s*(?:if|elif|else|endif)\\s*[^%]*?\\s*%\\})\\s*\\n/;\n\n// Regex for inline Jinja tags (non-greedy, captures tag type and condition)\nconst JINJA_INLINE_RE = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\ntype BranchType = 'if' | 'elif' | 'else';\n\nexport interface JinjaBranchMdast {\n branchType: BranchType;\n condition?: string;\n content: unknown[];\n}\n\nexport interface JinjaIfBlockMdastNode {\n type: 'jinjaIfBlockMdast';\n branches: JinjaBranchMdast[];\n}\n\nexport interface JinjaIfInlineMdastNode {\n type: 'jinjaIfInlineMdast';\n branches: JinjaBranchMdast[];\n}\n\ndeclare module 'mdast' {\n interface BlockContentMap {\n jinjaIfBlockMdast: JinjaIfBlockMdastNode;\n }\n interface PhrasingContentMap {\n jinjaIfInlineMdast: JinjaIfInlineMdastNode;\n }\n interface RootContentMap {\n jinjaIfBlockMdast: JinjaIfBlockMdastNode;\n }\n}\n\nfunction parseTag(text: string): { type: 'if' | 'elif' | 'else' | 'endif'; condition?: string } | null {\n const m = text.match(/^\\s*\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}\\s*$/);\n if (!m) return null;\n const type = m[1] as 'if' | 'elif' | 'else' | 'endif';\n const condition = m[2]?.trim() || undefined;\n return { type, condition };\n}\n\nfunction isTextOnlyParagraph(node: { type: string; children?: unknown[] }): string | null {\n if (node.type !== 'paragraph') return null;\n if (!node.children || node.children.length !== 1) return null;\n const child = node.children[0] as { type: string; value?: string };\n if (child.type !== 'text') return null;\n return child.value ?? null;\n}\n\n/**\n * Pass 1: Extract Jinja tags absorbed into list item text.\n * When there's no blank line between a Jinja tag and a list, mdast absorbs\n * the tag into the list item's text. We split these out.\n */\nfunction pass1ExtractFromLists(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse first\n for (const child of node.children) {\n pass1ExtractFromLists(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process list nodes\n if (node.type !== 'list') return;\n\n const list = node as { type: string; ordered?: boolean; start?: number; spread?: boolean; children: unknown[] };\n const items = list.children as Array<{ type: string; children: Array<{ type: string; children?: Array<{ type: string; value?: string }> }> }>;\n\n // Scan list items for Jinja tags at text boundaries\n type ExtractedPiece =\n | { kind: 'item'; item: unknown }\n | { kind: 'tag'; raw: string };\n\n const extracted: ExtractedPiece[] = [];\n let hadSplit = false;\n\n for (const item of items) {\n if (item.type !== 'listItem' || !item.children || item.children.length === 0) {\n extracted.push({ kind: 'item', item });\n continue;\n }\n\n // Check first paragraph for leading Jinja tag\n const firstChild = item.children[0];\n if (firstChild.type === 'paragraph' && firstChild.children && firstChild.children.length === 1 && firstChild.children[0].type === 'text') {\n const text = firstChild.children[0].value ?? '';\n const startMatch = text.match(JINJA_LINE_START_RE);\n if (startMatch) {\n hadSplit = true;\n extracted.push({ kind: 'tag', raw: startMatch[1] });\n const remainder = text.slice(startMatch[0].length);\n if (remainder.trim()) {\n firstChild.children[0] = { ...firstChild.children[0], value: remainder };\n extracted.push({ kind: 'item', item });\n } else if (item.children.length > 1) {\n item.children = item.children.slice(1);\n extracted.push({ kind: 'item', item });\n }\n continue;\n }\n }\n\n // Check last paragraph for trailing Jinja tag\n const lastChild = item.children[item.children.length - 1];\n if (lastChild.type === 'paragraph' && lastChild.children && lastChild.children.length === 1 && lastChild.children[0].type === 'text') {\n const text = lastChild.children[0].value ?? '';\n const endMatch = text.match(JINJA_LINE_END_RE);\n if (endMatch) {\n hadSplit = true;\n const remainder = text.slice(0, text.length - endMatch[0].length);\n if (remainder.trim()) {\n lastChild.children[0] = { ...lastChild.children[0], value: remainder };\n extracted.push({ kind: 'item', item });\n } else if (item.children.length > 1) {\n item.children = item.children.slice(0, -1);\n extracted.push({ kind: 'item', item });\n }\n extracted.push({ kind: 'tag', raw: endMatch[1] });\n continue;\n }\n }\n\n extracted.push({ kind: 'item', item });\n }\n\n if (!hadSplit) return;\n\n // Rebuild: replace parent's list node with a sequence of lists and tag paragraphs\n // We need to modify the parent's children. Since we're in the list node itself,\n // we'll reconstruct the list into segments.\n const parent = node as { type: string; children: unknown[] };\n\n // Actually, we need to replace this list node in its parent.\n // Instead, we mark the list with a special property to be expanded later.\n // Let's use a different approach: collect consecutive items into sub-lists,\n // interleaved with tag paragraphs.\n\n const result: unknown[] = [];\n let currentItems: unknown[] = [];\n let itemIndex = 0;\n\n function flushItems(): void {\n if (currentItems.length === 0) return;\n const startNum = list.ordered ? (list.start ?? 1) + itemIndex - currentItems.length : undefined;\n const subList = {\n type: 'list',\n ordered: list.ordered ?? false,\n spread: list.spread ?? false,\n ...(list.ordered ? { start: startNum } : {}),\n children: currentItems,\n };\n result.push(subList);\n currentItems = [];\n }\n\n for (const piece of extracted) {\n if (piece.kind === 'item') {\n currentItems.push(piece.item);\n itemIndex++;\n } else {\n flushItems();\n result.push({\n type: 'paragraph',\n children: [{ type: 'text', value: piece.raw }],\n });\n }\n }\n flushItems();\n\n // Mark this node for expansion in parent\n (node as { _jinjaExpanded?: unknown[] })._jinjaExpanded = result;\n}\n\n/**\n * After pass1, expand any list nodes that were marked with _jinjaExpanded.\n */\nfunction expandMarkedLists(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Process children first (bottom-up)\n for (const child of node.children) {\n expandMarkedLists(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n const newChildren: unknown[] = [];\n let changed = false;\n for (const child of node.children) {\n const c = child as { _jinjaExpanded?: unknown[] };\n if (c._jinjaExpanded) {\n newChildren.push(...c._jinjaExpanded);\n changed = true;\n } else {\n newChildren.push(child);\n }\n }\n if (changed) {\n node.children = newChildren;\n }\n}\n\n/**\n * Pass 2: Group standalone Jinja-tag paragraphs into jinjaIfBlockMdast nodes.\n * Works on children of root, blockquote, and listItem.\n */\nfunction pass2GroupBlocks(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse into children first\n for (const child of node.children) {\n pass2GroupBlocks(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process container nodes\n const containerTypes = new Set(['root', 'blockquote', 'listItem']);\n if (!containerTypes.has(node.type)) return;\n\n const children = node.children as Array<{ type: string; children?: unknown[] }>;\n const result: unknown[] = [];\n let i = 0;\n\n while (i < children.length) {\n const child = children[i];\n const text = isTextOnlyParagraph(child);\n const tag = text ? parseTag(text) : null;\n\n if (!tag || tag.type !== 'if') {\n result.push(child);\n i++;\n continue;\n }\n\n // Found {% if %} - use stack to find matching {% endif %}\n const ifParagraph = child; // save for position\n const branches: JinjaBranchMdast[] = [];\n let currentBranch: JinjaBranchMdast = {\n branchType: 'if',\n condition: tag.condition,\n content: [],\n };\n branches.push(currentBranch);\n\n let nestDepth = 1;\n i++; // skip the {% if %} paragraph\n\n let matched = false;\n let endifParagraph: { type: string; children?: unknown[]; position?: unknown } | null = null;\n while (i < children.length && nestDepth > 0) {\n const innerChild = children[i];\n const innerText = isTextOnlyParagraph(innerChild);\n const innerTag = innerText ? parseTag(innerText) : null;\n\n if (innerTag) {\n if (innerTag.type === 'if') {\n nestDepth++;\n if (nestDepth > 1) {\n currentBranch.content.push(innerChild);\n }\n } else if (innerTag.type === 'endif') {\n nestDepth--;\n if (nestDepth === 0) {\n matched = true;\n endifParagraph = innerChild;\n } else {\n currentBranch.content.push(innerChild);\n }\n } else if ((innerTag.type === 'elif' || innerTag.type === 'else') && nestDepth === 1) {\n currentBranch = {\n branchType: innerTag.type as BranchType,\n ...(innerTag.condition ? { condition: innerTag.condition } : {}),\n content: [],\n };\n branches.push(currentBranch);\n } else {\n currentBranch.content.push(innerChild);\n }\n } else {\n currentBranch.content.push(innerChild);\n }\n i++;\n }\n\n if (matched) {\n // Recursively process branch contents\n for (const branch of branches) {\n const wrapper = { type: node.type, children: branch.content };\n pass2GroupBlocks(wrapper, depth + 1);\n branch.content = wrapper.children as unknown[];\n }\n // Propagate position from {% if %} to {% endif %} for blank-line calculation\n const startPos = (ifParagraph as { position?: { start?: unknown } }).position?.start;\n const endPos = (endifParagraph as { position?: { end?: unknown } } | null)?.position?.end;\n const pos = startPos && endPos ? { position: { start: startPos, end: endPos } } : {};\n result.push({ type: 'jinjaIfBlockMdast', branches, ...pos });\n } else {\n // Unmatched {% if %} — restore as plain paragraph\n result.push({ type: 'paragraph', children: [{ type: 'text', value: text }] });\n // Rewind: the content we consumed needs to go back\n // Actually, we already advanced i, and the branches contain the consumed children.\n // We need to flatten them back.\n for (const branch of branches) {\n if (branch !== branches[0]) {\n // Re-emit the branch tag\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', children: [{ type: 'text', value: tagText }] });\n }\n result.push(...branch.content);\n }\n }\n }\n\n node.children = result;\n}\n\n/**\n * Pass 3: Structure inline Jinja tags within paragraph/heading text nodes.\n * Only processes direct text children (not inside marks like strong/emphasis).\n */\nfunction pass3InlineJinja(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse into block-level children\n for (const child of node.children) {\n pass3InlineJinja(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process paragraph and heading\n if (node.type !== 'paragraph' && node.type !== 'heading') return;\n\n const children = node.children as Array<{ type: string; value?: string }>;\n\n // Check if any text child contains Jinja tags\n let hasJinja = false;\n for (const child of children) {\n if (child.type === 'text' && child.value) {\n JINJA_INLINE_RE.lastIndex = 0;\n if (JINJA_INLINE_RE.test(child.value)) {\n hasJinja = true;\n break;\n }\n }\n }\n if (!hasJinja) return;\n\n // Split text nodes on Jinja tags, then structure with stack\n const flatParts: Array<{ kind: 'node'; node: unknown } | { kind: 'tag'; tagType: 'if' | 'elif' | 'else' | 'endif'; condition?: string }> = [];\n\n for (const child of children) {\n if (child.type !== 'text' || !child.value) {\n flatParts.push({ kind: 'node', node: child });\n continue;\n }\n\n const text = child.value;\n JINJA_INLINE_RE.lastIndex = 0;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = JINJA_INLINE_RE.exec(text)) !== null) {\n if (match.index > lastIndex) {\n flatParts.push({ kind: 'node', node: { type: 'text', value: text.slice(lastIndex, match.index) } });\n }\n flatParts.push({\n kind: 'tag',\n tagType: match[1] as 'if' | 'elif' | 'else' | 'endif',\n condition: match[2]?.trim() || undefined,\n });\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n flatParts.push({ kind: 'node', node: { type: 'text', value: text.slice(lastIndex) } });\n }\n }\n\n // Stack-based structuring\n const result = structureInlineParts(flatParts);\n if (result) {\n node.children = result;\n }\n}\n\nfunction structureInlineParts(\n parts: Array<{ kind: 'node'; node: unknown } | { kind: 'tag'; tagType: 'if' | 'elif' | 'else' | 'endif'; condition?: string }>,\n): unknown[] | null {\n const output: unknown[] = [];\n let i = 0;\n\n while (i < parts.length) {\n const part = parts[i];\n if (part.kind === 'node') {\n output.push(part.node);\n i++;\n } else if (part.kind === 'tag' && part.tagType === 'if') {\n // Collect branches until matching endif\n const branches: JinjaBranchMdast[] = [];\n let currentBranch: JinjaBranchMdast = {\n branchType: 'if',\n condition: part.condition,\n content: [],\n };\n branches.push(currentBranch);\n i++;\n\n let nestDepth = 1;\n let matched = false;\n\n while (i < parts.length && nestDepth > 0) {\n const inner = parts[i];\n if (inner.kind === 'tag') {\n if (inner.tagType === 'if') {\n nestDepth++;\n if (nestDepth > 1) {\n // Nested if — emit as text for now\n currentBranch.content.push({ type: 'text', value: `{% if ${inner.condition ?? ''} %}`.trim() });\n }\n } else if (inner.tagType === 'endif') {\n nestDepth--;\n if (nestDepth === 0) {\n matched = true;\n } else {\n currentBranch.content.push({ type: 'text', value: '{% endif %}' });\n }\n } else if ((inner.tagType === 'elif' || inner.tagType === 'else') && nestDepth === 1) {\n currentBranch = {\n branchType: inner.tagType as BranchType,\n ...(inner.condition ? { condition: inner.condition } : {}),\n content: [],\n };\n branches.push(currentBranch);\n } else {\n // Nested elif/else\n const tagText = inner.tagType === 'else'\n ? '{% else %}'\n : `{% ${inner.tagType} ${inner.condition ?? ''} %}`.trim();\n currentBranch.content.push({ type: 'text', value: tagText });\n }\n } else {\n currentBranch.content.push(inner.node);\n }\n i++;\n }\n\n if (matched) {\n output.push({ type: 'jinjaIfInlineMdast', branches });\n } else {\n // Unmatched — restore as text\n output.push({ type: 'text', value: `{% if ${branches[0].condition ?? ''} %}`.trim() });\n for (const branch of branches) {\n if (branch !== branches[0]) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n output.push({ type: 'text', value: tagText });\n }\n output.push(...branch.content);\n }\n }\n } else {\n // Stray elif/else/endif — keep as text\n const p = part as { tagType: string; condition?: string };\n const tagText = p.tagType === 'else'\n ? '{% else %}'\n : p.tagType === 'endif'\n ? '{% endif %}'\n : `{% ${p.tagType} ${p.condition ?? ''} %}`.trim();\n output.push({ type: 'text', value: tagText });\n i++;\n }\n }\n\n return output;\n}\n\n/**\n * Main transform: apply all three passes to an mdast tree.\n */\nexport function jinjaBlockTransform(tree: { type: string; children?: unknown[] }): void {\n // Pass 1: Extract Jinja tags from list item text\n pass1ExtractFromLists(tree, 0);\n expandMarkedLists(tree, 0);\n\n // Pass 2: Group block-level Jinja structures\n pass2GroupBlocks(tree, 0);\n\n // Pass 3: Structure inline Jinja\n pass3InlineJinja(tree, 0);\n}\n","import { parseMarkdown } from './parser';\nimport { serializeToMarkdown } from './serializer';\nimport type { AstNode, BlockNode, InlineNode, DocumentNode } from '../ast/types';\n\n/**\n * Serialize a list of AST nodes to markdown string (for clipboard).\n */\nexport function serializeFragment(nodes: AstNode[]): string {\n if (nodes.length === 0) return '';\n\n // Wrap in a doc for serialization\n const blocks: BlockNode[] = nodes.map((node) => {\n if (node.type === 'text' || node.type === 'resourceTag' || node.type === 'jumpPoint' || node.type === 'hardBreak') {\n return { type: 'paragraph', content: [node] };\n }\n if (node.type === 'doc') {\n // Flatten doc children\n return node.content;\n }\n return node as BlockNode;\n }).flat() as BlockNode[];\n\n const wrapper: DocumentNode = { type: 'doc', content: blocks };\n return serializeToMarkdown(wrapper);\n}\n\n/**\n * Parse a markdown string into a fragment (for clipboard paste).\n * Returns block nodes by default; if the markdown is a single paragraph,\n * returns its inline children.\n */\nexport function parseFragment(markdown: string): InlineNode[] | BlockNode[] {\n const doc = parseMarkdown(markdown);\n\n // If single paragraph, return inline content\n if (doc.content.length === 1 && doc.content[0].type === 'paragraph') {\n return doc.content[0].content as InlineNode[];\n }\n\n return doc.content as BlockNode[];\n}\n","/**\n * Pure text-based Jinja block scanner (no ProseMirror dependency).\n */\nimport type { JinjaBlock } from './types';\n\nconst JINJA_PATTERN = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\n/**\n * Scan all Jinja blocks from plain text.\n *\n * @param text - Plain text content\n * @returns All Jinja blocks sorted by position\n */\nexport function scanJinjaBlocks(text: string): JinjaBlock[] {\n const blocks: JinjaBlock[] = [];\n\n JINJA_PATTERN.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = JINJA_PATTERN.exec(text)) !== null) {\n const type = match[1] as JinjaBlock['type'];\n const conditionRaw = match[2].trim();\n const condition = type === 'if' || type === 'elif' ? conditionRaw : undefined;\n\n // Include trailing spaces after tag\n let endIndex = match.index + match[0].length;\n while (endIndex < text.length && text[endIndex] === ' ') {\n endIndex++;\n }\n\n blocks.push({\n type,\n condition,\n startIndex: match.index,\n endIndex,\n raw: match[0],\n });\n }\n\n return blocks.sort((a, b) => a.startIndex - b.startIndex);\n}\n","import type { JinjaBlock, JinjaIfStructure } from './types';\n\nfunction buildStructure(\n partial: { ifBlock: JinjaBlock; elifBlocks: JinjaBlock[]; elseBlock?: JinjaBlock },\n endifBlock: JinjaBlock,\n): JinjaIfStructure {\n const { ifBlock, elifBlocks, elseBlock } = partial;\n const contentRanges: JinjaIfStructure['contentRanges'] = [];\n\n // if branch content\n const ifContentEnd = elifBlocks[0]?.startIndex ?? elseBlock?.startIndex ?? endifBlock.startIndex;\n contentRanges.push({\n type: 'if',\n condition: ifBlock.condition!,\n startIndex: ifBlock.endIndex,\n endIndex: ifContentEnd,\n });\n\n // elif branches\n elifBlocks.forEach((elifBlock, idx) => {\n const nextBlock = elifBlocks[idx + 1] ?? elseBlock ?? endifBlock;\n contentRanges.push({\n type: 'elif',\n condition: elifBlock.condition!,\n startIndex: elifBlock.endIndex,\n endIndex: nextBlock.startIndex,\n });\n });\n\n // else branch\n if (elseBlock) {\n contentRanges.push({\n type: 'else',\n startIndex: elseBlock.endIndex,\n endIndex: endifBlock.startIndex,\n });\n }\n\n return {\n id: `jinja-${ifBlock.startIndex}-${endifBlock.endIndex}`,\n ifBlock,\n elifBlocks,\n elseBlock,\n endifBlock,\n contentRanges,\n };\n}\n\n/**\n * Structure scanned blocks into if~endif structures using stack-based approach.\n */\nexport function structureJinjaBlocks(blocks: JinjaBlock[]): JinjaIfStructure[] {\n const structures: JinjaIfStructure[] = [];\n const stack: Array<{\n ifBlock: JinjaBlock;\n elifBlocks: JinjaBlock[];\n elseBlock?: JinjaBlock;\n }> = [];\n\n for (const block of blocks) {\n switch (block.type) {\n case 'if':\n stack.push({ ifBlock: block, elifBlocks: [] });\n break;\n case 'elif':\n if (stack.length > 0) {\n stack[stack.length - 1].elifBlocks.push(block);\n }\n break;\n case 'else':\n if (stack.length > 0) {\n stack[stack.length - 1].elseBlock = block;\n }\n break;\n case 'endif': {\n const current = stack.pop();\n if (current) {\n structures.push(buildStructure(current, block));\n }\n break;\n }\n }\n }\n\n return structures;\n}\n","import type { DocumentNode } from '../ast/types';\nimport { textContent } from '../ast/traverse';\nimport { scanJinjaBlocks } from './scanner';\nimport { structureJinjaBlocks } from './structurer';\n\nexport interface JinjaVisualBranch {\n type: 'if' | 'elif' | 'else';\n condition?: string;\n blockStartIndex: number;\n blockEndIndex: number;\n tagBlockIndex: number;\n}\n\nexport interface JinjaVisualStructure {\n id: string;\n branches: JinjaVisualBranch[];\n ifTagBlockIndex: number;\n endifTagBlockIndex: number;\n}\n\n/**\n * Single pass: builds cumulative block-end offsets AND the full document text.\n * offsets[i] = exclusive end char index of block i.\n * Avoids calling textContent() twice (once for offsets, once for fullText).\n */\nfunction buildOffsetsAndText(doc: DocumentNode): { offsets: number[]; fullText: string } {\n const offsets: number[] = [];\n const parts: string[] = [];\n let cursor = 0;\n for (const block of doc.content) {\n const t = textContent(block);\n parts.push(t);\n cursor += t.length;\n offsets.push(cursor);\n }\n return { offsets, fullText: parts.join('') };\n}\n\n/**\n * Binary search: returns the block index that contains charIndex.\n * offsets[i] is the exclusive end of block i.\n */\nfunction charIndexToBlockIndex(offsets: number[], charIndex: number): number {\n if (offsets.length === 0) return 0;\n let lo = 0;\n let hi = offsets.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (offsets[mid] <= charIndex) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/**\n * Analyze a DocumentNode for Jinja if/elif/else/endif structures\n * and map them to block-level indices.\n */\nexport function analyzeJinjaBlocks(doc: DocumentNode): JinjaVisualStructure[] {\n if (doc.content.length === 0) return [];\n\n const { offsets, fullText } = buildOffsetsAndText(doc);\n\n const scanned = scanJinjaBlocks(fullText);\n if (scanned.length === 0) return [];\n\n const structures = structureJinjaBlocks(scanned);\n\n return structures.map((structure) => {\n const ifTagBlockIdx = charIndexToBlockIndex(offsets, structure.ifBlock.startIndex);\n const endifTagBlockIdx = charIndexToBlockIndex(offsets, structure.endifBlock.startIndex);\n\n const branches: JinjaVisualBranch[] = structure.contentRanges.map((range) => {\n // Find the tag block index for this branch\n let tagCharIndex: number;\n if (range.type === 'if') {\n tagCharIndex = structure.ifBlock.startIndex;\n } else if (range.type === 'elif') {\n const elifBlock = structure.elifBlocks.find((b) => b.condition === range.condition);\n tagCharIndex = elifBlock ? elifBlock.startIndex : range.startIndex;\n } else {\n tagCharIndex = structure.elseBlock!.startIndex;\n }\n\n const tagBlockIdx = charIndexToBlockIndex(offsets, tagCharIndex);\n\n // Content block range: from the block containing the content start\n // to the block containing the content end (exclusive)\n let contentStartBlock: number;\n let contentEndBlock: number;\n\n if (range.startIndex >= range.endIndex) {\n // Empty content range\n contentStartBlock = tagBlockIdx;\n contentEndBlock = tagBlockIdx;\n } else {\n contentStartBlock = charIndexToBlockIndex(offsets, range.startIndex);\n // If the content starts in the same block as the tag, the actual content blocks start after\n // But we keep the start as-is since the tag and content may share a block\n const lastContentChar = range.endIndex - 1;\n contentEndBlock = charIndexToBlockIndex(offsets, lastContentChar) + 1;\n }\n\n return {\n type: range.type,\n condition: range.condition,\n blockStartIndex: contentStartBlock,\n blockEndIndex: contentEndBlock,\n tagBlockIndex: tagBlockIdx,\n };\n });\n\n return {\n id: structure.id,\n branches,\n ifTagBlockIndex: ifTagBlockIdx,\n endifTagBlockIndex: endifTagBlockIdx,\n };\n });\n}\n","/**\n * Safe Jinja condition evaluator using recursive descent parsing.\n *\n * Supports:\n * Comparison: ==, !=, <, >, <=, >=\n * Logical: and, or, not\n * Identity: is, is not\n * Membership: in (value in identifier)\n * Literals: strings, numbers, booleans (True/False/true/false), None/null\n * Variables: dot-notation identifiers (e.g. context.planName)\n * Grouping: parentheses\n *\n * NO arbitrary code execution — only whitelisted operators and literal types.\n */\nimport type { VariableValue } from './types';\n\n// ── Tokenizer ──────────────────────────────────────────────────────\n\ntype TokenType =\n | 'STRING'\n | 'NUMBER'\n | 'BOOL'\n | 'NONE'\n | 'IDENT'\n | 'AND'\n | 'OR'\n | 'NOT'\n | 'IN'\n | 'IS'\n | 'EQ'\n | 'NEQ'\n | 'LT'\n | 'GT'\n | 'LTE'\n | 'GTE'\n | 'LPAREN'\n | 'RPAREN'\n | 'EOF';\n\ninterface Token {\n type: TokenType;\n value: string;\n}\n\nconst KEYWORDS: Record<string, TokenType> = {\n and: 'AND',\n or: 'OR',\n not: 'NOT',\n in: 'IN',\n is: 'IS',\n True: 'BOOL',\n False: 'BOOL',\n true: 'BOOL',\n false: 'BOOL',\n None: 'NONE',\n null: 'NONE',\n};\n\ninterface TokenizeResult {\n readonly tokens: Token[];\n readonly error?: string;\n}\n\nfunction tokenize(input: string): TokenizeResult {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < input.length) {\n // Skip whitespace\n if (/\\s/.test(input[i])) {\n i++;\n continue;\n }\n\n // String literals (single or double quoted)\n if (input[i] === '\"' || input[i] === \"'\") {\n const quote = input[i];\n let str = '';\n i++; // skip opening quote\n while (i < input.length && input[i] !== quote) {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n str += input[i + 1];\n i += 2;\n } else {\n str += input[i];\n i++;\n }\n }\n if (i >= input.length) return { tokens: [], error: 'Unterminated string literal' };\n i++; // skip closing quote\n tokens.push({ type: 'STRING', value: str });\n continue;\n }\n\n // Numbers (integer and float)\n if (/[0-9]/.test(input[i]) || (input[i] === '-' && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && (tokens.length === 0 || ['AND', 'OR', 'NOT', 'EQ', 'NEQ', 'LT', 'GT', 'LTE', 'GTE', 'LPAREN', 'IN', 'IS'].includes(tokens[tokens.length - 1].type)))) {\n let num = '';\n if (input[i] === '-') {\n num = '-';\n i++;\n }\n while (i < input.length && /[0-9]/.test(input[i])) {\n num += input[i];\n i++;\n }\n if (i < input.length && input[i] === '.') {\n num += '.';\n i++;\n while (i < input.length && /[0-9]/.test(input[i])) {\n num += input[i];\n i++;\n }\n }\n tokens.push({ type: 'NUMBER', value: num });\n continue;\n }\n\n // Identifiers and keywords\n if (/[a-zA-Z_]/.test(input[i])) {\n let ident = '';\n while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {\n ident += input[i];\n i++;\n }\n const kwType = KEYWORDS[ident];\n if (kwType) {\n tokens.push({ type: kwType, value: ident });\n } else {\n tokens.push({ type: 'IDENT', value: ident });\n }\n continue;\n }\n\n // Two-character operators\n if (i + 1 < input.length) {\n const two = input[i] + input[i + 1];\n if (two === '==') { tokens.push({ type: 'EQ', value: '==' }); i += 2; continue; }\n if (two === '!=') { tokens.push({ type: 'NEQ', value: '!=' }); i += 2; continue; }\n if (two === '<=') { tokens.push({ type: 'LTE', value: '<=' }); i += 2; continue; }\n if (two === '>=') { tokens.push({ type: 'GTE', value: '>=' }); i += 2; continue; }\n }\n\n // Single-character operators\n if (input[i] === '<') { tokens.push({ type: 'LT', value: '<' }); i++; continue; }\n if (input[i] === '>') { tokens.push({ type: 'GT', value: '>' }); i++; continue; }\n if (input[i] === '(') { tokens.push({ type: 'LPAREN', value: '(' }); i++; continue; }\n if (input[i] === ')') { tokens.push({ type: 'RPAREN', value: ')' }); i++; continue; }\n\n // Unknown character → fail\n return { tokens: [], error: `Unexpected character: ${input[i]}` };\n }\n\n tokens.push({ type: 'EOF', value: '' });\n return { tokens };\n}\n\n// ── Evaluated value ────────────────────────────────────────────────\n\ntype Value = string | number | boolean | null | Value[];\n\n// ── Recursive descent parser + evaluator ───────────────────────────\n\nclass Parser {\n private pos = 0;\n private readonly tokens: Token[];\n private readonly variables: Map<string, VariableValue>;\n\n constructor(tokens: Token[], variables: Map<string, VariableValue>) {\n this.tokens = tokens;\n this.variables = variables;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: 'EOF', value: '' };\n }\n\n private advance(): Token {\n const t = this.tokens[this.pos];\n this.pos++;\n return t;\n }\n\n private expect(type: TokenType): Token {\n const t = this.peek();\n if (t.type !== type) {\n throw new Error(`Expected ${type}, got ${t.type}`);\n }\n return this.advance();\n }\n\n // Grammar (precedence low→high):\n // expr → or_expr\n // or_expr → and_expr ('or' and_expr)*\n // and_expr → not_expr ('and' not_expr)*\n // not_expr → 'not' not_expr | cmp_expr\n // cmp_expr → primary (('=='|'!='|'<'|'>'|'<='|'>='|'in'|'is'|'is not') primary)?\n // primary → STRING | NUMBER | BOOL | NONE | IDENT | '(' expr ')'\n\n evaluate(): Value {\n const result = this.orExpr();\n if (this.peek().type !== 'EOF') {\n throw new Error(`Unexpected token: ${this.peek().value}`);\n }\n return result;\n }\n\n private orExpr(): Value {\n let left = this.andExpr();\n while (this.peek().type === 'OR') {\n this.advance();\n const right = this.andExpr();\n left = isTruthy(left) || isTruthy(right);\n }\n return left;\n }\n\n private andExpr(): Value {\n let left = this.notExpr();\n while (this.peek().type === 'AND') {\n this.advance();\n const right = this.notExpr();\n left = isTruthy(left) && isTruthy(right);\n }\n return left;\n }\n\n private notExpr(): Value {\n if (this.peek().type === 'NOT') {\n this.advance();\n const val = this.notExpr();\n return !isTruthy(val);\n }\n return this.cmpExpr();\n }\n\n private cmpExpr(): Value {\n const left = this.primary();\n const op = this.peek().type;\n\n switch (op) {\n case 'EQ':\n this.advance();\n return looseEqual(left, this.primary());\n case 'NEQ':\n this.advance();\n return !looseEqual(left, this.primary());\n case 'LT':\n this.advance();\n return toNumber(left) < toNumber(this.primary());\n case 'GT':\n this.advance();\n return toNumber(left) > toNumber(this.primary());\n case 'LTE':\n this.advance();\n return toNumber(left) <= toNumber(this.primary());\n case 'GTE':\n this.advance();\n return toNumber(left) >= toNumber(this.primary());\n case 'IN': {\n this.advance();\n const collection = this.primary();\n if (Array.isArray(collection)) {\n return collection.some((item) => looseEqual(item, left));\n }\n if (typeof collection === 'string' && typeof left === 'string') {\n return collection.includes(left);\n }\n return false;\n }\n case 'IS': {\n this.advance();\n // \"is not\"\n if (this.peek().type === 'NOT') {\n this.advance();\n return !looseEqual(left, this.primary());\n }\n return looseEqual(left, this.primary());\n }\n default:\n return left;\n }\n }\n\n private primary(): Value {\n const t = this.peek();\n\n switch (t.type) {\n case 'STRING':\n this.advance();\n return t.value;\n case 'NUMBER':\n this.advance();\n return parseFloat(t.value);\n case 'BOOL':\n this.advance();\n return t.value === 'True' || t.value === 'true';\n case 'NONE':\n this.advance();\n return null;\n case 'IDENT': {\n this.advance();\n return this.resolveVariable(t.value);\n }\n case 'LPAREN': {\n this.advance();\n const val = this.orExpr();\n this.expect('RPAREN');\n return val;\n }\n default:\n throw new Error(`Unexpected token in primary: ${t.type} \"${t.value}\"`);\n }\n }\n\n private resolveVariable(name: string): Value {\n const entry = this.variables.get(name);\n if (entry === undefined) {\n // Check for partial dot-notation matches:\n // e.g., \"user.plan\" might be stored as \"user.plan\" directly\n // No match → treat as undefined (falsy)\n return null;\n }\n\n switch (entry.type) {\n case 'string':\n return String(entry.value);\n case 'number':\n return Number(entry.value);\n case 'boolean':\n return entry.value === true || entry.value === 'true';\n default:\n return String(entry.value);\n }\n }\n}\n\n// ── Helper functions ───────────────────────────────────────────────\n\nfunction isTruthy(v: Value): boolean {\n if (v === null || v === undefined) return false;\n if (typeof v === 'boolean') return v;\n if (typeof v === 'number') return v !== 0;\n if (typeof v === 'string') return v.length > 0;\n if (Array.isArray(v)) return v.length > 0;\n return true;\n}\n\nfunction looseEqual(a: Value, b: Value): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n\n // Coerce number↔string for Jinja compatibility\n if (typeof a === 'number' && typeof b === 'string') return a === parseFloat(b);\n if (typeof a === 'string' && typeof b === 'number') return parseFloat(a) === b;\n\n return false;\n}\n\nfunction toNumber(v: Value): number {\n if (typeof v === 'number') return v;\n if (typeof v === 'string') return parseFloat(v) || 0;\n if (typeof v === 'boolean') return v ? 1 : 0;\n return 0;\n}\n\n// ── Public API ─────────────────────────────────────────────────────\n\n/**\n * Safely evaluate a Jinja conditional expression.\n *\n * Uses a recursive-descent parser with a whitelist of allowed operators.\n * No `eval`, `new Function`, or arbitrary code execution.\n *\n * @returns true/false if evaluation succeeded, null if parsing/evaluation failed\n */\nexport function evaluateCondition(condition: string, variables: Map<string, VariableValue>): boolean | null {\n try {\n const { tokens, error } = tokenize(condition.trim());\n if (error || tokens.length === 0) return null;\n\n const parser = new Parser(tokens, variables);\n const result = parser.evaluate();\n return isTruthy(result);\n } catch {\n return null;\n }\n}\n\n// ── Condition validation ──────────────────────────────────────────\n\nexport interface ConditionValidationResult {\n readonly valid: boolean;\n readonly error?: string;\n}\n\n/**\n * Validate a Jinja conditional expression without evaluating it.\n * Returns a structured result with an error message on failure.\n */\nexport function validateCondition(condition: string): ConditionValidationResult {\n const trimmed = condition.trim();\n if (trimmed === '') return { valid: true };\n\n const { tokens, error: tokenError } = tokenize(trimmed);\n if (tokenError) return { valid: false, error: tokenError };\n if (tokens.length === 0) return { valid: false, error: 'Empty expression' };\n\n try {\n // Parse without evaluating — use an empty variable map\n const parser = new Parser(tokens, new Map());\n parser.evaluate();\n return { valid: true };\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Invalid expression';\n return { valid: false, error: msg };\n }\n}\n","/**\n * Extract a hierarchical tree structure from a DocumentNode for the preview tree view.\n *\n * Walks the AST and produces a tree of:\n * - Headings (H1/H2 as sections, H3-H6 as subsections)\n * - Jump points with their IDs\n * - Jinja if blocks with condition branches\n * - Resource tags (tool, handoff, etc.)\n */\nimport type { DocumentNode, BlockNode, InlineNode } from '../ast/types';\nimport { textContent } from '../ast/traverse';\nimport { analyzeJinjaBlocks } from '../jinja/analyzer';\n\nconst MAX_DEPTH = 128;\n\nexport type DocumentTreeNodeType =\n | 'heading'\n | 'jumpPoint'\n | 'jinjaIf'\n | 'jinjaBranch'\n | 'resourceTag'\n | 'noteBlock'\n | 'endAction';\n\nexport interface DocumentTreeNode {\n readonly type: DocumentTreeNodeType;\n readonly label: string;\n readonly blockIndex: number;\n readonly children: readonly DocumentTreeNode[];\n readonly meta?: Record<string, unknown>;\n}\n\n/** Resource IDs that represent \"end action\" tools (close conversation, etc.). */\nconst END_ACTION_RESOURCE_IDS = new Set([\n 'close-happy-tiger', // PredefinedToolKey.CloseConversation\n]);\n\n/** Text labels that indicate an end action (fallback when resourceId doesn't match). */\nconst END_ACTION_TEXTS = new Set([\n 'end conversation',\n 'end_conversation',\n]);\n\nfunction isEndActionTag(tagType: string, resourceId: string, text: string): boolean {\n return tagType === 'handoff'\n || END_ACTION_RESOURCE_IDS.has(resourceId)\n || END_ACTION_TEXTS.has(text.toLowerCase());\n}\n\nfunction extractInlineItems(\n content: readonly InlineNode[],\n blockIndex: number,\n): DocumentTreeNode[] {\n const items: DocumentTreeNode[] = [];\n for (const node of content) {\n if (node.type === 'jumpPoint') {\n items.push({\n type: 'jumpPoint',\n label: node.id,\n blockIndex,\n children: [],\n });\n } else if (node.type === 'resourceTag') {\n const endAction = isEndActionTag(node.tagType, node.resourceId, node.text);\n items.push({\n type: endAction ? 'endAction' : 'resourceTag',\n label: endAction ? `End ${node.text}` : node.text,\n blockIndex,\n children: [],\n meta: { tagType: node.tagType, resourceId: node.resourceId },\n });\n }\n }\n return items;\n}\n\nfunction extractBlockItems(\n blocks: readonly BlockNode[],\n startIndex: number,\n depth: number,\n): DocumentTreeNode[] {\n if (depth > MAX_DEPTH) return [];\n\n const items: DocumentTreeNode[] = [];\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const blockIndex = startIndex + i;\n\n switch (block.type) {\n case 'heading': {\n const label = textContent(block) || `Heading ${block.level}`;\n const inlineItems = extractInlineItems(block.content, blockIndex);\n items.push({\n type: 'heading',\n label,\n blockIndex,\n children: inlineItems,\n meta: { level: block.level },\n });\n break;\n }\n\n case 'paragraph': {\n const inlineItems = extractInlineItems(block.content, blockIndex);\n items.push(...inlineItems);\n break;\n }\n\n case 'jinjaIfBlock': {\n const branches: DocumentTreeNode[] = block.branches.map((branch, branchIdx) => {\n const branchLabel =\n branch.branchType === 'else'\n ? 'ELSE'\n : `${branch.branchType.toUpperCase()} ${branch.condition || ''}`.trim();\n const branchChildren = extractBlockItems(branch.content, blockIndex, depth + 1);\n return {\n type: 'jinjaBranch' as const,\n label: branchLabel,\n blockIndex,\n children: branchChildren,\n meta: { branchIndex: branchIdx },\n };\n });\n\n items.push({\n type: 'jinjaIf',\n label: 'Jinja if',\n blockIndex,\n children: branches,\n });\n break;\n }\n\n case 'noteBlock': {\n const noteContent = textContent(block);\n items.push({\n type: 'noteBlock',\n label: noteContent ? `Note: ${noteContent.slice(0, 30)}` : 'Note',\n blockIndex,\n children: [],\n });\n break;\n }\n\n case 'bulletList':\n case 'orderedList': {\n for (const li of block.content) {\n const childItems = extractBlockItems(li.content, blockIndex, depth + 1);\n items.push(...childItems);\n }\n break;\n }\n\n case 'blockquote': {\n const childItems = extractBlockItems(block.content, blockIndex, depth + 1);\n items.push(...childItems);\n break;\n }\n\n default:\n break;\n }\n }\n\n return items;\n}\n\n/**\n * Build a document outline tree from a DocumentNode.\n * Extracts both structured jinjaIfBlock nodes and text-based {% if %} patterns.\n */\nexport function buildDocumentTree(doc: DocumentNode): DocumentTreeNode[] {\n const items = extractBlockItems(doc.content, 0, 0);\n\n // Also detect text-based Jinja ({% if %} stored as plain text in paragraphs)\n try {\n const structures = analyzeJinjaBlocks(doc);\n if (structures.length > 0) {\n // Only add text-based Jinja if no structured jinjaIf was already found\n const hasStructuredJinja = items.some((n) => n.type === 'jinjaIf');\n if (!hasStructuredJinja) {\n for (const s of structures) {\n const branches: DocumentTreeNode[] = s.branches.map((b, branchIdx) => ({\n type: 'jinjaBranch' as const,\n label: b.type === 'else' ? 'ELSE' : `${b.type.toUpperCase()} ${b.condition || ''}`.trim(),\n blockIndex: b.tagBlockIndex,\n children: [],\n meta: { branchIndex: branchIdx },\n }));\n\n const jinjaNode: DocumentTreeNode = {\n type: 'jinjaIf',\n label: 'Jinja if',\n blockIndex: s.ifTagBlockIndex,\n children: branches,\n };\n\n // Insert at the correct position based on blockIndex\n let inserted = false;\n for (let i = 0; i < items.length; i++) {\n if (items[i].blockIndex > s.ifTagBlockIndex) {\n items.splice(i, 0, jinjaNode);\n inserted = true;\n break;\n }\n }\n if (!inserted) items.push(jinjaNode);\n }\n }\n }\n } catch {\n // analyzeJinjaBlocks may fail on some documents — don't break the tree\n }\n\n return items;\n}\n","/**\n * Jump-point adjacent decoration + edit plugins.\n *\n * Adjacent plugin: marks jumpPoint nodes near the cursor with a decoration\n * so the NodeView can show `^id^` raw syntax when the cursor is beside them.\n *\n * Edit plugin: tracks a \"raw range\" after ArrowLeft explodes a jumpPoint atom\n * to `^aa^` text. When the cursor moves outside that range the plugin\n * auto-reconverts the text back to a jumpPoint node (if it still matches\n * `^validId^` and the id has no duplicates elsewhere in the doc).\n *\n * Keymap:\n * Backspace — explode atom to `^aa` (closing `^` consumed), cursor at end\n * ArrowLeft — explode atom to `^aa^`, cursor before closing `^`\n */\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\n// ── Adjacent decoration plugin ────────────────────────────\n\nconst adjacentKey = new PluginKey<DecorationSet>('jumpPointAdjacent');\n\n/** Decoration spec set on a jumpPoint node when the cursor is adjacent. */\nexport const JUMP_POINT_ADJACENT_SPEC = { jumpPointAdjacent: true } as const;\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const { selection } = state;\n if (!selection.empty) return DecorationSet.empty;\n\n const cursorPos = selection.$from.pos;\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (node.type.name !== 'jumpPoint') return;\n const nodeEnd = pos + node.nodeSize;\n if (cursorPos === pos || cursorPos === nodeEnd) {\n decorations.push(Decoration.node(pos, nodeEnd, {}, JUMP_POINT_ADJACENT_SPEC));\n }\n });\n\n return DecorationSet.create(state.doc, decorations);\n}\n\n// ── Edit plugin (raw-range tracking + auto-reconvert) ─────\n\ninterface JumpPointEditState {\n rawRange: { from: number; to: number } | null;\n}\n\nexport const jumpPointEditKey = new PluginKey<JumpPointEditState>('jumpPointEdit');\n\n/** Matches the full `^validId^` pattern (letters, numbers, underscore, hyphen). */\nconst JUMP_POINT_FULL_RE = /^\\^([\\p{L}\\p{N}_-]+)\\^$/u;\n\nfunction createJumpPointEditPlugin(): Plugin<JumpPointEditState> {\n return new Plugin<JumpPointEditState>({\n key: jumpPointEditKey,\n\n state: {\n init: (): JumpPointEditState => ({ rawRange: null }),\n\n apply(tr, prev): JumpPointEditState {\n const meta = tr.getMeta(jumpPointEditKey) as\n | { from: number; to: number }\n | null\n | undefined;\n\n if (meta !== undefined) return { rawRange: meta };\n\n if (prev.rawRange) {\n // Use assoc=-1 for `from` so it stays at the range start when text\n // is inserted/replaced from that position (forward assoc would push\n // it to from+addLen, collapsing the range).\n const from = tr.mapping.map(prev.rawRange.from, -1);\n const to = tr.mapping.map(prev.rawRange.to, 1);\n if (from >= to) return { rawRange: null };\n return { rawRange: { from, to } };\n }\n\n return prev;\n },\n },\n\n appendTransaction(_, __, newState) {\n const pluginState = jumpPointEditKey.getState(newState);\n if (!pluginState?.rawRange) return null;\n\n const { from, to } = pluginState.rawRange;\n const cursor = newState.selection.anchor;\n\n // Still inside the raw region — nothing to do.\n // Use strict `< to` so cursor AT the end of `^aa^` is already \"outside\",\n // meaning a single ArrowRight press from `^aa|^` triggers reconversion.\n if (cursor >= from && cursor < to) return null;\n\n const docSize = newState.doc.content.size;\n const safeFrom = Math.min(from, docSize);\n const safeTo = Math.min(to, docSize);\n\n const reconvertTr = newState.tr;\n reconvertTr.setMeta(jumpPointEditKey, null); // always clear tracking\n\n if (safeFrom < safeTo) {\n const text = newState.doc.textBetween(safeFrom, safeTo);\n const match = JUMP_POINT_FULL_RE.exec(text);\n\n if (match) {\n const [, id] = match;\n const jumpPointType = newState.schema.nodes.jumpPoint;\n\n if (jumpPointType) {\n // Always reconvert — duplicates are allowed; validation plugin shows error state\n reconvertTr.replaceWith(safeFrom, safeTo, jumpPointType.create({ id }));\n const mappedCursor = reconvertTr.mapping.map(cursor);\n const clampedCursor = Math.min(mappedCursor, reconvertTr.doc.content.size);\n reconvertTr.setSelection(TextSelection.near(reconvertTr.doc.resolve(clampedCursor)));\n }\n }\n }\n\n return reconvertTr;\n },\n });\n}\n\n// ── Shared helpers ────────────────────────────────────────\n\n/** Find jumpPoint atom — either immediately before cursor (TextSelection)\n * or the selected atom itself (NodeSelection). */\nfunction jumpPointAtOrBefore(\n state: EditorState,\n): { id: string; nodeStart: number; nodeEnd: number } | null {\n const { selection } = state;\n\n // NodeSelection — atom itself is selected\n if ('node' in selection) {\n const node = (selection as any).node;\n if (node?.type?.name === 'jumpPoint') {\n return { id: node.attrs.id as string, nodeStart: selection.from, nodeEnd: selection.to };\n }\n return null;\n }\n\n // TextSelection — cursor immediately after atom\n if (!selection.empty) return null;\n const { $from } = selection;\n const nodeBefore = $from.nodeBefore;\n if (!nodeBefore || nodeBefore.type.name !== 'jumpPoint') return null;\n const nodeEnd = $from.pos;\n const nodeStart = nodeEnd - nodeBefore.nodeSize;\n return { id: nodeBefore.attrs.id as string, nodeStart, nodeEnd };\n}\n\n/**\n * Backspace on a jumpPoint atom → explode to `^aa` (no closing `^`).\n * Cursor lands at end: `^aa|`\n */\nfunction explodeOnBackspace(state: EditorState): Transaction | null {\n const info = jumpPointAtOrBefore(state);\n if (!info) return null;\n const { id, nodeStart, nodeEnd } = info;\n const rawText = `^${id}`;\n const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));\n const cursorPos = Math.min(nodeStart + rawText.length, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n return tr;\n}\n\n/**\n * ArrowLeft on a jumpPoint atom → explode to `^aa^`, cursor before closing `^`.\n * Sets jumpPointEditKey meta so auto-reconvert kicks in when cursor leaves.\n * Result: `^aa|^`\n */\nfunction explodeOnArrowLeft(state: EditorState): Transaction | null {\n const info = jumpPointAtOrBefore(state);\n if (!info) return null;\n const { id, nodeStart, nodeEnd } = info;\n const rawText = `^${id}^`;\n const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));\n // cursor before closing `^`\n const cursorPos = Math.min(nodeStart + 1 + id.length, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n // Track range so appendTransaction can reconvert on cursor-leave\n tr.setMeta(jumpPointEditKey, { from: nodeStart, to: nodeStart + rawText.length });\n return tr;\n}\n\n// ── Public factory ────────────────────────────────────────\n\nexport function createJumpPointAdjacentPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointAdjacent',\n keymap: () => ({\n Backspace: (state, dispatch) => {\n const tr = explodeOnBackspace(state);\n if (!tr) return false;\n if (dispatch) dispatch(tr);\n return true;\n },\n ArrowLeft: (state, dispatch) => {\n const tr = explodeOnArrowLeft(state);\n if (!tr) return false;\n if (dispatch) dispatch(tr);\n return true;\n },\n }),\n plugins: () => [\n createJumpPointEditPlugin(),\n new Plugin({\n key: adjacentKey,\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, old, _oldState, newState) {\n if (tr.selectionSet || tr.docChanged) {\n return buildDecorations(newState);\n }\n return old.map(tr.mapping, tr.doc);\n },\n },\n props: {\n decorations(state) {\n return adjacentKey.getState(state);\n },\n },\n }),\n ],\n };\n}\n","/**\n * React NodeView plugin for the `jumpPoint` node.\n *\n * Normal state: styled badge (anchor icon + id, yellow background)\n * Adjacent state: shows `^id^` raw syntax when cursor is immediately before or after\n * Duplicate state: red error badge with X button and hover tooltip\n */\nimport React, { useCallback, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { createReactNodeView } from '../nodeView/ReactNodeView';\nimport type { ReactNodeViewProps } from '../nodeView/ReactNodeView';\nimport type { ActionbookPlugin } from './types';\nimport { IconAnchor } from '../components/icons';\n\n/** Diamond-shaped alert icon (◆ with ! inside) for duplicate jumpPoint indicator. */\nfunction IconDiamondAlert({ size = 12, fill = '#D9352C' }: { size?: number; fill?: string }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.293 1.293a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 0-1.414l4-4Z\"\n fill={fill}\n />\n <path d=\"M6 3.5v3\" stroke=\"#fff\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"6\" cy=\"8.25\" r=\"0.625\" fill=\"#fff\" />\n </svg>\n );\n}\n\n// ── Styles (Figma spec) ──────────────────────────────────\n\nconst JUMP_POINT_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: '#FFF2B6',\n border: '1px solid #FFC233',\n color: '#AA5D04',\n userSelect: 'none',\n cursor: 'default',\n boxSizing: 'border-box',\n // height, padding, borderRadius, fontSize, lineHeight, overflow\n // are set via CSS class .ab-jump-point for heading-level overrides\n};\n\nconst JUMP_POINT_ADJACENT_STYLE: React.CSSProperties = {\n ...JUMP_POINT_STYLE,\n};\n\nconst JUMP_POINT_DUPLICATE_STYLE: React.CSSProperties = {\n ...JUMP_POINT_STYLE,\n backgroundColor: '#FFD9DD',\n borderColor: '#D9352C',\n color: '#9D091E',\n};\n\nconst LABEL_STYLE: React.CSSProperties = {\n whiteSpace: 'nowrap',\n // padding is set via CSS .ab-jp-label for heading-level overrides\n};\n\nconst CLOSE_BTN_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '16px',\n height: '16px',\n padding: 0,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: '1px',\n flexShrink: 0,\n color: 'inherit',\n fontSize: '10px',\n lineHeight: 1,\n};\n\nconst TOOLTIP_STYLE: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n alignSelf: 'stretch',\n padding: '16px 20px',\n backgroundColor: '#fff',\n border: '1px solid #CCC',\n borderRadius: '4px',\n boxShadow: '0 8px 10px rgba(13,13,13,0.12), 0 3px 14px rgba(13,13,13,0.08), 0 3px 5px rgba(13,13,13,0.04)',\n fontSize: '14px',\n lineHeight: '20px',\n color: '#0D0D0D',\n maxWidth: '240px',\n zIndex: 1100,\n pointerEvents: 'none',\n};\n\nconst TOOLTIP_ARROW_STYLE: React.CSSProperties = {\n position: 'absolute',\n bottom: '-6px',\n left: '50%',\n transform: 'translateX(-50%) rotate(45deg)',\n width: '10px',\n height: '10px',\n backgroundColor: '#fff',\n border: '1px solid #CCC',\n borderTop: 'none',\n borderLeft: 'none',\n};\n\n// ── Component ────────────────────────────────────────────\n\nfunction JumpPointNodeViewComponent({ node, decorations }: ReactNodeViewProps) {\n const id = node.attrs.id as string;\n const isAdjacent = decorations?.some((d) => (d as any).spec?.jumpPointAdjacent === true) ?? false;\n const isDuplicate = decorations?.some((d) => (d as any).spec?.jumpPointDuplicate === true) ?? false;\n const [showTooltip, setShowTooltip] = useState(false);\n const spanRef = useRef<HTMLSpanElement>(null);\n const [tooltipPos, setTooltipPos] = useState<{ top: number; left: number } | null>(null);\n\n const handleMouseEnter = useCallback(() => {\n if (!spanRef.current) return;\n const rect = spanRef.current.getBoundingClientRect();\n setTooltipPos({ top: rect.top - 8, left: rect.left + rect.width / 2 });\n setShowTooltip(true);\n }, []);\n\n if (isDuplicate) {\n return (\n <span\n ref={spanRef}\n className=\"ab-jump-point ab-jump-point-duplicate\"\n style={JUMP_POINT_DUPLICATE_STYLE}\n id={`jp-${id}`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={() => setShowTooltip(false)}\n >\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#9D091E\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{id}</span>\n <span style={{ ...CLOSE_BTN_STYLE, cursor: 'default' }}>\n <IconDiamondAlert size={12} fill=\"#D9352C\" />\n </span>\n {showTooltip && tooltipPos && createPortal(\n <span style={{ ...TOOLTIP_STYLE, top: tooltipPos.top, left: tooltipPos.left, transform: 'translate(-50%, -100%)' }}>\n &ldquo;{id}&rdquo; is already used as an anchor\n <span style={TOOLTIP_ARROW_STYLE} />\n </span>,\n document.body,\n )}\n </span>\n );\n }\n\n if (isAdjacent) {\n return (\n <span className=\"ab-jump-point ab-jump-point-adjacent\" style={JUMP_POINT_ADJACENT_STYLE} id={`jp-${id}`}>\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#AA5D04\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{`^${id}^`}</span>\n </span>\n );\n }\n\n return (\n <span className=\"ab-jump-point\" style={JUMP_POINT_STYLE} id={`jp-${id}`}>\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#AA5D04\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{id}</span>\n </span>\n );\n}\n\nexport function createJumpPointNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointNodeView',\n nodeViews: () => ({\n jumpPoint: createReactNodeView({ component: JumpPointNodeViewComponent, inline: true }),\n }),\n };\n}\n","/**\n * ProseMirror plugin that validates jumpPoint nodes and anchor references.\n *\n * 1. Attaches `jumpPointDuplicate` node decoration to jumpPoints with non-unique IDs.\n * 2. Attaches `brokenAnchorRef` inline decoration to link marks whose href=\"#ID\"\n * references a jumpPoint that doesn't exist in the document.\n * 3. Exports validation helpers for save-time checks.\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\nconst pluginKey = new PluginKey<DecorationSet>('jumpPointValidation');\n\n/** Collect all jumpPoint IDs in the document. */\nfunction collectJumpPointIds(state: EditorState): Set<string> {\n const ids = new Set<string>();\n state.doc.descendants((node) => {\n if (node.type.name === 'jumpPoint') {\n ids.add(node.attrs.id as string);\n }\n });\n return ids;\n}\n\nfunction findDuplicatePositions(state: EditorState): { pos: number; size: number }[] {\n const idCount = new Map<string, number>();\n const nodes: { id: string; pos: number; size: number }[] = [];\n\n state.doc.descendants((node, pos) => {\n if (node.type.name === 'jumpPoint') {\n const id = node.attrs.id as string;\n idCount.set(id, (idCount.get(id) ?? 0) + 1);\n nodes.push({ id, pos, size: node.nodeSize });\n }\n });\n\n return nodes.filter((n) => (idCount.get(n.id) ?? 0) > 1);\n}\n\n/** Find link marks with href=\"#ID\" where ID doesn't exist as a jumpPoint. */\nfunction findBrokenAnchorRefs(state: EditorState, existingIds: Set<string>): { from: number; to: number; refId: string }[] {\n const broken: { from: number; to: number; refId: string }[] = [];\n const linkMarkType = state.schema.marks.link;\n if (!linkMarkType) return broken;\n\n state.doc.descendants((node, pos) => {\n if (!node.isText) return;\n const linkMark = node.marks.find((m) => m.type === linkMarkType);\n if (!linkMark) return;\n\n const href = linkMark.attrs.href as string;\n if (!href || !href.startsWith('#')) return;\n\n const refId = href.slice(1); // strip \"#\"\n if (refId && !existingIds.has(refId)) {\n broken.push({ from: pos, to: pos + node.nodeSize, refId });\n }\n });\n\n return broken;\n}\n\n/**\n * Check whether the editor state contains duplicate jumpPoint IDs.\n */\nexport function hasDuplicateJumpPoints(state: EditorState): boolean {\n return findDuplicatePositions(state).length > 0;\n}\n\n/**\n * Check whether the editor state contains broken anchor references.\n */\nexport function hasBrokenAnchorRefs(state: EditorState): boolean {\n const ids = collectJumpPointIds(state);\n return findBrokenAnchorRefs(state, ids).length > 0;\n}\n\nexport function createJumpPointValidationPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointValidation',\n plugins: () => [\n new Plugin<DecorationSet>({\n key: pluginKey,\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, oldSet, _oldState, newState) {\n if (tr.docChanged) {\n return buildDecorations(newState);\n }\n return oldSet.map(tr.mapping, tr.doc);\n },\n },\n props: {\n decorations(state) {\n return pluginKey.getState(state) ?? DecorationSet.empty;\n },\n },\n }),\n ],\n };\n}\n\nfunction createBrokenRefIcon(refId: string): HTMLElement {\n const wrapper = document.createElement('span');\n wrapper.style.cssText = 'position: relative; display: inline-flex; align-items: center; cursor: help;';\n wrapper.contentEditable = 'false';\n\n // SVG diamond-alert icon\n const ns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(ns, 'svg');\n svg.setAttribute('width', '14');\n svg.setAttribute('height', '14');\n svg.setAttribute('viewBox', '0 0 16 16');\n svg.setAttribute('fill', 'none');\n const path = document.createElementNS(ns, 'path');\n path.setAttribute('fill-rule', 'evenodd');\n path.setAttribute('clip-rule', 'evenodd');\n path.setAttribute('d', 'M8.00002 0.666626L15.3334 7.99996L8.00002 15.3333L0.666687 7.99996L8.00002 0.666626ZM7.33335 8.66663V4.66663H8.66669V8.66663H7.33335ZM8.00002 11.3333C8.46026 11.3333 8.83335 10.9602 8.83335 10.5C8.83335 10.0397 8.46026 9.66663 8.00002 9.66663C7.53978 9.66663 7.16669 10.0397 7.16669 10.5C7.16669 10.9602 7.53978 11.3333 8.00002 11.3333Z');\n path.setAttribute('fill', '#D9352C');\n svg.appendChild(path);\n\n const iconSpan = document.createElement('span');\n iconSpan.style.cssText = 'display: inline-flex; margin-left: 2px; vertical-align: middle;';\n iconSpan.appendChild(svg);\n\n // Tooltip (appended to body on hover)\n const tooltip = document.createElement('span');\n tooltip.textContent = `Anchor \"${refId}\" no longer exists`;\n tooltip.style.cssText = [\n 'display:none', 'position:fixed', 'z-index:1100', 'pointer-events:none',\n 'padding:16px 20px', 'background:#fff', 'border:1px solid #CCC', 'border-radius:4px',\n 'box-shadow:0 8px 10px rgba(13,13,13,0.12),0 3px 14px rgba(13,13,13,0.08),0 3px 5px rgba(13,13,13,0.04)',\n 'font-size:14px', 'line-height:20px', 'color:#0D0D0D', 'max-width:240px', 'white-space:normal',\n ].join(';');\n\n const arrow = document.createElement('span');\n arrow.style.cssText = [\n 'position:absolute', 'bottom:-6px', 'left:50%', 'transform:translateX(-50%) rotate(45deg)',\n 'width:10px', 'height:10px', 'background:#fff', 'border:1px solid #CCC',\n 'border-top:none', 'border-left:none',\n ].join(';');\n tooltip.appendChild(arrow);\n\n wrapper.addEventListener('mouseenter', () => {\n const rect = wrapper.getBoundingClientRect();\n tooltip.style.left = `${rect.left + rect.width / 2}px`;\n tooltip.style.top = `${rect.top - 8}px`;\n tooltip.style.transform = 'translate(-50%, -100%)';\n tooltip.style.display = 'flex';\n tooltip.style.flexDirection = 'column';\n tooltip.style.alignItems = 'flex-start';\n document.body.appendChild(tooltip);\n });\n wrapper.addEventListener('mouseleave', () => {\n tooltip.style.display = 'none';\n if (tooltip.parentElement === document.body) document.body.removeChild(tooltip);\n });\n\n wrapper.appendChild(iconSpan);\n return wrapper;\n}\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const decos: Decoration[] = [];\n\n // 1. Duplicate jumpPoints\n const duplicates = findDuplicatePositions(state);\n for (const { pos, size } of duplicates) {\n decos.push(\n Decoration.node(pos, pos + size, { class: 'jump-point-duplicate' }, { jumpPointDuplicate: true }),\n );\n }\n\n // 2. Broken anchor references (link marks with href=\"#ID\" where ID doesn't exist)\n const existingIds = collectJumpPointIds(state);\n const brokenRefs = findBrokenAnchorRefs(state, existingIds);\n for (const { from, to, refId } of brokenRefs) {\n decos.push(\n Decoration.inline(from, to, {\n class: 'broken-anchor-ref',\n 'data-broken-ref': refId,\n spellcheck: 'false',\n style: 'color: #D9352C; font-weight: 500; text-decoration: none !important; text-decoration-line: none !important;',\n }),\n );\n decos.push(Decoration.widget(to, () => createBrokenRefIcon(refId), { side: -1 }));\n }\n\n if (decos.length === 0) return DecorationSet.empty;\n return DecorationSet.create(state.doc, decos);\n}\n","/**\n * React NodeView plugin for the `inlineToolTag` node.\n *\n * Renders a styled badge matching ActionbookRenderer's resourceTag output:\n * colored icon block + colored text label with border.\n */\nimport React from 'react';\nimport { createReactNodeView } from '../nodeView/ReactNodeView';\nimport type { ReactNodeViewProps } from '../nodeView/ReactNodeView';\nimport type { ActionbookPlugin } from './types';\nimport {\n IconTool,\n IconManual,\n IconMessageTemplate,\n IconHandoff,\n IconTimeDiff,\n IconStop,\n} from '../components/icons';\n\nconst RESOURCE_TAG_COLORS: Record<string, string> = {\n tool: '#027D69',\n manual: '#5959D3',\n agent_message_template: '#8012B3',\n handoff: '#D25309',\n time_diff: '#FB6B6B',\n};\nconst DEFAULT_COLOR = '#027D69';\n\ntype IconComponent = React.ComponentType<{ size?: number; fill?: string; style?: React.CSSProperties }>;\n\nconst RESOURCE_TAG_ICONS: Record<string, IconComponent> = {\n tool: IconTool,\n manual: IconManual,\n agent_message_template: IconMessageTemplate,\n handoff: IconHandoff,\n time_diff: IconTimeDiff,\n};\nconst DEFAULT_ICON = IconTool;\n\n// Per-resourceId overrides (Figma spec: End conversation uses black, not green)\nconst RESOURCE_ID_OVERRIDES: Record<string, { color: string; icon: IconComponent }> = {\n 'close-happy-tiger': { color: '#0D0D0D', icon: IconStop },\n};\n\nconst OUTER_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n padding: '2px',\n border: '1px solid #CCCCCC',\n borderRadius: '2px',\n alignItems: 'center',\n backgroundColor: 'white',\n userSelect: 'none',\n cursor: 'default',\n boxSizing: 'border-box',\n};\n\nconst ICON_BLOCK_BASE: React.CSSProperties = {\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '16px',\n height: '16px',\n borderRadius: '2px',\n flexShrink: 0,\n};\n\nconst LABEL_BASE: React.CSSProperties = {\n padding: '0 4px',\n fontSize: '12px',\n lineHeight: '16px',\n userSelect: 'none',\n};\n\nfunction InlineToolTagNodeViewComponent({ node, selected }: ReactNodeViewProps) {\n const type = node.attrs.type as string;\n const text = node.attrs.text as string;\n const resourceId = node.attrs.resourceId as string;\n const override = RESOURCE_ID_OVERRIDES[resourceId];\n const color = override?.color ?? RESOURCE_TAG_COLORS[type] ?? DEFAULT_COLOR;\n const Icon = override?.icon ?? RESOURCE_TAG_ICONS[type] ?? DEFAULT_ICON;\n\n const style: React.CSSProperties = selected\n ? { ...OUTER_STYLE, boxShadow: `inset 0 0 0 1px ${color}` }\n : OUTER_STYLE;\n\n return (\n <span style={style} data-type={type} data-resource-id={node.attrs.resourceId as string}>\n <span style={{ ...ICON_BLOCK_BASE, backgroundColor: color }}>\n <Icon size={9} fill=\"white\" />\n </span>\n <span style={{ ...LABEL_BASE, color }}>{text}</span>\n </span>\n );\n}\n\nexport function createInlineToolTagNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'inlineToolTagNodeView',\n nodeViews: () => ({\n inlineToolTag: createReactNodeView({ component: InlineToolTagNodeViewComponent, inline: true }),\n }),\n };\n}\n","import { Plugin, PluginKey } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { fromProseMirrorJSON, type JSONContent } from '../../compat/prosemirror';\nimport { analyzeJinjaBlocks } from '../../jinja/analyzer';\nimport type { ActionbookPlugin } from './types';\n\nconst jinjaPluginKey = new PluginKey('jinjaDecoration');\n\nconst JINJA_TAG_RE = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\ninterface BlockPosInfo {\n index: number;\n from: number;\n to: number;\n}\n\nfunction getBlockPositions(doc: PMNode): BlockPosInfo[] {\n const blocks: BlockPosInfo[] = [];\n let index = 0;\n doc.forEach((node, offset) => {\n blocks.push({ index, from: offset, to: offset + node.nodeSize });\n index++;\n });\n return blocks;\n}\n\nfunction addInlineChipDecorations(doc: PMNode, decorations: Decoration[]) {\n doc.descendants((node, pos) => {\n if (!node.isText) return;\n const text = node.text!;\n JINJA_TAG_RE.lastIndex = 0;\n let match;\n while ((match = JINJA_TAG_RE.exec(text)) !== null) {\n const from = pos + match.index;\n const to = from + match[0].length;\n const keyword = match[1]; // if | elif | else | endif\n decorations.push(\n Decoration.inline(from, to, {\n class: `jinja-chip jinja-chip-${keyword}`,\n }),\n );\n }\n });\n}\n\nfunction addStructureBorderDecorations(\n doc: PMNode,\n blocks: BlockPosInfo[],\n decorations: Decoration[],\n) {\n const json = doc.toJSON() as JSONContent;\n let ast;\n try {\n ast = fromProseMirrorJSON(json);\n } catch {\n return;\n }\n\n const structures = analyzeJinjaBlocks(ast);\n\n for (const structure of structures) {\n // Build a map: blockIndex → branch type for every block in this structure\n // Tag lines (if/elif/else/endif) get the type of the branch they start\n // Content blocks get the type of their enclosing branch\n const blockBranchType = new Map<number, 'if' | 'elif' | 'else'>();\n\n for (const branch of structure.branches) {\n // The tag line itself\n blockBranchType.set(branch.tagBlockIndex, branch.type);\n // Content blocks under this branch\n for (let i = branch.blockStartIndex; i < branch.blockEndIndex; i++) {\n // Don't overwrite tag lines of subsequent branches\n if (!blockBranchType.has(i)) {\n blockBranchType.set(i, branch.type);\n }\n }\n }\n // endif tag line: use the last branch's type\n const lastBranch = structure.branches[structure.branches.length - 1];\n if (lastBranch && !blockBranchType.has(structure.endifTagBlockIndex)) {\n blockBranchType.set(structure.endifTagBlockIndex, lastBranch.type);\n }\n\n // Now emit decorations per contiguous run of same branch type\n const first = structure.ifTagBlockIndex;\n const last = structure.endifTagBlockIndex;\n\n for (let i = first; i <= last; i++) {\n const block = blocks[i];\n if (!block) continue;\n\n const branchType = blockBranchType.get(i) || 'if';\n const prevType = i > first ? blockBranchType.get(i - 1) : undefined;\n const nextType = i < last ? blockBranchType.get(i + 1) : undefined;\n\n const classes = ['jinja-bar', `jinja-bar-${branchType}`];\n // Segment boundaries: start/end of a contiguous same-color run\n if (i === first || prevType !== branchType) classes.push('jinja-bar-first');\n if (i === last || nextType !== branchType) classes.push('jinja-bar-last');\n\n decorations.push(Decoration.node(block.from, block.to, { class: classes.join(' ') }));\n }\n }\n}\n\n/** Quick scan: does the document contain any jinja tags at all? */\nfunction hasJinjaTags(doc: PMNode): boolean {\n let found = false;\n doc.descendants((node) => {\n if (found) return false; // stop early\n if (node.isText && node.text!.includes('{%')) {\n found = true;\n return false;\n }\n });\n return found;\n}\n\nfunction buildDecorations(doc: PMNode): DecorationSet {\n // Fast path: skip entirely when no jinja tags present\n if (!hasJinjaTags(doc)) return DecorationSet.empty;\n\n const blocks = getBlockPositions(doc);\n const decorations: Decoration[] = [];\n\n addInlineChipDecorations(doc, decorations);\n addStructureBorderDecorations(doc, blocks, decorations);\n\n if (decorations.length === 0) return DecorationSet.empty;\n return DecorationSet.create(doc, decorations);\n}\n\nexport function createJinjaDecorationPlugin(): ActionbookPlugin {\n return {\n name: 'jinjaDecoration',\n plugins: () => [\n new Plugin({\n key: jinjaPluginKey,\n state: {\n init(_, state) {\n return buildDecorations(state.doc);\n },\n apply(tr, oldDecos) {\n if (!tr.docChanged) return oldDecos;\n return buildDecorations(tr.doc);\n },\n },\n props: {\n decorations(state) {\n return jinjaPluginKey.getState(state) as DecorationSet;\n },\n },\n }),\n ],\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type { Node as PMNode, Schema } from 'prosemirror-model';\nimport { Plugin, TextSelection } from 'prosemirror-state';\nimport type { EditorView, NodeView, ViewMutationRecord } from 'prosemirror-view';\nimport { tokenizeCondition } from '../../jinja/conditionHighlighter';\nimport { validateCondition } from '../../jinja/evaluator';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\ntype BranchType = 'if' | 'elif' | 'else';\n\ninterface BranchContext {\n readonly blockNode: PMNode;\n readonly blockPos: number;\n readonly branchNode: PMNode;\n readonly branchPos: number;\n readonly branchIndex: number;\n}\n\ninterface PopupMenuItem {\n readonly label: string;\n readonly disabled?: boolean;\n readonly onSelect: () => void;\n}\n\ninterface MenuPosition {\n readonly top: number;\n readonly left?: number;\n readonly right?: number;\n}\n\ninterface JinjaBranchHeaderProps {\n readonly branchType: BranchType;\n readonly condition: string;\n readonly editable?: boolean;\n readonly isBodyEmpty: boolean;\n readonly isBodyTouched: boolean;\n readonly onConditionChange: (value: string) => void;\n readonly onDelete: () => void;\n readonly onAddBranch: (branchType: Exclude<BranchType, 'if'>) => void;\n readonly isLastBranch: boolean;\n readonly hasElseBranch: boolean;\n}\n\ninterface ConditionDisplayProps {\n readonly branchType: BranchType;\n readonly condition: string;\n readonly editable?: boolean;\n readonly onConditionChange: (value: string) => void;\n readonly onBackspaceEmpty?: () => void;\n readonly onConditionBlur?: () => void;\n}\n\ninterface BranchPopupMenuProps {\n readonly items: readonly PopupMenuItem[];\n readonly position: MenuPosition;\n}\n\nconst PLACEHOLDER_TEXT = 'Describe what AI agent should do when this condition is met';\nconst CONDITION_PLACEHOLDER = 'Write a condition in natural language';\nconst STYLE_ID = 'ab-jinja-if-block-styles';\n\nconst JINJA_STYLES = `\n.jinja-if-block {\n margin: 8px 0;\n}\n\n.jinja-branch {\n position: relative;\n display: grid;\n grid-template-areas:\n \"header\"\n \"error\"\n \"body\"\n \"body-error\"\n \"footer\";\n gap: 0;\n}\n\n.jinja-branch-controls {\n display: contents;\n}\n\n.jinja-branch-header {\n grid-area: header;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px;\n border: 1px solid #E0E0E0;\n border-radius: 4px;\n background: #FFFFFF;\n}\n\n.jinja-branch-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 32px;\n padding: 0 8px;\n border-radius: 4px;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n font-weight: 700;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.jinja-branch-badge-if,\n.jinja-branch-badge-elif {\n background: #E7F1FF;\n color: #0D0D0D;\n}\n\n.jinja-branch-badge-else {\n background: #F7F7F7;\n color: #424242;\n}\n\n.jinja-branch-condition {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n width: 100%;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n color: #0D0D0D;\n cursor: text;\n text-align: left;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n}\n\n.jinja-branch-condition:focus-visible,\n.jinja-ghost-btn:focus-visible,\n.jinja-popup-item:focus-visible {\n outline: 2px solid rgba(98, 16, 204, 0.28);\n outline-offset: 2px;\n}\n\n.jinja-condition-placeholder {\n color: #A6A6A6;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-branch-header-invalid {\n border: 1px solid #D9352C;\n border-radius: 4px;\n}\n\n.jinja-condition-error {\n grid-area: error;\n display: flex;\n align-items: center;\n padding: 4px 0 4px 52px;\n color: #D9352C;\n font-size: 12px;\n line-height: 16px;\n}\n\n.jinja-body-error {\n grid-area: body-error;\n display: flex;\n align-items: center;\n padding: 0 0 4px 52px;\n color: #D9352C;\n font-size: 12px;\n line-height: 16px;\n}\n\n.jinja-token-variable {\n color: #4141B2;\n}\n\n.jinja-token-operator {\n color: #858585;\n}\n\n.jinja-token-value {\n color: #0D0D0D;\n}\n\n.jinja-token-punctuation {\n color: #858585;\n}\n\n.jinja-otherwise {\n flex: 1;\n color: #858585;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-branch-actions,\n.jinja-add-footer-actions {\n position: relative;\n display: inline-flex;\n align-items: center;\n}\n\n.jinja-branch-body {\n grid-area: body;\n display: flex;\n gap: 12px;\n padding: 0 8px;\n min-height: 52px;\n}\n\n.jinja-branch-divider-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n justify-content: center;\n}\n\n.jinja-branch-divider {\n width: 1px;\n background: #E0E0E0;\n}\n\n/* L-shaped divider for the last branch (ELSE) */\n.jinja-branch-last .jinja-branch-divider-col {\n align-items: flex-start;\n padding-left: 16px;\n}\n\n.jinja-branch-last .jinja-branch-divider {\n width: 16px;\n height: 28px;\n background: none;\n border-left: 1px solid #E0E0E0;\n border-bottom: 1px solid #E0E0E0;\n border-bottom-left-radius: 8px;\n}\n\n.jinja-branch-content {\n position: relative;\n flex: 1;\n min-width: 0;\n padding: 16px 0;\n}\n\n.jinja-branch-content.jinja-branch-content-empty::before {\n content: attr(data-placeholder);\n position: absolute;\n top: 16px;\n left: 0;\n color: #A6A6A6;\n font-size: 14px;\n line-height: 20px;\n pointer-events: none;\n}\n\n.jinja-add-footer {\n grid-area: footer;\n display: flex;\n padding: 8px;\n}\n\n.jinja-add-footer .jinja-add-footer-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.jinja-ghost-btn {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: #858585;\n cursor: pointer;\n}\n\n.jinja-ghost-btn:hover:not(:disabled) {\n background: rgba(13, 13, 13, 0.04);\n}\n\n.jinja-ghost-btn:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.jinja-popup-menu {\n position: absolute;\n z-index: 20;\n min-width: 200px;\n padding: 8px 0;\n background: #FFFFFF;\n border-radius: 4px;\n box-shadow: 0px 8px 10px 0px rgba(13,13,13,0.12), 0px 3px 14px 0px rgba(13,13,13,0.08), 0px 3px 5px 0px rgba(13,13,13,0.04);\n}\n\n.jinja-popup-item {\n width: 100%;\n display: block;\n padding: 6px 16px;\n border: none;\n background: transparent;\n color: #0D0D0D;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: -0.1px;\n}\n\n.jinja-popup-item:hover:not(:disabled) {\n background: rgba(13, 13, 13, 0.04);\n}\n\n.jinja-popup-item:disabled {\n color: #A6A6A6;\n cursor: default;\n}\n\n.jinja-condition-input {\n width: 100%;\n min-width: 0;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n background: transparent;\n color: #0D0D0D;\n caret-color: #6210CC;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-condition-input::placeholder {\n color: #A6A6A6;\n}\n`;\n\nclass StyleManager {\n private static refCount = 0;\n private static styleEl: HTMLStyleElement | null = null;\n\n static acquire(): void {\n if (this.refCount++ > 0) return;\n\n const existing = document.getElementById(STYLE_ID);\n if (existing instanceof HTMLStyleElement) {\n this.styleEl = existing;\n return;\n }\n\n this.styleEl = document.createElement('style');\n this.styleEl.id = STYLE_ID;\n this.styleEl.textContent = JINJA_STYLES;\n document.head.appendChild(this.styleEl);\n }\n\n static release(): void {\n if (this.refCount === 0) return;\n if (--this.refCount > 0) return;\n\n if (this.styleEl?.parentNode) {\n this.styleEl.remove();\n }\n this.styleEl = null;\n }\n}\n\nfunction getBranchContext(view: EditorView, nodePos: number): BranchContext | null {\n try {\n const { doc } = view.state;\n const resolved = doc.resolve(nodePos);\n let blockDepth = -1;\n\n for (let depth = resolved.depth; depth >= 0; depth--) {\n if (resolved.node(depth).type.name === 'jinjaIfBlock') {\n blockDepth = depth;\n break;\n }\n }\n\n if (blockDepth < 0) {\n return null;\n }\n\n const blockNode = resolved.node(blockDepth);\n const blockPos = blockDepth === 0 ? 0 : resolved.before(blockDepth);\n\n let branchOffset = blockPos + 1;\n for (let index = 0; index < blockNode.childCount; index++) {\n const branchNode = blockNode.child(index);\n if (branchOffset === nodePos) {\n return {\n blockNode,\n blockPos,\n branchNode,\n branchPos: branchOffset,\n branchIndex: index,\n };\n }\n branchOffset += branchNode.nodeSize;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction isBranchBodyEmpty(node: PMNode): boolean {\n if (node.childCount !== 1) return false;\n const firstChild = node.firstChild;\n return firstChild?.type.name === 'paragraph' && firstChild.content.size === 0;\n}\n\nfunction isBranchNode(node: PMNode | null | undefined): node is PMNode {\n return node?.type.name === 'jinjaIfBranch';\n}\n\nfunction createBranchNode(schema: Schema, branchType: Exclude<BranchType, 'if'>, condition: string): PMNode | null {\n const branchNodeType = schema.nodes.jinjaIfBranch;\n const paragraphNode = schema.nodes.paragraph?.createAndFill();\n\n if (!branchNodeType || !paragraphNode) {\n return null;\n }\n\n return branchNodeType.create(\n {\n branchType,\n condition: branchType === 'else' ? '' : condition,\n },\n paragraphNode,\n );\n}\n\nfunction getLastBranchOfBlock(view: EditorView, nodePos: number): { index: number; node: PMNode } | null {\n const context = getBranchContext(view, nodePos);\n if (!context || context.blockNode.childCount === 0) {\n return null;\n }\n\n const index = context.blockNode.childCount - 1;\n return {\n index,\n node: context.blockNode.child(index),\n };\n}\n\nfunction getLastNonElseBranchIndex(view: EditorView, nodePos: number): number {\n const context = getBranchContext(view, nodePos);\n if (!context) return -1;\n for (let i = context.blockNode.childCount - 1; i >= 0; i--) {\n if ((context.blockNode.child(i).attrs.branchType as BranchType) !== 'else') return i;\n }\n return -1;\n}\n\nfunction getElseBranch(view: EditorView, nodePos: number): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n\n for (let index = 0; index < context.blockNode.childCount; index++) {\n if ((context.blockNode.child(index).attrs.branchType as BranchType) === 'else') {\n return true;\n }\n }\n\n return false;\n}\n\nfunction deleteBlock(view: EditorView, blockPos: number): boolean {\n const blockNode = view.state.doc.nodeAt(blockPos);\n if (blockNode?.type.name !== 'jinjaIfBlock') {\n return false;\n }\n\n view.dispatch(view.state.tr.delete(blockPos, blockPos + blockNode.nodeSize).scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction insertNewBranch(\n view: EditorView,\n nodePos: number,\n branchType: Exclude<BranchType, 'if'>,\n condition = '',\n): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n if ((context.branchNode.attrs.branchType as BranchType) === 'else') return false;\n\n const lastBranch = getLastBranchOfBlock(view, nodePos);\n if (!lastBranch) return false;\n\n if (branchType === 'else') {\n if (getElseBranch(view, nodePos)) return false;\n if (lastBranch.index !== context.branchIndex) return false;\n }\n\n const newBranch = createBranchNode(view.state.schema, branchType, condition);\n if (!newBranch) return false;\n\n const insertPos = context.branchPos + context.branchNode.nodeSize;\n const tr = view.state.tr.insert(insertPos, newBranch);\n // Move cursor into the new branch's content (branch > paragraph)\n const cursorPos = insertPos + 2; // +1 into branch, +1 into paragraph\n if (cursorPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n }\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction deleteBranch(view: EditorView, nodePos: number, branchType: BranchType): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n\n const { branchNode, branchPos, branchIndex, blockNode, blockPos } = context;\n\n if (branchType === 'if') {\n // Delete entire jinja block, replace with empty paragraph\n const tr = view.state.tr;\n tr.replaceWith(blockPos, blockPos + blockNode.nodeSize, view.state.schema.nodes.paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockPos)));\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n }\n\n // ELIF or ELSE → delete only this branch\n const tr = view.state.tr;\n tr.delete(branchPos, branchPos + branchNode.nodeSize);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(branchPos)), -1));\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction renderCondition(condition: string) {\n const tokens = tokenizeCondition(condition);\n const rendered: JSX.Element[] = [];\n\n for (let index = 0; index < tokens.length; index++) {\n const token = tokens[index];\n // Skip whitespace-only gaps — CSS gap handles spacing between tokens\n rendered.push(\n <span key={`token-${index}-${token.start}`} className={`jinja-token-${token.category}`}>\n {token.text}\n </span>,\n );\n }\n\n return rendered;\n}\n\nfunction ConditionDisplay({\n branchType,\n condition,\n editable = true,\n onConditionChange,\n onBackspaceEmpty,\n onConditionBlur,\n}: ConditionDisplayProps) {\n const [isEditing, setIsEditing] = useState(false);\n const [draftValue, setDraftValue] = useState(condition);\n const inputRef = useRef<HTMLInputElement>(null);\n const autoFocusedRef = useRef(false);\n\n useEffect(() => {\n if (!isEditing) {\n setDraftValue(condition);\n }\n }, [condition, isEditing]);\n\n useEffect(() => {\n if (isEditing) {\n inputRef.current?.focus();\n inputRef.current?.select();\n }\n }, [isEditing]);\n\n // Auto-enter edit mode once when condition is empty (newly inserted)\n useEffect(() => {\n if (editable && !condition && !autoFocusedRef.current) {\n autoFocusedRef.current = true;\n setIsEditing(true);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (branchType === 'else') {\n return <span className=\"jinja-otherwise\">Otherwise</span>;\n }\n\n const commit = () => {\n // Dispatch the value change BEFORE leaving edit mode.\n // If setIsEditing(false) runs first, ProseMirror regains focus and\n // triggers a re-render with stale node.attrs, losing the draft.\n if (draftValue !== condition) {\n onConditionChange(draftValue);\n }\n setIsEditing(false);\n onConditionBlur?.();\n };\n\n const cancel = () => {\n setDraftValue(condition);\n setIsEditing(false);\n };\n\n if (isEditing && editable) {\n return (\n <input\n ref={inputRef}\n className=\"jinja-condition-input\"\n value={draftValue}\n placeholder={CONDITION_PLACEHOLDER}\n onChange={(event) => setDraftValue(event.target.value)}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commit();\n }\n\n if (event.key === 'Escape') {\n event.preventDefault();\n cancel();\n }\n\n if (event.key === 'Backspace' && draftValue === '' && onBackspaceEmpty) {\n event.preventDefault();\n onBackspaceEmpty();\n }\n }}\n />\n );\n }\n\n return (\n <button\n type=\"button\"\n className=\"jinja-branch-condition\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (editable) {\n setDraftValue(condition);\n setIsEditing(true);\n }\n }}\n >\n {condition.length > 0 ? (\n renderCondition(condition)\n ) : (\n <span className=\"jinja-condition-placeholder\">{CONDITION_PLACEHOLDER}</span>\n )}\n </button>\n );\n}\n\nfunction BranchPopupMenu({ items, position }: BranchPopupMenuProps) {\n return (\n <div\n className=\"jinja-popup-menu\"\n style={{\n top: position.top,\n left: position.left,\n right: position.right,\n }}\n role=\"menu\"\n >\n {items.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n className=\"jinja-popup-item\"\n disabled={item.disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (!item.disabled) {\n item.onSelect();\n }\n }}\n role=\"menuitem\"\n >\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n\nfunction JinjaBranchHeader({\n branchType,\n condition,\n editable = true,\n isBodyEmpty,\n isBodyTouched,\n onConditionChange,\n onDelete,\n onAddBranch,\n isLastBranch,\n hasElseBranch,\n}: JinjaBranchHeaderProps) {\n const [menuSource, setMenuSource] = useState<'kebab' | 'footer' | null>(null);\n const kebabRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!menuSource) return;\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (kebabRef.current?.contains(target) || footerRef.current?.contains(target)) {\n return;\n }\n setMenuSource(null);\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setMenuSource(null);\n }\n };\n\n document.addEventListener('pointerdown', handlePointerDown, true);\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown, true);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [menuSource]);\n\n const menuItems: PopupMenuItem[] = [];\n\n if (editable) {\n menuItems.push({\n label: 'Delete',\n onSelect: onDelete,\n });\n }\n\n const canOpenFooterMenu = editable && isLastBranch && branchType !== 'else';\n const isMenuOpen = (source: 'kebab' | 'footer') => menuSource === source && menuItems.length > 0;\n\n // Track whether the condition input has been blurred at least once\n const [conditionTouched, setConditionTouched] = useState(false);\n\n // Condition validation — show error after blur:\n // - empty condition after touch → \"This field is required.\"\n // - non-empty invalid syntax → parser error message\n const conditionError = (() => {\n if (branchType === 'else') return null;\n if (condition.length === 0) {\n return conditionTouched ? 'This field is required.' : null;\n }\n const result = validateCondition(condition);\n return result.valid ? null : (result.error || 'Invalid condition');\n })();\n\n return (\n <>\n <div className={`jinja-branch-header${conditionError ? ' jinja-branch-header-invalid' : ''}`}>\n <span className={`jinja-branch-badge jinja-branch-badge-${branchType}`}>\n {branchType === 'elif' ? 'ELSE IF' : branchType.toUpperCase()}\n </span>\n <ConditionDisplay\n branchType={branchType}\n condition={condition}\n editable={editable}\n onConditionChange={onConditionChange}\n onBackspaceEmpty={onDelete}\n onConditionBlur={() => setConditionTouched(true)}\n />\n {editable ? (\n <div className=\"jinja-branch-actions\" ref={kebabRef}>\n <button\n type=\"button\"\n className=\"jinja-ghost-btn\"\n aria-label={`${branchType} branch options`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (menuItems.length > 0) {\n setMenuSource((current) => (current === 'kebab' ? null : 'kebab'));\n }\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\"><circle cx=\"8\" cy=\"3\" r=\"1.5\"/><circle cx=\"8\" cy=\"8\" r=\"1.5\"/><circle cx=\"8\" cy=\"13\" r=\"1.5\"/></svg>\n </button>\n {isMenuOpen('kebab') ? (\n <BranchPopupMenu\n position={{ top: 28, right: 0 }}\n items={menuItems.map((item) => ({\n ...item,\n onSelect: () => {\n setMenuSource(null);\n item.onSelect();\n },\n }))}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n\n {conditionError && <div className=\"jinja-condition-error\">{conditionError}</div>}\n\n {isBodyEmpty && isBodyTouched && editable && (\n <div className=\"jinja-body-error\">This field is required.</div>\n )}\n\n {isLastBranch && editable ? (\n <div className=\"jinja-add-footer\">\n <div className=\"jinja-add-footer-col\">\n <div className=\"jinja-add-footer-actions\" ref={footerRef}>\n <button\n type=\"button\"\n className=\"jinja-ghost-btn\"\n aria-label=\"Add branch\"\n disabled={!canOpenFooterMenu}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (canOpenFooterMenu && menuItems.length > 0) {\n setMenuSource((current) => (current === 'footer' ? null : 'footer'));\n }\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"><line x1=\"8\" y1=\"3\" x2=\"8\" y2=\"13\"/><line x1=\"3\" y1=\"8\" x2=\"13\" y2=\"8\"/></svg>\n </button>\n {isMenuOpen('footer') ? (\n <BranchPopupMenu\n position={{ top: 28, left: 0 }}\n items={menuItems\n .filter((item) => item.label === 'Else if' || item.label === 'Else')\n .map((item) => ({\n ...item,\n onSelect: () => {\n setMenuSource(null);\n item.onSelect();\n },\n }))}\n />\n ) : null}\n </div>\n </div>\n </div>\n ) : null}\n </>\n );\n}\n\nclass JinjaIfBlockView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n constructor() {\n this.dom = document.createElement('div');\n this.dom.className = 'jinja-if-block';\n this.dom.setAttribute('data-jinja-if-block', '');\n this.contentDOM = this.dom;\n // Deferred: notify children to re-render after all siblings are mounted\n requestAnimationFrame(() => this.notifyChildren());\n }\n\n private notifyChildren() {\n this.dom.querySelectorAll('.jinja-branch').forEach((el) => {\n el.dispatchEvent(new CustomEvent('jinja-siblings-changed', { bubbles: false }));\n });\n }\n\n update(node: PMNode): boolean {\n if (node.type.name !== 'jinjaIfBlock') return false;\n requestAnimationFrame(() => this.notifyChildren());\n return true;\n }\n}\n\nclass JinjaIfBranchView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n private headerContainer: HTMLElement;\n private root: Root;\n private node: PMNode;\n private view: EditorView;\n private getPos: () => number | undefined;\n private bodyTouched = false;\n\n constructor(node: PMNode, view: EditorView, getPos: () => number | undefined) {\n this.node = node;\n this.view = view;\n this.getPos = getPos;\n\n StyleManager.acquire();\n\n this.dom = document.createElement('div');\n this.headerContainer = document.createElement('div');\n const body = document.createElement('div');\n const dividerColumn = document.createElement('div');\n const divider = document.createElement('div');\n\n this.dom.appendChild(this.headerContainer);\n this.dom.appendChild(body);\n\n this.headerContainer.className = 'jinja-branch-controls';\n this.headerContainer.contentEditable = 'false';\n\n body.className = 'jinja-branch-body';\n dividerColumn.className = 'jinja-branch-divider-col';\n dividerColumn.contentEditable = 'false';\n divider.className = 'jinja-branch-divider';\n dividerColumn.appendChild(divider);\n\n this.contentDOM = document.createElement('div');\n this.contentDOM.className = 'jinja-branch-content';\n this.contentDOM.setAttribute('data-placeholder', PLACEHOLDER_TEXT);\n\n body.appendChild(dividerColumn);\n body.appendChild(this.contentDOM);\n\n // Track body blur — show \"required\" error when body is empty after losing focus\n this.contentDOM.addEventListener('focusout', () => {\n if (!this.bodyTouched && isBranchBodyEmpty(this.node)) {\n this.bodyTouched = true;\n this.render();\n }\n });\n\n this.root = createRoot(this.headerContainer);\n\n // Listen for sibling changes (dispatched by parent JinjaIfBlockView)\n this._onSiblingsChanged = () => this.render();\n this.dom.addEventListener('jinja-siblings-changed', this._onSiblingsChanged);\n\n // Listen for editable changes (dispatched by the editable-watcher plugin)\n this._onEditableChanged = () => this.render();\n this.dom.addEventListener('jinja-editable-changed', this._onEditableChanged);\n\n this.syncDOM();\n this.render();\n }\n\n private _onSiblingsChanged: (() => void) | null = null;\n private _onEditableChanged: (() => void) | null = null;\n\n private syncDOM(): void {\n const branchType = this.node.attrs.branchType as BranchType;\n this.dom.className = `jinja-branch jinja-branch-${branchType}`;\n this.dom.setAttribute('data-jinja-branch', '');\n this.dom.setAttribute('data-branch-type', branchType);\n this.dom.setAttribute('data-condition', String(this.node.attrs.condition ?? ''));\n\n this.contentDOM.classList.toggle('jinja-branch-content-empty', isBranchBodyEmpty(this.node));\n }\n\n private render(): void {\n const nodePos = this.getPos();\n\n let context: BranchContext | null = null;\n let lastBranch: { index: number } | null = null;\n if (nodePos != null) {\n context = getBranchContext(this.view, nodePos);\n lastBranch = getLastBranchOfBlock(this.view, nodePos);\n\n // Set data-branch-index\n let branchIdx = context?.branchIndex ?? -1;\n if (branchIdx < 0 && this.dom.parentElement) {\n const siblings = this.dom.parentElement.querySelectorAll(':scope > [data-jinja-branch]');\n branchIdx = Array.prototype.indexOf.call(siblings, this.dom);\n }\n if (branchIdx >= 0) {\n this.dom.setAttribute('data-branch-index', String(branchIdx));\n }\n }\n\n const branchType = this.node.attrs.branchType as BranchType;\n const condition = String(this.node.attrs.condition ?? '');\n\n // Use safe defaults when context is unavailable (e.g. right after insertion)\n const isLast = context && lastBranch ? lastBranch.index === context.branchIndex : true;\n const lastNonElseIdx = context ? getLastNonElseBranchIndex(this.view, nodePos!) : 0;\n const showAddButton = context ? context.branchIndex === lastNonElseIdx : true;\n\n // Add/remove last-branch class for L-shaped divider\n this.dom.classList.toggle('jinja-branch-last', isLast);\n\n this.root.render(\n <JinjaBranchHeader\n branchType={branchType}\n condition={condition}\n editable={this.view.editable && this.view.dom.getAttribute('contenteditable') !== 'false'}\n isBodyEmpty={isBranchBodyEmpty(this.node)}\n isBodyTouched={this.bodyTouched}\n isLastBranch={showAddButton}\n hasElseBranch={context && nodePos != null ? getElseBranch(this.view, nodePos) : false}\n onConditionChange={(value) => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n\n const tr = this.view.state.tr.setNodeMarkup(currentPos, undefined, {\n ...this.node.attrs,\n condition: value,\n });\n // Move cursor into the branch's content (first paragraph)\n // Branch structure: branchNode > paragraph > ...\n // Content starts at currentPos + 1 (inside branch) + 1 (inside first child)\n const contentPos = currentPos + 2;\n if (contentPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.near(tr.doc.resolve(contentPos)));\n }\n this.view.dispatch(tr.scrollIntoView());\n this.view.focus();\n }}\n onDelete={() => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n deleteBranch(this.view, currentPos, branchType);\n }}\n onAddBranch={(nextBranchType) => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n insertNewBranch(this.view, currentPos, nextBranchType, '');\n }}\n />,\n );\n }\n\n update(node: PMNode): boolean {\n if (!isBranchNode(node)) return false;\n\n this.node = node;\n this.syncDOM();\n this.render();\n return true;\n }\n\n stopEvent(event: Event): boolean {\n const target = event.target as Node | null;\n return target != null && this.headerContainer.contains(target);\n }\n\n ignoreMutation(mutation: ViewMutationRecord): boolean {\n // Must also ignore mutations on this.dom itself — syncDOM() and render()\n // modify className/attributes on the NodeView root element. Without this,\n // ProseMirror's DOMObserver re-parses the DOM on every attribute change,\n // triggering update() → syncDOM() → attribute change → re-parse → infinite loop.\n return mutation.target === this.dom || this.headerContainer.contains(mutation.target);\n }\n\n destroy(): void {\n if (this._onSiblingsChanged) {\n this.dom.removeEventListener('jinja-siblings-changed', this._onSiblingsChanged);\n }\n if (this._onEditableChanged) {\n this.dom.removeEventListener('jinja-editable-changed', this._onEditableChanged);\n }\n StyleManager.release();\n setTimeout(() => this.root.unmount(), 0);\n }\n}\n\n/**\n * ProseMirror plugin that watches for `view.editable` changes and notifies\n * JinjaIfBranchView NodeViews so they can re-render edit-only controls.\n *\n * ProseMirror does NOT trigger NodeView.update() when `editable` changes\n * (only when the document node changes). Without this plugin, stale UI\n * (e.g. the \"+\" add-branch button) persists after switching to view mode.\n */\nfunction createEditableWatcherPlugin(): Plugin {\n let lastEditable: boolean | null = null;\n\n return new Plugin({\n view(editorView) {\n lastEditable = editorView.editable;\n return {\n update(view) {\n const currentEditable = view.editable;\n if (lastEditable !== null && lastEditable !== currentEditable) {\n // Notify all jinja branch NodeViews to re-render\n const event = new Event('jinja-editable-changed', { bubbles: true });\n view.dom.querySelectorAll('[data-jinja-branch]').forEach((el) => {\n el.dispatchEvent(event);\n });\n }\n lastEditable = currentEditable;\n },\n };\n },\n });\n}\n\nexport function createJinjaIfBlockPlugin(): ActionbookPlugin {\n return {\n name: 'jinjaIfBlock',\n plugins: () => [createEditableWatcherPlugin()],\n nodeViews: () => ({\n jinjaIfBlock: (() => new JinjaIfBlockView()) as NodeViewFactory,\n jinjaIfBranch: ((node: PMNode, view: EditorView, getPos: () => number | undefined) => (\n new JinjaIfBranchView(node, view, getPos)\n )) as NodeViewFactory,\n }),\n };\n}\n","/**\n * Link editing plugin for the Actionbook editor.\n *\n * UX flow:\n * 1. `[aa](#aa)` is rendered as a clickable \"aa\" link mark.\n * 2. Pressing Backspace while cursor is inside or just after the link\n * \"explodes\" it to raw markdown `[aa](#aa)` for editing.\n * 3. While the cursor stays inside the raw text, normal editing applies.\n * 4. When the cursor leaves the raw region:\n * - If the text still matches `[label](href)` → reconverts to link mark.\n * - Otherwise → stays as plain text (user intentionally broke the link).\n * 5. Completing the markdown syntax by typing `)` triggers the input rule\n * and immediately converts to a link mark.\n */\n\nimport { InputRule, inputRules } from 'prosemirror-inputrules';\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport type { Mark, MarkType, ResolvedPos } from 'prosemirror-model';\nimport type { ActionbookPlugin } from './types';\n\n// ── Regexes ──────────────────────────────────────────────────────────────────\n\n/** Matches a fully typed `[label](href)` or `[label](href \"title\")` at end of input. */\n// Match [label](href) — also handles escaped brackets \\[ \\]\nconst LINK_INPUT_RE = /\\\\?\\[([^\\]]*?)\\\\?\\]\\(([^)\\s]*?)(?:\\s+\"([^\"]*)\")?\\)$/;\n\n/**\n * Matches raw link text that spans the entire string.\n * Used to validate/reconvert after cursor leaves the raw editing region.\n */\n// Match [label](href) — also handles escaped brackets \\[ \\] from markdown roundtrip\nconst LINK_FULL_RE = /^\\\\?\\[([^\\]]*?)\\\\?\\]\\(([^)\\s]*?)(?:\\s+\"([^\"]*)\")?\\)$/;\n\n// ── Plugin state ──────────────────────────────────────────────────────────────\n\ninterface LinkEditState {\n /** Absolute positions of the raw `[label](href)` text currently being edited. */\n rawRange: { from: number; to: number } | null;\n}\n\nconst linkEditKey = new PluginKey<LinkEditState>('linkEdit');\n\n// ── Utilities ─────────────────────────────────────────────────────────────────\n\n/**\n * Find the contiguous extent of a mark type around a resolved position.\n *\n * Handles `inclusive: false` marks (like `link`) correctly: when cursor is\n * placed just AFTER the mark text, the last node of the mark span is found\n * via `childBefore` and the full range is returned.\n */\nfunction getMarkRange(\n $pos: ResolvedPos,\n type: MarkType,\n): { from: number; to: number; mark: Mark } | null {\n const { parentOffset } = $pos;\n\n let child = $pos.parent.childAfter(parentOffset);\n\n // When cursor is exactly at a node boundary, also try the node ending here.\n if (parentOffset === child.offset && child.offset !== 0) {\n child = $pos.parent.childBefore(parentOffset);\n }\n\n if (!child.node) return null;\n\n const mark = child.node.marks.find((m) => m.type === type);\n if (!mark) return null;\n\n const parentStart = $pos.start();\n let { index: startIndex } = child;\n let startPos = parentStart + child.offset;\n let endIndex = startIndex + 1;\n let endPos = startPos + child.node.nodeSize;\n\n while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {\n startIndex -= 1;\n startPos -= $pos.parent.child(startIndex).nodeSize;\n }\n\n while (\n endIndex < $pos.parent.childCount &&\n mark.isInSet($pos.parent.child(endIndex).marks)\n ) {\n endPos += $pos.parent.child(endIndex).nodeSize;\n endIndex += 1;\n }\n\n return { from: startPos, to: endPos, mark };\n}\n\n/**\n * Replace a link mark span with its raw markdown text `[label](href)`.\n *\n * Cursor placement after explosion: maps the cursor offset within the link\n * label to the same relative position in the raw text (adding 1 for the\n * leading `[`). For cursor at the end of the label, this positions just\n * before `]`, which is natural for continued editing.\n *\n * Returns `null` when the cursor is not at/inside a link mark.\n */\nfunction explodeLinkToRaw(state: EditorState): Transaction | null {\n const { selection, doc, schema } = state;\n if (!selection.empty) return null;\n\n const linkMarkType = schema.marks.link;\n if (!linkMarkType) return null;\n\n const $pos = doc.resolve(selection.from);\n const range = getMarkRange($pos, linkMarkType);\n if (!range) return null;\n\n const { from, to, mark } = range;\n const label = doc.textBetween(from, to);\n const { href, title } = mark.attrs as { href: string; title: string | null };\n const titlePart = title ? ` \"${title}\"` : '';\n const rawText = `[${label}](${href}${titlePart})`;\n\n // +1 for the leading `[`, clamped to label length\n const cursorOffset = Math.min(selection.from - from, label.length);\n const rawCursorOffset = cursorOffset + 1;\n\n const tr = state.tr;\n tr.replaceWith(from, to, schema.text(rawText));\n\n const newPos = Math.min(from + rawCursorOffset, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));\n tr.setMeta(linkEditKey, { from, to: from + rawText.length });\n\n return tr;\n}\n\n// ── Auto-reconvert plugin ─────────────────────────────────────────────────────\n\n/**\n * Tracks the raw editing region after a link explosion and reconverts it back\n * to a link mark when the cursor moves outside that region.\n */\nfunction createLinkEditPlugin(): Plugin<LinkEditState> {\n return new Plugin<LinkEditState>({\n key: linkEditKey,\n\n state: {\n init: (): LinkEditState => ({ rawRange: null }),\n\n apply(tr, prev): LinkEditState {\n const meta = tr.getMeta(linkEditKey) as\n | { from: number; to: number }\n | null\n | undefined;\n\n if (meta !== undefined) return { rawRange: meta };\n\n if (prev.rawRange) {\n const from = tr.mapping.map(prev.rawRange.from, -1);\n const to = tr.mapping.map(prev.rawRange.to, -1);\n if (from >= to) return { rawRange: null };\n return { rawRange: { from, to } };\n }\n\n return prev;\n },\n },\n\n appendTransaction(_, __, newState) {\n const pluginState = linkEditKey.getState(newState);\n if (!pluginState?.rawRange) return null;\n\n const { from, to } = pluginState.rawRange;\n\n // Still inside — nothing to do (strict < to so cursor AT the end triggers reconvert)\n if (newState.selection.anchor >= from && newState.selection.anchor < to) {\n return null;\n }\n\n const docSize = newState.doc.content.size;\n const safeFrom = Math.min(from, docSize);\n const safeTo = Math.min(to, docSize);\n\n const reconvertTr = newState.tr;\n reconvertTr.setMeta(linkEditKey, null);\n\n if (safeFrom < safeTo) {\n const text = newState.doc.textBetween(safeFrom, safeTo);\n const match = LINK_FULL_RE.exec(text);\n\n if (match) {\n const [, label, href, title] = match;\n const linkMarkType = newState.schema.marks.link;\n\n // Empty label → delete the entire raw link text (no invisible markup left)\n if (!label) {\n reconvertTr.delete(safeFrom, safeTo);\n } else if (linkMarkType && href) {\n const attrs = title ? { href, title: title.trim() } : { href };\n reconvertTr.delete(safeFrom, safeTo);\n reconvertTr.insertText(label, safeFrom);\n reconvertTr.addMark(\n safeFrom,\n safeFrom + label.length,\n linkMarkType.create(attrs),\n );\n }\n }\n }\n\n return reconvertTr;\n },\n });\n}\n\n// ── Input rule ────────────────────────────────────────────────────────────────\n\n/**\n * When the user completes `[label](href)` by typing `)`, immediately convert\n * the matched text to a link mark. Works both for fresh typing and for\n * finalising an edited raw-exploded link.\n */\nfunction createLinkInputRule(): InputRule {\n return new InputRule(\n LINK_INPUT_RE,\n (state, match, start, end) => {\n const [, label, href, title] = match;\n const linkMarkType = state.schema.marks.link;\n if (!linkMarkType) return null;\n\n const { tr } = state;\n\n // Empty label → delete the entire link syntax (no invisible [](url) left)\n if (!label) {\n tr.delete(start, end);\n tr.setMeta(linkEditKey, null);\n return tr;\n }\n\n if (!href) return null;\n\n const attrs = title ? { href, title: title.trim() } : { href };\n tr.replaceWith(start, end, state.schema.text(label));\n tr.addMark(start, start + label.length, linkMarkType.create(attrs));\n tr.setMeta(linkEditKey, null);\n\n return tr;\n },\n );\n}\n\n// ── Click handler (anchor navigation) ────────────────────────────────────────\n\nfunction createLinkClickPlugin(): Plugin {\n return new Plugin({\n key: new PluginKey('linkClick'),\n props: {\n handleDOMEvents: {\n click: (_view, event) => {\n const target = event.target as HTMLElement;\n if (target.tagName !== 'A') return false;\n\n const href = (target as HTMLAnchorElement).getAttribute('href');\n if (!href) return false;\n\n // Internal jump-point links (#section) — scroll instead of navigate\n if (href.startsWith('#')) {\n event.preventDefault();\n const targetId = `jp-${href.slice(1)}`;\n const el = document.getElementById(targetId);\n if (el) {\n el.scrollIntoView({ block: 'end' });\n el.focus();\n if (el.parentElement) {\n el.parentElement.style.outline = '2px solid #6213cc';\n setTimeout(() => {\n (el.parentElement as HTMLElement).style.outline = 'none';\n }, 500);\n }\n }\n return true;\n }\n\n return false;\n },\n },\n },\n });\n}\n\n// ── Public factory ────────────────────────────────────────────────────────────\n\n/**\n * Creates the link editing `ActionbookPlugin`.\n *\n * Bundles:\n * - Backspace → explode to raw markdown\n * - `appendTransaction` auto-reconvert on cursor leave\n * - Input rule for `[label](href)` → link mark\n * - Click handler for internal `#anchor` links\n */\nexport function createLinkPlugin(): ActionbookPlugin {\n return {\n name: 'link',\n plugins: () => [\n createLinkEditPlugin(),\n createLinkClickPlugin(),\n inputRules({ rules: [createLinkInputRule()] }),\n ],\n keymap: () => ({\n Backspace: (state, dispatch) => {\n if (!state.selection.empty) return false;\n\n // Already in raw-edit mode — let normal Backspace through\n if (linkEditKey.getState(state)?.rawRange) return false;\n\n const tr = explodeLinkToRaw(state);\n if (!tr) return false;\n\n if (dispatch) dispatch(tr);\n return true;\n },\n }),\n };\n}\n","/**\n * Drag handle plugin v2 — enterprise-grade block reordering.\n *\n * Key improvements over v1:\n * - Diff-based handle updates (no full DOM rebuild per transaction)\n * - Pointer Events API (unified mouse/touch/pen)\n * - Auto-scroll during drag\n * - Keyboard accessibility (Alt+Arrow, ARIA)\n * - CSS custom properties for theming\n * - Proper style cleanup via adopted stylesheets / ref-count\n * - Class-based state management for testability\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorView } from 'prosemirror-view';\nimport type { Node as PMNode, ResolvedPos } from 'prosemirror-model';\nimport type { Transaction, EditorState, Command } from 'prosemirror-state';\nimport type { ActionbookPlugin } from './types';\n\n// ────────────────────────────────────────────────────────────\n// Constants\n// ────────────────────────────────────────────────────────────\n\nconst PLUGIN_KEY = new PluginKey('dragHandle');\n\nconst GRIP_SVG = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"4\" cy=\"2.5\" r=\"1.2\"/><circle cx=\"8\" cy=\"2.5\" r=\"1.2\"/>\n <circle cx=\"4\" cy=\"6\" r=\"1.2\"/><circle cx=\"8\" cy=\"6\" r=\"1.2\"/>\n <circle cx=\"4\" cy=\"9.5\" r=\"1.2\"/><circle cx=\"8\" cy=\"9.5\" r=\"1.2\"/>\n</svg>`;\n\nconst AUTO_SCROLL_ZONE = 40;\nconst AUTO_SCROLL_MAX_SPEED = 8;\nconst HANDLE_GAP = 4;\nexport const DRAG_THRESHOLD = 5;\n\n// ────────────────────────────────────────────────────────────\n// Styles (CSS custom properties for theming)\n// ────────────────────────────────────────────────────────────\n\nconst STYLES = /* css */ `\n.ab-drag-handle-layer {\n --ab-dh-color-idle: transparent;\n --ab-dh-color-hover: #c4c4c4;\n --ab-dh-color-visible: #8b8b8b;\n --ab-dh-color-accent: rgba(1,156,110,0.8);\n --ab-dh-bg-hover: rgba(13,13,13,0.04);\n --ab-dh-bg-active: rgba(13,13,13,0.04);\n --ab-dh-dragging-opacity: 0.4;\n --ab-dh-handle-size: 24px;\n --ab-dh-handle-radius: 4px;\n --ab-dh-transition-duration: 0.15s;\n\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n pointer-events: none;\n overflow: visible;\n}\n.ab-drag-handle {\n position: absolute;\n width: var(--ab-dh-handle-size);\n height: var(--ab-dh-handle-size);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: grab;\n color: transparent;\n border-radius: var(--ab-dh-handle-radius);\n transition: none;\n user-select: none;\n pointer-events: auto;\n touch-action: none;\n opacity: 0;\n pointer-events: none;\n overflow: visible;\n}\n.ab-drag-handle.ab-dh-active {\n opacity: 1;\n pointer-events: auto;\n color: var(--ab-dh-color-visible);\n}\n.ab-drag-handle:hover {\n color: var(--ab-dh-color-visible) !important;\n background: var(--ab-dh-bg-hover);\n}\n.ab-drag-handle:hover::after {\n content: 'Drag to move';\n position: absolute;\n bottom: calc(100% + 4px);\n left: 0;\n background: #2e2e2e;\n color: #fff;\n font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 400;\n line-height: 16px;\n padding: 4px 8px;\n border-radius: 4px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 30;\n}\n.ab-drag-handle:hover::before {\n content: '';\n position: absolute;\n bottom: calc(100% + 0px);\n left: 8px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 5px solid #2e2e2e;\n pointer-events: none;\n z-index: 31;\n}\n.ab-drag-handle.dragging::after,\n.ab-drag-handle.dragging::before {\n display: none;\n}\n.ab-dh-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: #fff;\n border-radius: 4px;\n box-shadow: 0px 8px 10px 1px rgba(13,13,13,0.12), 0px 3px 14px 2px rgba(13,13,13,0.08), 0px 3px 5px -3px rgba(13,13,13,0.04);\n padding: 8px 0;\n z-index: 40;\n min-width: 120px;\n}\n.ab-dh-menu-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 6px 16px;\n border: none;\n background: #fff;\n cursor: pointer;\n font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n letter-spacing: -0.1px;\n color: #0d0d0d;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.ab-dh-menu-item:hover {\n background: rgba(0,0,0,0.04);\n}\n.ab-drag-handle:active, .ab-drag-handle.dragging {\n cursor: grabbing;\n color: var(--ab-dh-color-accent) !important;\n background: var(--ab-dh-bg-active);\n}\n.ab-drop-indicator {\n position: absolute;\n left: 0; right: 0;\n height: 4px;\n background: rgba(1,156,110,0.4);\n border: 1px solid rgba(1,156,110,0.6);\n border-radius: 12px;\n pointer-events: none;\n z-index: 20;\n box-sizing: border-box;\n transition: top 60ms ease-out;\n}\n.ab-block-dragging {\n opacity: var(--ab-dh-dragging-opacity, 0.4);\n}\n@keyframes ab-block-flash {\n from { background: rgba(1,156,110,0.08); }\n to { background: transparent; }\n}\n.ab-block-just-moved {\n animation: ab-block-flash 0.4s ease-out;\n}\n.ab-sr-only {\n position: absolute;\n width: 1px; height: 1px;\n padding: 0; margin: -1px;\n overflow: hidden;\n clip: rect(0,0,0,0);\n white-space: nowrap;\n border: 0;\n}\n`;\n\n// ────────────────────────────────────────────────────────────\n// Style Manager (ref-counted, leak-free)\n// ────────────────────────────────────────────────────────────\n\nclass StyleManager {\n private static refCount = 0;\n private static sheet: CSSStyleSheet | null = null;\n private static styleEl: HTMLStyleElement | null = null;\n\n static acquire(): void {\n if (this.refCount++ > 0) return;\n\n if (typeof CSSStyleSheet !== 'undefined' && 'replaceSync' in CSSStyleSheet.prototype) {\n this.sheet = new CSSStyleSheet();\n this.sheet.replaceSync(STYLES);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, this.sheet];\n } else {\n // Fallback for older browsers\n this.styleEl = document.createElement('style');\n this.styleEl.id = 'ab-drag-handle-styles';\n this.styleEl.textContent = STYLES;\n document.head.appendChild(this.styleEl);\n }\n }\n\n static release(): void {\n if (--this.refCount > 0) return;\n\n if (this.sheet) {\n document.adoptedStyleSheets = document.adoptedStyleSheets.filter(s => s !== this.sheet);\n this.sheet = null;\n }\n if (this.styleEl) {\n this.styleEl.remove();\n this.styleEl = null;\n }\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Types\n// ────────────────────────────────────────────────────────────\n\ninterface BlockInfo {\n offset: number;\n nodeSize: number;\n dom: HTMLElement;\n}\n\ninterface HandleEntry {\n el: HTMLElement;\n block: BlockInfo;\n topPx: number;\n listenerCleanup: () => void;\n}\n\ninterface DragState {\n fromIndex: number;\n handle: HTMLElement;\n blockDom: HTMLElement;\n dropTargetIndex: number;\n pointerY: number;\n pointerId: number;\n startX: number;\n startY: number;\n activated: boolean;\n ghost: HTMLElement | null;\n}\n\n// ────────────────────────────────────────────────────────────\n// Pure helpers (exported for testing)\n// ────────────────────────────────────────────────────────────\n\n/**\n * Build a PM transaction that moves the top-level block at `fromIndex`\n * to `toIndex` (insert-before semantics: toIndex is counted in the\n * original ordering).\n *\n * Returns null if the move is a no-op or out of bounds.\n */\nexport function buildMoveTransaction(\n state: EditorState,\n fromIndex: number,\n toIndex: number,\n): Transaction | null {\n const { doc } = state;\n if (fromIndex === toIndex || fromIndex + 1 === toIndex) return null;\n if (fromIndex < 0 || fromIndex >= doc.childCount) return null;\n if (toIndex < 0 || toIndex > doc.childCount) return null;\n\n const node = doc.child(fromIndex);\n\n // Collect offsets of each top-level block\n const offsets: number[] = [];\n doc.forEach((_child, offset) => { offsets.push(offset); });\n\n const nodeStart = offsets[fromIndex];\n const nodeEnd = nodeStart + node.nodeSize;\n\n let tr = state.tr;\n\n if (toIndex > fromIndex) {\n // Moving down: insert first, then delete (keeps positions valid)\n const targetEnd = offsets[toIndex - 1] + doc.child(toIndex - 1).nodeSize;\n tr = tr.insert(targetEnd, node);\n tr = tr.delete(tr.mapping.map(nodeStart), tr.mapping.map(nodeEnd));\n } else {\n // Moving up: delete first, then insert\n const insertPos = offsets[toIndex];\n tr = tr.delete(nodeStart, nodeEnd);\n tr = tr.insert(tr.mapping.map(insertPos), node);\n }\n\n return tr;\n}\n\n/**\n * Given a list of block bounding rects (top/bottom relative to container),\n * determine which gap the pointer is closest to.\n * Returns an index in [0, blocks.length] (insert-before semantics).\n */\nexport function findDropTarget(\n blockRects: Array<{ top: number; bottom: number }>,\n pointerY: number,\n): number {\n if (blockRects.length === 0) return 0;\n\n let bestIndex = 0;\n let bestDist = Infinity;\n\n for (let i = 0; i <= blockRects.length; i++) {\n let gapY: number;\n if (i === 0) {\n gapY = blockRects[0].top;\n } else if (i === blockRects.length) {\n gapY = blockRects[blockRects.length - 1].bottom;\n } else {\n gapY = (blockRects[i - 1].bottom + blockRects[i].top) / 2;\n }\n const dist = Math.abs(pointerY - gapY);\n if (dist < bestDist) {\n bestDist = dist;\n bestIndex = i;\n }\n }\n\n return bestIndex;\n}\n\n/**\n * Compute auto-scroll speed based on pointer proximity to container edges.\n * Returns pixels-per-frame (negative = up, positive = down, 0 = no scroll).\n */\nexport function computeAutoScrollSpeed(\n pointerY: number,\n containerTop: number,\n containerBottom: number,\n): number {\n if (pointerY < containerTop + AUTO_SCROLL_ZONE) {\n const ratio = Math.max(0, (pointerY - containerTop) / AUTO_SCROLL_ZONE);\n return -AUTO_SCROLL_MAX_SPEED * (1 - ratio);\n }\n if (pointerY > containerBottom - AUTO_SCROLL_ZONE) {\n const ratio = Math.max(0, (containerBottom - pointerY) / AUTO_SCROLL_ZONE);\n return AUTO_SCROLL_MAX_SPEED * (1 - ratio);\n }\n return 0;\n}\n\n/**\n * Compare two block lists and return which indices need create/remove/reposition.\n * A block is \"same\" if its offset and nodeSize match.\n */\nexport function diffBlockList(\n prev: Array<{ offset: number; nodeSize: number }>,\n next: Array<{ offset: number; nodeSize: number }>,\n): { added: number[]; removed: number[]; kept: Array<{ prevIdx: number; nextIdx: number }> } {\n const prevMap = new Map<string, number>();\n prev.forEach((b, i) => prevMap.set(`${b.offset}:${b.nodeSize}`, i));\n\n const added: number[] = [];\n const kept: Array<{ prevIdx: number; nextIdx: number }> = [];\n const usedPrev = new Set<number>();\n\n next.forEach((b, i) => {\n const key = `${b.offset}:${b.nodeSize}`;\n const prevIdx = prevMap.get(key);\n if (prevIdx !== undefined && !usedPrev.has(prevIdx)) {\n kept.push({ prevIdx, nextIdx: i });\n usedPrev.add(prevIdx);\n } else {\n added.push(i);\n }\n });\n\n const removed: number[] = [];\n prev.forEach((_, i) => {\n if (!usedPrev.has(i)) removed.push(i);\n });\n\n return { added, removed, kept };\n}\n\n// ────────────────────────────────────────────────────────────\n// DragHandleController\n// ────────────────────────────────────────────────────────────\n\nclass DragHandleController {\n private view: EditorView;\n private layer: HTMLElement;\n private liveRegion: HTMLElement;\n private handles: HandleEntry[] = [];\n private prevBlocks: BlockInfo[] = [];\n private drag: DragState | null = null;\n private dropIndicator: HTMLElement | null = null;\n private scrollRAF: number | null = null;\n private updateRAF: number | null = null;\n private pendingUpdate = false;\n private scrollContainer: HTMLElement;\n private scrollSyncRAF: number | null = null;\n private resizeObserver: ResizeObserver | null = null;\n\n // Hover state\n private hoverBound: { enter: () => void; leave: () => void } | null = null;\n\n // Global fallback handlers active during drag\n private globalCleanup: (() => void) | null = null;\n\n constructor(view: EditorView) {\n this.view = view;\n StyleManager.acquire();\n\n const parent = view.dom.parentNode as HTMLElement;\n const pos = getComputedStyle(parent).position;\n if (pos === 'static' || pos === '') parent.style.position = 'relative';\n\n // Create overlay layer\n this.layer = document.createElement('div');\n this.layer.className = 'ab-drag-handle-layer';\n parent.insertBefore(this.layer, view.dom.nextSibling);\n\n // ARIA live region for announcements\n this.liveRegion = document.createElement('div');\n this.liveRegion.className = 'ab-sr-only';\n this.liveRegion.setAttribute('aria-live', 'assertive');\n this.liveRegion.setAttribute('aria-atomic', 'true');\n parent.appendChild(this.liveRegion);\n\n // Hover listeners removed — handle visibility is now based on cursor block position.\n // Kept hoverBound for cleanup compatibility.\n this.hoverBound = { enter: () => {}, leave: () => {} };\n\n // Find scroll container\n this.scrollContainer = this.findScrollContainer(view.dom);\n\n // Scroll listener — reposition handles when container scrolls\n this.scrollContainer.addEventListener('scroll', this.onScroll, { passive: true });\n\n // Resize observer — recompute when editor dimensions change\n this.resizeObserver = new ResizeObserver(() => this.scheduleUpdate());\n this.resizeObserver.observe(view.dom);\n\n // Hide in non-editable mode\n if (!view.editable) {\n this.layer.style.display = 'none';\n }\n\n // Initial render\n this.rebuildHandles();\n }\n\n update(view: EditorView, prevState: EditorState): void {\n this.view = view;\n\n // Hide all handles in non-editable mode\n if (!view.editable) {\n this.layer.style.display = 'none';\n return;\n }\n this.layer.style.display = '';\n\n // Skip updates during drag — flush when drag ends\n if (this.drag) {\n this.pendingUpdate = true;\n return;\n }\n\n // Recompute when doc structure changes\n if (!view.state.doc.eq(prevState.doc)) {\n this.scheduleUpdate();\n }\n\n // Update active handle when selection changes\n if (!view.state.selection.eq(prevState.selection) || !view.state.doc.eq(prevState.doc)) {\n this.updateActiveHandle();\n }\n }\n\n /** Show only the handle for the block containing the cursor. */\n private updateActiveHandle(): void {\n const { $from } = this.view.state.selection;\n // Find the top-level block index that contains the cursor\n const cursorBlockOffset = $from.start(1) - 1; // offset of the top-level block\n\n for (const h of this.handles) {\n if (h.block.offset === cursorBlockOffset) {\n h.el.classList.add('ab-dh-active');\n } else {\n h.el.classList.remove('ab-dh-active');\n }\n }\n }\n\n destroy(): void {\n this.cancelDrag();\n\n if (this.updateRAF !== null) cancelAnimationFrame(this.updateRAF);\n if (this.scrollSyncRAF !== null) cancelAnimationFrame(this.scrollSyncRAF);\n this.scrollContainer.removeEventListener('scroll', this.onScroll);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n\n // Remove handles and their listeners\n for (const h of this.handles) {\n h.listenerCleanup();\n h.el.remove();\n }\n this.handles = [];\n\n // Remove hover listeners\n if (this.hoverBound) {\n const parent = this.view.dom.parentNode as HTMLElement | null;\n if (parent) {\n parent.removeEventListener('mouseenter', this.hoverBound.enter);\n parent.removeEventListener('mouseleave', this.hoverBound.leave);\n }\n }\n\n this.liveRegion.remove();\n this.layer.remove();\n StyleManager.release();\n }\n\n // ── Private: update pipeline ──\n\n private scheduleUpdate(): void {\n if (this.updateRAF !== null) return;\n this.updateRAF = requestAnimationFrame(() => {\n this.updateRAF = null;\n this.rebuildHandles();\n });\n }\n\n private onScroll = (): void => {\n if (this.scrollSyncRAF !== null) return;\n this.scrollSyncRAF = requestAnimationFrame(() => {\n this.scrollSyncRAF = null;\n if (!this.drag) this.syncHandlePositions();\n });\n };\n\n private collectBlocks(): BlockInfo[] {\n const blocks: BlockInfo[] = [];\n\n this.view.state.doc.forEach((node, offset) => {\n // nodeDOM returns the outermost DOM node for the block at this offset.\n // This is more reliable than domAtPos(offset + 1) which can resolve to\n // the wrong element for leaf blocks (e.g. horizontalRule with nodeSize=1).\n const dom = this.view.nodeDOM(offset);\n if (dom instanceof HTMLElement) {\n blocks.push({ offset, nodeSize: node.nodeSize, dom });\n }\n });\n\n return blocks;\n }\n\n private rebuildHandles(): void {\n const newBlocks = this.collectBlocks();\n const diff = diffBlockList(\n this.prevBlocks.map(b => ({ offset: b.offset, nodeSize: b.nodeSize })),\n newBlocks.map(b => ({ offset: b.offset, nodeSize: b.nodeSize })),\n );\n\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n const handleSize = parseInt(getComputedStyle(this.layer).getPropertyValue('--ab-dh-handle-size') || '22', 10);\n const handleLeft = editorRect.left - parentRect.left - handleSize - HANDLE_GAP;\n\n // Build new handles array preserving kept entries\n const newHandles: HandleEntry[] = new Array(newBlocks.length);\n\n // Reuse kept handles (reposition if needed)\n for (const { prevIdx, nextIdx } of diff.kept) {\n const entry = this.handles[prevIdx];\n entry.block = newBlocks[nextIdx];\n const blockRect = entry.block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(entry.block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n entry.topPx = topPx;\n entry.el.style.top = `${topPx}px`;\n entry.el.style.left = `${handleLeft}px`;\n // Update the index in the pointerdown closure\n this.rebindHandleIndex(entry, nextIdx);\n newHandles[nextIdx] = entry;\n }\n\n // Remove obsolete handles\n for (const idx of diff.removed) {\n const entry = this.handles[idx];\n entry.listenerCleanup();\n entry.el.remove();\n }\n\n // Create new handles\n for (const idx of diff.added) {\n const block = newBlocks[idx];\n const blockRect = block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n\n const el = document.createElement('div');\n el.className = 'ab-drag-handle';\n el.setAttribute('data-ab-float', '');\n el.setAttribute('role', 'button');\n el.setAttribute('aria-roledescription', 'drag handle');\n el.setAttribute('aria-label', `블록 ${idx + 1} 이동`);\n // Tooltip is shown via CSS ::after pseudo-element (no native title to avoid double tooltip)\n el.setAttribute('tabindex', '-1');\n el.innerHTML = GRIP_SVG;\n el.style.left = `${handleLeft}px`;\n el.style.top = `${topPx}px`;\n this.layer.appendChild(el);\n\n const cleanup = this.bindHandleEvents(el, idx);\n newHandles[idx] = { el, block, topPx, listenerCleanup: cleanup };\n }\n\n this.handles = newHandles;\n this.prevBlocks = newBlocks;\n\n // Set initial active handle based on cursor position\n this.updateActiveHandle();\n }\n\n private activeMenu: HTMLElement | null = null;\n private activeMenuCleanup: (() => void) | null = null;\n\n private dismissMenu() {\n if (this.activeMenu) {\n this.activeMenu.remove();\n this.activeMenu = null;\n }\n if (this.activeMenuCleanup) {\n this.activeMenuCleanup();\n this.activeMenuCleanup = null;\n }\n }\n\n private showMenu(el: HTMLElement, blockIndex: number) {\n this.dismissMenu();\n\n const menu = document.createElement('div');\n menu.className = 'ab-dh-menu';\n\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'ab-dh-menu-item';\n deleteBtn.textContent = 'Delete';\n\n deleteBtn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.deleteBlock(blockIndex);\n this.dismissMenu();\n });\n\n menu.appendChild(deleteBtn);\n el.appendChild(menu);\n this.activeMenu = menu;\n\n // Close on outside click\n const onOutside = (e: MouseEvent) => {\n if (!menu.contains(e.target as Node)) {\n this.dismissMenu();\n }\n };\n setTimeout(() => document.addEventListener('mousedown', onOutside, true), 0);\n this.activeMenuCleanup = () => document.removeEventListener('mousedown', onOutside, true);\n }\n\n private deleteBlock(blockIndex: number) {\n const blocks = this.collectBlocks();\n if (blockIndex >= blocks.length) return;\n const block = blocks[blockIndex];\n const from = block.offset;\n const to = block.offset + block.nodeSize;\n const tr = this.view.state.tr;\n tr.replaceWith(from, to, this.view.state.schema.nodes.paragraph.create());\n this.view.dispatch(tr);\n this.view.focus();\n }\n\n private bindHandleEvents(el: HTMLElement, index: number): () => void {\n let currentIndex = index;\n let downX = 0;\n let downY = 0;\n let didDrag = false;\n\n let menuWasOpen = false;\n\n const onPointerDown = (e: PointerEvent) => {\n // If clicking inside the menu, let the menu handle it\n if (this.activeMenu && this.activeMenu.contains(e.target as Node)) return;\n\n e.preventDefault();\n if (!this.view.editable) return;\n\n menuWasOpen = !!this.activeMenu;\n this.dismissMenu();\n\n downX = e.clientX;\n downY = e.clientY;\n didDrag = false;\n el.setPointerCapture(e.pointerId);\n this.prevBlocks = this.collectBlocks();\n this.syncHandlePositions();\n this.startDrag(currentIndex, el, e);\n };\n const onPointerMove = (e: PointerEvent) => {\n if (Math.abs(e.clientX - downX) > 3 || Math.abs(e.clientY - downY) > 3) {\n didDrag = true;\n }\n this.onPointerMove(e);\n };\n const onPointerUp = (e: PointerEvent) => {\n this.onPointerUp(e);\n // Toggle menu: if it was open before this click, don't reopen\n if (!didDrag && !menuWasOpen) {\n this.showMenu(el, currentIndex);\n }\n };\n const onLostCapture = () => this.cancelDrag();\n const onPointerCancel = () => this.cancelDrag();\n\n el.addEventListener('pointerdown', onPointerDown);\n el.addEventListener('pointermove', onPointerMove);\n el.addEventListener('pointerup', onPointerUp);\n el.addEventListener('pointercancel', onPointerCancel);\n el.addEventListener('lostpointercapture', onLostCapture);\n\n const cleanup = () => {\n el.removeEventListener('pointerdown', onPointerDown);\n el.removeEventListener('pointermove', onPointerMove);\n el.removeEventListener('pointerup', onPointerUp);\n el.removeEventListener('pointercancel', onPointerCancel);\n el.removeEventListener('lostpointercapture', onLostCapture);\n };\n\n (el as any).__abUpdateIndex = (newIdx: number) => { currentIndex = newIdx; };\n\n return cleanup;\n }\n\n private rebindHandleIndex(entry: HandleEntry, newIndex: number): void {\n const fn = (entry.el as any).__abUpdateIndex;\n if (fn) fn(newIndex);\n entry.el.setAttribute('aria-label', `블록 ${newIndex + 1} 이동`);\n }\n\n private syncHandlePositions(): void {\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n const handleSize = parseInt(getComputedStyle(this.layer).getPropertyValue('--ab-dh-handle-size') || '22', 10);\n const handleLeft = editorRect.left - parentRect.left - handleSize - HANDLE_GAP;\n\n for (const entry of this.handles) {\n if (!entry) continue;\n const blockRect = entry.block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(entry.block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n entry.topPx = topPx;\n entry.el.style.top = `${topPx}px`;\n entry.el.style.left = `${handleLeft}px`;\n }\n }\n\n // ── Private: drag lifecycle ──\n\n private startDrag(index: number, handle: HTMLElement, e: PointerEvent): void {\n const block = this.prevBlocks[index];\n if (!block) return;\n\n // Guard: clean up any existing drag first (e.g. multi-touch edge case)\n if (this.drag) {\n this.cleanupDragState();\n }\n\n this.drag = {\n fromIndex: index,\n handle,\n blockDom: block.dom,\n dropTargetIndex: index,\n pointerY: e.clientY,\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n activated: false,\n ghost: null,\n };\n\n // Global fallback handlers: catch pointerup/pointercancel even when\n // pointer capture is lost or events don't reach the handle element\n this.addGlobalDragListeners(e.pointerId);\n }\n\n private activateDrag(): void {\n if (!this.drag) return;\n\n this.drag.activated = true;\n this.drag.handle.classList.add('dragging');\n this.drag.blockDom.classList.add('ab-block-dragging');\n\n // Create ghost element — semi-transparent clone following cursor\n const blockRect = this.drag.blockDom.getBoundingClientRect();\n const ghost = this.drag.blockDom.cloneNode(true) as HTMLElement;\n ghost.className = 'ab-drag-ghost';\n ghost.style.cssText = `\n position: fixed;\n top: ${blockRect.top}px;\n left: ${blockRect.left}px;\n width: ${blockRect.width}px;\n opacity: 0.4;\n pointer-events: none;\n z-index: 9999;\n transition: none;\n `;\n document.body.appendChild(ghost);\n this.drag.ghost = ghost;\n // Store initial offset so ghost follows cursor smoothly\n (this.drag as any)._ghostOffsetY = this.drag.startY - blockRect.top;\n\n // Create drop indicator\n const parent = this.view.dom.parentNode as HTMLElement;\n this.dropIndicator = document.createElement('div');\n this.dropIndicator.className = 'ab-drop-indicator';\n this.dropIndicator.style.display = 'none';\n parent.appendChild(this.dropIndicator);\n\n // Start auto-scroll loop\n this.tickAutoScroll();\n }\n\n private addGlobalDragListeners(pointerId: number): void {\n const onDocPointerUp = (e: PointerEvent) => {\n if (e.pointerId === pointerId) this.onPointerUp(e);\n };\n const onDocPointerCancel = (e: PointerEvent) => {\n if (e.pointerId === pointerId) this.cancelDrag();\n };\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') this.cancelDrag();\n };\n\n document.addEventListener('pointerup', onDocPointerUp);\n document.addEventListener('pointercancel', onDocPointerCancel);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n this.globalCleanup = () => {\n document.removeEventListener('pointerup', onDocPointerUp);\n document.removeEventListener('pointercancel', onDocPointerCancel);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.drag || e.pointerId !== this.drag.pointerId) return;\n if (!this.view.editable) { this.cancelDrag(); return; }\n\n // Threshold check — only activate drag after moving 5px\n if (!this.drag.activated) {\n const dx = e.clientX - this.drag.startX;\n const dy = e.clientY - this.drag.startY;\n if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) return;\n this.activateDrag();\n }\n\n this.drag.pointerY = e.clientY;\n\n // Move ghost to follow cursor\n if (this.drag.ghost) {\n const offsetY = (this.drag as any)._ghostOffsetY ?? 0;\n this.drag.ghost.style.top = `${e.clientY - offsetY}px`;\n }\n\n this.updateDropTarget();\n }\n\n private updateDropTarget(): void {\n if (!this.drag || !this.dropIndicator) return;\n\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n\n // Build block rects relative to viewport\n const blockRects = this.prevBlocks.map(b => {\n const r = b.dom.getBoundingClientRect();\n return { top: r.top, bottom: r.bottom };\n });\n\n const targetIndex = findDropTarget(blockRects, this.drag.pointerY);\n this.drag.dropTargetIndex = targetIndex;\n\n // Compute indicator position\n let indicatorY: number;\n if (targetIndex === 0) {\n indicatorY = (blockRects[0]?.top ?? parentRect.top) - parentRect.top + parent.scrollTop - 1;\n } else if (targetIndex >= blockRects.length) {\n const last = blockRects[blockRects.length - 1];\n indicatorY = (last?.bottom ?? parentRect.bottom) - parentRect.top + parent.scrollTop + 1;\n } else {\n const above = blockRects[targetIndex - 1].bottom;\n const below = blockRects[targetIndex].top;\n indicatorY = ((above + below) / 2) - parentRect.top + parent.scrollTop;\n }\n\n // Hide when drop position equals source (no-op)\n const isSamePos = targetIndex === this.drag.fromIndex || targetIndex === this.drag.fromIndex + 1;\n this.dropIndicator.style.display = isSamePos ? 'none' : '';\n this.dropIndicator.style.top = `${indicatorY}px`;\n this.dropIndicator.style.left = `${editorRect.left - parentRect.left}px`;\n this.dropIndicator.style.width = `${editorRect.width}px`;\n }\n\n private onPointerUp(e: PointerEvent): void {\n if (!this.drag || e.pointerId !== this.drag.pointerId) return;\n\n // If threshold was never met, cancel without moving\n if (!this.drag.activated) {\n this.cleanupDragState();\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n return;\n }\n\n const fromIndex = this.drag.fromIndex;\n const toIndex = this.drag.dropTargetIndex;\n\n this.cleanupDragState();\n\n // Execute the move\n if (fromIndex !== toIndex && fromIndex + 1 !== toIndex) {\n const tr = buildMoveTransaction(this.view.state, fromIndex, toIndex);\n if (tr) {\n this.view.dispatch(tr.scrollIntoView());\n this.view.focus();\n this.flashMovedBlock(toIndex > fromIndex ? toIndex - 1 : toIndex);\n this.announce(`블록이 위치 ${(toIndex > fromIndex ? toIndex : toIndex + 1)}(으)로 이동됨`);\n }\n }\n\n // Flush pending update\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n }\n\n cancelDrag(): void {\n if (!this.drag) return;\n this.cleanupDragState();\n\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n }\n\n private cleaningUp = false;\n\n private cleanupDragState(): void {\n if (!this.drag || this.cleaningUp) return;\n this.cleaningUp = true;\n\n this.drag.handle.classList.remove('dragging');\n this.drag.blockDom.classList.remove('ab-block-dragging');\n\n // Remove ghost element\n if (this.drag.ghost) {\n this.drag.ghost.remove();\n this.drag.ghost = null;\n }\n\n // Try to release pointer capture (may already be released).\n // releasePointerCapture can fire lostpointercapture synchronously,\n // so the cleaningUp guard prevents re-entrant calls.\n try {\n this.drag.handle.releasePointerCapture(this.drag.pointerId);\n } catch { /* already released */ }\n\n this.dropIndicator?.remove();\n this.dropIndicator = null;\n\n // Remove global fallback listeners\n if (this.globalCleanup) {\n this.globalCleanup();\n this.globalCleanup = null;\n }\n\n if (this.scrollRAF !== null) {\n cancelAnimationFrame(this.scrollRAF);\n this.scrollRAF = null;\n }\n\n this.drag = null;\n this.cleaningUp = false;\n // Restore hover state based on actual pointer position\n delete this.layer.dataset.hover;\n }\n\n // ── Private: auto-scroll ──\n\n private tickAutoScroll(): void {\n if (!this.drag) return;\n\n const rect = this.scrollContainer.getBoundingClientRect();\n const speed = computeAutoScrollSpeed(this.drag.pointerY, rect.top, rect.bottom);\n\n if (speed !== 0) {\n this.scrollContainer.scrollBy(0, speed);\n this.syncHandlePositions();\n this.updateDropTarget();\n }\n\n this.scrollRAF = requestAnimationFrame(() => this.tickAutoScroll());\n }\n\n private findScrollContainer(el: HTMLElement): HTMLElement {\n let current = el.parentElement;\n while (current) {\n const overflow = getComputedStyle(current).overflowY;\n if (overflow === 'auto' || overflow === 'scroll') return current;\n current = current.parentElement;\n }\n return el.parentElement ?? el;\n }\n\n // ── Private: feedback ──\n\n private flashMovedBlock(blockIndex: number): void {\n // Re-collect after transaction so we get the new DOM\n requestAnimationFrame(() => {\n const blocks = this.collectBlocks();\n const block = blocks[blockIndex];\n if (!block) return;\n block.dom.classList.add('ab-block-just-moved');\n const onEnd = () => {\n block.dom.classList.remove('ab-block-just-moved');\n block.dom.removeEventListener('animationend', onEnd);\n };\n block.dom.addEventListener('animationend', onEnd);\n });\n }\n\n private announce(message: string): void {\n this.liveRegion.textContent = '';\n // Force screen reader to re-read by clearing then setting\n requestAnimationFrame(() => {\n this.liveRegion.textContent = message;\n });\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Keyboard commands\n// ────────────────────────────────────────────────────────────\n\nfunction moveBlockCommand(direction: -1 | 1): Command {\n return (state, dispatch) => {\n const $from = state.selection.$from;\n // Resolve to top-level block\n const blockIndex = $from.index(0);\n const toIndex = direction === -1 ? blockIndex - 1 : blockIndex + 2;\n\n if (toIndex < 0 || toIndex > state.doc.childCount) return false;\n\n if (dispatch) {\n const tr = buildMoveTransaction(state, blockIndex, toIndex);\n if (tr) {\n dispatch(tr.scrollIntoView());\n } else {\n return false;\n }\n }\n return true;\n };\n}\n\n// ────────────────────────────────────────────────────────────\n// Plugin factory (public API — unchanged signature)\n// ────────────────────────────────────────────────────────────\n\nexport function createDragHandlePlugin(): ActionbookPlugin {\n return {\n name: 'dragHandle',\n\n plugins: () => {\n let controller: DragHandleController | null = null;\n\n return [\n new Plugin({\n key: PLUGIN_KEY,\n view(editorView) {\n controller = new DragHandleController(editorView);\n return {\n update(view, prevState) {\n controller?.update(view, prevState);\n },\n destroy() {\n controller?.destroy();\n controller = null;\n },\n };\n },\n }),\n ];\n },\n\n keymap: () => ({\n 'Alt-ArrowUp': moveBlockCommand(-1),\n 'Alt-ArrowDown': moveBlockCommand(1),\n }),\n };\n}\n","/**\n * NodeView plugin for todo/checkbox list items.\n * Renders a clickable checkbox when listItem.attrs.checked !== null.\n */\nimport React from 'react';\nimport type { NodeView, EditorView } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Plugin } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\nfunction createCheckboxDOM(checked: boolean): HTMLElement {\n const el = document.createElement('span');\n el.contentEditable = 'false';\n el.style.cssText = `\n display: inline-flex; align-items: center; justify-content: center;\n width: 18px; height: 18px; margin-right: 6px;\n cursor: pointer; border-radius: 4px;\n user-select: none; flex-shrink: 0; vertical-align: middle;\n position: relative; top: -1px; font-size: 12px; font-weight: 700;\n ${checked\n ? 'background: #6366f1; color: #fff; border: none;'\n : 'background: transparent; color: transparent; border: 2px solid #d1d5db;'\n }\n `;\n el.textContent = checked ? '✓' : '';\n return el;\n}\n\nclass TodoListItemView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n private checkbox: HTMLElement;\n\n constructor(\n private node: PMNode,\n private view: EditorView,\n private getPos: () => number | undefined,\n ) {\n const checked = node.attrs.checked as boolean;\n\n this.dom = document.createElement('li');\n this.dom.className = 'todo-item';\n this.dom.dataset.checked = String(checked);\n this.dom.style.display = 'flex';\n this.dom.style.alignItems = 'flex-start';\n\n this.checkbox = createCheckboxDOM(checked);\n this.checkbox.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const pos = this.getPos();\n if (pos == null) return;\n this.view.dispatch(\n this.view.state.tr.setNodeMarkup(pos, undefined, {\n ...this.node.attrs,\n checked: !this.node.attrs.checked,\n }),\n );\n });\n\n this.contentDOM = document.createElement('div');\n this.contentDOM.style.flex = '1';\n if (checked) {\n this.contentDOM.style.textDecoration = 'line-through';\n this.contentDOM.style.opacity = '0.6';\n }\n\n this.dom.appendChild(this.checkbox);\n this.dom.appendChild(this.contentDOM);\n }\n\n update(node: PMNode): boolean {\n if (node.type !== this.node.type) return false;\n // If checked changed from/to null, refuse update (different rendering)\n if ((node.attrs.checked == null) !== (this.node.attrs.checked == null)) return false;\n if (node.attrs.checked == null) return false;\n\n this.node = node;\n const checked = node.attrs.checked as boolean;\n this.dom.dataset.checked = String(checked);\n\n // Update checkbox\n const newCb = createCheckboxDOM(checked);\n newCb.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const pos = this.getPos();\n if (pos == null) return;\n this.view.dispatch(\n this.view.state.tr.setNodeMarkup(pos, undefined, {\n ...this.node.attrs,\n checked: !this.node.attrs.checked,\n }),\n );\n });\n this.dom.replaceChild(newCb, this.checkbox);\n this.checkbox = newCb;\n\n // Update content styling\n if (checked) {\n this.contentDOM.style.textDecoration = 'line-through';\n this.contentDOM.style.opacity = '0.6';\n } else {\n this.contentDOM.style.textDecoration = '';\n this.contentDOM.style.opacity = '';\n }\n\n return true;\n }\n}\n\n/**\n * appendTransaction: when splitListItem creates a new listItem,\n * the new item inherits the parent's `value` attr. Reset it to null\n * so it auto-increments from the previous item.\n */\nfunction createListItemValueResetPlugin() {\n return new Plugin({\n appendTransaction(trs: readonly Transaction[], oldState: EditorState, newState: EditorState) {\n if (!trs.some((tr) => tr.docChanged)) return null;\n\n const oldCount = oldState.doc.childCount;\n let hasNewListItems = false;\n\n // Quick check: did any transaction add list items?\n newState.doc.descendants((node: PMNode) => {\n if (hasNewListItems) return false;\n if (node.type.name === 'listItem' && node.attrs.value != null) {\n hasNewListItems = true;\n }\n });\n if (!hasNewListItems) return null;\n\n // Find listItems with value attrs that are inside orderedLists\n // and reset value to null for items that weren't explicitly set by the user\n // Strategy: if two consecutive items have the same value, the second one was inherited\n let tr = newState.tr;\n let changed = false;\n\n newState.doc.descendants((node: PMNode, pos: number) => {\n if (node.type.name !== 'orderedList') return;\n let prevValue: number | null = null;\n node.forEach((li: PMNode, offset: number) => {\n const liValue = li.attrs.value as number | null;\n if (liValue != null && liValue === prevValue) {\n // Duplicate value → this was inherited from splitListItem, reset it\n const liPos = pos + 1 + offset; // +1 for orderedList opening\n tr = tr.setNodeMarkup(liPos, undefined, { ...li.attrs, value: null });\n changed = true;\n }\n prevValue = liValue;\n });\n });\n\n return changed ? tr : null;\n },\n });\n}\n\nexport function createTodoNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'todoNodeView',\n plugins: () => [createListItemValueResetPlugin()],\n nodeViews: () => ({\n listItem: ((node: PMNode, view: EditorView, getPos: () => number | undefined): NodeView => {\n // Only use custom node view for todo items (checked !== null)\n if (node.attrs.checked == null) {\n const li = document.createElement('li');\n // Sync value attribute for per-item ordered list numbering\n if (node.attrs.value != null) {\n li.value = node.attrs.value as number;\n }\n return {\n dom: li,\n contentDOM: li,\n update(updatedNode: PMNode) {\n if (updatedNode.type.name !== 'listItem') return false;\n // If it became a todo item, let PM recreate with TodoListItemView\n if (updatedNode.attrs.checked != null) return false;\n // Sync value attribute\n if (updatedNode.attrs.value != null) {\n li.value = updatedNode.attrs.value as number;\n } else {\n li.removeAttribute('value');\n }\n return true;\n },\n };\n }\n return new TodoListItemView(node, view, getPos);\n }) as NodeViewFactory,\n }),\n };\n}\n","/**\n * Placeholder plugin — shows hint text in empty paragraphs.\n *\n * Uses a node decoration with CSS ::before and ::after pseudo-elements\n * to render \"Type to start writing, or press [/] to insert an action.\"\n * where [/] is a styled keycap badge.\n *\n * Only the paragraph that currently has the cursor gets the placeholder.\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\nconst pluginKey = new PluginKey<DecorationSet>('placeholder');\n\nfunction buildDecorations(state: import('prosemirror-state').EditorState): DecorationSet {\n const { doc, selection } = state;\n if (!selection.empty) return DecorationSet.empty;\n\n const $from = selection.$from;\n const parent = $from.parent;\n\n // Only show placeholder in empty paragraphs\n if (parent.type.name !== 'paragraph' || parent.content.size !== 0) {\n return DecorationSet.empty;\n }\n\n // Don't show placeholder inside noteBlock or blockquote (system prompt)\n const EXCLUDED_ANCESTORS = new Set(['noteBlock', 'blockquote', 'jinjaIfBranch']);\n for (let d = $from.depth - 1; d > 0; d--) {\n if (EXCLUDED_ANCESTORS.has($from.node(d).type.name)) {\n return DecorationSet.empty;\n }\n }\n\n const pos = $from.before($from.depth);\n const deco = Decoration.node(pos, pos + parent.nodeSize, {\n class: 'ab-empty-paragraph',\n 'data-placeholder': 'Type to start writing, or press / to insert an action.',\n });\n\n return DecorationSet.create(doc, [deco]);\n}\n\nexport function createPlaceholderPlugin(): ActionbookPlugin {\n let isEditable = true;\n\n return {\n name: 'placeholder',\n plugins: () => [\n new Plugin<DecorationSet>({\n key: pluginKey,\n view(editorView) {\n isEditable = editorView.editable;\n return {\n update(view) {\n isEditable = view.editable;\n },\n };\n },\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, oldSet, _oldState, newState) {\n if (tr.docChanged || tr.selectionSet) {\n return buildDecorations(newState);\n }\n return oldSet;\n },\n },\n props: {\n decorations(state) {\n if (!isEditable) return DecorationSet.empty;\n return pluginKey.getState(state) ?? DecorationSet.empty;\n },\n },\n }),\n ],\n };\n}\n","/**\n * SlashCommandMenu — injectable floating slash-command picker.\n *\n * Usage:\n * ```tsx\n * // Define items (inject from outside)\n * const items: SlashCommandItem[] = [\n * {\n * id: 'heading1',\n * title: 'Heading 1',\n * description: 'Large section heading',\n * icon: <span>H1</span>,\n * command({ view, range }) {\n * const { state, dispatch } = view;\n * const tr = state.tr.delete(range.from, range.to);\n * setBlockType(heading, { level: 1 })(\n * state.apply(tr),\n * (newTr) => dispatch(tr.steps.length ? tr : newTr),\n * );\n * },\n * },\n * ];\n *\n * // In your editor component:\n * const [editorState, setEditorState] = useState<EditorState | null>(null);\n * const handle = useEditorView({ ..., onTransaction: setEditorState });\n *\n * return (\n * <>\n * <EditorShell ref={handle.viewRef} />\n * <SlashCommandMenu\n * view={handle.view}\n * editorState={editorState}\n * items={items}\n * />\n * </>\n * );\n * ```\n *\n * The `command` callback receives the editor view and the range of the\n * `/query` trigger text. It is responsible for deleting the trigger and\n * inserting whatever content it wants.\n */\n\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { EditorView } from 'prosemirror-view';\nimport type { EditorState } from 'prosemirror-state';\nimport { slashCommandKey } from '../plugin/slashCommandPlugin';\nimport type { SlashCommandState } from '../plugin/slashCommandPlugin';\n\n// ── Public types ──────────────────────────────────────────\n\nexport interface SlashCommandItem {\n /** Unique key; falls back to `title` if omitted. */\n id?: string;\n title: string;\n description?: string;\n /** Optional icon node rendered to the left of the title. */\n icon?: React.ReactNode;\n /** Optional group name. When present, items are visually grouped with a header. */\n group?: string;\n /** Optional shortcut symbol displayed on the right side (e.g. \"#\", \"##\", \"---\"). */\n shortcut?: string;\n /**\n * Execute this command.\n *\n * @param view - Live EditorView; use `view.state` / `view.dispatch`.\n * @param range - Positions of the full `/query` text in the document.\n * Delete this range before inserting your content.\n */\n command: (props: { view: EditorView; range: { from: number; to: number } }) => void;\n}\n\nexport interface SlashCommandMenuProps {\n view: EditorView | null;\n editorState: EditorState | null;\n /** Full item list. Filtered by the current query automatically. */\n items: SlashCommandItem[];\n}\n\n// ── Filtering ─────────────────────────────────────────────\n\nfunction filterItems(items: SlashCommandItem[], query: string): SlashCommandItem[] {\n if (!query) return items;\n // Support 2-depth queries: \"Prefix:search\" → filter by \"search\" only\n const colonIdx = query.indexOf(':');\n const searchPart = colonIdx >= 0 ? query.slice(colonIdx + 1).trim() : query;\n if (!searchPart) return items;\n const words = searchPart.toLowerCase().split(/\\s+/);\n const filtered = items.filter(\n ({ title, description }) => {\n const hay = (title + ' ' + (description ?? '')).toLowerCase();\n return words.every((w) => hay.includes(w));\n },\n );\n // Fallback: if nothing matches, show all items (same pattern as legacy editor)\n return filtered.length > 0 ? filtered : items;\n}\n\n// ── Scrollbar CSS (webkit) ────────────────────────────────\n\nconst SCROLLBAR_STYLE_ID = 'ab-slash-menu-scrollbar';\n\nfunction injectScrollbarStyle() {\n if (document.getElementById(SCROLLBAR_STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = SCROLLBAR_STYLE_ID;\n style.textContent = `\n.ab-slash-menu::-webkit-scrollbar { display: none; }\n.ab-slash-menu { scrollbar-width: none; }\n`;\n document.head.appendChild(style);\n}\n\n// ── Shared styles ─────────────────────────────────────────\n\nconst POPUP_SHADOW =\n '0 3px 5px -3px rgba(13,13,13,0.04), 0 3px 14px 2px rgba(13,13,13,0.08), 0 8px 10px 1px rgba(13,13,13,0.12)';\n\nconst BTN_RESET: React.CSSProperties = {\n border: 'none',\n padding: 0,\n margin: 0,\n background: 'transparent',\n fontFamily: 'inherit',\n cursor: 'pointer',\n lineHeight: 1,\n textAlign: 'left',\n width: '100%',\n};\n\nconst VPORT_MARGIN = 8;\nconst MENU_WIDTH = 440;\nconst MAX_MENU_H = 400;\n\n// ── Menu component ────────────────────────────────────────\n\nexport function SlashCommandMenu({ view, editorState, items }: SlashCommandMenuProps) {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const listRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => { injectScrollbarStyle(); }, []);\n\n // Read plugin state\n const pluginState = editorState\n ? (slashCommandKey.getState(editorState) as SlashCommandState | undefined)\n : undefined;\n\n const active = pluginState?.active ?? false;\n const range = pluginState?.range ?? null;\n const query = pluginState?.query ?? '';\n\n const filtered = filterItems(items, query);\n\n // Reset selection when query or active state changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [query, active]);\n\n // Scroll selected item into view\n useEffect(() => {\n const list = listRef.current;\n if (!list) return;\n const item = list.querySelector(`[data-slash-index=\"${selectedIndex}\"]`) as HTMLElement | null;\n item?.scrollIntoView({ block: 'nearest' });\n }, [selectedIndex]);\n\n // Keyboard handler — captures Arrow/Enter before ProseMirror sees them\n // Only active when there are items to show (empty items = no menu, no key capture)\n useEffect(() => {\n if (!active || !view || filtered.length === 0) return;\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n setSelectedIndex((i) => Math.min(i + 1, filtered.length - 1));\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n setSelectedIndex((i) => Math.max(i - 1, 0));\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n if (filtered[selectedIndex] && range) {\n filtered[selectedIndex].command({ view, range });\n view.focus();\n }\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n // Delete the /query text to close the menu — user can type / again to reopen\n if (range) {\n view.dispatch(view.state.tr.delete(range.from, range.to));\n }\n view.focus();\n }\n };\n\n document.addEventListener('keydown', onKeyDown, true);\n return () => document.removeEventListener('keydown', onKeyDown, true);\n }, [active, view, filtered, selectedIndex, range]);\n\n // Compute position after DOM update via useLayoutEffect\n const [menuPos, setMenuPos] = useState<{ top: number; left: number } | null>(null);\n\n const menuRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!active || !view || !range || filtered.length === 0) {\n setMenuPos(null);\n return;\n }\n try {\n const coords = view.coordsAtPos(range.to);\n let left = coords.left;\n left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - MENU_WIDTH - VPORT_MARGIN));\n\n // Use actual menu height if rendered, otherwise estimate\n const menuHeight = menuRef.current?.offsetHeight ?? MAX_MENU_H;\n let top = coords.bottom + 4;\n if (top + menuHeight > window.innerHeight - VPORT_MARGIN) {\n top = coords.top - menuHeight - 4;\n }\n setMenuPos({ top, left });\n } catch {\n // coordsAtPos can fail if view is not attached\n }\n });\n\n if (!active || !view || !range || filtered.length === 0 || !menuPos) return null;\n\n return createPortal(\n <div\n ref={menuRef}\n className=\"ab-slash-menu\"\n style={{\n position: 'fixed',\n top: menuPos.top,\n left: menuPos.left,\n width: MENU_WIDTH,\n maxHeight: MAX_MENU_H,\n overflowY: 'auto',\n background: '#fff',\n borderRadius: 4,\n boxShadow: POPUP_SHADOW,\n padding: '8px 0',\n zIndex: 1100,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div ref={listRef}>\n {filtered.map((item, i) => {\n const prevGroup = i > 0 ? filtered[i - 1].group : undefined;\n const showGroupHeader = item.group && item.group !== prevGroup;\n return (\n <React.Fragment key={item.id ?? item.title}>\n {showGroupHeader && (\n <>\n <div\n style={{\n padding: '16px 16px 4px',\n fontSize: 12,\n fontWeight: 600,\n lineHeight: '12px',\n color: '#858585',\n }}\n >\n {item.group}\n </div>\n </>\n )}\n <SlashMenuItem\n item={item}\n index={i}\n selected={i === selectedIndex}\n onMouseEnter={() => setSelectedIndex(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n if (range) {\n item.command({ view, range });\n view.focus();\n }\n }}\n />\n </React.Fragment>\n );\n })}\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── SlashMenuItem ─────────────────────────────────────────\n\ninterface SlashMenuItemProps {\n item: SlashCommandItem;\n index: number;\n selected: boolean;\n onMouseEnter: () => void;\n onMouseDown: (e: React.MouseEvent) => void;\n}\n\nfunction SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }: SlashMenuItemProps) {\n return (\n <button\n data-slash-index={index}\n style={{\n ...BTN_RESET,\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n padding: '6px 16px',\n background: selected ? 'rgba(13, 13, 13, 0.04)' : 'transparent',\n transition: 'background 0.08s',\n }}\n onMouseEnter={onMouseEnter}\n onMouseDown={onMouseDown}\n >\n <span\n style={{\n flex: '1 0 0',\n fontSize: 14,\n fontWeight: 400,\n lineHeight: '20px',\n letterSpacing: '-0.1px',\n color: '#0d0d0d',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n minWidth: 0,\n }}\n >\n {item.title}\n </span>\n\n {/* Description or shortcut (right-aligned) */}\n {(item.description || item.shortcut) && (\n <span\n style={{\n fontSize: 12,\n lineHeight: '16px',\n color: '#5e5e5e',\n whiteSpace: 'nowrap',\n flexShrink: 0,\n textAlign: 'right',\n }}\n >\n {item.shortcut ?? item.description}\n </span>\n )}\n </button>\n );\n}\n","import React, { useState, type ReactElement } from 'react';\nimport type { DocumentNode } from '../../ast/types';\nimport { textContent } from '../../ast/traverse';\nimport { analyzeJinjaBlocks, type JinjaVisualStructure, type JinjaVisualBranch } from '../../jinja/analyzer';\n\nexport interface JinjaTreeViewProps {\n doc: DocumentNode;\n className?: string;\n}\n\nconst BRANCH_COLORS: Record<string, string> = {\n if: '#6366f1',\n elif: '#f59e0b',\n else: '#8b5cf6',\n};\n\nfunction getBlockPreview(doc: DocumentNode, startIdx: number, endIdx: number): string {\n const blocks = doc.content.slice(startIdx, endIdx);\n const text = blocks.map((b) => textContent(b)).join(' ').trim();\n return text.length > 40 ? text.slice(0, 40) + '...' : text;\n}\n\nfunction BranchNode({\n branch,\n doc,\n isLast,\n}: {\n branch: JinjaVisualBranch;\n doc: DocumentNode;\n isLast: boolean;\n}): ReactElement {\n const color = BRANCH_COLORS[branch.type] || '#6366f1';\n const blockCount = branch.blockEndIndex - branch.blockStartIndex;\n const preview = getBlockPreview(doc, branch.blockStartIndex, branch.blockEndIndex);\n const connector = isLast ? '\\u2514\\u2500' : '\\u251C\\u2500';\n\n return (\n <div className=\"jinja-tree-branch\">\n <span className=\"jinja-tree-connector\">{connector} </span>\n <span className=\"jinja-tree-badge\" style={{ color, borderColor: color }}>\n [{branch.type}]\n </span>\n {branch.condition && (\n <span className=\"jinja-tree-condition\"> {branch.condition}</span>\n )}\n <span className=\"jinja-tree-meta\">\n {' '}{blockCount} block{blockCount !== 1 ? 's' : ''}\n {preview && `: \"${preview}\"`}\n </span>\n </div>\n );\n}\n\nfunction StructureNode({ structure, doc }: { structure: JinjaVisualStructure; doc: DocumentNode }): ReactElement {\n const [expanded, setExpanded] = useState(true);\n const firstBranch = structure.branches[0];\n const label = firstBranch?.condition ? `if ${firstBranch.condition}` : 'if';\n\n return (\n <div className=\"jinja-tree-structure\">\n <button\n className=\"jinja-tree-toggle\"\n onClick={() => setExpanded(!expanded)}\n type=\"button\"\n >\n <span className=\"jinja-tree-arrow\">{expanded ? '\\u25BC' : '\\u25B6'}</span>\n <span className=\"jinja-tree-label\">{label}</span>\n </button>\n {expanded && (\n <div className=\"jinja-tree-branches\">\n {structure.branches.map((branch, i) => (\n <BranchNode\n key={`${structure.id}-${i}`}\n branch={branch}\n doc={doc}\n isLast={i === structure.branches.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function JinjaTreeView({ doc, className }: JinjaTreeViewProps): ReactElement | null {\n const structures = analyzeJinjaBlocks(doc);\n if (structures.length === 0) return null;\n\n return (\n <div className={`jinja-tree ${className || ''}`}>\n {structures.map((structure) => (\n <StructureNode key={structure.id} structure={structure} doc={doc} />\n ))}\n </div>\n );\n}\n","/**\n * DocumentTreeView — lightweight React tree component for document outline.\n * Shows headings, jump points, jinja if blocks, resource tags, end actions, and note blocks.\n * Supports selected item highlight (purple background like Figma).\n */\nimport { useState, type ReactElement } from 'react';\nimport type { DocumentNode } from '../../ast/types';\nimport { buildDocumentTree, type DocumentTreeNode } from '../../tree/documentTree';\n\nexport interface DocumentTreeViewProps {\n doc: DocumentNode;\n className?: string;\n onNavigate?: (blockIndex: number) => void;\n}\n\nconst ICONS: Record<string, string> = {\n heading: 'H',\n jumpPoint: '\\u2299',\n jinjaIf: '\\u2325',\n jinjaBranch: '\\u2387',\n resourceTag: '\\u229B',\n noteBlock: '\\u270D',\n endAction: '\\u2192',\n};\n\nconst COLORS: Record<string, string> = {\n heading: '#333',\n jumpPoint: '#d97706',\n jinjaIf: '#6366f1',\n jinjaBranch: '#8b5cf6',\n resourceTag: '#059669',\n noteBlock: '#999',\n endAction: '#059669',\n};\n\nfunction TreeNodeItem({\n node,\n onNavigate,\n depth,\n selectedPath,\n onSelect,\n path,\n}: {\n node: DocumentTreeNode;\n onNavigate?: (blockIndex: number) => void;\n depth: number;\n selectedPath: string | null;\n onSelect: (path: string) => void;\n path: string;\n}): ReactElement {\n const [collapsed, setCollapsed] = useState(false);\n const hasChildren = node.children.length > 0;\n const icon = ICONS[node.type] || '\\u2022';\n const color = COLORS[node.type] || '#666';\n const isSelected = selectedPath === path;\n\n const headingLevel = node.meta?.level as number | undefined;\n const headingLabel = headingLevel ? `H${headingLevel}` : icon;\n\n return (\n <div style={{ paddingLeft: depth > 0 ? 16 : 0 }}>\n <div\n className=\"doc-tree-node\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '3px 6px',\n borderRadius: 4,\n cursor: onNavigate ? 'pointer' : 'default',\n fontSize: 13,\n lineHeight: '1.5',\n background: isSelected ? 'rgba(99, 102, 241, 0.1)' : 'transparent',\n transition: 'background 0.12s ease',\n }}\n onClick={(e) => {\n e.stopPropagation();\n if (hasChildren) setCollapsed(!collapsed);\n onSelect(path);\n onNavigate?.(node.blockIndex);\n }}\n onMouseEnter={(e) => {\n if (!isSelected) (e.currentTarget as HTMLElement).style.background = '#f3f4f6';\n }}\n onMouseLeave={(e) => {\n if (!isSelected) (e.currentTarget as HTMLElement).style.background = 'transparent';\n }}\n >\n {hasChildren && (\n <span\n style={{\n width: 14,\n textAlign: 'center',\n fontSize: 10,\n color: '#999',\n flexShrink: 0,\n userSelect: 'none',\n }}\n >\n {collapsed ? '\\u25B8' : '\\u25BE'}\n </span>\n )}\n {!hasChildren && <span style={{ width: 14, flexShrink: 0 }} />}\n\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 22,\n height: 18,\n borderRadius: 3,\n fontSize: 10,\n fontWeight: 700,\n color: isSelected ? '#6366f1' : color,\n background: isSelected ? 'rgba(99, 102, 241, 0.15)' : `${color}11`,\n border: `1px solid ${isSelected ? 'rgba(99, 102, 241, 0.3)' : `${color}33`}`,\n flexShrink: 0,\n }}\n >\n {node.type === 'heading' ? headingLabel : icon}\n </span>\n\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: isSelected\n ? '#6366f1'\n : node.type === 'noteBlock'\n ? '#999'\n : node.type === 'endAction'\n ? '#059669'\n : '#333',\n fontStyle: node.type === 'noteBlock' ? 'italic' : 'normal',\n fontWeight: isSelected\n ? 600\n : node.type === 'heading' && headingLevel && headingLevel <= 2\n ? 600\n : 400,\n }}\n >\n {node.label}\n </span>\n\n {node.meta?.tagType != null && (\n <span\n style={{\n fontSize: 10,\n padding: '1px 5px',\n borderRadius: 999,\n background: node.type === 'endAction' ? 'rgba(5, 150, 105, 0.1)' : 'rgba(0, 0, 0, 0.04)',\n color: node.type === 'endAction' ? '#059669' : '#999',\n fontWeight: 500,\n }}\n >\n {String(node.meta.tagType)}\n </span>\n )}\n </div>\n\n {hasChildren && !collapsed && (\n <div>\n {node.children.map((child, i) => (\n <TreeNodeItem\n key={`${child.type}-${child.blockIndex}-${i}`}\n node={child}\n onNavigate={onNavigate}\n depth={depth + 1}\n selectedPath={selectedPath}\n onSelect={onSelect}\n path={`${path}/${i}`}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function DocumentTreeView({ doc, className, onNavigate }: DocumentTreeViewProps): ReactElement {\n const tree = buildDocumentTree(doc);\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n\n if (tree.length === 0) {\n return (\n <div className={className} style={{ color: '#999', fontSize: 13, padding: 16 }}>\n No document structure to display.\n </div>\n );\n }\n\n return (\n <div className={className} style={{ padding: '8px 0', fontFamily: 'Inter, sans-serif' }}>\n {tree.map((node, i) => (\n <TreeNodeItem\n key={`${node.type}-${node.blockIndex}-${i}`}\n node={node}\n onNavigate={onNavigate}\n depth={0}\n selectedPath={selectedPath}\n onSelect={setSelectedPath}\n path={`${i}`}\n />\n ))}\n </div>\n );\n}\n","/**\n * Floating UI for the Actionbook editor.\n *\n * Two interaction patterns:\n *\n * 1. SelectionToolbar — appears above a non-empty text selection.\n * Buttons: Bold · Italic · Underline · Strikethrough · Code · Link · ─ · Block type ▾\n *\n * 2. EmptyParaHandle — appears to the left of an empty paragraph/heading\n * after the cursor has dwelled there for DWELL_MS (600 ms).\n * A small \"+\" button opens a block-type picker menu.\n *\n * Both are rendered into document.body via React portals so they never\n * get clipped by overflow:hidden ancestors.\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { Mark, MarkType, ResolvedPos } from 'prosemirror-model';\nimport type { EditorView } from 'prosemirror-view';\nimport { TextSelection } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { setBlockType, toggleMark, wrapIn } from 'prosemirror-commands';\nimport { wrapInList } from 'prosemirror-schema-list';\nimport { actionbookSchema } from '../schema';\n\n// ── Schema refs ───────────────────────────────────────────\n\nconst { paragraph, heading, bulletList, orderedList, blockquote } = actionbookSchema.nodes;\nconst {\n bold,\n italic,\n underline,\n strikethrough,\n code,\n link: linkMark,\n} = actionbookSchema.marks;\n\n// ── Constants ─────────────────────────────────────────────\n\nconst DWELL_MS = 600;\nconst TOOLBAR_H = 36;\nconst TOOLBAR_GAP = 8;\nconst VPORT_MARGIN = 8;\n// attribute used to detect clicks inside any floating element\nconst FLOAT_ATTR = 'data-ab-float';\n\n// ── Editor state helpers ──────────────────────────────────\n\nfunction hasMark(state: EditorState, type: typeof bold): boolean {\n const { from, to, empty } = state.selection;\n if (empty) return false;\n return state.doc.rangeHasMark(from, to, type);\n}\n\nfunction getMarkRange(\n $pos: ResolvedPos,\n type: MarkType,\n): { from: number; to: number; mark: Mark } | null {\n const { parentOffset } = $pos;\n\n let child = $pos.parent.childAfter(parentOffset);\n\n if (parentOffset === child.offset && child.offset !== 0) {\n child = $pos.parent.childBefore(parentOffset);\n }\n\n if (!child.node) return null;\n\n const mark = child.node.marks.find((candidate) => candidate.type === type);\n if (!mark) return null;\n\n const parentStart = $pos.start();\n let { index: startIndex } = child;\n let startPos = parentStart + child.offset;\n let endIndex = startIndex + 1;\n let endPos = startPos + child.node.nodeSize;\n\n while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {\n startIndex -= 1;\n startPos -= $pos.parent.child(startIndex).nodeSize;\n }\n\n while (\n endIndex < $pos.parent.childCount &&\n mark.isInSet($pos.parent.child(endIndex).marks)\n ) {\n endPos += $pos.parent.child(endIndex).nodeSize;\n endIndex += 1;\n }\n\n return { from: startPos, to: endPos, mark };\n}\n\ninterface LinkAtCursor {\n href: string;\n text: string;\n from: number;\n to: number;\n}\n\nfunction getLinkAtCursor(state: EditorState): LinkAtCursor | null {\n const { selection, doc } = state;\n if (!selection.empty) return null;\n\n const range = getMarkRange(doc.resolve(selection.from), linkMark);\n if (!range) return null;\n\n return {\n href: (range.mark.attrs.href as string) || '',\n text: doc.textBetween(range.from, range.to),\n from: range.from,\n to: range.to,\n };\n}\n\nfunction normalizeLinkHref(href: string): string {\n const trimmedHref = href.trim();\n if (!trimmedHref) return '';\n return trimmedHref.startsWith('#') || trimmedHref.startsWith('/') || /^https?:\\/\\//i.test(trimmedHref)\n ? trimmedHref\n : `https://${trimmedHref}`;\n}\n\nfunction getNonLinkMarksInRange(state: EditorState, from: number, to: number): readonly Mark[] {\n let marks: readonly Mark[] = [];\n state.doc.nodesBetween(from, to, (node) => {\n if (!node.isText) return;\n marks = node.marks.filter((mark) => mark.type !== linkMark);\n return false;\n });\n return marks;\n}\n\nfunction activeHeadingLevel(state: EditorState): number | null {\n const { $from } = state.selection;\n const node = $from.parent;\n if (node.type === heading) return node.attrs.level as number;\n return null;\n}\n\n/** Returns 'bullet' | 'ordered' | null depending on whether the cursor is inside a list. */\nfunction activeListType(state: EditorState): 'bullet' | 'ordered' | null {\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n const t = $from.node(d).type;\n if (t === bulletList) return 'bullet';\n if (t === orderedList) return 'ordered';\n }\n return null;\n}\n\n/** Convert the nearest ancestor list to `toType`. */\nfunction convertList(\n state: EditorState,\n dispatch: EditorView['dispatch'] | undefined,\n toType: typeof bulletList | typeof orderedList,\n): boolean {\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n const node = $from.node(d);\n if (node.type === bulletList || node.type === orderedList) {\n if (node.type === toType) return false;\n if (dispatch) {\n dispatch(state.tr.setNodeMarkup($from.before(d), toType, node.attrs));\n }\n return true;\n }\n }\n return false;\n}\n\nfunction currentBlockLabel(state: EditorState): string {\n const hl = activeHeadingLevel(state);\n if (hl) return `H${hl}`;\n const lt = activeListType(state);\n if (lt === 'bullet') return '• List';\n if (lt === 'ordered') return '1. List';\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type === blockquote) return 'Quote';\n }\n return 'Text';\n}\n\nfunction emptyBlockCursorPos(state: EditorState): number | null {\n const { selection } = state;\n if (!selection.empty) return null;\n const { $from } = selection;\n const parent = $from.parent;\n if (\n (parent.type === paragraph || parent.type === heading) &&\n parent.content.size === 0\n ) {\n return selection.from;\n }\n return null;\n}\n\n/** Get the bounding rect of the current DOM selection (viewport-relative). */\nfunction getSelectionDOMRect(): DOMRect | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return null;\n const rect = sel.getRangeAt(0).getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return null;\n return rect;\n}\n\n// ── Shared styles ─────────────────────────────────────────\n\nconst POPUP_SHADOW =\n '0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)';\n\nconst BTN_RESET: React.CSSProperties = {\n border: 'none',\n padding: 0,\n background: 'transparent',\n fontFamily: 'inherit',\n cursor: 'pointer',\n lineHeight: 1,\n};\n\n// ── ToolbarButton ─────────────────────────────────────────\n\ninterface TBtnProps {\n children: React.ReactNode;\n active?: boolean;\n title?: string;\n onMouseDown: (e: React.MouseEvent) => void;\n style?: React.CSSProperties;\n}\n\nfunction TBtn({ children, active, title, onMouseDown, style }: TBtnProps) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n title={title}\n onMouseDown={(e) => { e.preventDefault(); onMouseDown(e); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n width: 28, height: 28, borderRadius: 6,\n fontSize: 13, fontWeight: 600, color: active ? '#6210CC' : '#0D0D0D',\n background: active\n ? 'rgba(98,16,204,0.08)'\n : hover ? 'rgba(0,0,0,0.05)' : 'transparent',\n transition: 'background 0.1s, color 0.1s',\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n\n// ── Divider ───────────────────────────────────────────────\n\nfunction Divider() {\n return (\n <div style={{ width: 1, height: 18, background: 'rgba(0,0,0,0.07)', margin: '0 2px', flexShrink: 0 }} />\n );\n}\n\n// ── BlockTypeDropdown ─────────────────────────────────────\n\ninterface BlockTypeDropdownProps {\n view: EditorView;\n state: EditorState;\n label: string;\n}\n\nfunction BlockTypeDropdown({ view, state, label }: BlockTypeDropdownProps) {\n const [open, setOpen] = useState(false);\n const btnRef = useRef<HTMLButtonElement>(null);\n const [hover, setHover] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [open]);\n\n const headingLevel = activeHeadingLevel(state);\n const listType = activeListType(state);\n\n const items: { label: string; shortLabel: string; active: boolean; run: () => void }[] = [\n { label: 'Text', shortLabel: '¶', active: !headingLevel && !listType, run: () => { setBlockType(paragraph)(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 1', shortLabel: 'H1', active: headingLevel === 1, run: () => { setBlockType(heading, { level: 1 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 2', shortLabel: 'H2', active: headingLevel === 2, run: () => { setBlockType(heading, { level: 2 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 3', shortLabel: 'H3', active: headingLevel === 3, run: () => { setBlockType(heading, { level: 3 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Bullet List', shortLabel: '•', active: listType === 'bullet', run: () => {\n if (listType === 'bullet') return;\n if (listType === 'ordered') { convertList(view.state, view.dispatch, bulletList); }\n else { wrapInList(bulletList)(view.state, view.dispatch); }\n view.focus();\n }},\n { label: 'Ordered List', shortLabel: '1.', active: listType === 'ordered', run: () => {\n if (listType === 'ordered') return;\n if (listType === 'bullet') { convertList(view.state, view.dispatch, orderedList); }\n else { wrapInList(orderedList)(view.state, view.dispatch); }\n view.focus();\n }},\n { label: 'Quote', shortLabel: '>', active: false, run: () => {\n // Block inside listItem\n const { $from } = view.state.selection;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'listItem') return;\n }\n wrapIn(blockquote)(view.state, view.dispatch); view.focus();\n }},\n ];\n\n const btnRect = btnRef.current?.getBoundingClientRect();\n\n return (\n <>\n <button\n ref={btnRef}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); setOpen((v) => !v); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 3,\n height: 28, padding: '0 6px', borderRadius: 6,\n fontSize: 11, fontWeight: 600, color: open ? '#6210CC' : '#0D0D0D',\n background: open ? 'rgba(98,16,204,0.08)' : hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s, color 0.1s',\n whiteSpace: 'nowrap',\n }}\n >\n {label}\n <span style={{ fontSize: 8, opacity: 0.6 }}>▾</span>\n </button>\n {open && btnRect && createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed', zIndex: 1001,\n left: btnRect.left, top: btnRect.bottom + 4,\n background: '#fff', borderRadius: 8, boxShadow: POPUP_SHADOW,\n padding: 4, minWidth: 168,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {items.map((item) => (\n <DropdownItem key={item.label} item={item} onRun={() => setOpen(false)} />\n ))}\n </div>,\n document.body,\n )}\n </>\n );\n}\n\nfunction DropdownItem({ item, onRun }: { item: { label: string; shortLabel: string; active: boolean; run: () => void }; onRun: () => void }) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); item.run(); onRun(); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 10,\n width: '100%', padding: '6px 8px',\n borderRadius: 4, textAlign: 'left',\n fontSize: 13, color: item.active ? '#6210CC' : '#0D0D0D',\n fontWeight: item.active ? 600 : 400,\n background: hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s',\n }}\n >\n <span style={{ width: 24, flexShrink: 0, textAlign: 'center', fontWeight: 700, fontSize: 12, fontFamily: 'monospace', color: '#6210CC' }}>\n {item.shortLabel}\n </span>\n {item.label}\n </button>\n );\n}\n\n// ── SelectionToolbar ──────────────────────────────────────\n\ninterface SelectionToolbarProps {\n view: EditorView;\n state: EditorState;\n selectionRect: DOMRect;\n}\n\nfunction SelectionToolbar({ view, state, selectionRect }: SelectionToolbarProps) {\n const [linkMode, setLinkMode] = useState(false);\n const [linkHref, setLinkHref] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Derived state\n const isBold = hasMark(state, bold);\n const isItalic = hasMark(state, italic);\n const isUnderline = hasMark(state, underline);\n const isStrike = hasMark(state, strikethrough);\n const isCode = hasMark(state, code);\n const isLink = hasMark(state, linkMark);\n const blockLabel = currentBlockLabel(state);\n\n const toolbarW = linkMode ? 300 : 380;\n const toolbarH = TOOLBAR_H;\n\n let left = selectionRect.left + selectionRect.width / 2 - toolbarW / 2;\n let top = selectionRect.top - toolbarH - TOOLBAR_GAP;\n // Flip below selection when there's no space above\n if (top < VPORT_MARGIN) top = selectionRect.bottom + TOOLBAR_GAP;\n // Clamp to viewport\n left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - toolbarW - VPORT_MARGIN));\n top = Math.max(VPORT_MARGIN, Math.min(top, window.innerHeight - toolbarH - VPORT_MARGIN));\n\n const run = useCallback(\n (cmd: (s: EditorState, d?: typeof view.dispatch) => boolean) => {\n cmd(view.state, view.dispatch);\n view.focus();\n },\n [view],\n );\n\n const openLinkInput = () => {\n // Pre-fill with the first href found in the selection (if any)\n const { from, to } = view.state.selection;\n let existingHref = '';\n view.state.doc.nodesBetween(from, to, (node) => {\n if (!existingHref) {\n const lm = node.marks.find((m) => m.type === linkMark);\n if (lm) existingHref = lm.attrs.href as string;\n }\n });\n setLinkHref(existingHref);\n setLinkMode(true);\n setTimeout(() => inputRef.current?.focus(), 0);\n };\n\n const applyLink = () => {\n const href = linkHref.trim();\n if (href) {\n const finalHref =\n href.startsWith('#') || href.startsWith('/') || /^https?:\\/\\//i.test(href)\n ? href\n : `https://${href}`;\n const { from, to } = view.state.selection;\n const tr = view.state.tr.addMark(from, to, linkMark.create({ href: finalHref }));\n view.dispatch(tr);\n }\n view.focus();\n setLinkMode(false);\n setLinkHref('');\n };\n\n const removeLink = () => {\n const { from, to } = view.state.selection;\n view.dispatch(view.state.tr.removeMark(from, to, linkMark));\n view.focus();\n };\n\n return (\n <div\n {...{ [FLOAT_ATTR]: 'selection-toolbar' }}\n style={{\n position: 'fixed', left, top, width: toolbarW, height: toolbarH,\n zIndex: 1000,\n display: 'flex', alignItems: 'center', gap: 2, padding: '0 6px',\n background: '#fff', borderRadius: 8, boxShadow: POPUP_SHADOW,\n userSelect: 'none',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {linkMode ? (\n /* ── Link input mode ── */\n <>\n <span style={{ fontSize: 13, color: '#9ca3af', paddingLeft: 4, flexShrink: 0 }}>↗</span>\n <input\n ref={inputRef}\n value={linkHref}\n onChange={(e) => setLinkHref(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyLink(); }\n if (e.key === 'Escape') { e.preventDefault(); setLinkMode(false); view.focus(); }\n }}\n placeholder=\"Paste link...\"\n style={{\n flex: 1, border: 'none', outline: 'none',\n fontSize: 13, fontFamily: 'inherit', color: '#171717',\n padding: '0 6px', background: 'transparent',\n minWidth: 0,\n }}\n />\n <TBtn\n title=\"Apply (Enter)\"\n onMouseDown={(e) => { e.preventDefault(); applyLink(); }}\n style={{ color: '#6210CC', width: 24, fontSize: 14 }}\n >↵</TBtn>\n <TBtn\n title=\"Cancel (Esc)\"\n onMouseDown={(e) => { e.preventDefault(); setLinkMode(false); view.focus(); }}\n style={{ color: '#9ca3af', width: 24, fontSize: 14 }}\n >✕</TBtn>\n </>\n ) : (\n /* ── Normal toolbar mode ── */\n <>\n {/* Marks */}\n <TBtn active={isBold} title=\"Bold (Cmd+B)\" onMouseDown={() => run(toggleMark(bold))}\n style={{ fontWeight: 700 }}>B</TBtn>\n <TBtn active={isItalic} title=\"Italic (Cmd+I)\" onMouseDown={() => run(toggleMark(italic))}\n style={{ fontStyle: 'italic' }}>I</TBtn>\n <TBtn active={isUnderline} title=\"Underline (Cmd+U)\" onMouseDown={() => run(toggleMark(underline))}\n style={{ textDecoration: 'underline' }}>U</TBtn>\n <TBtn active={isStrike} title=\"Strikethrough (Cmd+Shift+X)\" onMouseDown={() => run(toggleMark(strikethrough))}\n style={{ textDecoration: 'line-through' }}>S</TBtn>\n <TBtn active={isCode} title=\"Code (Cmd+E)\" onMouseDown={() => run(toggleMark(code))}\n style={{ fontFamily: 'monospace', fontSize: 11 }}>`·`</TBtn>\n <TBtn active={isLink} title={isLink ? 'Remove link' : 'Add link (Cmd+K)'}\n onMouseDown={() => isLink ? removeLink() : openLinkInput()}\n style={{ fontSize: 14 }}>↗</TBtn>\n\n <Divider />\n\n {/* Block type dropdown */}\n <BlockTypeDropdown view={view} state={state} label={blockLabel} />\n </>\n )}\n </div>\n );\n}\n\n// ── LinkHoverTooltip ──────────────────────────────────────\n\ninterface LinkHoverTooltipProps {\n view: EditorView;\n link: LinkAtCursor;\n onEdit: (link: LinkAtCursor) => void;\n}\n\nfunction LinkHoverTooltip({ view, link, onEdit }: LinkHoverTooltipProps) {\n const [hover, setHover] = useState(false);\n\n const startCoords = view.coordsAtPos(link.from);\n const endCoords = view.coordsAtPos(link.to);\n const anchorTop = Math.min(startCoords.top, endCoords.top);\n const linkLeft = Math.min(startCoords.left, endCoords.left);\n const linkRight = Math.max(startCoords.right, endCoords.right);\n const tooltipHalfW = Math.min(174, Math.max(0, (window.innerWidth - VPORT_MARGIN * 2) / 2));\n const safeCenterX = Math.max(\n VPORT_MARGIN + tooltipHalfW,\n Math.min((linkLeft + linkRight) / 2, window.innerWidth - VPORT_MARGIN - tooltipHalfW),\n );\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left: safeCenterX,\n top: Math.max(64, anchorTop - 4),\n transform: 'translate(-50%, -100%)',\n zIndex: 1000,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n animation: 'ab-float-in 0.12s ease',\n pointerEvents: 'auto',\n }}\n >\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n minHeight: 28,\n maxWidth: 'min(348px, calc(100vw - 16px))',\n padding: '6px 8px',\n background: '#2E2E2E',\n borderRadius: 4,\n boxSizing: 'border-box',\n }}\n >\n <span\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n color: '#FFFFFF',\n fontSize: 12,\n lineHeight: '16px',\n fontFamily: '\"SF Pro Text\", \"SF Pro\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n whiteSpace: 'normal',\n wordBreak: 'break-word',\n overflowWrap: 'anywhere',\n maxWidth: 300,\n }}\n >\n {link.href}\n </span>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n width: 1,\n height: 16,\n background: '#424242',\n flexShrink: 0,\n }}\n />\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n onEdit(link);\n }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n padding: '0 2px',\n color: '#FFFFFF',\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n fontFamily: '\"SF Pro Text\", \"SF Pro\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n opacity: hover ? 0.78 : 1,\n flexShrink: 0,\n }}\n >\n Edit\n </button>\n </div>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n width: 0,\n height: 0,\n borderLeft: '6px solid transparent',\n borderRight: '6px solid transparent',\n borderTop: '6px solid #2E2E2E',\n marginTop: -1,\n }}\n />\n </div>,\n document.body,\n );\n}\n\n// ── LinkEditDialog ────────────────────────────────────────\n\ninterface LinkEditDialogProps {\n view: EditorView;\n link: LinkAtCursor;\n onClose: () => void;\n}\n\nfunction LinkEditDialog({ view, link, onClose }: LinkEditDialogProps) {\n const [textValue, setTextValue] = useState(link.text);\n const [hrefValue, setHrefValue] = useState(link.href);\n const textInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setTextValue(link.text);\n setHrefValue(link.href);\n }, [link.from, link.href, link.text, link.to]);\n\n useEffect(() => {\n setTimeout(() => textInputRef.current?.focus(), 0);\n }, [link.from, link.to]);\n\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [onClose]);\n\n const startCoords = view.coordsAtPos(link.from);\n const endCoords = view.coordsAtPos(link.to);\n const anchorTop = Math.min(startCoords.top, endCoords.top);\n const anchorBottom = Math.max(startCoords.bottom, endCoords.bottom);\n const linkLeft = Math.min(startCoords.left, endCoords.left);\n const linkRight = Math.max(startCoords.right, endCoords.right);\n const dialogW = 280;\n const estimatedDialogH = 188;\n const centerX = (linkLeft + linkRight) / 2;\n const left = Math.max(\n VPORT_MARGIN,\n Math.min(centerX - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN),\n );\n let top = anchorTop - estimatedDialogH - 12;\n if (top < VPORT_MARGIN) {\n top = Math.min(anchorBottom + 12, window.innerHeight - estimatedDialogH - VPORT_MARGIN);\n }\n\n const finalHref = normalizeLinkHref(hrefValue);\n const finalText = textValue.trim() ? textValue : '';\n // Allow save when: label emptied (will delete link), or href/text changed\n const canSave = !textValue.trim()\n || (Boolean(finalHref) && (finalHref !== link.href || finalText !== link.text));\n\n const currentLink = () => {\n const activeLink = getLinkAtCursor(view.state);\n if (activeLink && activeLink.from === link.from && activeLink.to === link.to) {\n return activeLink;\n }\n return link;\n };\n\n const saveLink = () => {\n const activeLink = currentLink();\n const nextHref = normalizeLinkHref(hrefValue);\n\n // If label is completely empty, delete the entire link (text + mark)\n if (!textValue.trim()) {\n const tr = view.state.tr.delete(activeLink.from, activeLink.to);\n view.dispatch(tr);\n onClose();\n view.focus();\n return;\n }\n\n const nextText = textValue;\n if (!nextHref) return;\n if (nextHref === activeLink.href && nextText === activeLink.text) return;\n\n const cursorOffset = Math.max(0, view.state.selection.from - activeLink.from);\n const tr = view.state.tr;\n\n if (nextText === activeLink.text) {\n tr.removeMark(activeLink.from, activeLink.to, linkMark);\n tr.addMark(activeLink.from, activeLink.to, linkMark.create({ href: nextHref }));\n const nextCursor = Math.min(activeLink.from + cursorOffset, activeLink.to);\n tr.setSelection(TextSelection.near(tr.doc.resolve(nextCursor)));\n } else {\n const preservedMarks = getNonLinkMarksInRange(view.state, activeLink.from, activeLink.to);\n tr.insertText(nextText, activeLink.from, activeLink.to);\n const nextTo = activeLink.from + nextText.length;\n tr.removeMark(activeLink.from, nextTo, linkMark);\n for (const mark of preservedMarks) {\n tr.addMark(activeLink.from, nextTo, mark);\n }\n tr.addMark(activeLink.from, nextTo, linkMark.create({ href: nextHref }));\n const nextCursor = Math.min(activeLink.from + cursorOffset, nextTo);\n tr.setSelection(TextSelection.near(tr.doc.resolve(nextCursor)));\n }\n\n view.dispatch(tr);\n onClose();\n view.focus();\n };\n\n const removeLink = () => {\n const activeLink = currentLink();\n view.dispatch(view.state.tr.removeMark(activeLink.from, activeLink.to, linkMark));\n onClose();\n view.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n view.focus();\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n saveLink();\n }\n };\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left,\n top,\n zIndex: 1001,\n width: dialogW,\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n background: '#FFFFFF',\n borderRadius: 8,\n boxShadow: '0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)',\n boxSizing: 'border-box',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Text <span style={{ color: '#858585' }}>(optional)</span>\n </div>\n <input\n ref={textInputRef}\n {...{ [FLOAT_ATTR]: '' }}\n value={textValue}\n onChange={(e) => setTextValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Link\n </div>\n <input\n {...{ [FLOAT_ATTR]: '' }}\n value={hrefValue}\n onChange={(e) => setHrefValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n }}\n >\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n removeLink();\n }}\n style={{\n ...BTN_RESET,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Remove link\n </button>\n\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n onClose();\n view.focus();\n }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n disabled={!canSave}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n if (!canSave) return;\n saveLink();\n }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n background: canSave ? '#6210CC' : '#ECECEC',\n color: canSave ? '#FFFFFF' : '#A6A6A6',\n cursor: canSave ? 'pointer' : 'default',\n }}\n >\n Save\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── Link Insert Dialog (new link at cursor) ─────────────────────────────────\n\n/** Custom event name for triggering the insert-link dialog from outside. */\nexport const INSERT_LINK_EVENT = 'ab-insert-link';\n\ninterface LinkInsertDialogProps {\n view: EditorView;\n cursorPos: number;\n onClose: () => void;\n}\n\nfunction LinkInsertDialog({ view, cursorPos, onClose }: LinkInsertDialogProps) {\n const [textValue, setTextValue] = useState('');\n const [hrefValue, setHrefValue] = useState('');\n const textInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setTimeout(() => textInputRef.current?.focus(), 0);\n }, []);\n\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [onClose]);\n\n let coords: { top: number; bottom: number; left: number };\n try {\n coords = view.coordsAtPos(cursorPos);\n } catch {\n onClose();\n return null;\n }\n\n const dialogW = 280;\n const left = Math.max(\n VPORT_MARGIN,\n Math.min(coords.left - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN),\n );\n const top = Math.min(coords.bottom + 8, window.innerHeight - 220 - VPORT_MARGIN);\n\n const finalHref = normalizeLinkHref(hrefValue);\n const canSave = Boolean(finalHref);\n\n const saveLink = () => {\n if (!finalHref) return;\n const displayText = textValue.trim() || finalHref;\n const tr = view.state.tr;\n const linkMarkType = view.state.schema.marks.link;\n if (!linkMarkType) return;\n\n tr.insertText(displayText, cursorPos);\n tr.addMark(cursorPos, cursorPos + displayText.length, linkMarkType.create({ href: finalHref }));\n view.dispatch(tr);\n onClose();\n view.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n view.focus();\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n saveLink();\n }\n };\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left,\n top,\n zIndex: 1001,\n width: dialogW,\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n background: '#FFFFFF',\n borderRadius: 8,\n boxShadow: POPUP_SHADOW,\n boxSizing: 'border-box',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ fontSize: 12, lineHeight: '16px', fontWeight: 600, color: '#0D0D0D' }}>\n Text <span style={{ color: '#858585' }}>(optional)</span>\n </div>\n <input\n ref={textInputRef}\n {...{ [FLOAT_ATTR]: '' }}\n value={textValue}\n placeholder=\"\"\n onChange={(e) => setTextValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ fontSize: 12, lineHeight: '16px', fontWeight: 600, color: '#0D0D0D' }}>\n Link\n </div>\n <input\n {...{ [FLOAT_ATTR]: '' }}\n value={hrefValue}\n onChange={(e) => setHrefValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 8 }}>\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); onClose(); view.focus(); }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n disabled={!canSave}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); if (canSave) saveLink(); }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n background: canSave ? '#6210CC' : '#ECECEC',\n color: canSave ? '#FFFFFF' : '#A6A6A6',\n cursor: canSave ? 'pointer' : 'default',\n }}\n >\n Save\n </button>\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── Block menu items ──────────────────────────────────────\n\ninterface BlockItem {\n shortLabel: string;\n label: string;\n run: (view: EditorView) => void;\n}\n\nconst BLOCK_ITEMS: BlockItem[] = [\n {\n shortLabel: '¶',\n label: 'Text',\n run: (v) => { setBlockType(paragraph)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H1',\n label: 'Heading 1',\n run: (v) => { setBlockType(heading, { level: 1 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H2',\n label: 'Heading 2',\n run: (v) => { setBlockType(heading, { level: 2 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H3',\n label: 'Heading 3',\n run: (v) => { setBlockType(heading, { level: 3 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '•',\n label: 'Bullet List',\n run: (v) => { wrapInList(bulletList)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '1.',\n label: 'Ordered List',\n run: (v) => { wrapInList(orderedList)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '☐',\n label: 'Todo List',\n run: (v) => {\n const { listItem: liType, bulletList: blType, paragraph: pType } = actionbookSchema.nodes;\n const li = liType.create({ checked: false }, pType.create());\n const list = blType.create(null, li);\n v.dispatch(v.state.tr.replaceSelectionWith(list));\n v.focus();\n },\n },\n {\n shortLabel: '❝',\n label: 'Quote',\n run: (v) => { wrapIn(blockquote)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '▦',\n label: 'Table',\n run: (v) => {\n const { table: tblType, tableRow: trType, tableHeader: thType, tableCell: tdType } = actionbookSchema.nodes;\n const headerCells = [thType.create(), thType.create(), thType.create()];\n const bodyCells = [tdType.create(), tdType.create(), tdType.create()];\n const headerRow = trType.create(null, headerCells);\n const bodyRow = trType.create(null, bodyCells);\n const tbl = tblType.create(null, [headerRow, bodyRow]);\n v.dispatch(v.state.tr.replaceSelectionWith(tbl));\n v.focus();\n },\n },\n];\n\n// ── EmptyParaHandle ───────────────────────────────────────\n\ninterface EmptyParaHandleProps {\n view: EditorView;\n cursorPos: number;\n}\n\nfunction EmptyParaHandle({ view, cursorPos }: EmptyParaHandleProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n const coords = view.coordsAtPos(cursorPos);\n const lineH = Math.max(coords.bottom - coords.top, 18);\n const btnSize = 22;\n const btnLeft = coords.left - btnSize - 32;\n const btnTop = coords.top + (lineH - btnSize) / 2;\n const menuLeft = Math.max(VPORT_MARGIN, btnLeft);\n const menuTop = btnTop + btnSize + 4;\n\n // Close block menu when clicking outside floating elements\n useEffect(() => {\n if (!menuOpen) return;\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n setMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [menuOpen]);\n\n return (\n <>\n {/* + button */}\n <button\n {...{ [FLOAT_ATTR]: '' }}\n title=\"Add block\"\n onMouseDown={(e) => { e.preventDefault(); setMenuOpen((v) => !v); }}\n style={{\n ...BTN_RESET,\n position: 'fixed', zIndex: 999,\n left: btnLeft < VPORT_MARGIN ? VPORT_MARGIN : btnLeft,\n top: btnTop,\n width: btnSize, height: btnSize,\n border: '1px solid rgba(0,0,0,0.1)',\n borderRadius: 5,\n background: menuOpen ? 'rgba(98,16,204,0.08)' : '#fff',\n boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n color: menuOpen ? '#6210CC' : '#9ca3af',\n fontSize: 16,\n animation: 'ab-float-in 0.15s ease',\n transition: 'color 0.1s, background 0.1s, border-color 0.1s',\n }}\n >\n +\n </button>\n\n {/* Block picker menu */}\n {menuOpen && (\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed', zIndex: 1000,\n left: menuLeft, top: menuTop,\n background: '#fff',\n borderRadius: 8,\n boxShadow: POPUP_SHADOW,\n padding: 4,\n minWidth: 168,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {BLOCK_ITEMS.map((item) => (\n <BlockMenuItem\n key={item.label}\n item={item}\n view={view}\n onRun={() => setMenuOpen(false)}\n />\n ))}\n </div>\n )}\n </>\n );\n}\n\nfunction BlockMenuItem({\n item,\n view,\n onRun,\n}: {\n item: BlockItem;\n view: EditorView;\n onRun: () => void;\n}) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); item.run(view); onRun(); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 10,\n width: '100%', padding: '6px 8px',\n borderRadius: 6, textAlign: 'left',\n fontSize: 13, color: '#0D0D0D',\n background: hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s',\n }}\n >\n <span\n style={{\n width: 24, flexShrink: 0, textAlign: 'center',\n fontWeight: 700, fontSize: 12,\n fontFamily: 'monospace',\n color: '#6210CC',\n }}\n >\n {item.shortLabel}\n </span>\n {item.label}\n </button>\n );\n}\n\n// ── FloatingMenu (root) ───────────────────────────────────\n\nexport interface FloatingMenuProps {\n view: EditorView | null;\n editorState: EditorState | null;\n}\n\nexport function FloatingMenu({ view, editorState }: FloatingMenuProps) {\n // ── Dwell timer for empty paragraph ──\n const [showEmptyHandle, setShowEmptyHandle] = useState(false);\n const [editingLink, setEditingLink] = useState<LinkAtCursor | null>(null);\n const [insertLinkPos, setInsertLinkPos] = useState<number | null>(null);\n const dwellTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastEmptyPosRef = useRef<number | null>(null);\n\n // Listen for insert-link events from toolbar/slash command\n useEffect(() => {\n const dom = view?.dom;\n if (!dom) return;\n const handler = () => {\n const pos = view.state.selection.from;\n setInsertLinkPos(pos);\n };\n dom.addEventListener(INSERT_LINK_EVENT, handler);\n return () => dom.removeEventListener(INSERT_LINK_EVENT, handler);\n }, [view]);\n\n // ── Re-render on editor container scroll (position recalculation) ──\n const [, setScrollTick] = useState(0);\n useEffect(() => {\n const editorDom = view?.dom;\n if (!editorDom) return;\n const container = editorDom.closest('.editor-shell') ?? editorDom.parentElement;\n if (!container) return;\n const onScroll = () => setScrollTick((n) => n + 1);\n container.addEventListener('scroll', onScroll, { passive: true });\n return () => container.removeEventListener('scroll', onScroll);\n }, [view]);\n\n // ── Inject keyframe animation once ──\n useEffect(() => {\n const id = 'ab-float-keyframes';\n if (document.getElementById(id)) return;\n const style = document.createElement('style');\n style.id = id;\n style.textContent = `\n @keyframes ab-float-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(style);\n }, []);\n\n const emptyPos = editorState ? emptyBlockCursorPos(editorState) : null;\n const hasSelection = editorState ? !editorState.selection.empty : false;\n const linkAtCursor = editorState && !hasSelection ? getLinkAtCursor(editorState) : null;\n\n useEffect(() => {\n if (!editingLink) return;\n if (!linkAtCursor || linkAtCursor.from !== editingLink.from || linkAtCursor.to !== editingLink.to) {\n setEditingLink(null);\n }\n }, [editingLink, linkAtCursor]);\n\n if (!view || !editorState) return null;\n\n // Manage dwell timer\n if (emptyPos !== lastEmptyPosRef.current) {\n lastEmptyPosRef.current = emptyPos;\n\n if (dwellTimerRef.current) {\n clearTimeout(dwellTimerRef.current);\n dwellTimerRef.current = null;\n }\n\n if (emptyPos !== null) {\n dwellTimerRef.current = setTimeout(() => setShowEmptyHandle(true), DWELL_MS);\n } else {\n setShowEmptyHandle(false);\n }\n }\n\n const selectionRect = hasSelection ? getSelectionDOMRect() : null;\n\n return createPortal(\n <>\n {/* Selection toolbar */}\n {hasSelection && selectionRect && (\n <SelectionToolbar\n view={view}\n state={editorState}\n selectionRect={selectionRect}\n />\n )}\n\n {!hasSelection && linkAtCursor && !editingLink && (\n <LinkHoverTooltip\n view={view}\n link={linkAtCursor}\n onEdit={(link) => setEditingLink(link)}\n />\n )}\n\n {!hasSelection && editingLink && (\n <LinkEditDialog\n view={view}\n link={editingLink}\n onClose={() => setEditingLink(null)}\n />\n )}\n\n {/* Insert new link dialog */}\n {insertLinkPos !== null && (\n <LinkInsertDialog\n view={view}\n cursorPos={insertLinkPos}\n onClose={() => setInsertLinkPos(null)}\n />\n )}\n\n {/* Empty paragraph handle */}\n {!hasSelection && !linkAtCursor && !insertLinkPos && showEmptyHandle && emptyPos !== null && (\n <EmptyParaHandle view={view} cursorPos={emptyPos} />\n )}\n </>,\n document.body,\n );\n}\n","/**\n * Inline suggestion (ghost text) plugin.\n *\n * Debounces after the cursor stops moving, calls an LLM endpoint via a\n * user-supplied `InlineSuggestProvider`, then renders the response as gray\n * ghost text after the cursor using a ProseMirror widget decoration.\n *\n * Accepts:\n * Tab → insert the suggestion at the cursor\n * Escape → dismiss the suggestion\n *\n * Fully detachable: just omit `createInlineSuggestPlugin()` from the plugins\n * array to disable the feature entirely.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { EditorView } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\nimport type { LlmCompletionEndpoint } from '../../lint/types';\n\n// ── Public types ──────────────────────────────────────────\n\n/**\n * Cursor context passed to the provider's `buildPrompt`.\n */\nexport type InlineSuggestContext = {\n /** Text before the cursor — current paragraph plus up to 2 preceding paragraphs. */\n textBefore: string;\n /** Text in the current paragraph after the cursor (up to 100 chars). */\n textAfter: string;\n};\n\n/**\n * Extensible provider interface, analogous to `LlmLintRule`.\n *\n * Implement this to customize what gets sent to the LLM and how the\n * response is parsed into a suggestion string.\n */\nexport type InlineSuggestProvider = {\n /** Unique identifier for this provider. */\n id: string;\n /**\n * Build the prompt string sent to the LLM endpoint.\n * Return an empty string to suppress the request entirely.\n */\n buildPrompt: (ctx: InlineSuggestContext) => string;\n /**\n * Parse the raw LLM response into the text to insert at the cursor.\n * Return an empty string to suppress the decoration.\n * `ctx` is the same context that was passed to `buildPrompt`.\n */\n parseResponse: (response: string, ctx: InlineSuggestContext) => string;\n};\n\nexport interface InlineSuggestState {\n /** Ghost text currently shown, or null if nothing is active. */\n suggestion: string | null;\n /** Document position the suggestion is anchored to. */\n anchorPos: number | null;\n}\n\nexport const inlineSuggestKey = new PluginKey<InlineSuggestState>('inlineSuggest');\n\n// ── Constants ─────────────────────────────────────────────\n\nconst DEBOUNCE_MS = 600;\nconst CONTEXT_CHARS = 500;\n\n// ── Factory ───────────────────────────────────────────────\n\nexport function createInlineSuggestPlugin(\n provider: InlineSuggestProvider,\n endpoint: LlmCompletionEndpoint,\n options?: {\n /**\n * Called when the user accepts a suggestion (Tab) or the cursor moves to\n * a new context. Use this to pre-create a fresh completion session so it's\n * ready by the time the next debounce fires.\n */\n onContextChange?: () => void;\n },\n): ActionbookPlugin {\n const { onContextChange } = options ?? {};\n return {\n name: 'inlineSuggest',\n\n plugins: () => [\n new Plugin<InlineSuggestState>({\n key: inlineSuggestKey,\n\n state: {\n init: (): InlineSuggestState => ({ suggestion: null, anchorPos: null }),\n\n apply(tr, prev): InlineSuggestState {\n const meta = tr.getMeta(inlineSuggestKey) as InlineSuggestState | null | undefined;\n if (meta !== undefined) return meta ?? { suggestion: null, anchorPos: null };\n // Any document edit or cursor move clears the current ghost text\n if (tr.docChanged || tr.selectionSet) {\n return { suggestion: null, anchorPos: null };\n }\n return prev;\n },\n },\n\n props: {\n decorations(state: EditorState) {\n const ps = inlineSuggestKey.getState(state);\n if (!ps?.suggestion || !state.selection.empty) return DecorationSet.empty;\n\n const ghost = document.createElement('span');\n ghost.textContent = ps.suggestion;\n ghost.style.cssText =\n 'color: rgba(0,0,0,0.3); pointer-events: none; user-select: none;';\n ghost.setAttribute('aria-hidden', 'true');\n\n return DecorationSet.create(state.doc, [\n Decoration.widget(state.selection.from, ghost, {\n side: 1,\n key: 'inline-suggest',\n }),\n ]);\n },\n },\n\n view(editorView: EditorView) {\n // Capture Tab / Escape before the browser handles them (Tab moves\n // focus, Escape might bubble to parent dialogs).\n function onKeydown(event: KeyboardEvent) {\n if (event.key !== 'Tab' && event.key !== 'Escape') return;\n const ps = inlineSuggestKey.getState(editorView.state);\n console.debug('[inline-suggest] key pressed:', event.key, 'suggestion:', ps?.suggestion);\n if (!ps?.suggestion) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (event.key === 'Tab') {\n // Context changes after accept — pre-clone now so the next\n // fetch gets a fresh session without waiting for clone().\n onContextChange?.();\n const tr = editorView.state.tr.insertText(\n ps.suggestion,\n editorView.state.selection.from,\n );\n tr.setMeta(inlineSuggestKey, { suggestion: null, anchorPos: null });\n editorView.dispatch(tr);\n } else {\n const tr = editorView.state.tr;\n tr.setMeta(inlineSuggestKey, { suggestion: null, anchorPos: null });\n editorView.dispatch(tr);\n }\n }\n\n editorView.dom.addEventListener('keydown', onKeydown, { capture: true });\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let abortController: AbortController | null = null;\n\n function cancel() {\n if (debounceTimer != null) {\n clearTimeout(debounceTimer);\n debounceTimer = null;\n }\n abortController?.abort();\n abortController = null;\n }\n\n function schedule(view: EditorView) {\n cancel();\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n void fetchSuggestion(view);\n }, DEBOUNCE_MS);\n }\n\n async function fetchSuggestion(view: EditorView) {\n const { state } = view;\n if (!state.selection.empty) return;\n\n const cursorPos = state.selection.from;\n const $from = state.doc.resolve(cursorPos);\n const paraStart = $from.start();\n const paraEnd = $from.end();\n\n // Collect up to 3 block nodes ending at the cursor's block.\n const nearbyStart = (() => {\n const $cursor = state.doc.resolve(cursorPos);\n const depth = $cursor.depth; // depth of the paragraph node\n let blockStart = $cursor.before(depth); // pos of current block's opening token\n let count = 1;\n while (count < 3 && blockStart > 0) {\n const $prev = state.doc.resolve(blockStart - 1);\n blockStart = $prev.before($prev.depth);\n count++;\n }\n return blockStart;\n })();\n\n const textBefore = state.doc.textBetween(nearbyStart, cursorPos, '\\n', '');\n const textAfter = state.doc.textBetween(\n cursorPos,\n Math.min(paraEnd, cursorPos + 100),\n '\\n',\n '',\n );\n\n if (!textBefore.trim()) return;\n\n const ctx = { textBefore, textAfter };\n const prompt = provider.buildPrompt(ctx);\n if (!prompt) return;\n\n console.debug(`[inline-suggest] fetching (provider=${provider.id}) prompt=`, prompt);\n\n abortController = new AbortController();\n try {\n const response = await endpoint(prompt, { signal: abortController.signal });\n console.debug(`[inline-suggest] response=`, response);\n\n const suggestion = provider.parseResponse(response, ctx).trimEnd();\n console.debug(`[inline-suggest] parsed suggestion=`, JSON.stringify(suggestion));\n\n if (!suggestion) {\n console.debug('[inline-suggest] empty suggestion — skipping');\n return;\n }\n\n // Discard if cursor moved while we were waiting\n if (!view.state.selection.empty) return;\n if (view.state.selection.from !== cursorPos) {\n console.debug('[inline-suggest] cursor moved — discarding');\n return;\n }\n\n const tr = view.state.tr;\n tr.setMeta(inlineSuggestKey, { suggestion, anchorPos: cursorPos });\n view.dispatch(tr);\n console.debug('[inline-suggest] suggestion applied');\n } catch (err) {\n if ((err as Error)?.name === 'AbortError') {\n console.debug('[inline-suggest] request aborted');\n } else {\n console.warn('[inline-suggest] endpoint error:', err);\n }\n }\n }\n\n return {\n update(view: EditorView, prevState: EditorState) {\n const docChanged = view.state.doc !== prevState.doc;\n const selChanged = view.state.selection !== prevState.selection;\n if (!docChanged && !selChanged) return;\n\n // A suggestion was just set (meta transaction) — don't reschedule\n const ps = inlineSuggestKey.getState(view.state);\n if (ps?.suggestion) return;\n\n if (!view.state.selection.empty) {\n cancel();\n return;\n }\n\n // Context changed — pre-clone before the debounce fires so the\n // session is fresh and ready when the fetch runs.\n onContextChange?.();\n schedule(view);\n },\n\n destroy() {\n cancel();\n editorView.dom.removeEventListener('keydown', onKeydown, { capture: true });\n },\n };\n },\n }),\n ],\n };\n}\n","import type { EditorState } from 'prosemirror-state';\nimport { validateCondition } from '../../jinja/evaluator';\n\n/**\n * Check if any jinjaIfBranch in the editor has an invalid (non-empty) condition.\n * Used to block save when conditions have syntax errors.\n */\nexport function hasInvalidJinjaConditions(state: EditorState): boolean {\n let found = false;\n state.doc.descendants((node) => {\n if (found) return false;\n if (node.type.name === 'jinjaIfBranch') {\n const condition = String(node.attrs.condition ?? '');\n if (condition && !validateCondition(condition).valid) {\n found = true;\n }\n return false;\n }\n });\n return found;\n}\n\n/**\n * Check if any jinjaIfBranch has an empty body (single empty paragraph).\n * Used to block save when branch bodies have no content.\n */\nexport function hasEmptyJinjaBranches(state: EditorState): boolean {\n let found = false;\n state.doc.descendants((node) => {\n if (found) return false;\n if (node.type.name === 'jinjaIfBranch') {\n if (node.childCount === 1) {\n const first = node.firstChild;\n if (first?.type.name === 'paragraph' && first.content.size === 0) {\n found = true;\n }\n }\n return false;\n }\n });\n return found;\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["key","text","jsx","jsxs","key","text","doc","jsx","EditorShell","text","textContent","blocks","defaultHandlers","exit","exit","table","row","sizes","columnIndex","code","exit","defaultHandlers","text","text","MAX_DEPTH","ALLOWED_URL_PROTOCOLS","linkMark","doc","defaultHandlers","doc","ALLOWED_URL_PROTOCOLS","convertInline","convertBlock","convertBlock","doc","doc","derived","JUMP_POINT_RE","liDepth","liIndex","tr","textContent","keymap","Plugin","TextSelection","keymap","TextSelection","text","Plugin","doc","keymap","Plugin","PluginKey","MAX_DEPTH","MAX_DEPTH","code","code","constructs","ok","code","markdownSpace","ok","code","markdownLineEndingOrSpace","ok","code","markdownLineEndingOrSpace","strikethrough","text","ok","code","markdownLineEnding","markdownLineEndingOrSpace","markdownSpace","ok","code","markdownLineEnding","markdownSpace","markdownLineEndingOrSpace","map","table","markdownLineEnding","markdownLineEndingOrSpace","markdownSpace","ok","code","MAX_DEPTH","text","MAX_DEPTH","MAX_DEPTH","doc","text","doc","KEYWORDS","MAX_DEPTH","text","doc","PluginKey","doc","text","Plugin","linkMark","slice","Plugin","PluginKey","TextSelection","Decoration","DecorationSet","text","useCallback","useRef","useState","jsx","jsxs","useState","useRef","useCallback","Plugin","PluginKey","Decoration","DecorationSet","linkMark","buildDecorations","jsx","jsxs","RESOURCE_TAG_COLORS","RESOURCE_TAG_ICONS","text","Plugin","PluginKey","Decoration","DecorationSet","PluginKey","doc","text","Decoration","buildDecorations","DecorationSet","Plugin","useEffect","useRef","useState","createRoot","Plugin","TextSelection","Fragment","jsx","jsxs","doc","TextSelection","tr","jsx","useState","useRef","useEffect","jsxs","Fragment","createRoot","Plugin","InputRule","inputRules","Plugin","PluginKey","TextSelection","doc","text","Plugin","PluginKey","StyleManager","doc","key","Plugin","tr","Plugin","PluginKey","Decoration","DecorationSet","pluginKey","buildDecorations","doc","React","useEffect","useRef","useState","createPortal","Fragment","jsx","jsxs","useState","useRef","useEffect","createPortal","React","useState","jsx","jsxs","doc","text","useState","useState","jsx","jsxs","useState","doc","useCallback","useEffect","useRef","useState","createPortal","TextSelection","setBlockType","toggleMark","wrapInList","Fragment","jsx","jsxs","paragraph","heading","bulletList","orderedList","blockquote","bold","italic","underline","strikethrough","code","VPORT_MARGIN","getMarkRange","doc","POPUP_SHADOW","BTN_RESET","useState","useRef","useEffect","setBlockType","wrapInList","createPortal","useCallback","toggleMark","link","tr","TextSelection","Plugin","PluginKey","Decoration","DecorationSet","Plugin","DecorationSet","Decoration"]}
1
+ {"version":3,"sources":["../../src/ui/schema.ts","../../src/ui/plugin/registry.ts","../../src/ui/components/ActionbookRenderer.tsx","../../src/jinja/conditionHighlighter.ts","../../src/ui/components/icons.tsx","../../src/ui/components/EditorShell.tsx","../../src/ui/nodeView/ReactNodeView.ts","../../src/ui/hooks/useEditorView.ts","../../src/ast/types.ts","../../src/compat/prosemirror.ts","../../src/markdown/serializer.ts","../../node_modules/devlop/lib/default.js","../../node_modules/micromark-util-normalize-identifier/index.js","../../node_modules/mdast-util-gfm-footnote/lib/index.js","../../node_modules/mdast-util-gfm-strikethrough/lib/index.js","../../node_modules/markdown-table/index.js","../../node_modules/mdast-util-gfm-table/lib/index.js","../../node_modules/mdast-util-gfm-task-list-item/lib/index.js","../../src/markdown/plugins/resourceTag.ts","../../src/markdown/plugins/jumpPoint.ts","../../src/markdown/mdastAdapter.ts","../../src/ui/bridge/toProseMirrorJSON.ts","../../src/ui/styles/editorTextStyles.ts","../../src/ui/plugin/inputRulesPlugin.ts","../../src/ui/plugin/slashCommandPlugin.ts","../../src/ui/plugin/historyPlugin.ts","../../src/ui/plugin/keymapPlugin.ts","../../src/ui/plugin/noteBlockPlugin.tsx","../../src/ui/plugin/markdownClipboard.ts","../../src/ast/traverse.ts","../../src/markdown/parser.ts","../../node_modules/micromark-util-chunked/index.js","../../node_modules/micromark-util-combine-extensions/index.js","../../node_modules/micromark-util-classify-character/index.js","../../node_modules/micromark-util-resolve-all/index.js","../../node_modules/micromark-factory-space/index.js","../../node_modules/micromark-core-commonmark/lib/blank-line.js","../../node_modules/micromark-extension-gfm-footnote/lib/syntax.js","../../node_modules/micromark-extension-gfm-strikethrough/lib/syntax.js","../../node_modules/micromark-extension-gfm-table/lib/syntax.js","../../node_modules/micromark-extension-gfm-table/lib/edit-map.js","../../node_modules/micromark-extension-gfm-table/lib/infer.js","../../node_modules/micromark-extension-gfm-task-list-item/lib/syntax.js","../../src/markdown/plugins/jinjaBlock.ts","../../src/markdown/fragment.ts","../../src/jinja/scanner.ts","../../src/jinja/structurer.ts","../../src/jinja/analyzer.ts","../../src/jinja/evaluator.ts","../../src/tree/documentTree.ts","../../src/ui/plugin/jumpPointPlugin.ts","../../src/ui/plugin/jumpPointNodeViewPlugin.tsx","../../src/ui/plugin/jumpPointValidationPlugin.ts","../../src/ui/plugin/inlineToolTagNodeViewPlugin.tsx","../../src/ui/plugin/jinjaDecoration.ts","../../src/ui/plugin/jinjaIfBlockPlugin.tsx","../../src/ui/plugin/linkPlugin.ts","../../src/ui/plugin/dragHandlePlugin.ts","../../src/ui/plugin/todoNodeViewPlugin.tsx","../../src/ui/plugin/placeholderPlugin.ts","../../src/ui/components/SlashCommandMenu.tsx","../../src/ui/components/JinjaTreeView.tsx","../../src/ui/components/DocumentTreeView.tsx","../../src/ui/components/FloatingMenu.tsx","../../src/ui/plugin/inlineSuggestPlugin.ts","../../src/ui/bridge/jinjaValidation.ts"],"sourcesContent":["import { Schema } from 'prosemirror-model';\n\n/**\n * ProseMirror Schema for Actionbook documents.\n */\nexport const actionbookSchema = new Schema({\n nodes: {\n doc: {\n content: 'block*',\n },\n\n paragraph: {\n content: 'inline*',\n group: 'block',\n parseDOM: [{ tag: 'p' }],\n toDOM() {\n return ['p', 0];\n },\n },\n\n heading: {\n content: '(text | jumpPoint | hardBreak)*',\n group: 'block',\n attrs: { level: { default: 1 } },\n parseDOM: [\n { tag: 'h1', attrs: { level: 1 } },\n { tag: 'h2', attrs: { level: 2 } },\n { tag: 'h3', attrs: { level: 3 } },\n { tag: 'h4', attrs: { level: 4 } },\n { tag: 'h5', attrs: { level: 5 } },\n { tag: 'h6', attrs: { level: 6 } },\n ],\n toDOM(node) {\n return [`h${node.attrs.level}`, 0];\n },\n },\n\n bulletList: {\n content: 'listItem+',\n group: 'block',\n parseDOM: [{ tag: 'ul' }],\n toDOM() {\n return ['ul', 0];\n },\n },\n\n orderedList: {\n content: 'listItem+',\n group: 'block',\n attrs: { start: { default: 1 } },\n parseDOM: [\n {\n tag: 'ol',\n getAttrs(dom) {\n return { start: (dom as HTMLOListElement).start || 1 };\n },\n },\n ],\n toDOM(node) {\n return node.attrs.start === 1 ? ['ol', 0] : ['ol', { start: node.attrs.start }, 0];\n },\n },\n\n listItem: {\n content: 'block+',\n attrs: { checked: { default: null }, value: { default: null } },\n parseDOM: [\n {\n tag: 'li',\n getAttrs(dom) {\n const el = dom as HTMLLIElement;\n const checkbox = el.querySelector('input[type=\"checkbox\"]');\n if (checkbox) {\n return { checked: (checkbox as HTMLInputElement).checked, value: el.value || null };\n }\n if (el.dataset.checked != null) {\n return { checked: el.dataset.checked === 'true', value: el.value || null };\n }\n return { checked: null, value: el.value || null };\n },\n },\n ],\n toDOM(node) {\n const liAttrs: Record<string, string> = {};\n if (node.attrs.checked != null) {\n liAttrs.class = 'todo-item';\n liAttrs['data-checked'] = String(node.attrs.checked);\n }\n if (node.attrs.value != null) {\n liAttrs.value = String(node.attrs.value);\n }\n return Object.keys(liAttrs).length > 0 ? ['li', liAttrs, 0] : ['li', 0];\n },\n defining: true,\n },\n\n blockquote: {\n content: 'block+',\n group: 'block',\n parseDOM: [{ tag: 'blockquote' }],\n toDOM() {\n return ['blockquote', 0];\n },\n defining: true,\n },\n\n codeBlock: {\n content: 'text*',\n group: 'block',\n code: true,\n defining: true,\n marks: '',\n attrs: { language: { default: null } },\n parseDOM: [{\n tag: 'pre',\n preserveWhitespace: 'full' as const,\n getAttrs(dom) {\n return { language: (dom as HTMLElement).getAttribute('data-language') || null };\n },\n }],\n toDOM(node) {\n return ['pre', { 'data-language': node.attrs.language || undefined }, ['code', 0]];\n },\n },\n\n horizontalRule: {\n group: 'block',\n parseDOM: [{ tag: 'hr' }],\n toDOM() {\n return ['hr'];\n },\n },\n\n // ── Jinja conditional block ──\n\n jinjaIfBlock: {\n content: 'jinjaIfBranch+',\n group: 'block',\n isolating: true,\n defining: true,\n parseDOM: [{ tag: 'div[data-jinja-if-block]' }],\n toDOM() {\n return ['div', { 'data-jinja-if-block': '', class: 'jinja-if-block' }, 0];\n },\n },\n\n jinjaIfBranch: {\n content: 'block+',\n isolating: true,\n defining: true,\n attrs: {\n branchType: { default: 'if' }, // 'if' | 'elif' | 'else'\n condition: { default: '' },\n },\n parseDOM: [\n {\n tag: 'div[data-jinja-branch]',\n getAttrs(dom) {\n const el = dom as HTMLElement;\n return {\n branchType: el.getAttribute('data-branch-type') || 'if',\n condition: el.getAttribute('data-condition') || '',\n };\n },\n },\n ],\n toDOM(node) {\n return [\n 'div',\n {\n 'data-jinja-branch': '',\n 'data-branch-type': node.attrs.branchType,\n 'data-condition': node.attrs.condition,\n class: `jinja-branch jinja-branch-${node.attrs.branchType}`,\n },\n 0,\n ];\n },\n },\n\n noteBlock: {\n content: 'block+',\n group: 'block',\n defining: true,\n isolating: true,\n parseDOM: [{ tag: 'div[data-note-block]' }],\n toDOM() {\n return ['div', { 'data-note-block': '', class: 'ab-note-block' }, 0];\n },\n },\n // ── Table nodes ──\n\n table: {\n content: 'tableRow+',\n group: 'block',\n tableRole: 'table',\n isolating: true,\n parseDOM: [{ tag: 'table' }],\n toDOM() {\n return ['table', ['tbody', 0]];\n },\n },\n\n tableRow: {\n content: '(tableCell | tableHeader)+',\n tableRole: 'row',\n parseDOM: [{ tag: 'tr' }],\n toDOM() {\n return ['tr', 0];\n },\n },\n\n tableCell: {\n content: 'inline*',\n tableRole: 'cell',\n attrs: {\n colspan: { default: 1 },\n rowspan: { default: 1 },\n },\n isolating: true,\n parseDOM: [\n {\n tag: 'td',\n getAttrs(dom) {\n const el = dom as HTMLTableCellElement;\n return {\n colspan: el.colSpan || 1,\n rowspan: el.rowSpan || 1,\n };\n },\n },\n ],\n toDOM(node) {\n const attrs: Record<string, string | number> = {};\n if (node.attrs.colspan !== 1) attrs.colspan = node.attrs.colspan;\n if (node.attrs.rowspan !== 1) attrs.rowspan = node.attrs.rowspan;\n return ['td', attrs, 0];\n },\n },\n\n tableHeader: {\n content: 'inline*',\n tableRole: 'header_cell',\n attrs: {\n colspan: { default: 1 },\n rowspan: { default: 1 },\n },\n isolating: true,\n parseDOM: [\n {\n tag: 'th',\n getAttrs(dom) {\n const el = dom as HTMLTableCellElement;\n return {\n colspan: el.colSpan || 1,\n rowspan: el.rowSpan || 1,\n };\n },\n },\n ],\n toDOM(node) {\n const attrs: Record<string, string | number> = {};\n if (node.attrs.colspan !== 1) attrs.colspan = node.attrs.colspan;\n if (node.attrs.rowspan !== 1) attrs.rowspan = node.attrs.rowspan;\n return ['th', attrs, 0];\n },\n },\n\n text: {\n group: 'inline',\n },\n\n inlineToolTag: {\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n type: { default: 'tool' },\n resourceId: { default: '' },\n text: { default: '' },\n },\n toDOM(node) {\n return [\n 'span',\n {\n class: 'inline-tool-tag',\n 'data-type': node.attrs.type,\n 'data-resource-id': node.attrs.resourceId,\n },\n node.attrs.text,\n ];\n },\n parseDOM: [\n {\n tag: 'span.inline-tool-tag',\n getAttrs(dom) {\n const el = dom as HTMLElement;\n return {\n type: el.getAttribute('data-type') || 'tool',\n resourceId: el.getAttribute('data-resource-id') || '',\n text: el.textContent || '',\n };\n },\n },\n ],\n },\n\n jumpPoint: {\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n id: { default: '' },\n },\n toDOM(node) {\n return [\n 'span',\n {\n class: 'jump-point',\n 'data-jump-point-id': node.attrs.id,\n },\n `^${node.attrs.id}^`,\n ];\n },\n parseDOM: [\n {\n tag: 'span.jump-point',\n getAttrs(dom) {\n return {\n id: (dom as HTMLElement).getAttribute('data-jump-point-id') || '',\n };\n },\n },\n ],\n },\n\n hardBreak: {\n group: 'inline',\n inline: true,\n selectable: false,\n parseDOM: [{ tag: 'br' }],\n toDOM() {\n return ['br'];\n },\n },\n },\n\n marks: {\n bold: {\n parseDOM: [\n { tag: 'strong' },\n { tag: 'b', getAttrs: (node) => (node as HTMLElement).style.fontWeight !== 'normal' && null },\n {\n style: 'font-weight',\n getAttrs: (value) => /^(bold(er)?|[5-9]\\d{2,})$/.test(value as string) && null,\n },\n ],\n toDOM() {\n return ['strong', 0];\n },\n },\n\n italic: {\n parseDOM: [\n { tag: 'em' },\n { tag: 'i', getAttrs: (node) => (node as HTMLElement).style.fontStyle !== 'normal' && null },\n {\n style: 'font-style',\n getAttrs: (value) => (value as string) === 'italic' && null,\n },\n ],\n toDOM() {\n return ['em', 0];\n },\n },\n\n underline: {\n parseDOM: [\n { tag: 'u' },\n {\n style: 'text-decoration',\n getAttrs: (value) => (value as string).includes('underline') && null,\n },\n ],\n toDOM() {\n return ['u', 0];\n },\n },\n\n strikethrough: {\n parseDOM: [\n { tag: 's' },\n { tag: 'del' },\n { tag: 'strike' },\n {\n style: 'text-decoration',\n getAttrs: (value) => (value as string).includes('line-through') && null,\n },\n ],\n toDOM() {\n return ['s', 0];\n },\n },\n\n code: {\n parseDOM: [{ tag: 'code' }],\n toDOM() {\n return ['code', 0];\n },\n },\n\n link: {\n attrs: {\n href: { default: '' },\n title: { default: null },\n },\n inclusive: false,\n parseDOM: [\n {\n tag: 'a[href]',\n getAttrs(dom) {\n return {\n href: (dom as HTMLElement).getAttribute('href'),\n title: (dom as HTMLElement).getAttribute('title'),\n };\n },\n },\n ],\n toDOM(node) {\n const { href, title } = node.attrs;\n return ['a', { href, title, rel: 'noopener noreferrer nofollow' }, 0];\n },\n },\n\n diffMark: {\n attrs: {\n type: { default: 'added' },\n },\n parseDOM: [\n {\n tag: 'span[data-diff-type]',\n getAttrs(dom) {\n return { type: (dom as HTMLElement).getAttribute('data-diff-type') || 'added' };\n },\n },\n ],\n toDOM(node) {\n return ['span', { 'data-diff-type': node.attrs.type, class: `diff-${node.attrs.type}` }, 0];\n },\n },\n },\n});\n","import { Plugin } from 'prosemirror-state';\nimport { keymap } from 'prosemirror-keymap';\nimport { inputRules } from 'prosemirror-inputrules';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\n/**\n * Converts ActionbookPlugin[] into a flat array of PM Plugins.\n * Merges inputRules and keymaps from all plugins.\n *\n * Priority order (ProseMirror tries plugins in array order — first wins):\n * 1. Merged inputRules — highest priority for text-input transforms\n * 2. Merged keymap — custom handlers (e.g. splitListItem on Enter)\n * 3. Raw PM plugins — baseline behaviors (history, baseKeymap, etc.)\n *\n * Putting the merged keymap BEFORE raw plugins ensures that handlers like\n * `splitListItem` on Enter take priority over `baseKeymap`'s `splitBlock`.\n */\nexport function createPluginArray(plugins: ActionbookPlugin[]): {\n pmPlugins: Plugin[];\n nodeViews: Record<string, NodeViewFactory>;\n} {\n const rawPlugins: Plugin[] = [];\n const allNodeViews: Record<string, NodeViewFactory> = {};\n const allInputRules: import('prosemirror-inputrules').InputRule[] = [];\n const allKeymaps: Record<string, import('prosemirror-state').Command> = {};\n\n for (const plugin of plugins) {\n if (plugin.plugins) {\n rawPlugins.push(...plugin.plugins());\n }\n if (plugin.inputRules) {\n allInputRules.push(...plugin.inputRules());\n }\n if (plugin.keymap) {\n for (const [key, handler] of Object.entries(plugin.keymap())) {\n const prev = allKeymaps[key];\n // Chain: if an earlier plugin already claimed this key, run it first;\n // fall through to the new handler only if the earlier one returns false.\n allKeymaps[key] = prev\n ? (state, dispatch, view) => prev(state, dispatch, view) || handler(state, dispatch, view)\n : handler;\n }\n }\n if (plugin.nodeViews) {\n Object.assign(allNodeViews, plugin.nodeViews());\n }\n }\n\n const pmPlugins: Plugin[] = [];\n\n // 1. Input rules first (text-input events, no conflict with keydown)\n if (allInputRules.length > 0) {\n pmPlugins.push(inputRules({ rules: allInputRules }));\n }\n\n // 2. Merged keymap before raw plugins so custom handlers win on key conflicts\n if (Object.keys(allKeymaps).length > 0) {\n pmPlugins.push(keymap(allKeymaps));\n }\n\n // 3. Raw PM plugins (history, baseKeymap, etc.) as fallback\n pmPlugins.push(...rawPlugins);\n\n return { pmPlugins, nodeViews: allNodeViews };\n}\n","import React, { type ReactElement } from 'react';\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n AstNode,\n Mark,\n JinjaIfBranch,\n} from '../../ast/types';\nimport { tokenizeCondition } from '../../jinja/conditionHighlighter';\nimport {\n IconAnchor,\n IconHandoff,\n IconManual,\n IconMessageTemplate,\n IconTimeDiff,\n IconTool,\n} from './icons';\n\nexport interface ActionbookRendererProps {\n doc: DocumentNode;\n className?: string;\n /** Custom node renderer for extension points */\n renderNode?: (node: AstNode, defaultRender: () => ReactElement) => ReactElement;\n}\n\n// Color values matching Feather design tokens used in sbdashboard.\nconst RESOURCE_TAG_COLORS: Record<string, string> = {\n tool: '#027D69', // green-6\n manual: '#5959D3', // blue-6\n agent_message_template: '#8012B3', // violet-6\n handoff: '#D25309', // orange-6\n time_diff: '#FB6B6B', // data-viz-4 (red-4)\n};\nconst DEFAULT_RESOURCE_TAG_COLOR = '#027D69';\n\ntype IconComponent = typeof IconTool;\nconst RESOURCE_TAG_ICONS: Record<string, IconComponent> = {\n tool: IconTool,\n manual: IconManual,\n agent_message_template: IconMessageTemplate,\n handoff: IconHandoff,\n time_diff: IconTimeDiff,\n};\nconst DEFAULT_RESOURCE_TAG_ICON = IconTool;\n\nfunction renderMark(mark: Mark, children: ReactElement, key: string): ReactElement {\n switch (mark.type) {\n case 'bold':\n return <strong key={key}>{children}</strong>;\n case 'italic':\n return <em key={key}>{children}</em>;\n case 'underline':\n return <u key={key}>{children}</u>;\n case 'strikethrough':\n return <s key={key}>{children}</s>;\n case 'code':\n return <code key={key}>{children}</code>;\n case 'link':\n return (\n <a key={key} href={mark.href} title={mark.title} rel=\"noopener noreferrer nofollow\">\n {children}\n </a>\n );\n }\n}\n\nfunction wrapWithMarks(text: string, marks: readonly Mark[] | undefined, key: string): ReactElement {\n let element: ReactElement = <React.Fragment key={key}>{text}</React.Fragment>;\n if (!marks || marks.length === 0) return element;\n for (let i = 0; i < marks.length; i++) {\n element = renderMark(marks[i], element, `${key}-m${i}`);\n }\n return element;\n}\n\nfunction renderInline(\n node: InlineNode,\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const defaultRender = (): ReactElement => {\n switch (node.type) {\n case 'text':\n return wrapWithMarks(node.text, node.marks, key);\n case 'resourceTag': {\n const color = RESOURCE_TAG_COLORS[node.tagType] ?? DEFAULT_RESOURCE_TAG_COLOR;\n const Icon = RESOURCE_TAG_ICONS[node.tagType] ?? DEFAULT_RESOURCE_TAG_ICON;\n return (\n <span\n key={key}\n className=\"inline-tool-tag\"\n data-type={node.tagType}\n data-resource-id={node.resourceId}\n style={{\n display: 'inline-flex',\n height: '20px',\n padding: '1px',\n border: '1px solid #CCCCCC',\n borderRadius: '2px',\n alignItems: 'center',\n backgroundColor: 'white',\n verticalAlign: 'middle',\n userSelect: 'none',\n }}\n >\n <span\n style={{\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '16px',\n height: '16px',\n backgroundColor: color,\n borderRadius: '2px',\n flexShrink: 0,\n }}\n >\n <Icon size={9} fill=\"white\" />\n </span>\n <span\n style={{\n padding: '0 4px',\n color,\n fontSize: '11px',\n lineHeight: 1,\n userSelect: 'none',\n }}\n >\n {node.text}\n </span>\n </span>\n );\n }\n case 'jumpPoint':\n return (\n <span\n key={key}\n className=\"jump-point\"\n data-jump-point-id={node.id}\n id={`jp-${node.id}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: '#FFF2B6',\n border: '1px solid #FFC233',\n color: '#AA5D04',\n borderRadius: '4px',\n height: 'max(20px, 1em)',\n padding: '0 max(0.3em, 2px)',\n fontSize: 'max(0.9em, 14px)',\n lineHeight: '0.9em',\n verticalAlign: 'middle',\n userSelect: 'none',\n }}\n >\n <IconAnchor\n size={12}\n fill=\"#AA5D04\"\n style={{ marginRight: 'max(0.15em, 2px)', flexShrink: 0 }}\n />\n {node.id}\n </span>\n );\n case 'hardBreak':\n return <br key={key} />;\n default:\n return <span key={key} />;\n }\n };\n\n if (renderNode) return renderNode(node, defaultRender);\n return defaultRender();\n}\n\nfunction renderInlineContent(\n content: readonly InlineNode[],\n keyPrefix: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement[] {\n return content.map((node, i) => renderInline(node, `${keyPrefix}-${i}`, renderNode));\n}\n\n// --- Jinja If Block rendering (read-only) ---\n\nconst JINJA_RENDERER_STYLE_ID = 'ab-renderer-jinja-styles';\n\nconst JINJA_RENDERER_STYLES = `\n.ab-r-jinja-block {\n margin: 8px 0;\n}\n\n.ab-r-jinja-branch {\n position: relative;\n}\n\n.ab-r-jinja-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px;\n border: 1px solid #E0E0E0;\n border-radius: 4px;\n background: #FFFFFF;\n}\n\n.ab-r-jinja-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 32px;\n padding: 0 8px;\n border-radius: 4px;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n font-weight: 700;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.ab-r-jinja-badge-if,\n.ab-r-jinja-badge-elif {\n background: #E7F1FF;\n color: #0D0D0D;\n}\n\n.ab-r-jinja-badge-else {\n background: #F7F7F7;\n color: #424242;\n}\n\n.ab-r-jinja-condition {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n color: #0D0D0D;\n}\n\n.ab-r-jinja-otherwise {\n flex: 1;\n color: #858585;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.ab-r-jinja-body {\n display: flex;\n gap: 12px;\n padding: 0 8px;\n min-height: 32px;\n}\n\n.ab-r-jinja-divider-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n justify-content: center;\n}\n\n.ab-r-jinja-divider {\n width: 1px;\n background: #E0E0E0;\n}\n\n.ab-r-jinja-branch-last .ab-r-jinja-divider-col {\n align-items: flex-start;\n padding-left: 16px;\n}\n\n.ab-r-jinja-branch-last .ab-r-jinja-divider {\n width: 16px;\n height: 28px;\n background: none;\n border-left: 1px solid #E0E0E0;\n border-bottom: 1px solid #E0E0E0;\n border-bottom-left-radius: 8px;\n}\n\n.ab-r-jinja-content {\n flex: 1;\n min-width: 0;\n padding: 12px 0;\n}\n\n.ab-r-jinja-token-variable { color: #4141B2; }\n.ab-r-jinja-token-operator { color: #858585; }\n.ab-r-jinja-token-value { color: #0D0D0D; }\n.ab-r-jinja-token-punctuation { color: #858585; }\n`;\n\nlet jinjaRendererStyleRefCount = 0;\nlet jinjaRendererStyleEl: HTMLStyleElement | null = null;\n\nfunction ensureJinjaRendererStyles(): void {\n if (jinjaRendererStyleRefCount++ > 0) return;\n if (typeof document === 'undefined') return;\n const existing = document.getElementById(JINJA_RENDERER_STYLE_ID);\n if (existing instanceof HTMLStyleElement) {\n jinjaRendererStyleEl = existing;\n return;\n }\n jinjaRendererStyleEl = document.createElement('style');\n jinjaRendererStyleEl.id = JINJA_RENDERER_STYLE_ID;\n jinjaRendererStyleEl.textContent = JINJA_RENDERER_STYLES;\n document.head.appendChild(jinjaRendererStyleEl);\n}\n\nfunction renderConditionTokens(condition: string): ReactElement[] {\n const tokens = tokenizeCondition(condition);\n return tokens.map((token, i) => (\n <span key={`t-${i}-${token.start}`} className={`ab-r-jinja-token-${token.category}`}>\n {token.text}\n </span>\n ));\n}\n\nfunction renderJinjaBranch(\n branch: JinjaIfBranch<BlockNode>,\n key: string,\n isLast: boolean,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const branchType = branch.branchType;\n const badgeLabel = branchType === 'elif' ? 'ELSE IF' : branchType.toUpperCase();\n\n return (\n <div\n key={key}\n className={`ab-r-jinja-branch${isLast ? ' ab-r-jinja-branch-last' : ''}`}\n >\n <div className=\"ab-r-jinja-header\">\n <span className={`ab-r-jinja-badge ab-r-jinja-badge-${branchType}`}>\n {badgeLabel}\n </span>\n {branchType === 'else' ? (\n <span className=\"ab-r-jinja-otherwise\">otherwise</span>\n ) : (\n <span className=\"ab-r-jinja-condition\">\n {branch.condition ? renderConditionTokens(branch.condition) : null}\n </span>\n )}\n </div>\n <div className=\"ab-r-jinja-body\">\n <div className=\"ab-r-jinja-divider-col\">\n <div className=\"ab-r-jinja-divider\" />\n </div>\n <div className=\"ab-r-jinja-content\">\n {branch.content.map((child, i) => renderBlock(child, `${key}-c${i}`, renderNode))}\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderJinjaIfBlock(\n node: { readonly type: 'jinjaIfBlock'; readonly branches: readonly JinjaIfBranch<BlockNode>[] },\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n ensureJinjaRendererStyles();\n\n return (\n <div key={key} className=\"ab-r-jinja-block\">\n {node.branches.map((branch, i) =>\n renderJinjaBranch(\n branch,\n `${key}-b${i}`,\n i === node.branches.length - 1,\n renderNode,\n ),\n )}\n </div>\n );\n}\n\n// --- End Jinja If Block rendering ---\n\nfunction renderBlock(\n node: BlockNode,\n key: string,\n renderNode?: ActionbookRendererProps['renderNode'],\n): ReactElement {\n const defaultRender = (): ReactElement => {\n switch (node.type) {\n case 'paragraph':\n return <p key={key}>{renderInlineContent(node.content, key, renderNode)}</p>;\n case 'heading': {\n const Tag = `h${node.level}` as keyof JSX.IntrinsicElements;\n return <Tag key={key}>{renderInlineContent(node.content, key, renderNode)}</Tag>;\n }\n case 'bulletList':\n return (\n <ul key={key}>\n {node.content.map((item, i) => renderBlock(item, `${key}-${i}`, renderNode))}\n </ul>\n );\n case 'orderedList':\n return (\n <ol key={key} start={node.start !== 1 ? node.start : undefined}>\n {node.content.map((item, i) => renderBlock(item, `${key}-${i}`, renderNode))}\n </ol>\n );\n case 'listItem':\n if (node.checked != null) {\n return (\n <li key={key} style={{ display: 'flex', alignItems: 'flex-start', listStyle: 'none' }}>\n <input\n type=\"checkbox\"\n checked={node.checked}\n readOnly\n style={{ marginRight: 6, marginTop: 4, flexShrink: 0 }}\n />\n <div style={node.checked ? { textDecoration: 'line-through', opacity: 0.6 } : undefined}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </div>\n </li>\n );\n }\n return (\n <li key={key}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </li>\n );\n case 'blockquote':\n return (\n <blockquote key={key}>\n {node.content.map((child, i) => renderBlock(child, `${key}-${i}`, renderNode))}\n </blockquote>\n );\n case 'jinjaIfBlock':\n return renderJinjaIfBlock(node, key, renderNode);\n case 'horizontalRule':\n return <hr key={key} />;\n case 'table':\n return (\n <table key={key}>\n <tbody>\n {node.content.map((row, ri) => (\n <tr key={`${key}-r${ri}`}>\n {row.content.map((cell, ci) => {\n const CellTag = cell.header ? 'th' : 'td';\n return (\n <CellTag key={`${key}-r${ri}-c${ci}`}>\n {renderInlineContent(cell.content, `${key}-r${ri}-c${ci}`, renderNode)}\n </CellTag>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n );\n default:\n return <div key={key} />;\n }\n };\n\n if (renderNode) return renderNode(node, defaultRender);\n return defaultRender();\n}\n\nexport function ActionbookRenderer({ doc, className, renderNode }: ActionbookRendererProps): ReactElement {\n return (\n <div className={className}>\n {doc.content.map((node, i) => renderBlock(node, `ab-${i}`, renderNode))}\n </div>\n );\n}\n","type TokenType =\n | 'STRING'\n | 'NUMBER'\n | 'BOOL'\n | 'NONE'\n | 'IDENT'\n | 'AND'\n | 'OR'\n | 'NOT'\n | 'IN'\n | 'IS'\n | 'EQ'\n | 'NEQ'\n | 'LT'\n | 'GT'\n | 'LTE'\n | 'GTE'\n | 'LPAREN'\n | 'RPAREN';\n\nexport type HighlightCategory = 'variable' | 'operator' | 'value' | 'punctuation';\n\nexport interface ConditionToken {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n readonly category: HighlightCategory;\n}\n\ninterface RawToken {\n readonly type: TokenType;\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst KEYWORDS: Readonly<Record<string, TokenType>> = {\n and: 'AND',\n or: 'OR',\n not: 'NOT',\n in: 'IN',\n is: 'IS',\n True: 'BOOL',\n False: 'BOOL',\n true: 'BOOL',\n false: 'BOOL',\n None: 'NONE',\n null: 'NONE',\n};\n\nconst CATEGORY_BY_TYPE: Readonly<Record<TokenType, HighlightCategory>> = {\n STRING: 'value',\n NUMBER: 'value',\n BOOL: 'value',\n NONE: 'value',\n IDENT: 'variable',\n AND: 'operator',\n OR: 'operator',\n NOT: 'operator',\n IN: 'operator',\n IS: 'operator',\n EQ: 'operator',\n NEQ: 'operator',\n LT: 'operator',\n GT: 'operator',\n LTE: 'operator',\n GTE: 'operator',\n LPAREN: 'punctuation',\n RPAREN: 'punctuation',\n};\n\nconst NEGATIVE_NUMBER_PRECEDERS = new Set<TokenType>([\n 'AND',\n 'OR',\n 'NOT',\n 'IN',\n 'IS',\n 'EQ',\n 'NEQ',\n 'LT',\n 'GT',\n 'LTE',\n 'GTE',\n 'LPAREN',\n]);\n\nfunction canStartNegativeNumber(tokens: readonly RawToken[]): boolean {\n if (tokens.length === 0) {\n return true;\n }\n\n const previous = tokens[tokens.length - 1];\n return NEGATIVE_NUMBER_PRECEDERS.has(previous.type);\n}\n\nfunction finalizeTokens(input: string, rawTokens: readonly RawToken[]): ConditionToken[] {\n const highlighted: ConditionToken[] = [];\n\n for (let i = 0; i < rawTokens.length; i++) {\n const token = rawTokens[i];\n const next = rawTokens[i + 1];\n\n if (token.type === 'IS' && next?.type === 'NOT') {\n highlighted.push({\n text: input.slice(token.start, next.end),\n start: token.start,\n end: next.end,\n category: 'operator',\n });\n i++;\n continue;\n }\n\n highlighted.push({\n text: token.text,\n start: token.start,\n end: token.end,\n category: CATEGORY_BY_TYPE[token.type],\n });\n }\n\n return highlighted;\n}\n\nexport function tokenizeCondition(input: string): ConditionToken[] {\n const rawTokens: RawToken[] = [];\n let i = 0;\n\n while (i < input.length) {\n const char = input[i];\n\n if (/\\s/.test(char)) {\n i++;\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n const start = i;\n const quote = char;\n i++;\n\n while (i < input.length) {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i += 2;\n continue;\n }\n\n if (input[i] === quote) {\n i++;\n rawTokens.push({\n type: 'STRING',\n text: input.slice(start, i),\n start,\n end: i,\n });\n break;\n }\n\n i++;\n }\n\n if (rawTokens[rawTokens.length - 1]?.start !== start) {\n return finalizeTokens(input, rawTokens);\n }\n\n continue;\n }\n\n if (/[0-9]/.test(char) || (char === '-' && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && canStartNegativeNumber(rawTokens))) {\n const start = i;\n\n if (input[i] === '-') {\n i++;\n }\n\n while (i < input.length && /[0-9]/.test(input[i])) {\n i++;\n }\n\n if (i < input.length && input[i] === '.') {\n i++;\n while (i < input.length && /[0-9]/.test(input[i])) {\n i++;\n }\n }\n\n rawTokens.push({\n type: 'NUMBER',\n text: input.slice(start, i),\n start,\n end: i,\n });\n continue;\n }\n\n if (/[a-zA-Z_]/.test(char)) {\n const start = i;\n i++;\n\n while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {\n i++;\n }\n\n const text = input.slice(start, i);\n rawTokens.push({\n type: KEYWORDS[text] ?? 'IDENT',\n text,\n start,\n end: i,\n });\n continue;\n }\n\n if (i + 1 < input.length) {\n const twoChar = input.slice(i, i + 2);\n\n if (twoChar === '==') {\n rawTokens.push({ type: 'EQ', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '!=') {\n rawTokens.push({ type: 'NEQ', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '<=') {\n rawTokens.push({ type: 'LTE', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n\n if (twoChar === '>=') {\n rawTokens.push({ type: 'GTE', text: twoChar, start: i, end: i + 2 });\n i += 2;\n continue;\n }\n }\n\n if (char === '<') {\n rawTokens.push({ type: 'LT', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === '>') {\n rawTokens.push({ type: 'GT', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === '(') {\n rawTokens.push({ type: 'LPAREN', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n if (char === ')') {\n rawTokens.push({ type: 'RPAREN', text: char, start: i, end: i + 1 });\n i++;\n continue;\n }\n\n return finalizeTokens(input, rawTokens);\n }\n\n return finalizeTokens(input, rawTokens);\n}\n","/**\n * Inline SVG icons copied from sbdashboard/app/feather/components/icons/svg/.\n * Intentionally minimal — no external icon library required.\n */\nimport React from 'react';\n\ninterface IconProps {\n size?: number;\n fill?: string;\n style?: React.CSSProperties;\n}\n\n/** SBiDeveloperResources — used for \"tool\" resource tags */\nexport function IconTool({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path d=\"m14.064 3.649-6 16 1.873.702 6-16-1.873-.702ZM6.293 5.793.086 12l6.207 6.207 1.414-1.414L2.914 12l4.793-4.793-1.414-1.414ZM17.707 5.793 23.914 12l-6.207 6.207-1.414-1.414L21.086 12l-4.793-4.793 1.414-1.414Z\" />\n </svg>\n );\n}\n\n/** SBiDivide — used for \"manual\" resource tags */\nexport function IconManual({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M18.5 4C19.3284 4 20 4.67157 20 5.5C20 6.32843 19.3284 7 18.5 7C17.6716 7 17 6.32843 17 5.5C17 4.67157 17.6716 4 18.5 4ZM18.5 2C16.9145 2 15.5752 3.05426 15.1449 4.5H10.5V11H8.91946C8.57612 9.42741 7.17556 8.25 5.5 8.25C3.567 8.25 2 9.817 2 11.75C2 13.683 3.567 15.25 5.5 15.25C6.9926 15.25 8.26697 14.3157 8.77019 13H10.5V19.5H15.1449C15.5752 20.9457 16.9145 22 18.5 22C20.433 22 22 20.433 22 18.5C22 16.567 20.433 15 18.5 15C16.9145 15 15.5752 16.0543 15.1449 17.5H12.5V13V11V6.5H15.1449C15.5752 7.94574 16.9145 9 18.5 9C20.433 9 22 7.433 22 5.5C22 3.567 20.433 2 18.5 2ZM17 18.5C17 17.6716 17.6716 17 18.5 17C19.3284 17 20 17.6716 20 18.5C20 19.3284 19.3284 20 18.5 20C17.6716 20 17 19.3284 17 18.5ZM5.5 10.25C6.32843 10.25 7 10.9216 7 11.75C7 12.5784 6.32843 13.25 5.5 13.25C4.67157 13.25 4 12.5784 4 11.75C4 10.9216 4.67157 10.25 5.5 10.25Z\"\n />\n </svg>\n );\n}\n\n/** SBiReplyTemplate — used for \"agent_message_template\" resource tags */\nexport function IconMessageTemplate({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M2 4.5A2.5 2.5 0 0 1 4.5 2h15A2.5 2.5 0 0 1 22 4.5v11a2.5 2.5 0 0 1-2.5 2.5H6l-4 4V4.5Zm2 12.672L5.172 16H19.5a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15a.5.5 0 0 0-.5.5v12.672Z\"\n />\n <path d=\"m12 12.404 2.781 1.687-.738-3.179L16.5 8.774l-3.236-.276L12 5.5l-1.264 2.998-3.236.276 2.457 2.138-.738 3.179L12 12.404Z\" />\n </svg>\n );\n}\n\n/** SBiAgents — used for \"handoff\" resource tags */\nexport function IconHandoff({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M12 4a8 8 0 0 0-8 8v4a3 3 0 1 1 6 0v3a3 3 0 1 1-6 0v-.5H2V12C2 6.477 6.477 2 12 2s10 4.477 10 10v6.5h-2v.5a3 3 0 1 1-6 0v-3a3 3 0 1 1 6 0v-4a8 8 0 0 0-8-8ZM8 16v3a1 1 0 1 1-2 0v-3a1 1 0 1 1 2 0Zm10 3v-3a1 1 0 1 0-2 0v3a1 1 0 1 0 2 0Z\"\n />\n </svg>\n );\n}\n\n/** SBiTime — used for \"time_diff\" resource tags */\nexport function IconTimeDiff({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <path d=\"M12.485 6.244h-2v6.618l4.553 2.277.895-1.79-3.448-1.723V6.244Z\" />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm8-10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Z\"\n />\n </svg>\n );\n}\n\n/** SBiAnchor — used for jump points */\nexport function IconStop({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 8 8\" width={size} height={size} fill=\"none\" style={style}>\n <path d=\"M5.4375 3.375L2.0625 3.375V4.125L5.4375 4.125V3.375Z\" fill={fill} />\n <path fillRule=\"evenodd\" clipRule=\"evenodd\" d=\"M3.75 7.5C5.82107 7.5 7.5 5.82107 7.5 3.75C7.5 1.67893 5.82107 0 3.75 0C1.67893 0 0 1.67893 0 3.75C0 5.82107 1.67893 7.5 3.75 7.5ZM6.75 3.75C6.75 5.40685 5.40685 6.75 3.75 6.75C2.09315 6.75 0.75 5.40685 0.75 3.75C0.75 2.09315 2.09315 0.75 3.75 0.75C5.40685 0.75 6.75 2.09315 6.75 3.75Z\" fill={fill} />\n </svg>\n );\n}\n\nexport function IconAnchor({ size = 16, fill = 'currentColor', style }: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 16 16\"\n width={size}\n height={size}\n fill={fill}\n style={style}\n >\n <g fillRule=\"evenodd\" clipPath=\"url(#anchor-clip)\" clipRule=\"evenodd\">\n <path d=\"M8 5.333a2.667 2.667 0 1 1 0 5.333 2.667 2.667 0 0 1 0-5.333Zm0 1.333a1.333 1.333 0 1 0 0 2.667 1.333 1.333 0 0 0 0-2.667Z\" />\n <path d=\"M8.667 2.037a6 6 0 0 1 5.295 5.296h1.371v1.333h-1.37a6 6 0 0 1-5.296 5.295v1.372H7.333V13.96a6 6 0 0 1-5.295-5.295H.667V7.333h1.37a6 6 0 0 1 5.296-5.296V.666h1.334v1.371ZM8 3.333a4.667 4.667 0 1 0 0 9.333 4.667 4.667 0 0 0 0-9.333Z\" />\n </g>\n <defs>\n <clipPath id=\"anchor-clip\">\n <path d=\"M0 0H16V16H0z\" transform=\"translate(0 -.001)\" />\n </clipPath>\n </defs>\n </svg>\n );\n}\n","import React, { forwardRef } from 'react';\n\nexport interface EditorShellProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Contenteditable container for ProseMirror EditorView.\n * Pass the ref from `useEditorView().viewRef` to mount the editor.\n */\nexport const EditorShell = forwardRef<HTMLDivElement, EditorShellProps>(function EditorShell(\n { className, style },\n ref,\n) {\n return <div ref={ref} className={className} style={style} />;\n});\n","import { createElement } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport type { Decoration, DecorationSource, EditorView, NodeView } from 'prosemirror-view';\nimport type { NodeViewFactory } from '../plugin/types';\n\nexport interface ReactNodeViewProps {\n node: PMNode;\n view: EditorView;\n getPos: () => number | undefined;\n selected: boolean;\n /** Outer node decorations currently applied to this node. */\n decorations: readonly Decoration[];\n}\n\nexport interface ReactNodeViewOptions {\n /** The React component to render */\n component: React.ComponentType<ReactNodeViewProps>;\n /** Container tag name (default: 'span' for inline, 'div' for block) */\n as?: string;\n /** CSS class name for the container */\n className?: string;\n /** Whether this is an inline node (default: true) */\n inline?: boolean;\n /**\n * Optional wrapper component that provides context (Router, QueryClient, etc.)\n * around every NodeView React root. Receives `children` as its only prop.\n */\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n}\n\nclass ReactNodeViewImpl implements NodeView {\n dom: HTMLElement;\n private root: Root;\n private component: React.ComponentType<ReactNodeViewProps>;\n private wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n private _node: PMNode;\n private _view: EditorView;\n private _getPos: () => number | undefined;\n private _selected = false;\n private _decorations: readonly Decoration[] = [];\n\n constructor(\n node: PMNode,\n view: EditorView,\n getPos: () => number | undefined,\n decorations: readonly Decoration[],\n options: ReactNodeViewOptions,\n ) {\n this._node = node;\n this._view = view;\n this._getPos = getPos;\n this._decorations = decorations;\n this.component = options.component;\n this.wrapper = options.wrapper;\n\n const tag = options.as ?? (options.inline !== false ? 'span' : 'div');\n this.dom = document.createElement(tag);\n if (options.inline !== false) {\n this.dom.style.display = 'inline';\n this.dom.style.verticalAlign = 'baseline';\n }\n if (options.className) {\n this.dom.className = options.className;\n }\n\n this.root = createRoot(this.dom);\n this.render();\n }\n\n private render() {\n const element = createElement(this.component, {\n node: this._node,\n view: this._view,\n getPos: this._getPos,\n selected: this._selected,\n decorations: this._decorations,\n });\n this.root.render(\n this.wrapper ? createElement(this.wrapper, null, element) : element,\n );\n }\n\n update(node: PMNode, decorations: readonly Decoration[], _innerDecorations: DecorationSource): boolean {\n if (node.type !== this._node.type) return false;\n this._node = node;\n this._decorations = decorations;\n this.render();\n return true;\n }\n\n selectNode() {\n this._selected = true;\n this.render();\n }\n\n deselectNode() {\n this._selected = false;\n this.render();\n }\n\n destroy() {\n // Defer unmount to avoid flushSync warnings in React 18\n setTimeout(() => this.root.unmount(), 0);\n }\n\n stopEvent() {\n return false;\n }\n\n ignoreMutation() {\n return true;\n }\n}\n\n/**\n * Creates a NodeViewFactory that renders a React component as a PM NodeView.\n *\n * Usage:\n * ```ts\n * const jumpPointPlugin: ActionbookPlugin = {\n * name: 'jumpPoint',\n * nodeViews: () => ({\n * jumpPoint: createReactNodeView({ component: JumpPointView }),\n * }),\n * };\n * ```\n */\nexport function createReactNodeView(options: ReactNodeViewOptions): NodeViewFactory {\n return (node, view, getPos, decorations) => new ReactNodeViewImpl(node, view, getPos, decorations, options);\n}\n","import { useRef, useEffect, useCallback, useState, type RefCallback } from 'react';\nimport { EditorState, type Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { Node as PMNode } from 'prosemirror-model';\nimport type { DocumentNode } from '../../ast/types';\nimport type { LlmCompletionEndpoint } from '../../lint/types';\nimport { fromProseMirrorJSON, type JSONContent } from '../../compat/prosemirror';\nimport { serializeToMarkdown } from '../../markdown/serializer';\nimport { actionbookSchema } from '../schema';\nimport { createPluginArray } from '../plugin/registry';\nimport { toProseMirrorJSON } from '../bridge/toProseMirrorJSON';\nimport { EDITOR_TEXT_STYLES } from '../styles/editorTextStyles';\nimport type { ActionbookPlugin } from '../plugin/types';\n\nconst TEXT_STYLE_ID = 'ab-editor-text-styles';\nlet textStyleRefCount = 0;\n\nfunction acquireTextStyles(): void {\n if (textStyleRefCount++ > 0) return;\n if (document.getElementById(TEXT_STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = TEXT_STYLE_ID;\n el.textContent = EDITOR_TEXT_STYLES;\n document.head.appendChild(el);\n}\n\nfunction releaseTextStyles(): void {\n if (--textStyleRefCount > 0) return;\n document.getElementById(TEXT_STYLE_ID)?.remove();\n}\n\nexport interface EditorViewConfig {\n plugins?: ActionbookPlugin[];\n content?: DocumentNode | null;\n editable?: boolean;\n onTransaction?: (state: EditorState) => void;\n onContentChange?: (doc: DocumentNode) => void;\n /**\n * Optional LLM completion endpoint for LLM-based lint rules.\n * When provided, the editor can run async lint rules that leverage LLM analysis.\n * Accepts any backend: OpenAI, Anthropic, Gemini Nano, custom proxy, etc.\n */\n llmCompletionEndpoint?: LlmCompletionEndpoint;\n}\n\nexport interface EditorViewHandle {\n viewRef: RefCallback<HTMLDivElement>;\n view: EditorView | null;\n /** Always returns the current EditorView (not a stale snapshot). */\n getView: () => EditorView | null;\n getAST: () => DocumentNode | null;\n getMarkdown: () => string;\n setContent: (doc: DocumentNode) => void;\n focus: () => void;\n destroy: () => void;\n}\n\nfunction docToState(doc: DocumentNode | null | undefined, plugins: import('prosemirror-state').Plugin[]): EditorState {\n const pmJSON = doc ? toProseMirrorJSON(doc) : { type: 'doc', content: [{ type: 'paragraph' }] };\n const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);\n return EditorState.create({ doc: pmDoc, plugins });\n}\n\nfunction pmDocToAST(pmDoc: PMNode): DocumentNode {\n const json = pmDoc.toJSON() as JSONContent;\n return fromProseMirrorJSON(json);\n}\n\nexport function useEditorView(config: EditorViewConfig): EditorViewHandle {\n const viewInstanceRef = useRef<EditorView | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [, forceUpdate] = useState(0);\n\n // Stable refs for callbacks\n const configRef = useRef(config);\n configRef.current = config;\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n viewInstanceRef.current?.destroy();\n viewInstanceRef.current = null;\n };\n }, []);\n\n // When `editable` changes, dispatch a no-op transaction so ProseMirror plugins\n // (e.g. editableWatcher in jinjaIfBlockPlugin) can detect the change and\n // re-render NodeViews that show/hide edit-only controls.\n const prevEditableRef = useRef(config.editable);\n useEffect(() => {\n if (prevEditableRef.current !== config.editable) {\n prevEditableRef.current = config.editable;\n const view = viewInstanceRef.current;\n if (view) {\n const tr = view.state.tr;\n tr.setMeta('editableChanged', true);\n view.dispatch(tr);\n }\n }\n }, [config.editable]);\n\n // Ref callback: create EditorView when DOM element appears, destroy when removed\n const viewRef: RefCallback<HTMLDivElement> = useCallback((container: HTMLDivElement | null) => {\n // Same element — nothing to do\n if (container === containerRef.current) return;\n\n // Previous container removed — destroy old view\n if (viewInstanceRef.current) {\n viewInstanceRef.current.destroy();\n viewInstanceRef.current = null;\n releaseTextStyles();\n }\n\n containerRef.current = container;\n if (!container) {\n forceUpdate((n) => n + 1);\n return;\n }\n\n acquireTextStyles();\n const { pmPlugins, nodeViews } = createPluginArray(configRef.current.plugins ?? []);\n const state = docToState(configRef.current.content, pmPlugins);\n\n const view = new EditorView(container, {\n state,\n nodeViews,\n attributes: { spellcheck: 'false' },\n editable: () => configRef.current.editable === true,\n dispatchTransaction(tr: Transaction) {\n const newState = view.state.apply(tr);\n view.updateState(newState);\n configRef.current.onTransaction?.(newState);\n if (tr.docChanged) {\n const ast = pmDocToAST(newState.doc);\n configRef.current.onContentChange?.(ast);\n }\n },\n });\n\n viewInstanceRef.current = view;\n forceUpdate((n) => n + 1);\n }, []);\n\n const getAST = useCallback((): DocumentNode | null => {\n const view = viewInstanceRef.current;\n if (!view) return null;\n return pmDocToAST(view.state.doc);\n }, []);\n\n const getMarkdown = useCallback((): string => {\n const ast = getAST();\n if (!ast) return '';\n return serializeToMarkdown(ast);\n }, [getAST]);\n\n const setContent = useCallback((doc: DocumentNode) => {\n const view = viewInstanceRef.current;\n if (!view) return;\n const pmJSON = toProseMirrorJSON(doc);\n const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);\n const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, pmDoc.content);\n // Don't record initial content load in undo history\n tr.setMeta('addToHistory', false);\n view.dispatch(tr);\n }, []);\n\n const focus = useCallback(() => {\n viewInstanceRef.current?.focus();\n }, []);\n\n const destroy = useCallback(() => {\n if (viewInstanceRef.current) {\n viewInstanceRef.current.destroy();\n viewInstanceRef.current = null;\n releaseTextStyles();\n }\n }, []);\n\n const getView = useCallback(() => viewInstanceRef.current, []);\n\n return {\n viewRef,\n view: viewInstanceRef.current,\n getView,\n getAST,\n getMarkdown,\n setContent,\n focus,\n destroy,\n };\n}\n","// === Marks (인라인 서식) ===\nexport type BoldMark = { readonly type: 'bold' };\nexport type ItalicMark = { readonly type: 'italic' };\nexport type UnderlineMark = { readonly type: 'underline' };\nexport type StrikethroughMark = { readonly type: 'strikethrough' };\nexport type CodeMark = { readonly type: 'code' };\nexport type LinkMark = { readonly type: 'link'; readonly href: string; readonly title?: string };\nexport type Mark = BoldMark | ItalicMark | UnderlineMark | StrikethroughMark | CodeMark | LinkMark;\n\n// === Resource tag type values ===\nexport const RESOURCE_TAG_TYPES = ['tool', 'manual', 'agent_message_template', 'handoff', 'time_diff', 'time_difference'] as const;\nexport type ResourceTagType = (typeof RESOURCE_TAG_TYPES)[number];\n\n// === Inline Nodes ===\nexport type TextNode = {\n readonly type: 'text';\n readonly text: string;\n readonly marks?: readonly Mark[];\n};\n\nexport type ResourceTagNode = {\n readonly type: 'resourceTag';\n readonly tagType: ResourceTagType;\n readonly resourceId: string;\n readonly text: string;\n};\n\nexport type JumpPointNode = {\n readonly type: 'jumpPoint';\n readonly id: string; // /^[\\p{L}\\p{N}_-]+$/u\n};\n\nexport type HardBreakNode = { readonly type: 'hardBreak' };\n\n// === Jinja If (Inline) ===\nexport type JinjaIfBranch<T> = {\n readonly branchType: 'if' | 'elif' | 'else';\n readonly condition?: string;\n readonly content: readonly T[];\n};\n\nexport type JinjaIfInlineNode = {\n readonly type: 'jinjaIfInline';\n readonly branches: readonly JinjaIfBranch<InlineNode>[];\n};\n\nexport type InlineNode = TextNode | ResourceTagNode | JumpPointNode | HardBreakNode | JinjaIfInlineNode;\n\n// === Block Nodes ===\nexport type ParagraphNode = {\n readonly type: 'paragraph';\n readonly content: readonly InlineNode[];\n};\n\nexport type HeadingNode = {\n readonly type: 'heading';\n readonly level: 1 | 2 | 3 | 4 | 5 | 6;\n readonly content: readonly InlineNode[];\n};\n\nexport type ListItemNode = {\n readonly type: 'listItem';\n readonly checked?: boolean | null;\n readonly value?: number | null;\n readonly spread?: boolean;\n readonly content: readonly BlockNode[];\n};\n\nexport type BulletListNode = {\n readonly type: 'bulletList';\n readonly spread?: boolean;\n readonly content: readonly ListItemNode[];\n};\n\nexport type OrderedListNode = {\n readonly type: 'orderedList';\n readonly start: number;\n readonly spread?: boolean;\n readonly content: readonly ListItemNode[];\n};\n\nexport type BlockquoteNode = {\n readonly type: 'blockquote';\n readonly content: readonly BlockNode[];\n};\n\nexport type HorizontalRuleNode = { readonly type: 'horizontalRule' };\n\nexport type CodeBlockNode = {\n readonly type: 'codeBlock';\n readonly language?: string;\n readonly content: string;\n};\n\nexport type TableCellNode = {\n readonly type: 'tableCell';\n readonly header?: boolean;\n readonly content: readonly InlineNode[];\n};\n\nexport type TableRowNode = {\n readonly type: 'tableRow';\n readonly content: readonly TableCellNode[];\n};\n\nexport type TableNode = {\n readonly type: 'table';\n readonly content: readonly TableRowNode[];\n};\n\n// === Jinja If (Block) ===\nexport type JinjaIfBlockNode = {\n readonly type: 'jinjaIfBlock';\n readonly branches: readonly JinjaIfBranch<BlockNode>[];\n};\n\n// === Note Block (editor-only, not serialized to markdown) ===\nexport type NoteBlockNode = {\n readonly type: 'noteBlock';\n readonly content: readonly BlockNode[];\n};\n\nexport type BlockNode =\n | ParagraphNode\n | HeadingNode\n | BulletListNode\n | OrderedListNode\n | ListItemNode\n | BlockquoteNode\n | HorizontalRuleNode\n | CodeBlockNode\n | TableNode\n | JinjaIfBlockNode\n | NoteBlockNode;\n\n// === Document Root ===\nexport type DocumentNode = {\n readonly type: 'doc';\n readonly content: readonly BlockNode[];\n};\n\n// === Union ===\nexport type AstNode = DocumentNode | BlockNode | InlineNode | TableRowNode | TableCellNode;\n\n// === Node Path (향후 CRDT/undo-redo 지원) ===\nexport type NodePath = readonly number[];\n\n// === Jump point ID validation ===\nexport const JUMP_POINT_ID_PATTERN = /^[\\p{L}\\p{N}_-]+$/u;\n","/**\n * Convert ProseMirror/Tiptap JSONContent to ActionbookAST.\n *\n * This handles the legacy editor_data format stored in LogicV2.\n */\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n Mark,\n ResourceTagType,\n TableNode,\n TableRowNode,\n TableCellNode,\n JinjaIfBranch,\n} from '../ast/types';\nimport { RESOURCE_TAG_TYPES } from '../ast/types';\n\nconst MAX_DEPTH = 128;\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nconst LIST_TYPES = new Set(['bulletList', 'orderedList']);\n\n/**\n * A list is \"loose\" (spread) if any item has multiple non-list block children.\n * Nested sub-lists don't count — a listItem with [paragraph, bulletList] is still tight.\n */\nfunction isLooseList(items: { content: BlockNode[] }[]): boolean {\n return items.some((li) => {\n const nonListBlocks = li.content.filter((b) => !LIST_TYPES.has(b.type));\n return nonListBlocks.length > 1;\n });\n}\n\n// Minimal JSONContent type (compatible with @tiptap/core)\nexport type JSONContent = {\n type?: string;\n attrs?: Record<string, unknown>;\n content?: JSONContent[];\n marks?: { type: string; attrs?: Record<string, unknown> }[];\n text?: string;\n};\n\nfunction convertPMMark(mark: { type: string; attrs?: Record<string, unknown> }): Mark | null {\n switch (mark.type) {\n case 'bold':\n return { type: 'bold' };\n case 'italic':\n return { type: 'italic' };\n case 'underline':\n return { type: 'underline' };\n case 'strikethrough':\n return { type: 'strikethrough' };\n case 'code':\n return { type: 'code' };\n case 'link': {\n const rawHref = (mark.attrs?.href as string) ?? '';\n // Strip dangerous URL protocols\n if (!ALLOWED_URL_PROTOCOLS.test(rawHref)) return null;\n const title = mark.attrs?.title as string | undefined;\n return title ? { type: 'link', href: rawHref, title } : { type: 'link', href: rawHref };\n }\n // Ignored marks (UI-only or unused)\n case 'diffMark':\n case 'inlineResource':\n case 'textStyle':\n return null;\n default:\n return null;\n }\n}\n\nfunction convertPMInline(node: JSONContent, depth: number): InlineNode[] {\n if (depth > MAX_DEPTH) return [];\n const type = node.type ?? '';\n\n switch (type) {\n case 'text': {\n const marks = (node.marks ?? []).map(convertPMMark).filter((m): m is Mark => m !== null);\n const textNode = node.text ?? '';\n return marks.length > 0 ? [{ type: 'text', text: textNode, marks }] : [{ type: 'text', text: textNode }];\n }\n\n case 'inlineToolTag': {\n const attrs = node.attrs ?? {};\n const tagType = (attrs.type as string) ?? 'tool';\n const text = (attrs.text as string) ?? '';\n // Fallback: unknown tag types become plain text to avoid validation failure\n if (!(RESOURCE_TAG_TYPES as readonly string[]).includes(tagType)) {\n return text ? [{ type: 'text', text }] : [];\n }\n return [\n {\n type: 'resourceTag',\n tagType: tagType as ResourceTagType,\n resourceId: (attrs.resourceId as string) ?? '',\n text,\n },\n ];\n }\n\n case 'jumpPoint': {\n const id = (node.attrs?.id as string) ?? '';\n return [{ type: 'jumpPoint', id }];\n }\n\n case 'hardBreak':\n return [{ type: 'hardBreak' }];\n\n default:\n if (node.text) {\n return [{ type: 'text', text: node.text }];\n }\n if (node.content) {\n return node.content.flatMap((c) => convertPMInline(c, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertPMBlock(node: JSONContent, depth: number = 0): BlockNode[] {\n if (depth > MAX_DEPTH) return [];\n const type = node.type ?? '';\n const children = node.content ?? [];\n\n switch (type) {\n case 'paragraph':\n return [{ type: 'paragraph', content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];\n\n case 'heading': {\n const level = ((node.attrs?.level as number) ?? 1) as 1 | 2 | 3 | 4 | 5 | 6;\n return [{ type: 'heading', level, content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];\n }\n\n case 'bulletList': {\n const items = children.map((c) => convertPMListItem(c, depth + 1));\n const spread = isLooseList(items);\n return [\n {\n type: 'bulletList',\n ...(spread ? { spread: true } : {}),\n content: items.map((li) => spread ? { ...li, spread: true } : li),\n },\n ];\n }\n\n case 'orderedList': {\n const start = (node.attrs?.start as number) ?? 1;\n const items = children.map((c) => convertPMListItem(c, depth + 1));\n const spread = isLooseList(items);\n return [\n {\n type: 'orderedList',\n start,\n ...(spread ? { spread: true } : {}),\n content: items.map((li) => spread ? { ...li, spread: true } : li),\n },\n ];\n }\n\n case 'listItem': {\n return [convertPMListItem(node, depth)];\n }\n\n case 'blockquote':\n return [{ type: 'blockquote', content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];\n\n case 'horizontalRule':\n return [{ type: 'horizontalRule' }];\n\n case 'codeBlock': {\n const textContent = children.map(c => (c as any).text ?? '').join('');\n return [{ type: 'codeBlock', content: textContent, ...(node.attrs?.language ? { language: node.attrs.language } : {}) } as BlockNode];\n }\n\n case 'noteBlock':\n return [{ type: 'noteBlock', content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];\n\n case 'table': {\n const rows: TableRowNode[] = children.map((rowNode) => {\n const cells: TableCellNode[] = (rowNode.content ?? []).map((cellNode) => {\n const cellType = cellNode.type ?? '';\n const isHeader = cellType === 'tableHeader';\n const inlines = (cellNode.content ?? []).flatMap((c) => convertPMInline(c, depth + 3));\n return {\n type: 'tableCell' as const,\n ...(isHeader ? { header: true } : {}),\n content: inlines,\n };\n });\n return { type: 'tableRow' as const, content: cells };\n });\n return [{ type: 'table', content: rows }];\n }\n\n case 'jinjaIfBlock': {\n const branches: JinjaIfBranch<BlockNode>[] = children.map((branchNode) => {\n const branchType = (branchNode.attrs?.branchType ?? 'if') as 'if' | 'elif' | 'else';\n const condition = branchNode.attrs?.condition as string | undefined;\n const branchContent = (branchNode.content ?? []).flatMap((c) => convertPMBlock(c, depth + 2));\n return {\n branchType,\n ...(branchType !== 'else' && condition ? { condition } : {}),\n content: branchContent,\n };\n });\n if (branches.length === 0) return [];\n return [{ type: 'jinjaIfBlock', branches } as BlockNode];\n }\n\n case 'jinjaIfBranch':\n // Standalone jinjaIfBranch outside a jinjaIfBlock — flatten content\n return children.flatMap((c) => convertPMBlock(c, depth + 1));\n\n default:\n if (children.length > 0) {\n return children.flatMap((c) => convertPMBlock(c, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertPMListItem(node: JSONContent, depth: number = 0): { type: 'listItem'; checked?: boolean | null; spread?: boolean; content: BlockNode[] } {\n if (depth > MAX_DEPTH) return { type: 'listItem', content: [{ type: 'paragraph', content: [] }] };\n const children = node.content ?? [];\n const content = children.flatMap((c) => convertPMBlock(c, depth + 1));\n const base: { type: 'listItem'; checked?: boolean | null; spread?: boolean; content: BlockNode[] } = {\n type: 'listItem',\n content: content.length > 0 ? content : [{ type: 'paragraph', content: [] }],\n };\n const checked = node.attrs?.checked as boolean | null | undefined;\n if (typeof checked === 'boolean') {\n base.checked = checked;\n }\n const value = node.attrs?.value as number | null | undefined;\n if (value != null) {\n (base as any).value = value;\n }\n return base;\n}\n\nexport function fromProseMirrorJSON(pmJSON: JSONContent): DocumentNode {\n if (pmJSON.type !== 'doc') {\n const blocks = convertPMBlock(pmJSON, 0);\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n }\n\n const children = pmJSON.content ?? [];\n const blocks = children.flatMap((c) => convertPMBlock(c, 0));\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n}\n","import type { Link, List, ListItem, Parents, Text } from 'mdast';\nimport { defaultHandlers, toMarkdown } from 'mdast-util-to-markdown';\nimport type { Handle, Info, Options, State } from 'mdast-util-to-markdown';\nimport { gfmFootnoteToMarkdown } from 'mdast-util-gfm-footnote';\nimport { gfmStrikethroughToMarkdown } from 'mdast-util-gfm-strikethrough';\nimport { gfmTableToMarkdown } from 'mdast-util-gfm-table';\nimport { gfmTaskListItemToMarkdown } from 'mdast-util-gfm-task-list-item';\nimport { resourceTagToMarkdown } from './plugins/resourceTag';\nimport { jumpPointToMarkdown } from './plugins/jumpPoint';\nimport { toMdast } from './mdastAdapter';\nimport type { DocumentNode } from '../ast/types';\n\n// GFM without autolink literal — see parser.ts for rationale.\nconst gfmNoAutolinkToMarkdown = () => ({\n extensions: [\n gfmFootnoteToMarkdown(),\n gfmStrikethroughToMarkdown(),\n gfmTableToMarkdown(),\n gfmTaskListItemToMarkdown(),\n ],\n});\n\nfunction isEmptyParagraph(node: Parents | { type: string; children?: unknown[] }): boolean {\n return node.type === 'paragraph' && (!('children' in node) || !node.children || node.children.length === 0);\n}\n\nconst JINJA_TAG_RE = /^\\{%\\s*(if|elif|else|endif)\\b/;\n\nfunction isJinjaTagParagraph(node: { type: string; children?: unknown[] }): boolean {\n if (node.type !== 'paragraph') return false;\n const children = (node as Parents).children;\n if (!children || children.length !== 1) return false;\n const child = children[0] as { type: string; value?: string };\n return child.type === 'text' && typeof child.value === 'string' && JINJA_TAG_RE.test(child.value);\n}\n\n/**\n * Custom text handler that prevents unnecessary `_` escaping in inline text.\n *\n * mdast-util-to-markdown's default unsafe rules include\n * `{character: '_', inConstruct: 'phrasing'}`, which escapes every underscore\n * in paragraph/heading text (e.g. `ENUM_VALUE` → `ENUM\\_VALUE`). Since we\n * generate emphasis and strong with `*`, underscores in plain text are never\n * interpreted as emphasis markers and do not need escaping.\n *\n * The `unsafe` option in `toMarkdown` is ADDITIVE (it pushes into the default\n * list, never replaces it), so we cannot override this via options alone.\n * Instead, we temporarily remove the phrasing-`_` rule from `state.unsafe`\n * before delegating to the default text handler.\n */\nfunction textHandler(node: Text, parent: Parents | undefined, state: State, info: Info): string {\n const originalUnsafe = state.unsafe;\n state.unsafe = originalUnsafe.filter((p) => !(p.character === '_' && !p.atBreak));\n const result = (defaultHandlers.text as Options['handlers'] & ((n: Text, p: Parents | undefined, s: State, i: Info) => string))(node, parent, state, info);\n state.unsafe = originalUnsafe;\n return result;\n}\n\n/**\n * Custom link handler — emits `[text](url)` without angle brackets, even when\n * the URL contains spaces. tiptap-markdown uses this form; CommonMark would\n * require `<>` but micromark accepts both.\n */\nfunction linkHandler(node: Link, parent: Parents | undefined, state: State, info: Info): string {\n const childrenText = state.containerPhrasing(node, { ...info, before: '[', after: ']' });\n const url = node.url ?? '';\n const title = node.title;\n const titlePart = title ? ` \"${title.replace(/\"/g, '\\\\\"')}\"` : '';\n return `[${childrenText}](${url}${titlePart})`;\n}\n\n/**\n * Custom listItem handler that uses `_ordinalValue` (set by mdastAdapter)\n * to output the correct per-item number with \".\" marker.\n */\n/**\n * Custom listItem handler that uses `_ordinalValue` (set by mdastAdapter)\n * to output the correct per-item number with \".\" marker.\n * Patches `state.bulletLastUsed` / `state.options.bulletOrdered` temporarily\n * so the default handler emits \"N.\" with the right number.\n */\nfunction listItemHandler(node: ListItem, parent: Parents | undefined, state: State, info: Info): string {\n const value = (node as any)._ordinalValue as number | undefined;\n if (value != null && parent && (parent as List).ordered) {\n // Temporarily override the list start so the default handler uses our number\n const list = parent as List;\n const savedStart = list.start;\n const idx = list.children.indexOf(node);\n // The default handler computes: start + index. We want: value.\n // So set start = value - index.\n list.start = value - idx;\n const result = defaultHandlers.listItem(node, parent, state, info);\n list.start = savedStart;\n return result;\n }\n return defaultHandlers.listItem(node, parent, state, info);\n}\n\nexport function serializeToMarkdown(doc: DocumentNode): string {\n const mdastTree = toMdast(doc);\n\n const raw = toMarkdown(mdastTree, {\n bullet: '-',\n bulletOrdered: '.',\n rule: '-',\n listItemIndent: 'one',\n incrementListMarker: true,\n emphasis: '*',\n strong: '*',\n resourceLink: true,\n join: [\n // Empty paragraphs represent blank-line spacers.\n // Reduce the separator after an empty paragraph from \\n\\n to \\n\n // so that 1 empty paragraph = 1 extra blank line in the output.\n (left) => (isEmptyParagraph(left) ? 0 : null),\n // Consecutive paragraphs: single newline instead of blank line\n // (skip jinja tag paragraphs — they need blank lines for proper roundtrip)\n (left, right) =>\n left.type === 'paragraph' && right.type === 'paragraph' && !isJinjaTagParagraph(left) && !isJinjaTagParagraph(right) ? 0 : null,\n ],\n handlers: {\n text: textHandler as Handle,\n link: linkHandler as Handle,\n listItem: listItemHandler as Handle,\n ...resourceTagToMarkdown().handlers,\n ...jumpPointToMarkdown().handlers,\n },\n extensions: [gfmNoAutolinkToMarkdown()],\n });\n\n // Post-process to match tiptap-markdown's serialization conventions:\n // 1. `\\>` at break positions → `&gt;` (entity-based escaping)\n // 2. Bare `>` in text (non-blockquote) → `&gt;` (tiptap encodes all `>`)\n // 3. `]` after `\\[` patterns → `\\]` (tiptap escapes both brackets)\n // 4. `&#x20;` → plain space (remark encodes leading spaces to prevent\n // markdown interpretation, but downstream consumers expect plain spaces)\n let result = raw\n .replace(/^(\\s*)\\\\>/gm, '$1&gt;')\n .replace(/(\\S) *>/g, (match, pre) => `${pre} &gt;`)\n .replace(/\\\\\\[([^\\]]*)\\]/g, '\\\\[$1\\\\]')\n .replace(/&#x20;/g, ' ');\n\n return result;\n}\n","export function deprecate(fn) {\n return fn\n}\n\nexport function equal() {}\n\nexport function ok() {}\n\nexport function unreachable() {}\n","/**\n * Normalize an identifier (as found in references, definitions).\n *\n * Collapses markdown whitespace, trim, and then lower- and uppercase.\n *\n * Some characters are considered “uppercase”, such as U+03F4 (`ϴ`), but if their\n * lowercase counterpart (U+03B8 (`θ`)) is uppercased will result in a different\n * uppercase character (U+0398 (`Θ`)).\n * So, to get a canonical form, we perform both lower- and uppercase.\n *\n * Using uppercase last makes sure keys will never interact with default\n * prototypal values (such as `constructor`): nothing in the prototype of\n * `Object` is uppercase.\n *\n * @param {string} value\n * Identifier to normalize.\n * @returns {string}\n * Normalized identifier.\n */\nexport function normalizeIdentifier(value) {\n return value\n // Collapse markdown whitespace.\n .replace(/[\\t\\n\\r ]+/g, \" \")\n // Trim.\n .replace(/^ | $/g, '')\n // Some characters are considered “uppercase”, but if their lowercase\n // counterpart is uppercased will result in a different uppercase\n // character.\n // Hence, to get that form, we perform both lower- and uppercase.\n // Upper case makes sure keys will not interact with default prototypal\n // methods: no method is uppercase.\n .toLowerCase().toUpperCase();\n}","/**\n * @import {\n * CompileContext,\n * Extension as FromMarkdownExtension,\n * Handle as FromMarkdownHandle\n * } from 'mdast-util-from-markdown'\n * @import {ToMarkdownOptions} from 'mdast-util-gfm-footnote'\n * @import {\n * Handle as ToMarkdownHandle,\n * Map,\n * Options as ToMarkdownExtension\n * } from 'mdast-util-to-markdown'\n * @import {FootnoteDefinition, FootnoteReference} from 'mdast'\n */\n\nimport {ok as assert} from 'devlop'\nimport {normalizeIdentifier} from 'micromark-util-normalize-identifier'\n\nfootnoteReference.peek = footnoteReferencePeek\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteCallString() {\n this.buffer()\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteCall(token) {\n this.enter({type: 'footnoteReference', identifier: '', label: ''}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteDefinitionLabelString() {\n this.buffer()\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterFootnoteDefinition(token) {\n this.enter(\n {type: 'footnoteDefinition', identifier: '', label: '', children: []},\n token\n )\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteCallString(token) {\n const label = this.resume()\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'footnoteReference')\n node.identifier = normalizeIdentifier(\n this.sliceSerialize(token)\n ).toLowerCase()\n node.label = label\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteCall(token) {\n this.exit(token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteDefinitionLabelString(token) {\n const label = this.resume()\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'footnoteDefinition')\n node.identifier = normalizeIdentifier(\n this.sliceSerialize(token)\n ).toLowerCase()\n node.label = label\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitFootnoteDefinition(token) {\n this.exit(token)\n}\n\n/** @type {ToMarkdownHandle} */\nfunction footnoteReferencePeek() {\n return '['\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {FootnoteReference} node\n */\nfunction footnoteReference(node, _, state, info) {\n const tracker = state.createTracker(info)\n let value = tracker.move('[^')\n const exit = state.enter('footnoteReference')\n const subexit = state.enter('reference')\n value += tracker.move(\n state.safe(state.associationId(node), {after: ']', before: value})\n )\n subexit()\n exit()\n value += tracker.move(']')\n return value\n}\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM footnotes\n * in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown`.\n */\nexport function gfmFootnoteFromMarkdown() {\n return {\n enter: {\n gfmFootnoteCallString: enterFootnoteCallString,\n gfmFootnoteCall: enterFootnoteCall,\n gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString,\n gfmFootnoteDefinition: enterFootnoteDefinition\n },\n exit: {\n gfmFootnoteCallString: exitFootnoteCallString,\n gfmFootnoteCall: exitFootnoteCall,\n gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString,\n gfmFootnoteDefinition: exitFootnoteDefinition\n }\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM footnotes\n * in markdown.\n *\n * @param {ToMarkdownOptions | null | undefined} [options]\n * Configuration (optional).\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown`.\n */\nexport function gfmFootnoteToMarkdown(options) {\n // To do: next major: change default.\n let firstLineBlank = false\n\n if (options && options.firstLineBlank) {\n firstLineBlank = true\n }\n\n return {\n handlers: {footnoteDefinition, footnoteReference},\n // This is on by default already.\n unsafe: [{character: '[', inConstruct: ['label', 'phrasing', 'reference']}]\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {FootnoteDefinition} node\n */\n function footnoteDefinition(node, _, state, info) {\n const tracker = state.createTracker(info)\n let value = tracker.move('[^')\n const exit = state.enter('footnoteDefinition')\n const subexit = state.enter('label')\n value += tracker.move(\n state.safe(state.associationId(node), {before: value, after: ']'})\n )\n subexit()\n\n value += tracker.move(']:')\n\n if (node.children && node.children.length > 0) {\n tracker.shift(4)\n\n value += tracker.move(\n (firstLineBlank ? '\\n' : ' ') +\n state.indentLines(\n state.containerFlow(node, tracker.current()),\n firstLineBlank ? mapAll : mapExceptFirst\n )\n )\n }\n\n exit()\n\n return value\n }\n}\n\n/** @type {Map} */\nfunction mapExceptFirst(line, index, blank) {\n return index === 0 ? line : mapAll(line, index, blank)\n}\n\n/** @type {Map} */\nfunction mapAll(line, index, blank) {\n return (blank ? '' : ' ') + line\n}\n","/**\n * @typedef {import('mdast').Delete} Delete\n *\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n *\n * @typedef {import('mdast-util-to-markdown').ConstructName} ConstructName\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n */\n\n/**\n * List of constructs that occur in phrasing (paragraphs, headings), but cannot\n * contain strikethrough.\n * So they sort of cancel each other out.\n * Note: could use a better name.\n *\n * Note: keep in sync with: <https://github.com/syntax-tree/mdast-util-to-markdown/blob/8ce8dbf/lib/unsafe.js#L14>\n *\n * @type {Array<ConstructName>}\n */\nconst constructsWithoutStrikethrough = [\n 'autolink',\n 'destinationLiteral',\n 'destinationRaw',\n 'reference',\n 'titleQuote',\n 'titleApostrophe'\n]\n\nhandleDelete.peek = peekDelete\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM\n * strikethrough in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM strikethrough.\n */\nexport function gfmStrikethroughFromMarkdown() {\n return {\n canContainEols: ['delete'],\n enter: {strikethrough: enterStrikethrough},\n exit: {strikethrough: exitStrikethrough}\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM\n * strikethrough in markdown.\n *\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM strikethrough.\n */\nexport function gfmStrikethroughToMarkdown() {\n return {\n unsafe: [\n {\n character: '~',\n inConstruct: 'phrasing',\n notInConstruct: constructsWithoutStrikethrough\n }\n ],\n handlers: {delete: handleDelete}\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterStrikethrough(token) {\n this.enter({type: 'delete', children: []}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitStrikethrough(token) {\n this.exit(token)\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {Delete} node\n */\nfunction handleDelete(node, _, state, info) {\n const tracker = state.createTracker(info)\n const exit = state.enter('strikethrough')\n let value = tracker.move('~~')\n value += state.containerPhrasing(node, {\n ...tracker.current(),\n before: value,\n after: '~'\n })\n value += tracker.move('~~')\n exit()\n return value\n}\n\n/** @type {ToMarkdownHandle} */\nfunction peekDelete() {\n return '~'\n}\n","// To do: next major: remove.\n/**\n * @typedef {Options} MarkdownTableOptions\n * Configuration.\n */\n\n/**\n * @typedef Options\n * Configuration.\n * @property {boolean | null | undefined} [alignDelimiters=true]\n * Whether to align the delimiters (default: `true`);\n * they are aligned by default:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * Pass `false` to make them staggered:\n *\n * ```markdown\n * | Alpha | B |\n * | - | - |\n * | C | Delta |\n * ```\n * @property {ReadonlyArray<string | null | undefined> | string | null | undefined} [align]\n * How to align columns (default: `''`);\n * one style for all columns or styles for their respective columns;\n * each style is either `'l'` (left), `'r'` (right), or `'c'` (center);\n * other values are treated as `''`, which doesn’t place the colon in the\n * alignment row but does align left;\n * *only the lowercased first character is used, so `Right` is fine.*\n * @property {boolean | null | undefined} [delimiterEnd=true]\n * Whether to end each row with the delimiter (default: `true`).\n *\n * > 👉 **Note**: please don’t use this: it could create fragile structures\n * > that aren’t understandable to some markdown parsers.\n *\n * When `true`, there are ending delimiters:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there are no ending delimiters:\n *\n * ```markdown\n * | Alpha | B\n * | ----- | -----\n * | C | Delta\n * ```\n * @property {boolean | null | undefined} [delimiterStart=true]\n * Whether to begin each row with the delimiter (default: `true`).\n *\n * > 👉 **Note**: please don’t use this: it could create fragile structures\n * > that aren’t understandable to some markdown parsers.\n *\n * When `true`, there are starting delimiters:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there are no starting delimiters:\n *\n * ```markdown\n * Alpha | B |\n * ----- | ----- |\n * C | Delta |\n * ```\n * @property {boolean | null | undefined} [padding=true]\n * Whether to add a space of padding between delimiters and cells\n * (default: `true`).\n *\n * When `true`, there is padding:\n *\n * ```markdown\n * | Alpha | B |\n * | ----- | ----- |\n * | C | Delta |\n * ```\n *\n * When `false`, there is no padding:\n *\n * ```markdown\n * |Alpha|B |\n * |-----|-----|\n * |C |Delta|\n * ```\n * @property {((value: string) => number) | null | undefined} [stringLength]\n * Function to detect the length of table cell content (optional);\n * this is used when aligning the delimiters (`|`) between table cells;\n * full-width characters and emoji mess up delimiter alignment when viewing\n * the markdown source;\n * to fix this, you can pass this function,\n * which receives the cell content and returns its “visible” size;\n * note that what is and isn’t visible depends on where the text is displayed.\n *\n * Without such a function, the following:\n *\n * ```js\n * markdownTable([\n * ['Alpha', 'Bravo'],\n * ['中文', 'Charlie'],\n * ['👩‍❤️‍👩', 'Delta']\n * ])\n * ```\n *\n * Yields:\n *\n * ```markdown\n * | Alpha | Bravo |\n * | - | - |\n * | 中文 | Charlie |\n * | 👩‍❤️‍👩 | Delta |\n * ```\n *\n * With [`string-width`](https://github.com/sindresorhus/string-width):\n *\n * ```js\n * import stringWidth from 'string-width'\n *\n * markdownTable(\n * [\n * ['Alpha', 'Bravo'],\n * ['中文', 'Charlie'],\n * ['👩‍❤️‍👩', 'Delta']\n * ],\n * {stringLength: stringWidth}\n * )\n * ```\n *\n * Yields:\n *\n * ```markdown\n * | Alpha | Bravo |\n * | ----- | ------- |\n * | 中文 | Charlie |\n * | 👩‍❤️‍👩 | Delta |\n * ```\n */\n\n/**\n * @param {string} value\n * Cell value.\n * @returns {number}\n * Cell size.\n */\nfunction defaultStringLength(value) {\n return value.length\n}\n\n/**\n * Generate a markdown\n * ([GFM](https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables))\n * table.\n *\n * @param {ReadonlyArray<ReadonlyArray<string | null | undefined>>} table\n * Table data (matrix of strings).\n * @param {Readonly<Options> | null | undefined} [options]\n * Configuration (optional).\n * @returns {string}\n * Result.\n */\nexport function markdownTable(table, options) {\n const settings = options || {}\n // To do: next major: change to spread.\n const align = (settings.align || []).concat()\n const stringLength = settings.stringLength || defaultStringLength\n /** @type {Array<number>} Character codes as symbols for alignment per column. */\n const alignments = []\n /** @type {Array<Array<string>>} Cells per row. */\n const cellMatrix = []\n /** @type {Array<Array<number>>} Sizes of each cell per row. */\n const sizeMatrix = []\n /** @type {Array<number>} */\n const longestCellByColumn = []\n let mostCellsPerRow = 0\n let rowIndex = -1\n\n // This is a superfluous loop if we don’t align delimiters, but otherwise we’d\n // do superfluous work when aligning, so optimize for aligning.\n while (++rowIndex < table.length) {\n /** @type {Array<string>} */\n const row = []\n /** @type {Array<number>} */\n const sizes = []\n let columnIndex = -1\n\n if (table[rowIndex].length > mostCellsPerRow) {\n mostCellsPerRow = table[rowIndex].length\n }\n\n while (++columnIndex < table[rowIndex].length) {\n const cell = serialize(table[rowIndex][columnIndex])\n\n if (settings.alignDelimiters !== false) {\n const size = stringLength(cell)\n sizes[columnIndex] = size\n\n if (\n longestCellByColumn[columnIndex] === undefined ||\n size > longestCellByColumn[columnIndex]\n ) {\n longestCellByColumn[columnIndex] = size\n }\n }\n\n row.push(cell)\n }\n\n cellMatrix[rowIndex] = row\n sizeMatrix[rowIndex] = sizes\n }\n\n // Figure out which alignments to use.\n let columnIndex = -1\n\n if (typeof align === 'object' && 'length' in align) {\n while (++columnIndex < mostCellsPerRow) {\n alignments[columnIndex] = toAlignment(align[columnIndex])\n }\n } else {\n const code = toAlignment(align)\n\n while (++columnIndex < mostCellsPerRow) {\n alignments[columnIndex] = code\n }\n }\n\n // Inject the alignment row.\n columnIndex = -1\n /** @type {Array<string>} */\n const row = []\n /** @type {Array<number>} */\n const sizes = []\n\n while (++columnIndex < mostCellsPerRow) {\n const code = alignments[columnIndex]\n let before = ''\n let after = ''\n\n if (code === 99 /* `c` */) {\n before = ':'\n after = ':'\n } else if (code === 108 /* `l` */) {\n before = ':'\n } else if (code === 114 /* `r` */) {\n after = ':'\n }\n\n // There *must* be at least one hyphen-minus in each alignment cell.\n let size =\n settings.alignDelimiters === false\n ? 1\n : Math.max(\n 1,\n longestCellByColumn[columnIndex] - before.length - after.length\n )\n\n const cell = before + '-'.repeat(size) + after\n\n if (settings.alignDelimiters !== false) {\n size = before.length + size + after.length\n\n if (size > longestCellByColumn[columnIndex]) {\n longestCellByColumn[columnIndex] = size\n }\n\n sizes[columnIndex] = size\n }\n\n row[columnIndex] = cell\n }\n\n // Inject the alignment row.\n cellMatrix.splice(1, 0, row)\n sizeMatrix.splice(1, 0, sizes)\n\n rowIndex = -1\n /** @type {Array<string>} */\n const lines = []\n\n while (++rowIndex < cellMatrix.length) {\n const row = cellMatrix[rowIndex]\n const sizes = sizeMatrix[rowIndex]\n columnIndex = -1\n /** @type {Array<string>} */\n const line = []\n\n while (++columnIndex < mostCellsPerRow) {\n const cell = row[columnIndex] || ''\n let before = ''\n let after = ''\n\n if (settings.alignDelimiters !== false) {\n const size =\n longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0)\n const code = alignments[columnIndex]\n\n if (code === 114 /* `r` */) {\n before = ' '.repeat(size)\n } else if (code === 99 /* `c` */) {\n if (size % 2) {\n before = ' '.repeat(size / 2 + 0.5)\n after = ' '.repeat(size / 2 - 0.5)\n } else {\n before = ' '.repeat(size / 2)\n after = before\n }\n } else {\n after = ' '.repeat(size)\n }\n }\n\n if (settings.delimiterStart !== false && !columnIndex) {\n line.push('|')\n }\n\n if (\n settings.padding !== false &&\n // Don’t add the opening space if we’re not aligning and the cell is\n // empty: there will be a closing space.\n !(settings.alignDelimiters === false && cell === '') &&\n (settings.delimiterStart !== false || columnIndex)\n ) {\n line.push(' ')\n }\n\n if (settings.alignDelimiters !== false) {\n line.push(before)\n }\n\n line.push(cell)\n\n if (settings.alignDelimiters !== false) {\n line.push(after)\n }\n\n if (settings.padding !== false) {\n line.push(' ')\n }\n\n if (\n settings.delimiterEnd !== false ||\n columnIndex !== mostCellsPerRow - 1\n ) {\n line.push('|')\n }\n }\n\n lines.push(\n settings.delimiterEnd === false\n ? line.join('').replace(/ +$/, '')\n : line.join('')\n )\n }\n\n return lines.join('\\n')\n}\n\n/**\n * @param {string | null | undefined} [value]\n * Value to serialize.\n * @returns {string}\n * Result.\n */\nfunction serialize(value) {\n return value === null || value === undefined ? '' : String(value)\n}\n\n/**\n * @param {string | null | undefined} value\n * Value.\n * @returns {number}\n * Alignment.\n */\nfunction toAlignment(value) {\n const code = typeof value === 'string' ? value.codePointAt(0) : 0\n\n return code === 67 /* `C` */ || code === 99 /* `c` */\n ? 99 /* `c` */\n : code === 76 /* `L` */ || code === 108 /* `l` */\n ? 108 /* `l` */\n : code === 82 /* `R` */ || code === 114 /* `r` */\n ? 114 /* `r` */\n : 0\n}\n","/**\n * @typedef {import('mdast').InlineCode} InlineCode\n * @typedef {import('mdast').Table} Table\n * @typedef {import('mdast').TableCell} TableCell\n * @typedef {import('mdast').TableRow} TableRow\n *\n * @typedef {import('markdown-table').Options} MarkdownTableOptions\n *\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n *\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').State} State\n * @typedef {import('mdast-util-to-markdown').Info} Info\n */\n\n/**\n * @typedef Options\n * Configuration.\n * @property {boolean | null | undefined} [tableCellPadding=true]\n * Whether to add a space of padding between delimiters and cells (default:\n * `true`).\n * @property {boolean | null | undefined} [tablePipeAlign=true]\n * Whether to align the delimiters (default: `true`).\n * @property {MarkdownTableOptions['stringLength'] | null | undefined} [stringLength]\n * Function to detect the length of table cell content, used when aligning\n * the delimiters between cells (optional).\n */\n\nimport {ok as assert} from 'devlop'\nimport {markdownTable} from 'markdown-table'\nimport {defaultHandlers} from 'mdast-util-to-markdown'\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM tables in\n * markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM tables.\n */\nexport function gfmTableFromMarkdown() {\n return {\n enter: {\n table: enterTable,\n tableData: enterCell,\n tableHeader: enterCell,\n tableRow: enterRow\n },\n exit: {\n codeText: exitCodeText,\n table: exitTable,\n tableData: exit,\n tableHeader: exit,\n tableRow: exit\n }\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterTable(token) {\n const align = token._align\n assert(align, 'expected `_align` on table')\n this.enter(\n {\n type: 'table',\n align: align.map(function (d) {\n return d === 'none' ? null : d\n }),\n children: []\n },\n token\n )\n this.data.inTable = true\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitTable(token) {\n this.exit(token)\n this.data.inTable = undefined\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterRow(token) {\n this.enter({type: 'tableRow', children: []}, token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exit(token) {\n this.exit(token)\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction enterCell(token) {\n this.enter({type: 'tableCell', children: []}, token)\n}\n\n// Overwrite the default code text data handler to unescape escaped pipes when\n// they are in tables.\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitCodeText(token) {\n let value = this.resume()\n\n if (this.data.inTable) {\n value = value.replace(/\\\\([\\\\|])/g, replace)\n }\n\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'inlineCode')\n node.value = value\n this.exit(token)\n}\n\n/**\n * @param {string} $0\n * @param {string} $1\n * @returns {string}\n */\nfunction replace($0, $1) {\n // Pipes work, backslashes don’t (but can’t escape pipes).\n return $1 === '|' ? $1 : $0\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM tables in\n * markdown.\n *\n * @param {Options | null | undefined} [options]\n * Configuration.\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM tables.\n */\nexport function gfmTableToMarkdown(options) {\n const settings = options || {}\n const padding = settings.tableCellPadding\n const alignDelimiters = settings.tablePipeAlign\n const stringLength = settings.stringLength\n const around = padding ? ' ' : '|'\n\n return {\n unsafe: [\n {character: '\\r', inConstruct: 'tableCell'},\n {character: '\\n', inConstruct: 'tableCell'},\n // A pipe, when followed by a tab or space (padding), or a dash or colon\n // (unpadded delimiter row), could result in a table.\n {atBreak: true, character: '|', after: '[\\t :-]'},\n // A pipe in a cell must be encoded.\n {character: '|', inConstruct: 'tableCell'},\n // A colon must be followed by a dash, in which case it could start a\n // delimiter row.\n {atBreak: true, character: ':', after: '-'},\n // A delimiter row can also start with a dash, when followed by more\n // dashes, a colon, or a pipe.\n // This is a stricter version than the built in check for lists, thematic\n // breaks, and setex heading underlines though:\n // <https://github.com/syntax-tree/mdast-util-to-markdown/blob/51a2038/lib/unsafe.js#L57>\n {atBreak: true, character: '-', after: '[:|-]'}\n ],\n handlers: {\n inlineCode: inlineCodeWithTable,\n table: handleTable,\n tableCell: handleTableCell,\n tableRow: handleTableRow\n }\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {Table} node\n */\n function handleTable(node, _, state, info) {\n return serializeData(handleTableAsData(node, state, info), node.align)\n }\n\n /**\n * This function isn’t really used normally, because we handle rows at the\n * table level.\n * But, if someone passes in a table row, this ensures we make somewhat sense.\n *\n * @type {ToMarkdownHandle}\n * @param {TableRow} node\n */\n function handleTableRow(node, _, state, info) {\n const row = handleTableRowAsData(node, state, info)\n const value = serializeData([row])\n // `markdown-table` will always add an align row\n return value.slice(0, value.indexOf('\\n'))\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {TableCell} node\n */\n function handleTableCell(node, _, state, info) {\n const exit = state.enter('tableCell')\n const subexit = state.enter('phrasing')\n const value = state.containerPhrasing(node, {\n ...info,\n before: around,\n after: around\n })\n subexit()\n exit()\n return value\n }\n\n /**\n * @param {Array<Array<string>>} matrix\n * @param {Array<string | null | undefined> | null | undefined} [align]\n */\n function serializeData(matrix, align) {\n return markdownTable(matrix, {\n align,\n // @ts-expect-error: `markdown-table` types should support `null`.\n alignDelimiters,\n // @ts-expect-error: `markdown-table` types should support `null`.\n padding,\n // @ts-expect-error: `markdown-table` types should support `null`.\n stringLength\n })\n }\n\n /**\n * @param {Table} node\n * @param {State} state\n * @param {Info} info\n */\n function handleTableAsData(node, state, info) {\n const children = node.children\n let index = -1\n /** @type {Array<Array<string>>} */\n const result = []\n const subexit = state.enter('table')\n\n while (++index < children.length) {\n result[index] = handleTableRowAsData(children[index], state, info)\n }\n\n subexit()\n\n return result\n }\n\n /**\n * @param {TableRow} node\n * @param {State} state\n * @param {Info} info\n */\n function handleTableRowAsData(node, state, info) {\n const children = node.children\n let index = -1\n /** @type {Array<string>} */\n const result = []\n const subexit = state.enter('tableRow')\n\n while (++index < children.length) {\n // Note: the positional info as used here is incorrect.\n // Making it correct would be impossible due to aligning cells?\n // And it would need copy/pasting `markdown-table` into this project.\n result[index] = handleTableCell(children[index], node, state, info)\n }\n\n subexit()\n\n return result\n }\n\n /**\n * @type {ToMarkdownHandle}\n * @param {InlineCode} node\n */\n function inlineCodeWithTable(node, parent, state) {\n let value = defaultHandlers.inlineCode(node, parent, state)\n\n if (state.stack.includes('tableCell')) {\n value = value.replace(/\\|/g, '\\\\$&')\n }\n\n return value\n }\n}\n","/**\n * @typedef {import('mdast').ListItem} ListItem\n * @typedef {import('mdast').Paragraph} Paragraph\n * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext\n * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension\n * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle\n * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension\n * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle\n */\n\nimport {ok as assert} from 'devlop'\nimport {defaultHandlers} from 'mdast-util-to-markdown'\n\n/**\n * Create an extension for `mdast-util-from-markdown` to enable GFM task\n * list items in markdown.\n *\n * @returns {FromMarkdownExtension}\n * Extension for `mdast-util-from-markdown` to enable GFM task list items.\n */\nexport function gfmTaskListItemFromMarkdown() {\n return {\n exit: {\n taskListCheckValueChecked: exitCheck,\n taskListCheckValueUnchecked: exitCheck,\n paragraph: exitParagraphWithTaskListItem\n }\n }\n}\n\n/**\n * Create an extension for `mdast-util-to-markdown` to enable GFM task list\n * items in markdown.\n *\n * @returns {ToMarkdownExtension}\n * Extension for `mdast-util-to-markdown` to enable GFM task list items.\n */\nexport function gfmTaskListItemToMarkdown() {\n return {\n unsafe: [{atBreak: true, character: '-', after: '[:|-]'}],\n handlers: {listItem: listItemWithTaskListItem}\n }\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitCheck(token) {\n // We’re always in a paragraph, in a list item.\n const node = this.stack[this.stack.length - 2]\n assert(node.type === 'listItem')\n node.checked = token.type === 'taskListCheckValueChecked'\n}\n\n/**\n * @this {CompileContext}\n * @type {FromMarkdownHandle}\n */\nfunction exitParagraphWithTaskListItem(token) {\n const parent = this.stack[this.stack.length - 2]\n\n if (\n parent &&\n parent.type === 'listItem' &&\n typeof parent.checked === 'boolean'\n ) {\n const node = this.stack[this.stack.length - 1]\n assert(node.type === 'paragraph')\n const head = node.children[0]\n\n if (head && head.type === 'text') {\n const siblings = parent.children\n let index = -1\n /** @type {Paragraph | undefined} */\n let firstParaghraph\n\n while (++index < siblings.length) {\n const sibling = siblings[index]\n if (sibling.type === 'paragraph') {\n firstParaghraph = sibling\n break\n }\n }\n\n if (firstParaghraph === node) {\n // Must start with a space or a tab.\n head.value = head.value.slice(1)\n\n if (head.value.length === 0) {\n node.children.shift()\n } else if (\n node.position &&\n head.position &&\n typeof head.position.start.offset === 'number'\n ) {\n head.position.start.column++\n head.position.start.offset++\n node.position.start = Object.assign({}, head.position.start)\n }\n }\n }\n }\n\n this.exit(token)\n}\n\n/**\n * @type {ToMarkdownHandle}\n * @param {ListItem} node\n */\nfunction listItemWithTaskListItem(node, parent, state, info) {\n const head = node.children[0]\n const checkable =\n typeof node.checked === 'boolean' && head && head.type === 'paragraph'\n const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '\n const tracker = state.createTracker(info)\n\n if (checkable) {\n tracker.move(checkbox)\n }\n\n let value = defaultHandlers.listItem(node, parent, state, {\n ...info,\n ...tracker.current()\n })\n\n if (checkable) {\n value = value.replace(/^(?:[*+-]|\\d+\\.)([\\r\\n]| {1,3})/, check)\n }\n\n return value\n\n /**\n * @param {string} $0\n * @returns {string}\n */\n function check($0) {\n return $0 + checkbox\n }\n}\n","/**\n * Micromark syntax extension + mdast extension for resource tags: {{type:resourceId:text}}\n *\n * Instead of a full micromark extension (which requires complex token/state handling),\n * we use mdast-util-from-markdown's transform hook to post-process text nodes.\n * This is simpler and matches the existing regex approach.\n */\nimport type { Root, PhrasingContent, Text } from 'mdast';\n\nconst RESOURCE_TAG_RE = /\\{\\{([^:}]+):([^:}]*):([^}]+)\\}\\}/g;\nconst VALID_TYPES = new Set(['tool', 'manual', 'agent_message_template', 'handoff', 'end_call', 'time_diff']);\nconst MAX_DEPTH = 128;\n\nexport type ResourceTagMdastNode = {\n type: 'resourceTagMdast';\n data: {\n tagType: string;\n resourceId: string;\n };\n value: string;\n};\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n resourceTagMdast: ResourceTagMdastNode;\n }\n\n interface RootContentMap {\n resourceTagMdast: ResourceTagMdastNode;\n }\n}\n\nfunction splitTextWithResourceTags(text: string): (Text | ResourceTagMdastNode)[] {\n const results: (Text | ResourceTagMdastNode)[] = [];\n let lastIndex = 0;\n\n RESOURCE_TAG_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = RESOURCE_TAG_RE.exec(text)) !== null) {\n const [full, tagType, resourceId, displayText] = match;\n if (!VALID_TYPES.has(tagType)) continue;\n\n if (match.index > lastIndex) {\n results.push({ type: 'text', value: text.slice(lastIndex, match.index) });\n }\n results.push({\n type: 'resourceTagMdast',\n data: { tagType, resourceId },\n value: displayText,\n });\n lastIndex = match.index + full.length;\n }\n\n if (lastIndex < text.length) {\n results.push({ type: 'text', value: text.slice(lastIndex) });\n }\n\n return results;\n}\n\nfunction visitNode(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n visitNode(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n if ((child as { type: string }).type === 'text') {\n const parts = splitTextWithResourceTags((child as Text).value);\n newChildren.push(...parts);\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function resourceTagFromMarkdown() {\n return (tree: Root) => {\n visitNode(tree as unknown as { children?: unknown[] }, 0);\n };\n}\n\n/**\n * Exported for use in combined single-pass transform.\n * Returns the per-node text splitter without constructing a full plugin.\n */\nexport { splitTextWithResourceTags };\n\nexport function resourceTagToMarkdown() {\n return {\n handlers: {\n resourceTagMdast(node: ResourceTagMdastNode): string {\n return `{{${node.data.tagType}:${node.data.resourceId}:${node.value}}}`;\n },\n },\n };\n}\n","/**\n * mdast transform for jump points: ^id^\n * id must match /^[\\p{L}\\p{N}_-]+$/u\n */\nimport type { Root, Text, PhrasingContent } from 'mdast';\n\nconst JUMP_POINT_RE = /\\^([\\p{L}\\p{N}_-]+)\\^/gu;\nconst MAX_DEPTH = 128;\n\nexport type JumpPointMdastNode = {\n type: 'jumpPointMdast';\n data: {\n id: string;\n };\n value: string;\n};\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n jumpPointMdast: JumpPointMdastNode;\n }\n\n interface RootContentMap {\n jumpPointMdast: JumpPointMdastNode;\n }\n}\n\nfunction splitTextWithJumpPoints(text: string): (Text | JumpPointMdastNode)[] {\n const results: (Text | JumpPointMdastNode)[] = [];\n let lastIndex = 0;\n\n JUMP_POINT_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = JUMP_POINT_RE.exec(text)) !== null) {\n const [full, id] = match;\n\n if (match.index > lastIndex) {\n results.push({ type: 'text', value: text.slice(lastIndex, match.index) });\n }\n results.push({\n type: 'jumpPointMdast',\n data: { id },\n value: id,\n });\n lastIndex = match.index + full.length;\n }\n\n if (lastIndex < text.length) {\n results.push({ type: 'text', value: text.slice(lastIndex) });\n }\n\n return results;\n}\n\nfunction visitNode(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n visitNode(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n if ((child as { type: string }).type === 'text') {\n const parts = splitTextWithJumpPoints((child as Text).value);\n newChildren.push(...parts);\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function jumpPointFromMarkdown() {\n return (tree: Root) => {\n visitNode(tree as unknown as { children?: unknown[] }, 0);\n };\n}\n\n/**\n * Exported for use in combined single-pass transform.\n * Returns the per-node text splitter without constructing a full plugin.\n */\nexport { splitTextWithJumpPoints };\n\nexport function jumpPointToMarkdown() {\n return {\n handlers: {\n jumpPointMdast(node: JumpPointMdastNode): string {\n return `^${node.data.id}^`;\n },\n },\n };\n}\n","/**\n * Bidirectional conversion between mdast and ActionbookAST.\n */\nimport type { Root, RootContent, PhrasingContent, List, ListItem, Paragraph, Heading, Blockquote, ThematicBreak, Text as MdastText, Strong, Emphasis, InlineCode, Link, Break, Delete } from 'mdast';\nimport type { ResourceTagMdastNode } from './plugins/resourceTag';\nimport type { JumpPointMdastNode } from './plugins/jumpPoint';\nimport type { JinjaIfBlockMdastNode, JinjaIfInlineMdastNode, JinjaBranchMdast } from './plugins/jinjaBlock';\nimport type {\n DocumentNode,\n BlockNode,\n InlineNode,\n Mark,\n TextNode,\n ParagraphNode,\n HeadingNode,\n BulletListNode,\n OrderedListNode,\n ListItemNode,\n BlockquoteNode,\n HorizontalRuleNode,\n ResourceTagNode,\n JumpPointNode,\n HardBreakNode,\n TableNode,\n TableRowNode,\n TableCellNode,\n JinjaIfBlockNode,\n JinjaIfInlineNode,\n JinjaIfBranch,\n} from '../ast/types';\n\nconst MAX_DEPTH = 128;\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nfunction sanitizeUrl(url: string): string {\n if (ALLOWED_URL_PROTOCOLS.test(url)) return url;\n // Strip dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '';\n}\n\nclass DepthError extends Error {\n constructor(depth: number) {\n super(`Maximum mdast conversion depth (${MAX_DEPTH}) exceeded at depth ${depth}`);\n this.name = 'DepthError';\n }\n}\n\n// === mdast → ActionbookAST ===\n\nfunction convertInline(node: PhrasingContent, marks: Mark[] = [], depth: number = 0): InlineNode[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'text':\n return [marks.length > 0 ? { type: 'text', text: node.value, marks } : { type: 'text', text: node.value }];\n\n case 'strong': {\n const childMarks: Mark[] = [...marks, { type: 'bold' }];\n return (node as Strong).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'emphasis': {\n const childMarks: Mark[] = [...marks, { type: 'italic' }];\n return (node as Emphasis).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'delete': {\n const childMarks: Mark[] = [...marks, { type: 'strikethrough' }];\n return (node as Delete).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'inlineCode':\n return [\n marks.length > 0\n ? { type: 'text', text: (node as InlineCode).value, marks: [...marks, { type: 'code' }] }\n : { type: 'text', text: (node as InlineCode).value, marks: [{ type: 'code' }] },\n ];\n\n case 'link': {\n const href = sanitizeUrl((node as Link).url);\n if (!href) {\n // Dangerous URL protocol → strip the link, keep children as plain text\n return (node as Link).children.flatMap((child) => convertInline(child as PhrasingContent, marks, depth + 1));\n }\n const linkMark: Mark = { type: 'link', href, ...((node as Link).title ? { title: (node as Link).title! } : {}) };\n const childMarks: Mark[] = [...marks, linkMark];\n return (node as Link).children.flatMap((child) => convertInline(child as PhrasingContent, childMarks, depth + 1));\n }\n\n case 'break':\n return [{ type: 'hardBreak' }];\n\n case 'resourceTagMdast' as string: {\n const rtNode = node as unknown as ResourceTagMdastNode;\n return [\n {\n type: 'resourceTag',\n tagType: rtNode.data.tagType as ResourceTagNode['tagType'],\n resourceId: rtNode.data.resourceId,\n text: rtNode.value,\n },\n ];\n }\n\n case 'jumpPointMdast' as string: {\n const jpNode = node as unknown as JumpPointMdastNode;\n return [{ type: 'jumpPoint', id: jpNode.data.id }];\n }\n\n case 'jinjaIfInlineMdast' as string: {\n const jNode = node as unknown as JinjaIfInlineMdastNode;\n const branches: JinjaIfBranch<InlineNode>[] = jNode.branches.map(b => ({\n branchType: b.branchType,\n ...(b.condition ? { condition: b.condition } : {}),\n content: (b.content as PhrasingContent[]).flatMap(c => convertInline(c, [], depth + 1)),\n }));\n return [{ type: 'jinjaIfInline', branches } as InlineNode];\n }\n\n default:\n if ('value' in node && typeof (node as { value: unknown }).value === 'string') {\n return [{ type: 'text', text: (node as { value: string }).value }];\n }\n if ('children' in node && Array.isArray((node as { children: unknown[] }).children)) {\n return (node as { children: PhrasingContent[] }).children.flatMap((child) => convertInline(child, marks, depth + 1));\n }\n return [];\n }\n}\n\nfunction convertBlock(node: RootContent, depth: number = 0): BlockNode[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'paragraph': {\n const para = node as Paragraph;\n const content = para.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 1));\n return [{ type: 'paragraph', content }];\n }\n\n case 'heading': {\n const h = node as Heading;\n const content = h.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 1));\n return [{ type: 'heading', level: h.depth as HeadingNode['level'], content }];\n }\n\n case 'list': {\n const list = node as List;\n const items = list.children.map((li) => convertListItem(li, depth + 1));\n const spread = list.spread ?? false;\n if (list.ordered) {\n return [{ type: 'orderedList', start: list.start ?? 1, spread, content: items }];\n }\n return [{ type: 'bulletList', spread, content: items }];\n }\n\n case 'blockquote': {\n const bq = node as Blockquote;\n const content = bq.children.flatMap((child) => convertBlock(child, depth + 1));\n return [{ type: 'blockquote', content }];\n }\n\n case 'thematicBreak':\n return [{ type: 'horizontalRule' }];\n\n case 'code': {\n const codeNode = node as import('mdast').Code;\n return [{ type: 'codeBlock', content: codeNode.value, ...(codeNode.lang ? { language: codeNode.lang } : {}) } as BlockNode];\n }\n\n case 'jinjaIfBlockMdast' as string: {\n const jNode = node as unknown as JinjaIfBlockMdastNode;\n const branches: JinjaIfBranch<BlockNode>[] = jNode.branches.map(b => ({\n branchType: b.branchType,\n ...(b.condition ? { condition: b.condition } : {}),\n content: (b.content as RootContent[]).flatMap(c => convertBlock(c, depth + 1)),\n }));\n return [{ type: 'jinjaIfBlock', branches } as BlockNode];\n }\n\n case 'table': {\n const tbl = node as { type: 'table'; children: Array<{ type: 'tableRow'; children: Array<{ type: 'tableCell'; children: PhrasingContent[] }> }>; align?: (string | null)[] };\n const rows: TableRowNode[] = tbl.children.map((row, rowIdx) => {\n const cells: TableCellNode[] = row.children.map((cell) => {\n const content = cell.children.flatMap((child) => convertInline(child as PhrasingContent, [], depth + 2));\n return {\n type: 'tableCell' as const,\n ...(rowIdx === 0 ? { header: true } : {}),\n content,\n };\n });\n return { type: 'tableRow' as const, content: cells };\n });\n return [{ type: 'table', content: rows }];\n }\n\n default:\n if ('children' in node && Array.isArray((node as { children: unknown[] }).children)) {\n const inlines = (node as { children: PhrasingContent[] }).children.flatMap((child) =>\n convertInline(child as PhrasingContent, [], depth + 1),\n );\n if (inlines.length > 0) return [{ type: 'paragraph', content: inlines }];\n }\n if ('value' in node && typeof (node as { value: unknown }).value === 'string') {\n return [{ type: 'paragraph', content: [{ type: 'text', text: (node as { value: string }).value }] }];\n }\n return [];\n }\n}\n\nfunction convertListItem(node: ListItem, depth: number = 0): ListItemNode {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n const content = node.children.flatMap((child) => convertBlock(child as RootContent, depth + 1));\n const base: ListItemNode = {\n type: 'listItem',\n spread: node.spread ?? false,\n content: content.length > 0 ? content : [{ type: 'paragraph', content: [] }],\n };\n if (typeof node.checked === 'boolean') {\n return { ...base, checked: node.checked };\n }\n return base;\n}\n\nexport function fromMdast(root: Root): DocumentNode {\n const blocks: BlockNode[] = [];\n\n for (let i = 0; i < root.children.length; i++) {\n // Detect extra blank lines between consecutive blocks and restore as empty paragraphs.\n // Standard markdown block separation = 1 blank line. Each additional blank line\n // maps to one empty paragraph (1:1), matching the serializer's join function\n // that outputs \\n (instead of \\n\\n) after empty paragraphs.\n if (i > 0) {\n const prev = root.children[i - 1] as { position?: { end?: { line?: number } } };\n const curr = root.children[i] as { position?: { start?: { line?: number } } };\n const prevEndLine = prev.position?.end?.line ?? 0;\n const currStartLine = curr.position?.start?.line ?? 0;\n const emptyCount = currStartLine - prevEndLine - 2;\n for (let j = 0; j < emptyCount; j++) {\n blocks.push({ type: 'paragraph', content: [] });\n }\n }\n\n blocks.push(...convertBlock(root.children[i], 0));\n }\n\n return { type: 'doc', content: blocks.length > 0 ? blocks : [{ type: 'paragraph', content: [] }] };\n}\n\n// === ActionbookAST → mdast ===\n\nfunction inlineToMdast(node: InlineNode, depth: number = 0): PhrasingContent[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'text': {\n const marks = node.marks ?? [];\n let result: PhrasingContent[] = [{ type: 'text', value: node.text } as MdastText];\n\n for (const mark of marks) {\n switch (mark.type) {\n case 'bold':\n result = [{ type: 'strong', children: result as Strong['children'] }];\n break;\n case 'italic':\n result = [{ type: 'emphasis', children: result as Emphasis['children'] }];\n break;\n case 'strikethrough':\n result = [{ type: 'delete', children: result as Delete['children'] }];\n break;\n case 'underline':\n // Underline has no markdown representation; mark is lost on serialization\n break;\n case 'code':\n result = [{ type: 'inlineCode', value: node.text }];\n break;\n case 'link':\n result = [\n {\n type: 'link',\n url: mark.href,\n ...(mark.title ? { title: mark.title } : {}),\n children: result as Link['children'],\n },\n ];\n break;\n }\n }\n return result;\n }\n\n case 'resourceTag':\n return [\n {\n type: 'resourceTagMdast',\n data: { tagType: node.tagType, resourceId: node.resourceId },\n value: node.text,\n } as unknown as PhrasingContent,\n ];\n\n case 'jumpPoint':\n return [\n {\n type: 'jumpPointMdast',\n data: { id: node.id },\n value: node.id,\n } as unknown as PhrasingContent,\n ];\n\n case 'hardBreak':\n return [{ type: 'break' } as Break];\n\n case 'jinjaIfInline': {\n const jNode = node as JinjaIfInlineNode;\n const result: PhrasingContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'text', value: tagText } as MdastText);\n for (const child of branch.content) {\n result.push(...inlineToMdast(child, depth + 1));\n }\n }\n result.push({ type: 'text', value: '{% endif %}' } as MdastText);\n return result;\n }\n }\n}\n\nfunction blockToMdast(node: BlockNode, depth: number = 0): RootContent[] {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n\n switch (node.type) {\n case 'paragraph':\n return [{ type: 'paragraph', children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];\n\n case 'heading':\n return [{ type: 'heading', depth: node.level, children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];\n\n case 'bulletList': {\n const items = node.content.map((li) => listItemToMdast(li, depth + 1));\n return [\n {\n type: 'list',\n ordered: false,\n spread: node.spread ?? false,\n children: items,\n },\n ];\n }\n\n case 'orderedList': {\n const spread = node.spread ?? false;\n let counter = node.start;\n const items = node.content.map((li) => {\n const mdastLi = listItemToMdast(li, depth + 1);\n if (li.value != null) counter = li.value;\n // Store the effective number on the mdast node for the serializer\n (mdastLi as any)._ordinalValue = counter;\n counter++;\n return mdastLi;\n });\n return [\n {\n type: 'list',\n ordered: true,\n start: node.content[0]?.value ?? node.start,\n spread,\n children: items,\n },\n ];\n }\n\n case 'listItem':\n return listItemToMdast(node, depth).children.flatMap((child) => [child as RootContent]);\n\n case 'blockquote':\n return [{ type: 'blockquote', children: node.content.flatMap((c) => blockToMdast(c, depth + 1)) as Blockquote['children'] }];\n\n case 'horizontalRule':\n return [{ type: 'thematicBreak' }];\n\n case 'codeBlock': {\n const cb = node as import('../ast/types').CodeBlockNode;\n return [{ type: 'code', value: cb.content, ...(cb.language ? { lang: cb.language } : {}) } as RootContent];\n }\n\n case 'jinjaIfBlock': {\n const jNode = node as JinjaIfBlockNode;\n const result: RootContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', children: [{ type: 'text', value: tagText } as MdastText] } as Paragraph);\n for (const child of branch.content) {\n result.push(...blockToMdast(child, depth + 1));\n }\n }\n result.push({ type: 'paragraph', children: [{ type: 'text', value: '{% endif %}' } as MdastText] } as Paragraph);\n return result;\n }\n\n case 'table': {\n const rows = node.content.map((row) => ({\n type: 'tableRow' as const,\n children: row.content.map((cell) => ({\n type: 'tableCell' as const,\n children: cell.content.flatMap((c) => inlineToMdast(c, depth + 2)) as PhrasingContent[],\n })),\n }));\n return [{ type: 'table', children: rows } as unknown as RootContent];\n }\n\n case 'noteBlock':\n // Note blocks are editor-only — not serialized to markdown\n return [];\n }\n}\n\nfunction listItemToMdast(node: ListItemNode, depth: number = 0): ListItem {\n if (depth > MAX_DEPTH) throw new DepthError(depth);\n const children = node.content.flatMap((child) => blockToMdast(child, depth + 1)) as ListItem['children'];\n // A list item is \"loose\" (spread) when it has nested lists or multiple\n // block-level children beyond a single paragraph. This matches the blank\n // lines that tiptap-markdown inserts in the original instruction text.\n const isSpread = node.spread ?? false;\n const result: ListItem = {\n type: 'listItem',\n spread: isSpread,\n children,\n };\n if (typeof node.checked === 'boolean') {\n result.checked = node.checked;\n }\n return result;\n}\n\nexport function toMdast(doc: DocumentNode): Root {\n return {\n type: 'root',\n children: doc.content.flatMap((c) => blockToMdast(c, 0)),\n };\n}\n","/**\n * Convert ActionbookAST → ProseMirror JSONContent.\n */\nimport type { BlockNode, DocumentNode, InlineNode, JinjaIfBlockNode, JinjaIfInlineNode, Mark } from '../../ast/types';\nimport type { JSONContent } from '../../compat/prosemirror';\n\nconst ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\\/|www\\.)/i;\n\nfunction assertNever(value: never): never {\n throw new Error(`Unexpected AST node: ${JSON.stringify(value)}`);\n}\n\nfunction convertMark(mark: Mark): NonNullable<JSONContent['marks']>[number] {\n switch (mark.type) {\n case 'bold':\n return { type: 'bold' };\n case 'italic':\n return { type: 'italic' };\n case 'underline':\n return { type: 'underline' };\n case 'strikethrough':\n return { type: 'strikethrough' };\n case 'code':\n return { type: 'code' };\n case 'link': {\n const href = ALLOWED_URL_PROTOCOLS.test(mark.href) ? mark.href : '';\n return mark.title ? { type: 'link', attrs: { href, title: mark.title } } : { type: 'link', attrs: { href } };\n }\n default:\n return assertNever(mark);\n }\n}\n\nfunction convertInlineToArray(node: InlineNode): JSONContent[] {\n switch (node.type) {\n case 'jinjaIfInline': {\n const jNode = node as JinjaIfInlineNode;\n const parts: JSONContent[] = [];\n for (const branch of jNode.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n parts.push({ type: 'text', text: tagText });\n for (const child of branch.content) {\n parts.push(...convertInlineToArray(child));\n }\n }\n parts.push({ type: 'text', text: '{% endif %}' });\n return parts;\n }\n default:\n return [convertInline(node)];\n }\n}\n\nexport function convertInline(node: InlineNode): JSONContent {\n switch (node.type) {\n case 'text': {\n const result: JSONContent = { type: 'text', text: node.text };\n if (node.marks && node.marks.length > 0) {\n result.marks = node.marks.map(convertMark);\n }\n return result;\n }\n case 'resourceTag':\n return {\n type: 'inlineToolTag',\n attrs: {\n type: node.tagType,\n resourceId: node.resourceId,\n text: node.text,\n },\n };\n case 'jumpPoint':\n return {\n type: 'jumpPoint',\n attrs: { id: node.id },\n };\n case 'hardBreak':\n return { type: 'hardBreak' };\n case 'jinjaIfInline': {\n // Flatten to single text node for PM\n const parts = convertInlineToArray(node);\n const fullText = parts.map(p => p.text ?? '').join('');\n return { type: 'text', text: fullText };\n }\n default:\n return assertNever(node as never);\n }\n}\n\nfunction convertBlockToArray(node: BlockNode): JSONContent[] {\n if (node.type === 'jinjaIfBlock') {\n return [convertJinjaIfBlock(node as JinjaIfBlockNode)];\n }\n return [convertBlock(node)];\n}\n\nfunction convertJinjaIfBlock(node: JinjaIfBlockNode): JSONContent {\n return {\n type: 'jinjaIfBlock',\n content: node.branches.map((branch) => ({\n type: 'jinjaIfBranch',\n attrs: {\n branchType: branch.branchType,\n condition: branch.condition ?? '',\n },\n content: branch.content.length > 0\n ? branch.content.flatMap(convertBlockToArray)\n : [{ type: 'paragraph', content: [] }],\n })),\n };\n}\n\n/**\n * Flatten jinjaIfBlock to text paragraphs (legacy format for editors without structured jinja support).\n */\nfunction convertJinjaIfBlockFlat(node: JinjaIfBlockNode): JSONContent[] {\n const result: JSONContent[] = [];\n for (const branch of node.branches) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', content: [{ type: 'text', text: tagText }] });\n for (const child of branch.content) {\n result.push(...convertBlockToArray(child));\n }\n }\n result.push({ type: 'paragraph', content: [{ type: 'text', text: '{% endif %}' }] });\n return result;\n}\n\nexport function convertBlock(node: BlockNode): JSONContent {\n switch (node.type) {\n case 'paragraph':\n return {\n type: 'paragraph',\n content: node.content.flatMap(convertInlineToArray),\n };\n case 'heading':\n return {\n type: 'heading',\n attrs: { level: node.level },\n content: node.content.flatMap(convertInlineToArray),\n };\n case 'bulletList':\n return {\n type: 'bulletList',\n content: node.content.map(convertBlock),\n };\n case 'orderedList':\n return {\n type: 'orderedList',\n attrs: { start: node.start },\n content: node.content.map(convertBlock),\n };\n case 'listItem': {\n const result: JSONContent = {\n type: 'listItem',\n content: node.content.flatMap(convertBlockToArray),\n };\n if (node.checked != null || node.value != null) {\n result.attrs = {\n ...(node.checked != null ? { checked: node.checked } : {}),\n ...(node.value != null ? { value: node.value } : {}),\n };\n }\n return result;\n }\n case 'blockquote':\n return {\n type: 'blockquote',\n content: node.content.flatMap(convertBlockToArray),\n };\n case 'horizontalRule':\n return { type: 'horizontalRule' };\n case 'codeBlock': {\n const cb = node as import('../../ast/types').CodeBlockNode;\n return {\n type: 'codeBlock',\n attrs: { language: cb.language ?? null },\n content: cb.content ? [{ type: 'text', text: cb.content }] : undefined,\n };\n }\n case 'noteBlock':\n return {\n type: 'noteBlock',\n content: node.content.flatMap(convertBlockToArray),\n };\n case 'table':\n return {\n type: 'table',\n content: node.content.map((row) => ({\n type: 'tableRow',\n content: row.content.map((cell) => ({\n type: cell.header ? 'tableHeader' : 'tableCell',\n content: cell.content.flatMap(convertInlineToArray),\n })),\n })),\n };\n case 'jinjaIfBlock':\n return convertJinjaIfBlock(node as JinjaIfBlockNode);\n default:\n return assertNever(node as never);\n }\n}\n\nexport function toProseMirrorJSON(doc: DocumentNode): JSONContent {\n return {\n type: 'doc',\n content: doc.content.flatMap(convertBlockToArray),\n };\n}\n\n/**\n * Convert parseFragment() output (InlineNode[] | BlockNode[]) to PM JSONContent[].\n * If nodes are inline, wraps them in a single paragraph.\n */\nexport function astNodesToJSONContent(nodes: (InlineNode | BlockNode)[]): JSONContent[] {\n if (nodes.length === 0) return [];\n\n const firstType = nodes[0].type;\n const isInlineFragment =\n firstType === 'text' || firstType === 'resourceTag' || firstType === 'jumpPoint' || firstType === 'hardBreak';\n\n if (isInlineFragment) {\n return [{ type: 'paragraph', content: (nodes as InlineNode[]).flatMap(convertInlineToArray) }];\n }\n\n return (nodes as BlockNode[]).flatMap(convertBlockToArray);\n}\n","/**\n * CSS custom properties for editor text styles.\n *\n * Consumers can override any `--ab-*` variable on the `.ProseMirror` element\n * or a wrapper to customize fonts, sizes, colors, etc.\n *\n * Usage in consumer CSS:\n * .ProseMirror {\n * --ab-font-heading: 'Gellix', sans-serif;\n * --ab-font-body: 'SF Pro Text', -apple-system, sans-serif;\n * --ab-font-code: 'Roboto Mono', monospace;\n * --ab-color-body: #0d0d0d;\n * }\n */\nexport const EDITOR_TEXT_STYLES = `\n/* ── CSS custom properties (override on .ProseMirror to customize) ── */\n.ProseMirror {\n /* Font families */\n --ab-font-heading: 'Gellix', sans-serif;\n --ab-font-body: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n --ab-font-code: 'Roboto Mono', monospace;\n\n /* Body text */\n --ab-body-size: 14px;\n --ab-body-weight: 400;\n --ab-body-line-height: 20px;\n --ab-body-letter-spacing: -0.1px;\n --ab-color-body: #0d0d0d;\n\n /* H1 */\n --ab-h1-size: 24px;\n --ab-h1-weight: 700;\n --ab-h1-line-height: 32px;\n --ab-h1-letter-spacing: -0.25px;\n\n /* H2 */\n --ab-h2-size: 20px;\n --ab-h2-weight: 700;\n --ab-h2-line-height: 24px;\n --ab-h2-letter-spacing: -0.25px;\n\n /* H3 */\n --ab-h3-size: 18px;\n --ab-h3-weight: 700;\n --ab-h3-line-height: 24px;\n --ab-h3-letter-spacing: -0.25px;\n\n /* Inline code */\n --ab-code-size: 13px;\n --ab-code-weight: 400;\n --ab-code-line-height: 20px;\n --ab-code-letter-spacing: -0.3px;\n --ab-code-bg: #ececec;\n --ab-code-padding: 0 8px;\n --ab-code-radius: 2px;\n\n /* Code block */\n --ab-pre-bg: #ececec;\n --ab-pre-radius: 4px;\n --ab-pre-padding: 16px 8px 16px 24px;\n\n /* Link */\n --ab-link-color: #6210cc;\n --ab-link-weight: 500;\n\n /* Blockquote */\n --ab-blockquote-border-color: #0d0d0d;\n\n /* HR */\n --ab-hr-color: #e0e0e0;\n\n /* Block spacing */\n --ab-block-gap: 16px;\n}\n\n/* ── Base text ── */\n.ProseMirror {\n font-family: var(--ab-font-body);\n font-size: var(--ab-body-size);\n font-weight: var(--ab-body-weight);\n line-height: var(--ab-body-line-height);\n letter-spacing: var(--ab-body-letter-spacing);\n color: var(--ab-color-body);\n}\n\n.ProseMirror > * + * {\n margin-top: var(--ab-block-gap);\n}\n\n/* ── Headings ── */\n.ProseMirror h1 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h1-size);\n font-weight: var(--ab-h1-weight);\n line-height: var(--ab-h1-line-height);\n letter-spacing: var(--ab-h1-letter-spacing);\n}\n\n.ProseMirror h2 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h2-size);\n font-weight: var(--ab-h2-weight);\n line-height: var(--ab-h2-line-height);\n letter-spacing: var(--ab-h2-letter-spacing);\n}\n\n.ProseMirror h3 {\n font-family: var(--ab-font-heading);\n font-size: var(--ab-h3-size);\n font-weight: var(--ab-h3-weight);\n line-height: var(--ab-h3-line-height);\n letter-spacing: var(--ab-h3-letter-spacing);\n}\n\n/* ── Inline code ── */\n.ProseMirror code {\n font-family: var(--ab-font-code);\n font-size: var(--ab-code-size);\n font-weight: var(--ab-code-weight);\n line-height: var(--ab-code-line-height);\n letter-spacing: var(--ab-code-letter-spacing);\n background: var(--ab-code-bg);\n padding: var(--ab-code-padding);\n border-radius: var(--ab-code-radius);\n}\n\n/* ── Code block ── */\n.ProseMirror pre {\n font-family: var(--ab-font-code);\n font-size: var(--ab-code-size);\n font-weight: var(--ab-code-weight);\n line-height: var(--ab-code-line-height);\n letter-spacing: var(--ab-code-letter-spacing);\n color: var(--ab-color-body);\n background: var(--ab-pre-bg);\n border-radius: var(--ab-pre-radius);\n padding: var(--ab-pre-padding);\n overflow-x: auto;\n white-space: pre;\n}\n\n.ProseMirror pre code {\n background: transparent;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n}\n\n/* ── Link ── */\n.ProseMirror a {\n color: var(--ab-link-color);\n font-weight: var(--ab-link-weight);\n text-decoration: none;\n}\n\n.ProseMirror a:hover {\n text-decoration: none;\n}\n\n/* ── Blockquote ── */\n.ProseMirror blockquote {\n border-left: 2px solid var(--ab-blockquote-border-color);\n border-radius: 0;\n padding-left: 20px;\n color: var(--ab-color-body);\n}\n\n/* ── HR ── */\n.ProseMirror hr {\n border: none;\n height: 1px;\n background: var(--ab-hr-color);\n margin: 8px 0;\n}\n`;\n","/**\n * Input rules for markdown-style text formatting.\n *\n * Provides real-time conversion of typed markdown syntax into ProseMirror nodes/marks:\n *\n * \"# \" ~ \"###### \" → heading (h1–h6)\n * \"> \" → blockquote\n * \"```lang\" → codeBlock (with optional language)\n * \"---\" / \"***\" / \"___\" → horizontalRule\n * \"- \" or \"* \" → bulletList\n * \"1. \" → orderedList\n * \"- [ ] \" / \"- [x] \" → bulletList with todo item\n * \"^id^\" → jumpPoint (duplicate IDs are rejected)\n * **text** → bold\n * *text* → italic\n * ~~text~~ → strikethrough\n * `text` → inline code\n */\nimport { InputRule, textblockTypeInputRule, wrappingInputRule } from 'prosemirror-inputrules';\nimport type { MarkType, NodeType } from 'prosemirror-model';\nimport type { EditorState } from 'prosemirror-state';\nimport { TextSelection } from 'prosemirror-state';\nimport { actionbookSchema } from '../schema';\nimport { slashCommandKey } from './slashCommandPlugin';\nimport type { ActionbookPlugin } from './types';\n\n// Block-level patterns\nconst HEADING_RE = /^(#{1,6})\\s$/;\nconst BLOCKQUOTE_RE = /^\\s*>\\s$/;\nconst CODE_BLOCK_RE = /^```([a-zA-Z0-9]*)$/;\nconst HR_RE = /^([-*_])\\1{2,}$/;\n\nconst BULLET_LIST_RE = /^\\s*([-*])\\s$/;\nconst ORDERED_LIST_RE = /^(\\d+)\\.\\s$/;\nconst JUMP_POINT_RE = /\\^([\\p{L}\\p{N}_-]+)\\^$/u;\n\n// Inline mark autoformat patterns\n// **text** → bold\nconst BOLD_RE = /(?:^|[^*])\\*\\*([^*]+)\\*\\*$/;\n// __text__ → italic\nconst ITALIC_RE = /(?:^|[^_])__([^_]+)__$/;\n// ~~text~~ → strikethrough\nconst STRIKE_RE = /(?:^|[^~])~~([^~]+)~~$/;\n// `text` → inline code\nconst CODE_RE = /(?:^|[^`])`([^`]+)`$/;\n\n/**\n * Find the nearest ancestor list node around the cursor.\n * Returns { depth, node } or null if not inside a list.\n */\nfunction findParentList(state: EditorState, pos: number): { depth: number; node: any } | null {\n const $pos = state.doc.resolve(pos);\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d);\n const name = node.type.name;\n if (name === 'bulletList' || name === 'orderedList') {\n return { depth: d, node: node as any };\n }\n }\n return null;\n}\n\n/** Check if position is inside a listItem. */\nfunction isInsideList(state: EditorState, pos: number): boolean {\n const $pos = state.doc.resolve(pos);\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'listItem') return true;\n }\n return false;\n}\n\n/** Sentinel value: same list type detected → no-op (distinct from null = \"not in a list\") */\nconst NOOP = Symbol('noop');\n\n/**\n * Smart list input rule handler:\n * - Inside SAME list type + empty → update orderedList start attr (or NOOP for bullet)\n * - Inside SAME list type + content → NOOP (prevent nesting)\n * - Inside DIFFERENT list type + empty content → convert ONLY this item to target type\n * - Inside DIFFERENT list type + content → NOOP (prevent nesting)\n * - Not in a list → null (let wrappingInputRule handle new list creation)\n */\nfunction handleListInputRule(\n state: EditorState,\n start: number,\n end: number,\n listType: NodeType,\n attrs?: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): any {\n // Resolve from inside the matched text (not at the boundary which may be outside paragraph)\n const resolvePos = Math.max(start, end - 1);\n const parentList = findParentList(state, resolvePos);\n if (!parentList) return null; // not in a list — return null to fall through\n\n const $from = state.doc.resolve(resolvePos);\n const { depth: listDepth, node: listNode } = parentList;\n\n const paraContentSize = $from.parent.content.size;\n const matchedLen = end - start;\n const isMarkerOnly = paraContentSize === matchedLen;\n\n if (listNode.type.name === listType.name) {\n // Same orderedList → set this item's value attr (per-item numbering)\n if (listType.name === 'orderedList' && attrs?.start != null) {\n const newValue = attrs.start as number;\n // Find the listItem depth and compute natural number\n let liDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'listItem') { liDepth = d; break; }\n }\n if (liDepth > 0) {\n const liIndex = $from.index(listDepth);\n const listStartNum = (listNode.attrs.start as number) ?? 1;\n const naturalNumber = listStartNum + liIndex;\n const currentValue = ($from.node(liDepth).attrs.value as number | null);\n if (currentValue === newValue || (currentValue == null && newValue === naturalNumber)) {\n // Same number — just consume the typed marker so it doesn't stay as text\n const tr = state.tr.delete(start, end);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n // Delete the typed marker, then re-resolve to find the listItem safely\n const tr = state.tr.delete(start, end);\n const $afterDelete = tr.doc.resolve(tr.mapping.map(resolvePos));\n for (let d = $afterDelete.depth; d > 0; d--) {\n if ($afterDelete.node(d).type.name === 'listItem') {\n const pos = $afterDelete.before(d);\n const node = $afterDelete.node(d);\n tr.setNodeMarkup(pos, undefined, { ...node.attrs, value: newValue });\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n }\n }\n }\n return NOOP;\n }\n\n // Different type → split list, convert only this item\n const tr = state.tr.delete(start, end);\n const $pos = tr.doc.resolve(tr.mapping.map(resolvePos));\n\n // Find the listItem containing the cursor\n let liDepth = -1;\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'listItem') { liDepth = d; break; }\n }\n if (liDepth < 0) return null;\n\n const parentListAfterDelete = $pos.node(liDepth - 1);\n const liIndex = $pos.index(liDepth - 1);\n const liNode = parentListAfterDelete.child(liIndex);\n const parentListStart = $pos.before(liDepth - 1);\n const parentListEnd = $pos.after(liDepth - 1);\n\n // Build replacement fragments: [before items in original type] + [this item in new type] + [after items in original type]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fragments: any[] = [];\n\n // Before items (keep in original list type)\n if (liIndex > 0) {\n const beforeItems = [];\n for (let i = 0; i < liIndex; i++) beforeItems.push(parentListAfterDelete.child(i));\n fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, beforeItems));\n }\n\n // This item in new list type\n fragments.push(listType.create(attrs ?? null, liNode));\n\n // After items (keep in original list type)\n if (liIndex < parentListAfterDelete.childCount - 1) {\n const afterItems = [];\n for (let i = liIndex + 1; i < parentListAfterDelete.childCount; i++) {\n afterItems.push(parentListAfterDelete.child(i));\n }\n fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, afterItems));\n }\n\n tr.replaceWith(parentListStart, parentListEnd, fragments);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n}\n\nfunction markInputRule(pattern: RegExp, markType: MarkType, markerLen: number): InputRule {\n return new InputRule(pattern, (state, match, start, end) => {\n // Suppress mark input rules while slash command menu is active.\n // e.g. typing /anchor_point:_test_ should not italicize \"_test_\".\n const slashState = slashCommandKey.getState(state);\n if (slashState?.active) return null;\n\n const textContent = match[1];\n // ProseMirror provides `start` as the position where the full match begins\n // and `end` as the position where it ends (after the just-typed character).\n // The regex (?:^|[^x]) may match one extra char before the opening marker.\n // We need to only delete the marker+content portion, not the preceding char.\n const fullMatch = match[0];\n const markedLength = markerLen * 2 + textContent.length;\n // How many prefix chars before the actual marker (0 if matched at ^, 1 otherwise)\n const prefixLen = fullMatch.length - markedLength;\n const deleteFrom = start + prefixLen;\n\n const tr = state.tr;\n tr.delete(deleteFrom, end);\n const textNode = state.schema.text(textContent, [markType.create()]);\n tr.insert(deleteFrom, textNode);\n // Remove stored marks so subsequent typing is not marked\n tr.removeStoredMark(markType);\n return tr;\n });\n}\n\nexport function createInputRulesPlugin(): ActionbookPlugin {\n return {\n name: 'inputRules',\n inputRules: () => {\n const rules: InputRule[] = [];\n\n // \"# \" through \"###### \" → heading (h1–h6)\n rules.push(\n textblockTypeInputRule(HEADING_RE, actionbookSchema.nodes.heading, (match) => ({\n level: match[1].length,\n })),\n );\n\n // \"> \" → blockquote (not inside lists)\n rules.push(\n new InputRule(BLOCKQUOTE_RE, (state, match, start, end) => {\n if (isInsideList(state, start)) return null;\n const fallback = wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote);\n return (fallback as any).handler(state, match, start, end);\n }),\n );\n\n // \"```lang\" → codeBlock (not inside lists)\n rules.push(\n new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {\n if (isInsideList(state, start)) return null;\n const language = match[1] || null;\n const $start = state.doc.resolve(start);\n const blockStart = $start.before($start.depth);\n const blockEnd = $start.after($start.depth);\n const tr = state.tr;\n tr.replaceWith(\n blockStart,\n blockEnd,\n actionbookSchema.nodes.codeBlock.create({ language }),\n );\n return tr;\n }),\n );\n\n // \"---\" / \"***\" / \"___\" → horizontalRule (not inside lists)\n rules.push(\n new InputRule(HR_RE, (state, _match, start, end) => {\n if (isInsideList(state, start)) return null;\n const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;\n const $start = state.doc.resolve(start);\n // Find the parent paragraph boundaries\n const blockStart = $start.before($start.depth);\n const blockEnd = $start.after($start.depth);\n const tr = state.tr;\n // Replace the entire paragraph with hr + empty paragraph\n tr.replaceWith(blockStart, blockEnd, [hrType.create(), pType.create()]);\n // Place cursor in the new paragraph\n tr.setSelection(\n TextSelection.near(tr.doc.resolve(blockStart + hrType.createAndFill()!.nodeSize + 1)),\n );\n return tr;\n }),\n );\n\n // \"- [ ] \" or \"- [x] \" → bulletList with checked listItem\n // MUST be before bullet/ordered rules so the more specific pattern matches first\n rules.push(\n new InputRule(/^\\s*[-*]\\s\\[([ xX])\\]\\s$/, (state, match, start, end) => {\n const checked = match[1] !== ' ';\n const { bulletList: blType, listItem: liType } = actionbookSchema.nodes;\n const li = liType.create({ checked }, state.schema.nodes.paragraph.create());\n const list = blType.create(null, li);\n return state.tr.delete(start, end).insert(start, list);\n }),\n );\n\n // \"- \" or \"* \" → bulletList (with toggle/convert behavior inside existing lists)\n {\n const blType = actionbookSchema.nodes.bulletList;\n const fallback = wrappingInputRule(BULLET_LIST_RE, blType);\n rules.push(\n new InputRule(BULLET_LIST_RE, (state, match, start, end) => {\n const result = handleListInputRule(state, start, end, blType);\n if (result === NOOP) return null; // same type → let text be typed as-is\n if (result) return result;\n // Not in a list — delegate to standard wrapping behavior\n const handler = (fallback as any).handler;\n return handler(state, match, start, end);\n }),\n );\n }\n\n // \"1. \" → orderedList (with toggle/convert behavior inside existing lists)\n {\n const olType = actionbookSchema.nodes.orderedList;\n const fallback = wrappingInputRule(ORDERED_LIST_RE, olType, (m) => ({ start: +m[1] }));\n rules.push(\n new InputRule(ORDERED_LIST_RE, (state, match, start, end) => {\n const typedNumber = +match[1];\n\n // Check if we're inside an existing list\n const resolvePos = Math.max(start, end - 1);\n const parentList = findParentList(state, resolvePos);\n if (parentList) {\n const { node: listNode } = parentList;\n\n // Inside an orderedList → change this item's number\n if (listNode.type.name === 'orderedList') {\n const tr = state.tr.delete(start, end);\n const $after = tr.doc.resolve(tr.mapping.map(resolvePos));\n for (let d = $after.depth; d > 0; d--) {\n if ($after.node(d).type.name === 'listItem') {\n const liPos = $after.before(d);\n const liNode = $after.node(d);\n tr.setNodeMarkup(liPos, undefined, { ...liNode.attrs, value: typedNumber });\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));\n return tr;\n }\n }\n return null;\n }\n\n // Inside a bulletList → convert (only if empty item)\n const result = handleListInputRule(state, start, end, olType, { start: typedNumber });\n if (result === NOOP) return null;\n if (result) return result;\n }\n\n // Not in a list — create new orderedList\n const handler = (fallback as any).handler;\n return handler(state, match, start, end);\n }),\n );\n }\n\n // \"^id^\" → jumpPoint (duplicates allowed — validation plugin shows error state)\n const jumpPointType = actionbookSchema.nodes.jumpPoint;\n rules.push(\n new InputRule(JUMP_POINT_RE, (state, match, start, end) => {\n const id = match[1];\n const tr = state.tr.delete(start, end).insert(start, jumpPointType.create({ id }));\n // Insert trailing space so the jump point exits adjacent/edit state\n const afterAtom = start + 1; // atom nodeSize = 1\n tr.insertText(' ', afterAtom);\n // Place cursor after the space\n const cursorPos = afterAtom + 1;\n tr.setSelection(TextSelection.near(tr.doc.resolve(Math.min(cursorPos, tr.doc.content.size))));\n return tr;\n }),\n );\n\n // Inline mark input rules\n rules.push(markInputRule(BOLD_RE, actionbookSchema.marks.bold, 2));\n rules.push(markInputRule(ITALIC_RE, actionbookSchema.marks.italic, 2));\n rules.push(markInputRule(STRIKE_RE, actionbookSchema.marks.strikethrough, 2));\n rules.push(markInputRule(CODE_RE, actionbookSchema.marks.code, 1));\n\n return rules;\n },\n };\n}\n","/**\n * Slash-command trigger plugin.\n *\n * Tracks whether the cursor is inside a `/query` pattern and exposes the\n * active range + query string via `slashCommandKey` so that the\n * `SlashCommandMenu` React component can read it and render the popup.\n *\n * The plugin also handles:\n * - Escape → dismisses the menu (sets dismissed state so the same `/`\n * position doesn't re-trigger until the user moves away and types `/` again)\n * - ArrowUp / ArrowDown / Enter → consumed by the React component through\n * a capture-phase keydown listener; the plugin just marks them as handled\n * when the menu is active so ProseMirror doesn't move the cursor.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\n// ── Public types ──────────────────────────────────────────\n\nexport interface SlashCommandState {\n /** Whether a slash trigger is currently active. */\n active: boolean;\n /** Document positions of the full `/query` text (inclusive). */\n range: { from: number; to: number } | null;\n /** Text typed after `/`, not including the slash itself. */\n query: string;\n /** The parent node type name where the slash trigger is active (e.g. 'paragraph', 'heading'). */\n parentType: string;\n}\n\n// ── Plugin key (exported so SlashCommandMenu can read state) ──\n\nexport const slashCommandKey = new PluginKey<SlashCommandState>('slashCommand');\n\n// ── Internal helpers ──────────────────────────────────────\n\n/**\n * Regex matching `/` followed by zero-or-more non-whitespace chars at the\n * end of the current paragraph text up to the cursor.\n *\n * Allows the trigger at the very start of the line or after whitespace,\n * but not inside a word (e.g. `foo/bar` should NOT trigger).\n */\nconst TRIGGER_RE = /(?:^|\\s)(\\/[^\\s]*)$/;\n\n/** Derive slash-command state purely from editor state + dismissed position. */\nfunction deriveState(\n state: EditorState,\n dismissedFrom: number | null,\n): SlashCommandState {\n const inactive: SlashCommandState = { active: false, range: null, query: '', parentType: '' };\n const { selection } = state;\n if (!selection.empty) return inactive;\n\n const { $from } = selection;\n const parentType = $from.parent.type.name;\n\n // Don't trigger inside noteBlock\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'noteBlock') return inactive;\n }\n\n const textBefore = $from.parent.textBetween(0, $from.parentOffset, '\\n', '\\0');\n const match = TRIGGER_RE.exec(textBefore);\n if (!match) return inactive;\n\n const slashText = match[1]; // e.g. '/foo'\n const slashStartInParent = textBefore.lastIndexOf(slashText);\n const from = $from.start() + slashStartInParent;\n const to = $from.pos;\n\n // If the user dismissed at this exact slash position, stay inactive\n if (dismissedFrom === from) return inactive;\n\n return {\n active: true,\n range: { from, to },\n query: slashText.slice(1),\n parentType,\n };\n}\n\n// ── Meta shape ────────────────────────────────────────────\n\ninterface SlashMeta {\n /** Position of the slash that was dismissed (Escape key). */\n dismiss?: number;\n}\n\n// ── Internal plugin state (extends public state with dismiss tracking) ──\n\ninterface InternalState extends SlashCommandState {\n _dismissedFrom: number | null;\n}\n\n// ── Factory ───────────────────────────────────────────────\n\nexport function createSlashCommandPlugin(): ActionbookPlugin {\n const plugin = new Plugin<InternalState>({\n key: slashCommandKey as unknown as PluginKey<InternalState>,\n\n state: {\n init(_, state): InternalState {\n const derived = deriveState(state, null);\n return { ...derived, _dismissedFrom: null };\n },\n\n apply(tr: Transaction, prev: InternalState, _old, newState: EditorState): InternalState {\n const meta = tr.getMeta(slashCommandKey) as SlashMeta | undefined;\n\n let dismissedFrom = prev._dismissedFrom;\n\n if (meta?.dismiss !== undefined) {\n dismissedFrom = meta.dismiss;\n } else if (dismissedFrom !== null) {\n // Clear dismiss if the user typed a new `/` somewhere else\n const derived = deriveState(newState, null);\n if (derived.active && derived.range && derived.range.from !== dismissedFrom) {\n dismissedFrom = null;\n }\n }\n\n const derived = deriveState(newState, dismissedFrom);\n return { ...derived, _dismissedFrom: dismissedFrom };\n },\n },\n\n props: {\n decorations(state) {\n const s = plugin.getState(state);\n if (!s?.active || !s.range) return DecorationSet.empty;\n\n const decos: Decoration[] = [\n // Inline highlight for the slash command text\n Decoration.inline(s.range.from, s.range.to, {\n class: 'ab-slash-trigger',\n }),\n ];\n\n // Placeholder widget at cursor when query ends with \":\" and nothing after\n if (s.query.endsWith(':')) {\n decos.push(\n Decoration.widget(s.range.to, () => {\n const span = document.createElement('span');\n span.className = 'ab-slash-trigger-placeholder';\n span.textContent = 'Type a name';\n return span;\n }, { side: 1 }),\n );\n }\n\n return DecorationSet.create(state.doc, decos);\n },\n },\n });\n\n return {\n name: 'slashCommand',\n plugins: () => [plugin],\n\n keymap: () => ({\n Escape: (state, dispatch) => {\n const s = slashCommandKey.getState(state) as InternalState | undefined;\n if (!s?.active || !s.range) return false;\n\n // Dismiss: store the slash position so it won't re-trigger\n if (dispatch) {\n const tr = state.tr;\n tr.setMeta(slashCommandKey, { dismiss: s.range.from } satisfies SlashMeta);\n dispatch(tr);\n }\n return true;\n },\n }),\n };\n}\n","/**\n * History (undo/redo) plugin for the Actionbook editor.\n *\n * Wraps prosemirror-history with standard Mod-z / Mod-Shift-z / Mod-y keybindings.\n */\nimport { history, undo, redo } from 'prosemirror-history';\nimport { keymap } from 'prosemirror-keymap';\nimport type { ActionbookPlugin } from './types';\n\nexport function createHistoryPlugin(): ActionbookPlugin {\n return {\n name: 'history',\n plugins: () => [\n history(),\n keymap({ 'Mod-z': undo, 'Mod-Shift-z': redo, 'Mod-y': redo }),\n ],\n };\n}\n","/**\n * Keymap plugin for the Actionbook editor.\n *\n * Provides keyboard shortcuts matching the sbdashboard Tiptap editor:\n *\n * Backspace — lift list item out one depth when cursor is at start\n * — delete horizontalRule when in empty paragraph after it\n * — joinBackward fallback (heading/blockquote/codeBlock join)\n * Tab — sink (indent) list item, or insert tab char\n * Shift-Tab — lift (outdent) list item, or delete tab char\n * Enter — split list item; lift empty list item out of list\n * Shift-Enter — insert hardBreak\n * Mod-Shift-7 — wrap selection in bulletList\n * Mod-Shift-8 — wrap selection in orderedList\n */\nimport { baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark, setBlockType, joinBackward } from 'prosemirror-commands';\nimport { AllSelection, Plugin, TextSelection } from 'prosemirror-state';\nimport { keymap } from 'prosemirror-keymap';\nimport { liftListItem, sinkListItem, splitListItem, wrapInList } from 'prosemirror-schema-list';\nimport type { Command } from 'prosemirror-state';\nimport { actionbookSchema } from '../schema';\nimport { exitNoteBlockOnEnter } from './noteBlockPlugin';\nimport type { ActionbookPlugin } from './types';\n\nconst TAB_CHAR = '\\u0009';\n\nconst { listItem, bulletList, orderedList, hardBreak, heading, paragraph, horizontalRule, blockquote } = actionbookSchema.nodes;\n\n/** Check if a node is effectively empty (no content, or only whitespace text) */\nfunction isEffectivelyEmpty(node: import('prosemirror-model').Node): boolean {\n if (node.content.size === 0) return true;\n return node.textContent.trim().length === 0 && !node.firstChild?.isAtom;\n}\nconst { bold: boldMark, italic: italicMark, underline: underlineMark, strikethrough: strikethroughMark, code: codeMark } = actionbookSchema.marks;\n\n/**\n * Returns true only when the cursor's block is the direct child of a listItem.\n * Using `depth - 1` instead of walking all ancestors avoids false positives\n * when a listItem is a distant ancestor (e.g. cursor in a blockquote inside a\n * listItem) — those cases should fall through to the default Backspace handler.\n */\nfunction cursorDirectlyInListItem(state: Parameters<Command>[0]): boolean {\n const { $from } = state.selection;\n return $from.depth >= 2 && $from.node($from.depth - 1).type === listItem;\n}\n\n/**\n * Backspace at the start of an empty paragraph right after a list →\n * delete the paragraph and move cursor to end of the last list item.\n *\n * Spec: \"리스트 아이템 다음 빈 paragraph에서 backspace → paragraph 삭제, 커서가 리스트 아이템 끝으로\"\n */\nconst backspaceAfterList: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n\n // Must be in a paragraph at the top-level or inside a block container\n if ($from.parent.type !== paragraph) return false;\n\n // The paragraph must be empty (whitespace-only counts as empty)\n if (!isEffectivelyEmpty($from.parent)) return false;\n\n // Look at the previous sibling — it must be a list\n const parentDepth = $from.depth - 1;\n if (parentDepth < 0) return false;\n const indexInParent = $from.index(parentDepth);\n if (indexInParent === 0) return false;\n\n const prevNode = $from.node(parentDepth).child(indexInParent - 1);\n const isList = prevNode.type === bulletList || prevNode.type === orderedList;\n if (!isList) return false;\n\n if (dispatch) {\n // Delete the empty paragraph\n const from = $from.before($from.depth);\n const to = $from.after($from.depth);\n const tr = state.tr.delete(from, to);\n // Cursor lands at the position just before the deleted paragraph,\n // which is the end of the last list item\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\n/**\n * Backspace at the start of an empty paragraph that follows a leaf block\n * (horizontalRule) → delete the leaf block, keep the paragraph.\n */\nconst backspaceAfterLeafBlock: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parent.type !== paragraph) return false;\n if (!isEffectivelyEmpty($from.parent)) return false;\n\n const parentDepth = $from.depth - 1;\n if (parentDepth < 0) return false;\n const indexInParent = $from.index(parentDepth);\n if (indexInParent === 0) return false;\n\n const prevNode = $from.node(parentDepth).child(indexInParent - 1);\n if (prevNode.type !== horizontalRule) return false;\n\n if (dispatch) {\n const hrPos = $from.posAtIndex(indexInParent - 1, parentDepth);\n dispatch(state.tr.delete(hrPos, hrPos + prevNode.nodeSize).scrollIntoView());\n }\n return true;\n};\n\n/**\n * Backspace at the start of a list item → lift one depth out.\n * Prevents the default join-backward behaviour and acts like Shift-Tab.\n * Falls back to joinBackward for remaining cases (e.g. empty para after\n * heading/blockquote/codeBlock).\n */\n/** Backspace in an empty block (jinja/note/blockquote) → delete the entire block */\nconst backspaceDeleteEmptyBlock: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parent.type !== paragraph || !isEffectivelyEmpty($from.parent)) return false;\n\n const deletableTypes = new Set(['jinjaIfBlock', 'jinjaIfBranch', 'noteBlock', 'blockquote']);\n\n for (let d = $from.depth - 1; d > 0; d--) {\n const ancestor = $from.node(d);\n if (!deletableTypes.has(ancestor.type.name)) continue;\n\n // For jinjaIfBranch, check if the branch content is just this empty paragraph\n if (ancestor.type.name === 'jinjaIfBranch' && ancestor.childCount === 1 && ancestor.child(0).content.size === 0) {\n // Go up to jinjaIfBlock\n for (let dd = d - 1; dd > 0; dd--) {\n if ($from.node(dd).type.name === 'jinjaIfBlock') {\n d = dd;\n break;\n }\n }\n }\n\n // Only delete if the block has no meaningful content\n const blockNode = $from.node(d);\n const blockText = blockNode.textContent.trim();\n if (blockText.length > 0) return false;\n\n if (dispatch) {\n const blockStart = $from.before(d);\n const blockEnd = $from.after(d);\n const tr = state.tr.replaceWith(blockStart, blockEnd, paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockStart)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n return false;\n};\n\n/**\n * Backspace at the start of a list item's first paragraph:\n *\n * Case A: First item, block above list exists → join with block above\n * Case B: First item, nothing above → lift out of list\n * Case C: Non-first item → join with previous item's last paragraph\n * (nested content moves to previous item as children)\n */\nconst joinListItemBackward: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parentOffset !== 0) return false;\n if (!cursorDirectlyInListItem(state)) return false;\n // Must be in the FIRST child (paragraph) of the listItem\n if ($from.index($from.depth - 1) !== 0) return false;\n\n const liDepth = $from.depth - 1; // listItem depth\n const listDepth = liDepth - 1; // bulletList/orderedList depth\n if (listDepth < 0) return false;\n\n const listNode = $from.node(listDepth);\n if (listNode.type !== bulletList && listNode.type !== orderedList) return false;\n\n const liIndex = $from.index(listDepth); // index of this item in the list\n\n if (liIndex > 0) {\n // Case C: Non-first item → join with previous item's last paragraph\n // Two joins needed:\n // 1. Join list items (merges children into one item)\n // 2. Join the adjacent paragraphs inside the merged item\n if (dispatch) {\n const joinPos = $from.before(liDepth); // boundary between prev and current listItem\n const tr = state.tr.join(joinPos);\n // After list item join, the two paragraphs are now adjacent inside one item.\n // Join them at the mapped position (same pos, now between paragraphs).\n const mappedPos = tr.mapping.map(joinPos);\n if (tr.doc.resolve(mappedPos).nodeBefore?.isTextblock && tr.doc.resolve(mappedPos).nodeAfter?.isTextblock) {\n tr.join(mappedPos);\n }\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n\n // First item — check what's above the list\n const listStart = $from.before(listDepth);\n const parentOfList = $from.node(listDepth - 1);\n const listIndexInParent = $from.index(listDepth - 1);\n\n if (listIndexInParent > 0) {\n // Case A: There's a block above the list → join first item with it\n const prevBlock = parentOfList.child(listIndexInParent - 1);\n\n // Only join if the previous block is a textblock (paragraph, heading, etc.)\n if (prevBlock.isTextblock) {\n if (dispatch) {\n const liNode = listNode.child(0);\n const firstPara = liNode.firstChild!;\n\n // Build the transaction:\n // 1. Delete the first list item from the list\n const liStart = $from.before(liDepth);\n const liEnd = $from.after(liDepth);\n const tr = state.tr;\n\n if (listNode.childCount === 1) {\n // Only item in list → delete entire list, append content to prev block\n tr.delete(listStart, $from.after(listDepth));\n } else {\n // Multiple items → delete just the first item\n tr.delete(liStart, liEnd);\n }\n\n // 2. Append the first paragraph's content to the previous block\n const prevBlockEnd = tr.mapping.map(listStart) - 1; // end of previous block's content\n if (firstPara.content.size > 0) {\n tr.insert(prevBlockEnd, firstPara.content);\n }\n\n // 3. If the list item had nested content (sub-lists etc.), insert after prev block\n if (liNode.childCount > 1) {\n const nestedContent = [];\n for (let i = 1; i < liNode.childCount; i++) {\n nestedContent.push(liNode.child(i));\n }\n const insertPos = tr.mapping.map(listStart);\n for (const node of nestedContent) {\n tr.insert(insertPos, node);\n }\n }\n\n tr.setSelection(TextSelection.near(tr.doc.resolve(prevBlockEnd)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n }\n }\n\n // Case B: Nothing above (or prev block not textblock) → lift\n return liftListItem(listItem)(state, dispatch);\n};\n\nconst backspaceCommand: Command = chainCommands(\n backspaceDeleteEmptyBlock,\n backspaceAfterList,\n backspaceAfterLeafBlock,\n (state, dispatch) => {\n const { $from } = state.selection;\n if (!state.selection.empty) return false;\n if ($from.parentOffset !== 0) return false;\n\n // At start of a heading → convert to paragraph\n if ($from.parent.type === heading) {\n return setBlockType(paragraph)(state, dispatch);\n }\n\n return false;\n },\n joinListItemBackward,\n (state, dispatch) => {\n // Fallback: lift list item if joinListItemBackward didn't handle it\n if (!cursorDirectlyInListItem(state)) return false;\n const { $from } = state.selection;\n if ($from.parentOffset !== 0) return false;\n if ($from.index($from.depth - 1) !== 0) return false;\n return liftListItem(listItem)(state, dispatch);\n },\n joinBackward,\n);\n\nconst tabCommand: Command = (state, dispatch) => {\n const { $from } = state.selection;\n // In list items: try to indent regardless of cursor position\n if (cursorDirectlyInListItem(state)) {\n if (sinkListItem(listItem)(state, dispatch)) return true;\n // If sink fails (e.g. already max depth), swallow the Tab — don't insert tab char\n return true;\n }\n if (dispatch) dispatch(state.tr.insertText(TAB_CHAR));\n return true;\n};\n\nconst shiftTabCommand: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if (cursorDirectlyInListItem(state) && $from.parentOffset === 0) {\n return liftListItem(listItem)(state, dispatch);\n }\n const pos = $from.pos;\n if (state.doc.textBetween(pos - 1, pos) === TAB_CHAR) {\n if (dispatch) dispatch(state.tr.delete(pos - 1, pos));\n return true;\n }\n return true;\n};\n\n// ── Double-enter exit for blockquote and jinjaIfBranch ────\n// On 2nd consecutive Enter in an empty paragraph inside these blocks,\n// exit the block and create a new paragraph after it.\nlet blockExitEnterCount = 0;\nlet blockExitLastTime = 0;\nconst BLOCK_EXIT_TYPES = new Set(['blockquote', 'jinjaIfBranch']);\n\nconst exitBlockOnDoubleEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n\n // Find qualifying ancestor block\n let blockDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if (BLOCK_EXIT_TYPES.has($from.node(d).type.name)) {\n blockDepth = d;\n break;\n }\n }\n if (blockDepth < 0) {\n blockExitEnterCount = 0;\n return false;\n }\n\n // Must be in an empty paragraph\n if ($from.parent.type.name !== 'paragraph' || $from.parent.content.size !== 0) {\n blockExitEnterCount = 0;\n return false;\n }\n\n const now = Date.now();\n if (now - blockExitLastTime > 2000) blockExitEnterCount = 0;\n blockExitLastTime = now;\n blockExitEnterCount++;\n\n if (blockExitEnterCount < 2) return false;\n blockExitEnterCount = 0;\n\n if (!dispatch) return true;\n\n // Delete current empty paragraph\n const paraStart = $from.before($from.depth);\n const paraEnd = $from.after($from.depth);\n const tr = state.tr.delete(paraStart, paraEnd);\n\n // Delete previous empty paragraph (from first Enter)\n const mapped = tr.mapping.map($from.before($from.depth));\n const $m = tr.doc.resolve(Math.min(mapped, tr.doc.content.size));\n for (let d = $m.depth; d > 0; d--) {\n if (BLOCK_EXIT_TYPES.has($m.node(d).type.name)) {\n const last = $m.node(d).lastChild;\n if (last?.type.name === 'paragraph' && last.content.size === 0) {\n const lastPos = $m.end(d) - last.nodeSize;\n tr.delete(lastPos, lastPos + last.nodeSize);\n }\n break;\n }\n }\n\n // For jinjaIfBranch, exit the parent jinjaIfBlock (not just the branch)\n let exitDepth = blockDepth;\n const blockTypeName = $from.node(blockDepth).type.name;\n if (blockTypeName === 'jinjaIfBranch') {\n // Go up one more level to exit jinjaIfBlock\n for (let d = blockDepth - 1; d > 0; d--) {\n if ($from.node(d).type.name === 'jinjaIfBlock') {\n exitDepth = d;\n break;\n }\n }\n }\n\n // Insert new paragraph after the block\n const blockEnd = tr.mapping.map($from.after(exitDepth));\n const newPara = paragraph.create();\n tr.insert(blockEnd, newPara);\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockEnd + 1)));\n\n dispatch(tr.scrollIntoView());\n return true;\n};\n\n/**\n * Enter at the end of a codeBlock when the last line is empty →\n * remove the trailing newline and create a new paragraph after the block.\n */\nconst exitCodeBlockOnEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n if ($from.parent.type.name !== 'codeBlock') return false;\n\n const codeBlock = $from.parent;\n const text = codeBlock.textContent;\n\n // Only exit if cursor is at the end AND text ends with a newline (empty last line)\n if ($from.parentOffset !== text.length) return false;\n if (!text.endsWith('\\n')) return false;\n\n if (dispatch) {\n const codeBlockPos = $from.before($from.depth);\n // Remove trailing newline\n const tr = state.tr.delete($from.pos - 1, $from.pos);\n // Insert new paragraph after the codeBlock\n const blockEnd = tr.mapping.map(codeBlockPos + codeBlock.nodeSize);\n tr.insert(blockEnd, paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockEnd + 1)));\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\nconst enterCommand: Command = chainCommands(\n exitNoteBlockOnEnter,\n exitBlockOnDoubleEnter,\n exitCodeBlockOnEnter,\n newlineInCode,\n // Split list item on Enter; lift empty list item out of list\n splitListItem(listItem),\n createParagraphNear,\n liftEmptyBlock,\n splitBlock,\n);\n\nconst shiftEnterCommand: Command = (state, dispatch) => {\n if (dispatch) {\n const { from, to, $from } = state.selection;\n const tr = state.tr;\n // Delete selection range first (if non-empty).\n if (from !== to) tr.delete(from, to);\n const insertPos = tr.mapping.map(from);\n const marks = $from.marks();\n\n // Insert hardBreak followed by a zero-width space (U+200B).\n // Without the ZWS, browsers merge typed text into the text node BEFORE\n // the <br> (contenteditable treats the cursor position between two <br>\n // elements as \"end of preceding text node\"). The ZWS creates a separate\n // text node after the <br> that anchors the cursor. ProseMirror will\n // absorb it into the next typed character automatically.\n tr.insert(insertPos, hardBreak.create());\n const afterBr = insertPos + 1;\n tr.insertText('\\u200B', afterBr);\n // Place cursor AFTER the ZWS (it will be replaced by the first typed char)\n const cursorPos = afterBr + 1;\n if (cursorPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.create(tr.doc, cursorPos));\n }\n if (marks.length > 0) tr.setStoredMarks(marks);\n dispatch(tr.scrollIntoView());\n }\n return true;\n};\n\n/**\n * When the document is reduced to a single empty non-paragraph block\n * (e.g. Cmd+A → Delete leaves an empty heading), auto-convert it to a\n * paragraph so the user can continue typing normally.\n */\nfunction createEmptyDocGuardPlugin(): Plugin {\n return new Plugin({\n appendTransaction(_, __, newState) {\n const { doc } = newState;\n if (doc.childCount !== 1) return null;\n const only = doc.child(0);\n if (only.type === paragraph) return null;\n if (only.content.size !== 0) return null;\n\n // Single empty non-paragraph block → convert to paragraph\n return newState.tr.setNodeMarkup(0, paragraph);\n },\n });\n}\n\n/**\n * Smart Cmd+A: first press selects current top-level block,\n * second press (when block is already fully selected) selects entire document.\n */\nconst selectAllCommand: Command = (state, dispatch) => {\n const { $from, from, to } = state.selection;\n\n // Find the top-level block containing the cursor\n const depth = Math.min($from.depth, 1); // top-level = depth 1\n const blockStart = $from.start(depth);\n const blockEnd = $from.end(depth);\n\n // If the current block is already fully selected, select entire document\n const blockFullySelected = from <= blockStart && to >= blockEnd;\n if (blockFullySelected) {\n if (dispatch) dispatch(state.tr.setSelection(new AllSelection(state.doc)));\n return true;\n }\n\n // Otherwise, select the entire current block content\n if (dispatch) dispatch(state.tr.setSelection(TextSelection.create(state.doc, blockStart, blockEnd)));\n return true;\n};\n\nexport function createKeymapPlugin(): ActionbookPlugin {\n return {\n name: 'keymapPlugin',\n keymap: () => ({\n Backspace: backspaceCommand,\n Tab: tabCommand,\n 'Shift-Tab': shiftTabCommand,\n Enter: enterCommand,\n 'Shift-Enter': shiftEnterCommand,\n 'Mod-a': selectAllCommand,\n 'Mod-b': toggleMark(boldMark),\n 'Mod-i': toggleMark(italicMark),\n 'Mod-u': toggleMark(underlineMark),\n 'Mod-Shift-s': toggleMark(strikethroughMark),\n 'Mod-e': toggleMark(codeMark),\n 'Mod-Shift-7': wrapInList(bulletList),\n 'Mod-Shift-8': wrapInList(orderedList),\n }),\n plugins: () => [keymap(baseKeymap), createEmptyDocGuardPlugin()],\n };\n}\n","/**\n * NodeView plugin for noteBlock — editor-only content not sent to LLM.\n * Renders with a \"Note\" label chip, gray italic text, and a dashed border.\n *\n * Design tokens (from Figma):\n * Block: bg #FFF, border 1px dashed #CCC, radius 4px, padding 16px 24px\n * Label: bg #F7F7F7, border 1px solid #E0E0E0, radius 4px, padding 2px 4px\n * font 12px/16px Regular #858585\n * Body: font 14px/20px Regular Italic #858585, letter-spacing -0.1px\n * Gap: 4px between label and body\n */\nimport type { NodeView, EditorView } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Selection } from 'prosemirror-state';\nimport type { Command } from 'prosemirror-state';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\nclass NoteBlockView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n constructor(\n _node: PMNode,\n _view: EditorView,\n _getPos: () => number | undefined,\n ) {\n // Outer wrapper — dashed border box\n this.dom = document.createElement('div');\n this.dom.setAttribute('data-note-block', '');\n this.dom.className = 'ab-note-block';\n this.dom.style.cssText = [\n 'position: relative',\n 'margin: 8px 0',\n 'padding: 16px 24px',\n 'background: #fff',\n 'border: 1px dashed #ccc',\n 'border-radius: 4px',\n 'display: flex',\n 'flex-direction: column',\n 'gap: 4px',\n ].join(';');\n\n // Label chip\n const label = document.createElement('span');\n label.contentEditable = 'false';\n label.textContent = 'Note';\n label.style.cssText = [\n 'font-family: SF Pro Text, -apple-system, BlinkMacSystemFont, sans-serif',\n 'display: inline-flex',\n 'align-items: center',\n 'justify-content: center',\n 'align-self: flex-start',\n 'font-size: 12px',\n 'font-weight: 400',\n 'font-style: normal',\n 'line-height: 16px',\n 'color: #858585',\n 'background: #f7f7f7',\n 'border: 1px solid #e0e0e0',\n 'border-radius: 4px',\n 'padding: 2px 4px',\n 'user-select: none',\n 'height: 20px',\n ].join(';');\n this.dom.appendChild(label);\n\n // Content area — italic gray text\n this.contentDOM = document.createElement('div');\n this.contentDOM.className = 'ab-note-block-content';\n this.contentDOM.style.cssText = [\n 'font-size: 14px',\n 'font-style: italic',\n 'font-weight: 400',\n 'line-height: 20px',\n 'letter-spacing: -0.1px',\n 'color: #858585',\n ].join(';');\n this.dom.appendChild(this.contentDOM);\n }\n}\n\n/**\n * Exit noteBlock on Enter in an empty paragraph.\n * Deletes the empty paragraph and creates a new paragraph after the noteBlock.\n */\nconst exitNoteBlockOnEnter: Command = (state, dispatch) => {\n const { $from } = state.selection;\n\n // Find noteBlock ancestor\n let noteBlockDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'noteBlock') {\n noteBlockDepth = d;\n break;\n }\n }\n if (noteBlockDepth < 0) return false;\n\n // Must be in an empty paragraph\n const parentNode = $from.parent;\n if (parentNode.type.name !== 'paragraph' || parentNode.content.size !== 0) {\n return false;\n }\n\n if (!dispatch) return true;\n\n // Delete the current empty paragraph\n const paragraphStart = $from.before($from.depth);\n const paragraphEnd = $from.after($from.depth);\n const tr = state.tr.delete(paragraphStart, paragraphEnd);\n\n // Insert new paragraph after the noteBlock\n const noteBlockEnd = tr.mapping.map($from.after(noteBlockDepth));\n const newParagraph = state.schema.nodes.paragraph.create();\n tr.insert(noteBlockEnd, newParagraph);\n\n // Move cursor into the new paragraph\n tr.setSelection(Selection.near(tr.doc.resolve(noteBlockEnd + 1)));\n\n dispatch(tr.scrollIntoView());\n return true;\n};\n\n/** Exported so keymapPlugin can include it in the Enter chain with correct priority. */\nexport { exitNoteBlockOnEnter };\n\nexport function createNoteBlockPlugin(): ActionbookPlugin {\n return {\n name: 'noteBlockNodeView',\n nodeViews: (): Record<string, NodeViewFactory> => ({\n noteBlock: (node, view, getPos) => new NoteBlockView(node, view, getPos),\n }),\n };\n}\n","/**\n * Clipboard plugin: paste plain-text / markdown → ProseMirror nodes,\n * copy ProseMirror nodes → markdown text.\n *\n * Mirrors the MarkdownClipboardManager from sbdashboard, using\n * actionbook-core's own parseFragment / serializeFragment / fromProseMirrorJSON.\n *\n * Jump-point deduplication: if a pasted `^id^` already exists in the doc,\n * the caret `^...^` markers are stripped so the text is kept as plain text\n * rather than creating a duplicate node.\n */\nimport { DOMParser as ProseMirrorDOMParser, Fragment, Slice } from 'prosemirror-model';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorView } from 'prosemirror-view';\nimport { parseFragment, serializeFragment, fromProseMirrorJSON } from '../../index';\nimport { astNodesToJSONContent } from '../bridge/toProseMirrorJSON';\nimport { actionbookSchema } from '../schema';\nimport type { ActionbookPlugin } from './types';\n\nconst key = new PluginKey('markdownClipboard');\n\n/**\n * Maximum list nesting depth allowed on paste.\n * Lists deeper than this are flattened to this depth.\n */\nconst MAX_PASTE_LIST_DEPTH = 15;\n\n/**\n * Flatten deeply nested lists in a ProseMirror node tree.\n * Lists beyond MAX_PASTE_LIST_DEPTH have their nested sublists removed —\n * only the direct paragraph content of list items is kept.\n */\nconst MAX_FLATTEN_DEPTH = 128;\n\nfunction flattenDeepLists(node: PMNode, listDepth: number = 0, _recurseDepth: number = 0): PMNode {\n if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;\n const isList = node.type.name === 'bulletList' || node.type.name === 'orderedList';\n const currentDepth = isList ? listDepth + 1 : listDepth;\n\n if (isList && currentDepth >= MAX_PASTE_LIST_DEPTH) {\n // At max depth: strip any nested lists from list items, keep only blocks\n const flatItems: PMNode[] = [];\n node.forEach((li) => {\n const nonListBlocks: PMNode[] = [];\n li.forEach((block) => {\n if (block.type.name !== 'bulletList' && block.type.name !== 'orderedList') {\n nonListBlocks.push(block);\n }\n // Nested lists are dropped — their content is already too deep\n });\n if (nonListBlocks.length > 0) {\n flatItems.push(li.type.create(li.attrs, nonListBlocks));\n }\n });\n if (flatItems.length === 0) return node;\n return node.copy(Fragment.fromArray(flatItems));\n }\n\n // Recurse into children\n const children: PMNode[] = [];\n let changed = false;\n node.forEach((child) => {\n const flattened = flattenDeepLists(child, currentDepth, _recurseDepth + 1);\n if (flattened !== child) changed = true;\n children.push(flattened);\n });\n\n if (!changed) return node;\n return node.copy(Fragment.fromArray(children));\n}\n\n/**\n * Parse HTML clipboard content through ProseMirror's DOMParser,\n * then flatten deep lists to prevent Chrome hangs.\n *\n * Uses ProseMirror's DOMParser which only creates nodes allowed by the schema,\n * effectively sanitizing the HTML through the schema whitelist.\n */\nfunction htmlToSlice(html: string): Slice | null {\n if (typeof document === 'undefined') return null;\n try {\n // Parse HTML into DOM using the browser's safe HTML parser\n const domParser = new DOMParser();\n const parsed = domParser.parseFromString(html, 'text/html');\n const body = parsed.body;\n if (!body || !body.childNodes.length) return null;\n\n // Use ProseMirror's schema-aware DOMParser to convert to PM nodes\n const pmParser = ProseMirrorDOMParser.fromSchema(actionbookSchema);\n const doc = pmParser.parse(body);\n\n // Flatten deep lists to prevent hanging\n const flattened = flattenDeepLists(doc);\n const content = flattened.content;\n\n // Skip if we only got empty paragraphs\n let hasContent = false;\n content.forEach((node) => {\n if (node.type.name !== 'paragraph' || node.content.size > 0) {\n hasContent = true;\n }\n });\n if (!hasContent) return null;\n\n const openDepth = content.childCount === 1 && content.firstChild?.type.name === 'paragraph' ? 1 : 0;\n return new Slice(content, openDepth, openDepth);\n } catch {\n return null;\n }\n}\n\nfunction textToSlice(text: string, view: EditorView): Slice | null {\n try {\n const existingIds = new Set<string>();\n view.state.doc.descendants((node) => {\n if (node.type.name === 'jumpPoint') existingIds.add(node.attrs.id as string);\n });\n\n // Strip duplicate jump-point markers\n const deduped = text.replace(/\\^([\\p{L}\\p{N}_-]+)\\^/gmu, (match, id) => {\n if (existingIds.has(id)) return id; // keep as plain text\n existingIds.add(id);\n return match;\n });\n\n const astNodes = parseFragment(deduped);\n const pmJSONNodes = astNodesToJSONContent(astNodes);\n const pmNodes = pmJSONNodes.map((json) => actionbookSchema.nodeFromJSON(json));\n const fragment = Fragment.fromArray(pmNodes);\n // Single paragraph → inline paste (openDepth 1); otherwise block paste\n const openDepth = pmJSONNodes.length === 1 && pmJSONNodes[0].type === 'paragraph' ? 1 : 0;\n return new Slice(fragment, openDepth, openDepth);\n } catch {\n return null;\n }\n}\n\n/** Check if text is a plain URL (http/https) */\nconst URL_RE = /^https?:\\/\\/[^\\s]+$/i;\n\nlet shiftHeld = false;\n\nfunction createPlugin(): Plugin {\n return new Plugin({\n key,\n props: {\n handleDOMEvents: {\n keydown(_view, event) {\n shiftHeld = event.shiftKey;\n return false;\n },\n keyup() {\n shiftHeld = false;\n return false;\n },\n paste(view, event) {\n if (shiftHeld) return false;\n const clipboardData = (event as ClipboardEvent).clipboardData;\n const text = clipboardData?.getData('text/plain');\n if (!text || !URL_RE.test(text.trim())) return false;\n const { from, to } = view.state.selection;\n if (from >= to) return false;\n const selectedText = view.state.doc.textBetween(from, to);\n if (!selectedText) return false;\n // Selected text + URL paste → wrap text as link label\n event.preventDefault();\n const linkType = view.state.schema.marks.link;\n if (!linkType) return false;\n const linkMark = linkType.create({ href: text.trim() });\n view.dispatch(view.state.tr.addMark(from, to, linkMark));\n return true;\n },\n },\n handlePaste(view: EditorView, event: ClipboardEvent) {\n const text = event.clipboardData?.getData('text/plain');\n\n // Cmd+Shift+V (or Ctrl+Shift+V) → paste without formatting\n if (shiftHeld) {\n if (!text) return false;\n const textNode = actionbookSchema.text(text);\n const slice = new Slice(Fragment.from(textNode), 0, 0);\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n }\n\n const html = event.clipboardData?.getData('text/html');\n\n // Try HTML first (preserves formatting from Google Docs, Confluence, etc.)\n if (html) {\n const htmlSlice = htmlToSlice(html);\n if (htmlSlice) {\n view.dispatch(view.state.tr.replaceSelection(htmlSlice));\n return true;\n }\n }\n\n // Plain URL (no selection) → insert as link\n if (text && URL_RE.test(text.trim())) {\n const url = text.trim();\n const linkMark = actionbookSchema.marks.link.create({ href: url });\n const textNode = actionbookSchema.text(url, [linkMark]);\n const slice = new Slice(Fragment.from(textNode), 0, 0);\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n }\n\n // Fall back to plain text / markdown\n if (!text) return false;\n const slice = textToSlice(text, view);\n if (!slice) return false;\n\n view.dispatch(view.state.tr.replaceSelection(slice));\n return true;\n },\n\n clipboardTextParser(text: string, _$context, _plain, view) {\n if (!text) return Slice.empty;\n const slice = textToSlice(text, view!);\n if (!slice) {\n const textNode = actionbookSchema.text(text);\n return new Slice(Fragment.from(textNode), 0, 0);\n }\n return slice;\n },\n\n // Transform pasted HTML: keep structure but flatten deep lists\n // to prevent Chrome contentEditable hanging\n transformPasted(slice: Slice) {\n const nodes: PMNode[] = [];\n slice.content.forEach((node) => {\n nodes.push(flattenDeepLists(node));\n });\n return new Slice(Fragment.fromArray(nodes), slice.openStart, slice.openEnd);\n },\n\n clipboardTextSerializer(slice: Slice) {\n try {\n const jsonNodes: Record<string, unknown>[] = [];\n slice.content.forEach((node) => jsonNodes.push(node.toJSON()));\n const doc = fromProseMirrorJSON({ type: 'doc', content: jsonNodes });\n return serializeFragment(doc.content as Parameters<typeof serializeFragment>[0]);\n } catch {\n return '';\n }\n },\n },\n });\n}\n\nexport function createMarkdownClipboardPlugin(): ActionbookPlugin {\n return {\n name: 'markdownClipboard',\n plugins: () => [createPlugin()],\n };\n}\n","import type { AstNode, BlockNode, DocumentNode, InlineNode, JinjaIfBlockNode, JinjaIfInlineNode, NodePath } from './types';\n\n/**\n * Maximum recursion depth for all tree traversal functions.\n * Prevents stack overflow from maliciously deep or malformed input.\n */\nexport const MAX_DEPTH = 128;\n\nexport class TraversalDepthError extends Error {\n constructor(depth: number) {\n super(`Maximum traversal depth (${MAX_DEPTH}) exceeded at depth ${depth}`);\n this.name = 'TraversalDepthError';\n }\n}\n\nfunction getChildren(node: AstNode): readonly AstNode[] {\n switch (node.type) {\n case 'doc':\n case 'blockquote':\n case 'listItem':\n case 'noteBlock':\n return node.content;\n case 'paragraph':\n case 'heading':\n return node.content;\n case 'bulletList':\n case 'orderedList':\n return node.content;\n case 'jinjaIfBlock':\n return node.branches.flatMap(b => b.content as readonly AstNode[]);\n case 'jinjaIfInline':\n return node.branches.flatMap(b => b.content as readonly AstNode[]);\n default:\n return [];\n }\n}\n\n// Internal recursive implementation shared by visit()\nfunction visitInternal(\n node: AstNode,\n callback: (node: AstNode, parent?: AstNode, path?: NodePath) => void,\n parent: AstNode | undefined,\n path: NodePath,\n depth: number,\n trackPath: boolean,\n): void {\n if (depth > MAX_DEPTH) {\n throw new TraversalDepthError(depth);\n }\n callback(node, parent, trackPath ? path : undefined);\n const children = getChildren(node);\n for (let i = 0; i < children.length; i++) {\n const nextPath = trackPath ? [...path, i] : path;\n visitInternal(children[i], callback, node, nextPath, depth + 1, trackPath);\n }\n}\n\nexport interface VisitOptions {\n /**\n * Whether to compute and pass a NodePath to each callback invocation.\n * Defaults to true for backward compatibility.\n * Set to false for performance-critical traversals that don't need path info.\n */\n trackPath?: boolean;\n}\n\nexport function visit(\n node: AstNode,\n callback: (node: AstNode, parent?: AstNode, path?: NodePath) => void,\n options?: VisitOptions,\n): void {\n visitInternal(node, callback, undefined, [], 0, options?.trackPath ?? true);\n}\n\nexport function map(node: AstNode, fn: (node: AstNode) => AstNode, _depth: number = 0): AstNode {\n if (_depth > MAX_DEPTH) {\n throw new TraversalDepthError(_depth);\n }\n const mapped = fn(node);\n const children = getChildren(mapped);\n if (children.length === 0) return mapped;\n\n const newChildren = children.map((child) => map(child, fn, _depth + 1));\n const changed = newChildren.some((c, i) => c !== children[i]);\n if (!changed) return mapped;\n\n switch (mapped.type) {\n case 'doc':\n return { ...mapped, content: newChildren as BlockNode[] };\n case 'blockquote':\n case 'listItem':\n case 'noteBlock':\n return { ...mapped, content: newChildren as BlockNode[] };\n case 'paragraph':\n case 'heading':\n return { ...mapped, content: newChildren as InlineNode[] };\n case 'bulletList':\n return { ...mapped, content: newChildren as typeof mapped.content };\n case 'orderedList':\n return { ...mapped, content: newChildren as typeof mapped.content };\n case 'jinjaIfBlock': {\n const jNode = mapped as JinjaIfBlockNode;\n let offset = 0;\n const newBranches = jNode.branches.map(b => {\n const slice = newChildren.slice(offset, offset + b.content.length) as BlockNode[];\n offset += b.content.length;\n return { ...b, content: slice };\n });\n return { ...jNode, branches: newBranches };\n }\n case 'jinjaIfInline': {\n const jNode = mapped as JinjaIfInlineNode;\n let offset = 0;\n const newBranches = jNode.branches.map(b => {\n const slice = newChildren.slice(offset, offset + b.content.length) as InlineNode[];\n offset += b.content.length;\n return { ...b, content: slice };\n });\n return { ...jNode, branches: newBranches };\n }\n default:\n return mapped;\n }\n}\n\nexport function textContent(node: AstNode, _depth: number = 0): string {\n if (_depth > MAX_DEPTH) {\n throw new TraversalDepthError(_depth);\n }\n switch (node.type) {\n case 'text':\n return node.text;\n case 'resourceTag':\n return node.text;\n case 'jumpPoint':\n return `^${node.id}^`;\n case 'hardBreak':\n return '\\n';\n case 'jinjaIfInline': {\n // Reconstruct original {% %} text for analyzer compatibility\n let out = '';\n for (const branch of node.branches) {\n if (branch.branchType === 'if') out += `{% if ${branch.condition} %}`;\n else if (branch.branchType === 'elif') out += `{% elif ${branch.condition} %}`;\n else out += '{% else %}';\n for (const child of branch.content) out += textContent(child, _depth + 1);\n }\n out += '{% endif %}';\n return out;\n }\n case 'horizontalRule':\n return '';\n default: {\n const children = getChildren(node);\n let out = '';\n for (const child of children) out += textContent(child, _depth + 1);\n return out;\n }\n }\n}\n\nexport function findAll(node: AstNode, predicate: (n: AstNode) => boolean): AstNode[] {\n const results: AstNode[] = [];\n visit(node, (n) => {\n if (predicate(n)) results.push(n);\n }, { trackPath: false });\n return results;\n}\n\nexport function nodeAtPath(root: DocumentNode, path: NodePath): AstNode | undefined {\n if (path.length > MAX_DEPTH) {\n throw new TraversalDepthError(path.length);\n }\n let current: AstNode = root;\n for (const index of path) {\n const children = getChildren(current);\n if (index < 0 || index >= children.length) return undefined;\n current = children[index];\n }\n return current;\n}\n","import { fromMarkdown } from 'mdast-util-from-markdown';\nimport { combineExtensions } from 'micromark-util-combine-extensions';\nimport { gfmFootnote } from 'micromark-extension-gfm-footnote';\nimport { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough';\nimport { gfmTable } from 'micromark-extension-gfm-table';\nimport { gfmTaskListItem } from 'micromark-extension-gfm-task-list-item';\nimport { gfmFootnoteFromMarkdown } from 'mdast-util-gfm-footnote';\nimport { gfmStrikethroughFromMarkdown } from 'mdast-util-gfm-strikethrough';\nimport { gfmTableFromMarkdown } from 'mdast-util-gfm-table';\nimport { gfmTaskListItemFromMarkdown } from 'mdast-util-gfm-task-list-item';\nimport { splitTextWithResourceTags } from './plugins/resourceTag';\nimport { splitTextWithJumpPoints } from './plugins/jumpPoint';\nimport type { ResourceTagMdastNode } from './plugins/resourceTag';\nimport type { JumpPointMdastNode } from './plugins/jumpPoint';\nimport { fromMdast } from './mdastAdapter';\nimport { jinjaBlockTransform } from './plugins/jinjaBlock';\nimport type { DocumentNode } from '../ast/types';\nimport type { Link, Root, Text } from 'mdast';\n\nexport interface ParseMarkdownOptions {\n jinjaNodes?: boolean;\n}\n\n// GFM without autolink literal — autolink literal converts escaped emails/URLs\n// (e.g. bookings\\@flynorse.com) into link nodes during the mdast transform pass,\n// which then serialize as <bookings@flynorse.com> instead of preserving the\n// original backslash escaping.\nconst gfmNoAutolink = () =>\n combineExtensions([gfmFootnote(), gfmStrikethrough(), gfmTable(), gfmTaskListItem()]);\n\nconst gfmNoAutolinkFromMarkdown = () => [\n gfmFootnoteFromMarkdown(),\n gfmStrikethroughFromMarkdown(),\n gfmTableFromMarkdown(),\n gfmTaskListItemFromMarkdown(),\n];\n\nconst MAX_DEPTH = 128;\n\ntype CustomNode = ResourceTagMdastNode | JumpPointMdastNode;\n\n/**\n * Recover markdown links that micromark failed to parse because the URL\n * contains spaces (e.g. `[Go to #Wrap up](#Wrap up)`). CommonMark requires\n * `<>` around such URLs, but tiptap-markdown emits the bare form.\n */\nconst BRACKET_LINK_RE = /\\[([^\\]]+)\\]\\(([^)]*\\s[^)]*)\\)/g;\n\nfunction splitTextWithBracketLinks(value: string): Array<Text | Link> {\n const results: Array<Text | Link> = [];\n let lastIndex = 0;\n for (const m of value.matchAll(BRACKET_LINK_RE)) {\n const idx = m.index!;\n if (idx > lastIndex) results.push({ type: 'text', value: value.slice(lastIndex, idx) } as Text);\n results.push({\n type: 'link',\n url: m[2],\n children: [{ type: 'text', value: m[1] } as Text],\n } as Link);\n lastIndex = idx + m[0].length;\n }\n if (lastIndex < value.length) results.push({ type: 'text', value: value.slice(lastIndex) } as Text);\n return results;\n}\n\n/**\n * Combined single-pass transform for resource tags and jump points.\n * Each text node is scanned for both patterns in one iteration,\n * avoiding two separate full-tree traversals.\n */\nfunction combinedTokensFromMarkdown(node: { children?: unknown[] }, depth: number = 0): void {\n if (depth > MAX_DEPTH) return;\n if (!node.children) return;\n for (const child of node.children) {\n combinedTokensFromMarkdown(child as { children?: unknown[] }, depth + 1);\n }\n if (Array.isArray(node.children)) {\n const newChildren: unknown[] = [];\n for (const child of node.children) {\n const c = child as { type: string };\n if (c.type === 'text') {\n // Split pipeline: bracket links → resource tags → jump points\n const afterLinks = splitTextWithBracketLinks((child as Text).value);\n for (const linkPart of afterLinks) {\n if (linkPart.type !== 'text') { newChildren.push(linkPart); continue; }\n const afterResourceTags = splitTextWithResourceTags(linkPart.value);\n for (const part of afterResourceTags) {\n if (part.type === 'text') {\n const afterJumpPoints = splitTextWithJumpPoints(part.value);\n newChildren.push(...afterJumpPoints);\n } else {\n newChildren.push(part as unknown as CustomNode);\n }\n }\n }\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n}\n\nexport function parseMarkdown(markdown: string, options?: ParseMarkdownOptions): DocumentNode {\n const tree = fromMarkdown(markdown, {\n extensions: [gfmNoAutolink()],\n mdastExtensions: [gfmNoAutolinkFromMarkdown()],\n });\n\n // Single combined pass for resource tags and jump points\n combinedTokensFromMarkdown(tree as unknown as { children?: unknown[] });\n\n // Optional: transform Jinja tags into structured mdast nodes\n if (options?.jinjaNodes) {\n jinjaBlockTransform(tree as unknown as { type: string; children?: unknown[] });\n }\n\n return fromMdast(tree);\n}\n","/**\n * Like `Array#splice`, but smarter for giant arrays.\n *\n * `Array#splice` takes all items to be inserted as individual argument which\n * causes a stack overflow in V8 when trying to insert 100k items for instance.\n *\n * Otherwise, this does not return the removed items, and takes `items` as an\n * array instead of rest parameters.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array<T>} list\n * List to operate on.\n * @param {number} start\n * Index to remove/insert at (can be negative).\n * @param {number} remove\n * Number of items to remove.\n * @param {Array<T>} items\n * Items to inject into `list`.\n * @returns {undefined}\n * Nothing.\n */\nexport function splice(list, start, remove, items) {\n const end = list.length;\n let chunkStart = 0;\n /** @type {Array<unknown>} */\n let parameters;\n\n // Make start between zero and `end` (included).\n if (start < 0) {\n start = -start > end ? 0 : end + start;\n } else {\n start = start > end ? end : start;\n }\n remove = remove > 0 ? remove : 0;\n\n // No need to chunk the items if there’s only a couple (10k) items.\n if (items.length < 10000) {\n parameters = Array.from(items);\n parameters.unshift(start, remove);\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters);\n } else {\n // Delete `remove` items starting from `start`\n if (remove) list.splice(start, remove);\n\n // Insert the items in chunks to not cause stack overflows.\n while (chunkStart < items.length) {\n parameters = items.slice(chunkStart, chunkStart + 10000);\n parameters.unshift(start, 0);\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters);\n chunkStart += 10000;\n start += 10000;\n }\n }\n}\n\n/**\n * Append `items` (an array) at the end of `list` (another array).\n * When `list` was empty, returns `items` instead.\n *\n * This prevents a potentially expensive operation when `list` is empty,\n * and adds items in batches to prevent V8 from hanging.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array<T>} list\n * List to operate on.\n * @param {Array<T>} items\n * Items to add to `list`.\n * @returns {Array<T>}\n * Either `list` or `items`.\n */\nexport function push(list, items) {\n if (list.length > 0) {\n splice(list, list.length, 0, items);\n return list;\n }\n return items;\n}","/**\n * @import {\n * Extension,\n * Handles,\n * HtmlExtension,\n * NormalizedExtension\n * } from 'micromark-util-types'\n */\n\nimport {splice} from 'micromark-util-chunked'\n\nconst hasOwnProperty = {}.hasOwnProperty\n\n/**\n * Combine multiple syntax extensions into one.\n *\n * @param {ReadonlyArray<Extension>} extensions\n * List of syntax extensions.\n * @returns {NormalizedExtension}\n * A single combined extension.\n */\nexport function combineExtensions(extensions) {\n /** @type {NormalizedExtension} */\n const all = {}\n let index = -1\n\n while (++index < extensions.length) {\n syntaxExtension(all, extensions[index])\n }\n\n return all\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {NormalizedExtension} all\n * Extension to merge into.\n * @param {Extension} extension\n * Extension to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction syntaxExtension(all, extension) {\n /** @type {keyof Extension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n /** @type {Record<string, unknown>} */\n const left = maybe || (all[hook] = {})\n /** @type {Record<string, unknown> | undefined} */\n const right = extension[hook]\n /** @type {string} */\n let code\n\n if (right) {\n for (code in right) {\n if (!hasOwnProperty.call(left, code)) left[code] = []\n const value = right[code]\n constructs(\n // @ts-expect-error Looks like a list.\n left[code],\n Array.isArray(value) ? value : value ? [value] : []\n )\n }\n }\n }\n}\n\n/**\n * Merge `list` into `existing` (both lists of constructs).\n * Mutates `existing`.\n *\n * @param {Array<unknown>} existing\n * List of constructs to merge into.\n * @param {Array<unknown>} list\n * List of constructs to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction constructs(existing, list) {\n let index = -1\n /** @type {Array<unknown>} */\n const before = []\n\n while (++index < list.length) {\n // @ts-expect-error Looks like an object.\n ;(list[index].add === 'after' ? existing : before).push(list[index])\n }\n\n splice(existing, 0, 0, before)\n}\n\n/**\n * Combine multiple HTML extensions into one.\n *\n * @param {ReadonlyArray<HtmlExtension>} htmlExtensions\n * List of HTML extensions.\n * @returns {HtmlExtension}\n * Single combined HTML extension.\n */\nexport function combineHtmlExtensions(htmlExtensions) {\n /** @type {HtmlExtension} */\n const handlers = {}\n let index = -1\n\n while (++index < htmlExtensions.length) {\n htmlExtension(handlers, htmlExtensions[index])\n }\n\n return handlers\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {HtmlExtension} all\n * Extension to merge into.\n * @param {HtmlExtension} extension\n * Extension to merge.\n * @returns {undefined}\n * Nothing.\n */\nfunction htmlExtension(all, extension) {\n /** @type {keyof HtmlExtension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n const left = maybe || (all[hook] = {})\n const right = extension[hook]\n /** @type {keyof Handles} */\n let type\n\n if (right) {\n for (type in right) {\n // @ts-expect-error assume document vs regular handler are managed correctly.\n left[type] = right[type]\n }\n }\n }\n}\n","/**\n * @import {Code} from 'micromark-util-types'\n */\n\nimport { markdownLineEndingOrSpace, unicodePunctuation, unicodeWhitespace } from 'micromark-util-character';\n/**\n * Classify whether a code represents whitespace, punctuation, or something\n * else.\n *\n * Used for attention (emphasis, strong), whose sequences can open or close\n * based on the class of surrounding characters.\n *\n * > 👉 **Note**: eof (`null`) is seen as whitespace.\n *\n * @param {Code} code\n * Code.\n * @returns {typeof constants.characterGroupWhitespace | typeof constants.characterGroupPunctuation | undefined}\n * Group.\n */\nexport function classifyCharacter(code) {\n if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) {\n return 1;\n }\n if (unicodePunctuation(code)) {\n return 2;\n }\n}","/**\n * @import {Event, Resolver, TokenizeContext} from 'micromark-util-types'\n */\n\n/**\n * Call all `resolveAll`s.\n *\n * @param {ReadonlyArray<{resolveAll?: Resolver | undefined}>} constructs\n * List of constructs, optionally with `resolveAll`s.\n * @param {Array<Event>} events\n * List of events.\n * @param {TokenizeContext} context\n * Context used by `tokenize`.\n * @returns {Array<Event>}\n * Changed events.\n */\nexport function resolveAll(constructs, events, context) {\n /** @type {Array<Resolver>} */\n const called = []\n let index = -1\n\n while (++index < constructs.length) {\n const resolve = constructs[index].resolveAll\n\n if (resolve && !called.includes(resolve)) {\n events = resolve(events, context)\n called.push(resolve)\n }\n }\n\n return events\n}\n","/**\n * @import {Effects, State, TokenType} from 'micromark-util-types'\n */\n\nimport { markdownSpace } from 'micromark-util-character';\n\n// To do: implement `spaceOrTab`, `spaceOrTabMinMax`, `spaceOrTabWithOptions`.\n\n/**\n * Parse spaces and tabs.\n *\n * There is no `nok` parameter:\n *\n * * spaces in markdown are often optional, in which case this factory can be\n * used and `ok` will be switched to whether spaces were found or not\n * * one line ending or space can be detected with `markdownSpace(code)` right\n * before using `factorySpace`\n *\n * ###### Examples\n *\n * Where `␉` represents a tab (plus how much it expands) and `␠` represents a\n * single space.\n *\n * ```markdown\n * ␉\n * ␠␠␠␠\n * ␉␠\n * ```\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {TokenType} type\n * Type (`' \\t'`).\n * @param {number | undefined} [max=Infinity]\n * Max (exclusive).\n * @returns {State}\n * Start state.\n */\nexport function factorySpace(effects, ok, type, max) {\n const limit = max ? max - 1 : Number.POSITIVE_INFINITY;\n let size = 0;\n return start;\n\n /** @type {State} */\n function start(code) {\n if (markdownSpace(code)) {\n effects.enter(type);\n return prefix(code);\n }\n return ok(code);\n }\n\n /** @type {State} */\n function prefix(code) {\n if (markdownSpace(code) && size++ < limit) {\n effects.consume(code);\n return prefix;\n }\n effects.exit(type);\n return ok(code);\n }\n}","/**\n * @import {\n * Construct,\n * State,\n * TokenizeContext,\n * Tokenizer\n * } from 'micromark-util-types'\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownSpace } from 'micromark-util-character';\n/** @type {Construct} */\nexport const blankLine = {\n partial: true,\n tokenize: tokenizeBlankLine\n};\n\n/**\n * @this {TokenizeContext}\n * Context.\n * @type {Tokenizer}\n */\nfunction tokenizeBlankLine(effects, ok, nok) {\n return start;\n\n /**\n * Start of blank line.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n return markdownSpace(code) ? factorySpace(effects, after, \"linePrefix\")(code) : after(code);\n }\n\n /**\n * At eof/eol, after optional whitespace.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n return code === null || markdownLineEnding(code) ? ok(code) : nok(code);\n }\n}","/**\n * @import {Event, Exiter, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { blankLine } from 'micromark-core-commonmark';\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEndingOrSpace } from 'micromark-util-character';\nimport { normalizeIdentifier } from 'micromark-util-normalize-identifier';\nconst indent = {\n tokenize: tokenizeIndent,\n partial: true\n};\n\n// To do: micromark should support a `_hiddenGfmFootnoteSupport`, which only\n// affects label start (image).\n// That will let us drop `tokenizePotentialGfmFootnote*`.\n// It currently has a `_hiddenFootnoteSupport`, which affects that and more.\n// That can be removed when `micromark-extension-footnote` is archived.\n\n/**\n * Create an extension for `micromark` to enable GFM footnote syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions` to\n * enable GFM footnote syntax.\n */\nexport function gfmFootnote() {\n /** @type {Extension} */\n return {\n document: {\n [91]: {\n name: 'gfmFootnoteDefinition',\n tokenize: tokenizeDefinitionStart,\n continuation: {\n tokenize: tokenizeDefinitionContinuation\n },\n exit: gfmFootnoteDefinitionEnd\n }\n },\n text: {\n [91]: {\n name: 'gfmFootnoteCall',\n tokenize: tokenizeGfmFootnoteCall\n },\n [93]: {\n name: 'gfmPotentialFootnoteCall',\n add: 'after',\n tokenize: tokenizePotentialGfmFootnoteCall,\n resolveTo: resolveToPotentialGfmFootnoteCall\n }\n }\n };\n}\n\n// To do: remove after micromark update.\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizePotentialGfmFootnoteCall(effects, ok, nok) {\n const self = this;\n let index = self.events.length;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n /** @type {Token} */\n let labelStart;\n\n // Find an opening.\n while (index--) {\n const token = self.events[index][1];\n if (token.type === \"labelImage\") {\n labelStart = token;\n break;\n }\n\n // Exit if we’ve walked far enough.\n if (token.type === 'gfmFootnoteCall' || token.type === \"labelLink\" || token.type === \"label\" || token.type === \"image\" || token.type === \"link\") {\n break;\n }\n }\n return start;\n\n /**\n * @type {State}\n */\n function start(code) {\n if (!labelStart || !labelStart._balanced) {\n return nok(code);\n }\n const id = normalizeIdentifier(self.sliceSerialize({\n start: labelStart.end,\n end: self.now()\n }));\n if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) {\n return nok(code);\n }\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n return ok(code);\n }\n}\n\n// To do: remove after micromark update.\n/** @type {Resolver} */\nfunction resolveToPotentialGfmFootnoteCall(events, context) {\n let index = events.length;\n /** @type {Token | undefined} */\n let labelStart;\n\n // Find an opening.\n while (index--) {\n if (events[index][1].type === \"labelImage\" && events[index][0] === 'enter') {\n labelStart = events[index][1];\n break;\n }\n }\n // Change the `labelImageMarker` to a `data`.\n events[index + 1][1].type = \"data\";\n events[index + 3][1].type = 'gfmFootnoteCallLabelMarker';\n\n // The whole (without `!`):\n /** @type {Token} */\n const call = {\n type: 'gfmFootnoteCall',\n start: Object.assign({}, events[index + 3][1].start),\n end: Object.assign({}, events[events.length - 1][1].end)\n };\n // The `^` marker\n /** @type {Token} */\n const marker = {\n type: 'gfmFootnoteCallMarker',\n start: Object.assign({}, events[index + 3][1].end),\n end: Object.assign({}, events[index + 3][1].end)\n };\n // Increment the end 1 character.\n marker.end.column++;\n marker.end.offset++;\n marker.end._bufferIndex++;\n /** @type {Token} */\n const string = {\n type: 'gfmFootnoteCallString',\n start: Object.assign({}, marker.end),\n end: Object.assign({}, events[events.length - 1][1].start)\n };\n /** @type {Token} */\n const chunk = {\n type: \"chunkString\",\n contentType: 'string',\n start: Object.assign({}, string.start),\n end: Object.assign({}, string.end)\n };\n\n /** @type {Array<Event>} */\n const replacement = [\n // Take the `labelImageMarker` (now `data`, the `!`)\n events[index + 1], events[index + 2], ['enter', call, context],\n // The `[`\n events[index + 3], events[index + 4],\n // The `^`.\n ['enter', marker, context], ['exit', marker, context],\n // Everything in between.\n ['enter', string, context], ['enter', chunk, context], ['exit', chunk, context], ['exit', string, context],\n // The ending (`]`, properly parsed and labelled).\n events[events.length - 2], events[events.length - 1], ['exit', call, context]];\n events.splice(index, events.length - index + 1, ...replacement);\n return events;\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeGfmFootnoteCall(effects, ok, nok) {\n const self = this;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n let size = 0;\n /** @type {boolean} */\n let data;\n\n // Note: the implementation of `markdown-rs` is different, because it houses\n // core *and* extensions in one project.\n // Therefore, it can include footnote logic inside `label-end`.\n // We can’t do that, but luckily, we can parse footnotes in a simpler way than\n // needed for labels.\n return start;\n\n /**\n * Start of footnote label.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n effects.enter('gfmFootnoteCall');\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n return callStart;\n }\n\n /**\n * After `[`, at `^`.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function callStart(code) {\n if (code !== 94) return nok(code);\n effects.enter('gfmFootnoteCallMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallMarker');\n effects.enter('gfmFootnoteCallString');\n effects.enter('chunkString').contentType = 'string';\n return callData;\n }\n\n /**\n * In label.\n *\n * ```markdown\n * > | a [^b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function callData(code) {\n if (\n // Too long.\n size > 999 ||\n // Closing brace with nothing.\n code === 93 && !data ||\n // Space or tab is not supported by GFM for some reason.\n // `\\n` and `[` not being supported makes sense.\n code === null || code === 91 || markdownLineEndingOrSpace(code)) {\n return nok(code);\n }\n if (code === 93) {\n effects.exit('chunkString');\n const token = effects.exit('gfmFootnoteCallString');\n if (!defined.includes(normalizeIdentifier(self.sliceSerialize(token)))) {\n return nok(code);\n }\n effects.enter('gfmFootnoteCallLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteCallLabelMarker');\n effects.exit('gfmFootnoteCall');\n return ok;\n }\n if (!markdownLineEndingOrSpace(code)) {\n data = true;\n }\n size++;\n effects.consume(code);\n return code === 92 ? callEscape : callData;\n }\n\n /**\n * On character after escape.\n *\n * ```markdown\n * > | a [^b\\c] d\n * ^\n * ```\n *\n * @type {State}\n */\n function callEscape(code) {\n if (code === 91 || code === 92 || code === 93) {\n effects.consume(code);\n size++;\n return callData;\n }\n return callData(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeDefinitionStart(effects, ok, nok) {\n const self = this;\n const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);\n /** @type {string} */\n let identifier;\n let size = 0;\n /** @type {boolean | undefined} */\n let data;\n return start;\n\n /**\n * Start of GFM footnote definition.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n effects.enter('gfmFootnoteDefinition')._container = true;\n effects.enter('gfmFootnoteDefinitionLabel');\n effects.enter('gfmFootnoteDefinitionLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionLabelMarker');\n return labelAtMarker;\n }\n\n /**\n * In label, at caret.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelAtMarker(code) {\n if (code === 94) {\n effects.enter('gfmFootnoteDefinitionMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionMarker');\n effects.enter('gfmFootnoteDefinitionLabelString');\n effects.enter('chunkString').contentType = 'string';\n return labelInside;\n }\n return nok(code);\n }\n\n /**\n * In label.\n *\n * > 👉 **Note**: `cmark-gfm` prevents whitespace from occurring in footnote\n * > definition labels.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelInside(code) {\n if (\n // Too long.\n size > 999 ||\n // Closing brace with nothing.\n code === 93 && !data ||\n // Space or tab is not supported by GFM for some reason.\n // `\\n` and `[` not being supported makes sense.\n code === null || code === 91 || markdownLineEndingOrSpace(code)) {\n return nok(code);\n }\n if (code === 93) {\n effects.exit('chunkString');\n const token = effects.exit('gfmFootnoteDefinitionLabelString');\n identifier = normalizeIdentifier(self.sliceSerialize(token));\n effects.enter('gfmFootnoteDefinitionLabelMarker');\n effects.consume(code);\n effects.exit('gfmFootnoteDefinitionLabelMarker');\n effects.exit('gfmFootnoteDefinitionLabel');\n return labelAfter;\n }\n if (!markdownLineEndingOrSpace(code)) {\n data = true;\n }\n size++;\n effects.consume(code);\n return code === 92 ? labelEscape : labelInside;\n }\n\n /**\n * After `\\`, at a special character.\n *\n * > 👉 **Note**: `cmark-gfm` currently does not support escaped brackets:\n * > <https://github.com/github/cmark-gfm/issues/240>\n *\n * ```markdown\n * > | [^a\\*b]: c\n * ^\n * ```\n *\n * @type {State}\n */\n function labelEscape(code) {\n if (code === 91 || code === 92 || code === 93) {\n effects.consume(code);\n size++;\n return labelInside;\n }\n return labelInside(code);\n }\n\n /**\n * After definition label.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelAfter(code) {\n if (code === 58) {\n effects.enter('definitionMarker');\n effects.consume(code);\n effects.exit('definitionMarker');\n if (!defined.includes(identifier)) {\n defined.push(identifier);\n }\n\n // Any whitespace after the marker is eaten, forming indented code\n // is not possible.\n // No space is also fine, just like a block quote marker.\n return factorySpace(effects, whitespaceAfter, 'gfmFootnoteDefinitionWhitespace');\n }\n return nok(code);\n }\n\n /**\n * After definition prefix.\n *\n * ```markdown\n * > | [^a]: b\n * ^\n * ```\n *\n * @type {State}\n */\n function whitespaceAfter(code) {\n // `markdown-rs` has a wrapping token for the prefix that is closed here.\n return ok(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeDefinitionContinuation(effects, ok, nok) {\n /// Start of footnote definition continuation.\n ///\n /// ```markdown\n /// | [^a]: b\n /// > | c\n /// ^\n /// ```\n //\n // Either a blank line, which is okay, or an indented thing.\n return effects.check(blankLine, ok, effects.attempt(indent, ok, nok));\n}\n\n/** @type {Exiter} */\nfunction gfmFootnoteDefinitionEnd(effects) {\n effects.exit('gfmFootnoteDefinition');\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeIndent(effects, ok, nok) {\n const self = this;\n return factorySpace(effects, afterPrefix, 'gfmFootnoteDefinitionIndent', 4 + 1);\n\n /**\n * @type {State}\n */\n function afterPrefix(code) {\n const tail = self.events[self.events.length - 1];\n return tail && tail[1].type === 'gfmFootnoteDefinitionIndent' && tail[2].sliceSerialize(tail[1], true).length === 4 ? ok(code) : nok(code);\n }\n}","/**\n * @import {Options} from 'micromark-extension-gfm-strikethrough'\n * @import {Event, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { splice } from 'micromark-util-chunked';\nimport { classifyCharacter } from 'micromark-util-classify-character';\nimport { resolveAll } from 'micromark-util-resolve-all';\n/**\n * Create an extension for `micromark` to enable GFM strikethrough syntax.\n *\n * @param {Options | null | undefined} [options={}]\n * Configuration.\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions`, to\n * enable GFM strikethrough syntax.\n */\nexport function gfmStrikethrough(options) {\n const options_ = options || {};\n let single = options_.singleTilde;\n const tokenizer = {\n name: 'strikethrough',\n tokenize: tokenizeStrikethrough,\n resolveAll: resolveAllStrikethrough\n };\n if (single === null || single === undefined) {\n single = true;\n }\n return {\n text: {\n [126]: tokenizer\n },\n insideSpan: {\n null: [tokenizer]\n },\n attentionMarkers: {\n null: [126]\n }\n };\n\n /**\n * Take events and resolve strikethrough.\n *\n * @type {Resolver}\n */\n function resolveAllStrikethrough(events, context) {\n let index = -1;\n\n // Walk through all events.\n while (++index < events.length) {\n // Find a token that can close.\n if (events[index][0] === 'enter' && events[index][1].type === 'strikethroughSequenceTemporary' && events[index][1]._close) {\n let open = index;\n\n // Now walk back to find an opener.\n while (open--) {\n // Find a token that can open the closer.\n if (events[open][0] === 'exit' && events[open][1].type === 'strikethroughSequenceTemporary' && events[open][1]._open &&\n // If the sizes are the same:\n events[index][1].end.offset - events[index][1].start.offset === events[open][1].end.offset - events[open][1].start.offset) {\n events[index][1].type = 'strikethroughSequence';\n events[open][1].type = 'strikethroughSequence';\n\n /** @type {Token} */\n const strikethrough = {\n type: 'strikethrough',\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[index][1].end)\n };\n\n /** @type {Token} */\n const text = {\n type: 'strikethroughText',\n start: Object.assign({}, events[open][1].end),\n end: Object.assign({}, events[index][1].start)\n };\n\n // Opening.\n /** @type {Array<Event>} */\n const nextEvents = [['enter', strikethrough, context], ['enter', events[open][1], context], ['exit', events[open][1], context], ['enter', text, context]];\n const insideSpan = context.parser.constructs.insideSpan.null;\n if (insideSpan) {\n // Between.\n splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));\n }\n\n // Closing.\n splice(nextEvents, nextEvents.length, 0, [['exit', text, context], ['enter', events[index][1], context], ['exit', events[index][1], context], ['exit', strikethrough, context]]);\n splice(events, open - 1, index - open + 3, nextEvents);\n index = open + nextEvents.length - 2;\n break;\n }\n }\n }\n }\n index = -1;\n while (++index < events.length) {\n if (events[index][1].type === 'strikethroughSequenceTemporary') {\n events[index][1].type = \"data\";\n }\n }\n return events;\n }\n\n /**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\n function tokenizeStrikethrough(effects, ok, nok) {\n const previous = this.previous;\n const events = this.events;\n let size = 0;\n return start;\n\n /** @type {State} */\n function start(code) {\n if (previous === 126 && events[events.length - 1][1].type !== \"characterEscape\") {\n return nok(code);\n }\n effects.enter('strikethroughSequenceTemporary');\n return more(code);\n }\n\n /** @type {State} */\n function more(code) {\n const before = classifyCharacter(previous);\n if (code === 126) {\n // If this is the third marker, exit.\n if (size > 1) return nok(code);\n effects.consume(code);\n size++;\n return more;\n }\n if (size < 2 && !single) return nok(code);\n const token = effects.exit('strikethroughSequenceTemporary');\n const after = classifyCharacter(code);\n token._open = !after || after === 2 && Boolean(before);\n token._close = !before || before === 2 && Boolean(after);\n return ok(code);\n }\n }\n}","/**\n * @import {Event, Extension, Point, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\n/**\n * @typedef {[number, number, number, number]} Range\n * Cell info.\n *\n * @typedef {0 | 1 | 2 | 3} RowKind\n * Where we are: `1` for head row, `2` for delimiter row, `3` for body row.\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace } from 'micromark-util-character';\nimport { EditMap } from './edit-map.js';\nimport { gfmTableAlign } from './infer.js';\n\n/**\n * Create an HTML extension for `micromark` to support GitHub tables syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `extensions` to enable GFM\n * table syntax.\n */\nexport function gfmTable() {\n return {\n flow: {\n null: {\n name: 'table',\n tokenize: tokenizeTable,\n resolveAll: resolveTable\n }\n }\n };\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeTable(effects, ok, nok) {\n const self = this;\n let size = 0;\n let sizeB = 0;\n /** @type {boolean | undefined} */\n let seen;\n return start;\n\n /**\n * Start of a GFM table.\n *\n * If there is a valid table row or table head before, then we try to parse\n * another row.\n * Otherwise, we try to parse a head.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * > | | b |\n * ^\n * ```\n * @type {State}\n */\n function start(code) {\n let index = self.events.length - 1;\n while (index > -1) {\n const type = self.events[index][1].type;\n if (type === \"lineEnding\" ||\n // Note: markdown-rs uses `whitespace` instead of `linePrefix`\n type === \"linePrefix\") index--;else break;\n }\n const tail = index > -1 ? self.events[index][1].type : null;\n const next = tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore;\n\n // Don’t allow lazy body rows.\n if (next === bodyRowStart && self.parser.lazy[self.now().line]) {\n return nok(code);\n }\n return next(code);\n }\n\n /**\n * Before table head row.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowBefore(code) {\n effects.enter('tableHead');\n effects.enter('tableRow');\n return headRowStart(code);\n }\n\n /**\n * Before table head row, after whitespace.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowStart(code) {\n if (code === 124) {\n return headRowBreak(code);\n }\n\n // To do: micromark-js should let us parse our own whitespace in extensions,\n // like `markdown-rs`:\n //\n // ```js\n // // 4+ spaces.\n // if (markdownSpace(code)) {\n // return nok(code)\n // }\n // ```\n\n seen = true;\n // Count the first character, that isn’t a pipe, double.\n sizeB += 1;\n return headRowBreak(code);\n }\n\n /**\n * At break in table head row.\n *\n * ```markdown\n * > | | a |\n * ^\n * ^\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowBreak(code) {\n if (code === null) {\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n if (markdownLineEnding(code)) {\n // If anything other than one pipe (ignoring whitespace) was used, it’s fine.\n if (sizeB > 1) {\n sizeB = 0;\n // To do: check if this works.\n // Feel free to interrupt:\n self.interrupt = true;\n effects.exit('tableRow');\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return headDelimiterStart;\n }\n\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n if (markdownSpace(code)) {\n // To do: check if this is fine.\n // effects.attempt(State::Next(StateName::GfmTableHeadRowBreak), State::Nok)\n // State::Retry(space_or_tab(tokenizer))\n return factorySpace(effects, headRowBreak, \"whitespace\")(code);\n }\n sizeB += 1;\n if (seen) {\n seen = false;\n // Header cell count.\n size += 1;\n }\n if (code === 124) {\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n // Whether a delimiter was seen.\n seen = true;\n return headRowBreak;\n }\n\n // Anything else is cell data.\n effects.enter(\"data\");\n return headRowData(code);\n }\n\n /**\n * In table head row data.\n *\n * ```markdown\n * > | | a |\n * ^\n * | | - |\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headRowData(code) {\n if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {\n effects.exit(\"data\");\n return headRowBreak(code);\n }\n effects.consume(code);\n return code === 92 ? headRowEscape : headRowData;\n }\n\n /**\n * In table head row escape.\n *\n * ```markdown\n * > | | a\\-b |\n * ^\n * | | ---- |\n * | | c |\n * ```\n *\n * @type {State}\n */\n function headRowEscape(code) {\n if (code === 92 || code === 124) {\n effects.consume(code);\n return headRowData;\n }\n return headRowData(code);\n }\n\n /**\n * Before delimiter row.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headDelimiterStart(code) {\n // Reset `interrupt`.\n self.interrupt = false;\n\n // Note: in `markdown-rs`, we need to handle piercing here too.\n if (self.parser.lazy[self.now().line]) {\n return nok(code);\n }\n effects.enter('tableDelimiterRow');\n // Track if we’ve seen a `:` or `|`.\n seen = false;\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterBefore, \"linePrefix\", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code);\n }\n return headDelimiterBefore(code);\n }\n\n /**\n * Before delimiter row, after optional whitespace.\n *\n * Reused when a `|` is found later, to parse another cell.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * | | b |\n * ```\n *\n * @type {State}\n */\n function headDelimiterBefore(code) {\n if (code === 45 || code === 58) {\n return headDelimiterValueBefore(code);\n }\n if (code === 124) {\n seen = true;\n // If we start with a pipe, we open a cell marker.\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n return headDelimiterCellBefore;\n }\n\n // More whitespace / empty row not allowed at start.\n return headDelimiterNok(code);\n }\n\n /**\n * After `|`, before delimiter cell.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterCellBefore(code) {\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterValueBefore, \"whitespace\")(code);\n }\n return headDelimiterValueBefore(code);\n }\n\n /**\n * Before delimiter cell value.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterValueBefore(code) {\n // Align: left.\n if (code === 58) {\n sizeB += 1;\n seen = true;\n effects.enter('tableDelimiterMarker');\n effects.consume(code);\n effects.exit('tableDelimiterMarker');\n return headDelimiterLeftAlignmentAfter;\n }\n\n // Align: none.\n if (code === 45) {\n sizeB += 1;\n // To do: seems weird that this *isn’t* left aligned, but that state is used?\n return headDelimiterLeftAlignmentAfter(code);\n }\n if (code === null || markdownLineEnding(code)) {\n return headDelimiterCellAfter(code);\n }\n return headDelimiterNok(code);\n }\n\n /**\n * After delimiter cell left alignment marker.\n *\n * ```markdown\n * | | a |\n * > | | :- |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterLeftAlignmentAfter(code) {\n if (code === 45) {\n effects.enter('tableDelimiterFiller');\n return headDelimiterFiller(code);\n }\n\n // Anything else is not ok after the left-align colon.\n return headDelimiterNok(code);\n }\n\n /**\n * In delimiter cell filler.\n *\n * ```markdown\n * | | a |\n * > | | - |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterFiller(code) {\n if (code === 45) {\n effects.consume(code);\n return headDelimiterFiller;\n }\n\n // Align is `center` if it was `left`, `right` otherwise.\n if (code === 58) {\n seen = true;\n effects.exit('tableDelimiterFiller');\n effects.enter('tableDelimiterMarker');\n effects.consume(code);\n effects.exit('tableDelimiterMarker');\n return headDelimiterRightAlignmentAfter;\n }\n effects.exit('tableDelimiterFiller');\n return headDelimiterRightAlignmentAfter(code);\n }\n\n /**\n * After delimiter cell right alignment marker.\n *\n * ```markdown\n * | | a |\n * > | | -: |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterRightAlignmentAfter(code) {\n if (markdownSpace(code)) {\n return factorySpace(effects, headDelimiterCellAfter, \"whitespace\")(code);\n }\n return headDelimiterCellAfter(code);\n }\n\n /**\n * After delimiter cell.\n *\n * ```markdown\n * | | a |\n * > | | -: |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterCellAfter(code) {\n if (code === 124) {\n return headDelimiterBefore(code);\n }\n if (code === null || markdownLineEnding(code)) {\n // Exit when:\n // * there was no `:` or `|` at all (it’s a thematic break or setext\n // underline instead)\n // * the header cell count is not the delimiter cell count\n if (!seen || size !== sizeB) {\n return headDelimiterNok(code);\n }\n\n // Note: in markdown-rs`, a reset is needed here.\n effects.exit('tableDelimiterRow');\n effects.exit('tableHead');\n // To do: in `markdown-rs`, resolvers need to be registered manually.\n // effects.register_resolver(ResolveName::GfmTable)\n return ok(code);\n }\n return headDelimiterNok(code);\n }\n\n /**\n * In delimiter row, at a disallowed byte.\n *\n * ```markdown\n * | | a |\n * > | | x |\n * ^\n * ```\n *\n * @type {State}\n */\n function headDelimiterNok(code) {\n // Note: in `markdown-rs`, we need to reset, in `micromark-js` we don‘t.\n return nok(code);\n }\n\n /**\n * Before table body row.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowStart(code) {\n // Note: in `markdown-rs` we need to manually take care of a prefix,\n // but in `micromark-js` that is done for us, so if we’re here, we’re\n // never at whitespace.\n effects.enter('tableRow');\n return bodyRowBreak(code);\n }\n\n /**\n * At break in table body row.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ^\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowBreak(code) {\n if (code === 124) {\n effects.enter('tableCellDivider');\n effects.consume(code);\n effects.exit('tableCellDivider');\n return bodyRowBreak;\n }\n if (code === null || markdownLineEnding(code)) {\n effects.exit('tableRow');\n return ok(code);\n }\n if (markdownSpace(code)) {\n return factorySpace(effects, bodyRowBreak, \"whitespace\")(code);\n }\n\n // Anything else is cell content.\n effects.enter(\"data\");\n return bodyRowData(code);\n }\n\n /**\n * In table body row data.\n *\n * ```markdown\n * | | a |\n * | | - |\n * > | | b |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowData(code) {\n if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {\n effects.exit(\"data\");\n return bodyRowBreak(code);\n }\n effects.consume(code);\n return code === 92 ? bodyRowEscape : bodyRowData;\n }\n\n /**\n * In table body row escape.\n *\n * ```markdown\n * | | a |\n * | | ---- |\n * > | | b\\-c |\n * ^\n * ```\n *\n * @type {State}\n */\n function bodyRowEscape(code) {\n if (code === 92 || code === 124) {\n effects.consume(code);\n return bodyRowData;\n }\n return bodyRowData(code);\n }\n}\n\n/** @type {Resolver} */\n\nfunction resolveTable(events, context) {\n let index = -1;\n let inFirstCellAwaitingPipe = true;\n /** @type {RowKind} */\n let rowKind = 0;\n /** @type {Range} */\n let lastCell = [0, 0, 0, 0];\n /** @type {Range} */\n let cell = [0, 0, 0, 0];\n let afterHeadAwaitingFirstBodyRow = false;\n let lastTableEnd = 0;\n /** @type {Token | undefined} */\n let currentTable;\n /** @type {Token | undefined} */\n let currentBody;\n /** @type {Token | undefined} */\n let currentCell;\n const map = new EditMap();\n while (++index < events.length) {\n const event = events[index];\n const token = event[1];\n if (event[0] === 'enter') {\n // Start of head.\n if (token.type === 'tableHead') {\n afterHeadAwaitingFirstBodyRow = false;\n\n // Inject previous (body end and) table end.\n if (lastTableEnd !== 0) {\n flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);\n currentBody = undefined;\n lastTableEnd = 0;\n }\n\n // Inject table start.\n currentTable = {\n type: 'table',\n start: Object.assign({}, token.start),\n // Note: correct end is set later.\n end: Object.assign({}, token.end)\n };\n map.add(index, 0, [['enter', currentTable, context]]);\n } else if (token.type === 'tableRow' || token.type === 'tableDelimiterRow') {\n inFirstCellAwaitingPipe = true;\n currentCell = undefined;\n lastCell = [0, 0, 0, 0];\n cell = [0, index + 1, 0, 0];\n\n // Inject table body start.\n if (afterHeadAwaitingFirstBodyRow) {\n afterHeadAwaitingFirstBodyRow = false;\n currentBody = {\n type: 'tableBody',\n start: Object.assign({}, token.start),\n // Note: correct end is set later.\n end: Object.assign({}, token.end)\n };\n map.add(index, 0, [['enter', currentBody, context]]);\n }\n rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1;\n }\n // Cell data.\n else if (rowKind && (token.type === \"data\" || token.type === 'tableDelimiterMarker' || token.type === 'tableDelimiterFiller')) {\n inFirstCellAwaitingPipe = false;\n\n // First value in cell.\n if (cell[2] === 0) {\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, undefined, currentCell);\n lastCell = [0, 0, 0, 0];\n }\n cell[2] = index;\n }\n } else if (token.type === 'tableCellDivider') {\n if (inFirstCellAwaitingPipe) {\n inFirstCellAwaitingPipe = false;\n } else {\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, undefined, currentCell);\n }\n lastCell = cell;\n cell = [lastCell[1], index, 0, 0];\n }\n }\n }\n // Exit events.\n else if (token.type === 'tableHead') {\n afterHeadAwaitingFirstBodyRow = true;\n lastTableEnd = index;\n } else if (token.type === 'tableRow' || token.type === 'tableDelimiterRow') {\n lastTableEnd = index;\n if (lastCell[1] !== 0) {\n cell[0] = cell[1];\n currentCell = flushCell(map, context, lastCell, rowKind, index, currentCell);\n } else if (cell[1] !== 0) {\n currentCell = flushCell(map, context, cell, rowKind, index, currentCell);\n }\n rowKind = 0;\n } else if (rowKind && (token.type === \"data\" || token.type === 'tableDelimiterMarker' || token.type === 'tableDelimiterFiller')) {\n cell[3] = index;\n }\n }\n if (lastTableEnd !== 0) {\n flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);\n }\n map.consume(context.events);\n\n // To do: move this into `html`, when events are exposed there.\n // That’s what `markdown-rs` does.\n // That needs updates to `mdast-util-gfm-table`.\n index = -1;\n while (++index < context.events.length) {\n const event = context.events[index];\n if (event[0] === 'enter' && event[1].type === 'table') {\n event[1]._align = gfmTableAlign(context.events, index);\n }\n }\n return events;\n}\n\n/**\n * Generate a cell.\n *\n * @param {EditMap} map\n * @param {Readonly<TokenizeContext>} context\n * @param {Readonly<Range>} range\n * @param {RowKind} rowKind\n * @param {number | undefined} rowEnd\n * @param {Token | undefined} previousCell\n * @returns {Token | undefined}\n */\n// eslint-disable-next-line max-params\nfunction flushCell(map, context, range, rowKind, rowEnd, previousCell) {\n // `markdown-rs` uses:\n // rowKind === 2 ? 'tableDelimiterCell' : 'tableCell'\n const groupName = rowKind === 1 ? 'tableHeader' : rowKind === 2 ? 'tableDelimiter' : 'tableData';\n // `markdown-rs` uses:\n // rowKind === 2 ? 'tableDelimiterCellValue' : 'tableCellText'\n const valueName = 'tableContent';\n\n // Insert an exit for the previous cell, if there is one.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- exit\n // ^^^^-- this cell\n // ```\n if (range[0] !== 0) {\n previousCell.end = Object.assign({}, getPoint(context.events, range[0]));\n map.add(range[0], 0, [['exit', previousCell, context]]);\n }\n\n // Insert enter of this cell.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- enter\n // ^^^^-- this cell\n // ```\n const now = getPoint(context.events, range[1]);\n previousCell = {\n type: groupName,\n start: Object.assign({}, now),\n // Note: correct end is set later.\n end: Object.assign({}, now)\n };\n map.add(range[1], 0, [['enter', previousCell, context]]);\n\n // Insert text start at first data start and end at last data end, and\n // remove events between.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- enter\n // ^-- exit\n // ^^^^-- this cell\n // ```\n if (range[2] !== 0) {\n const relatedStart = getPoint(context.events, range[2]);\n const relatedEnd = getPoint(context.events, range[3]);\n /** @type {Token} */\n const valueToken = {\n type: valueName,\n start: Object.assign({}, relatedStart),\n end: Object.assign({}, relatedEnd)\n };\n map.add(range[2], 0, [['enter', valueToken, context]]);\n if (rowKind !== 2) {\n // Fix positional info on remaining events\n const start = context.events[range[2]];\n const end = context.events[range[3]];\n start[1].end = Object.assign({}, end[1].end);\n start[1].type = \"chunkText\";\n start[1].contentType = \"text\";\n\n // Remove if needed.\n if (range[3] > range[2] + 1) {\n const a = range[2] + 1;\n const b = range[3] - range[2] - 1;\n map.add(a, b, []);\n }\n }\n map.add(range[3] + 1, 0, [['exit', valueToken, context]]);\n }\n\n // Insert an exit for the last cell, if at the row end.\n //\n // ```markdown\n // > | | aa | bb | cc |\n // ^-- exit\n // ^^^^^^-- this cell (the last one contains two “between” parts)\n // ```\n if (rowEnd !== undefined) {\n previousCell.end = Object.assign({}, getPoint(context.events, rowEnd));\n map.add(rowEnd, 0, [['exit', previousCell, context]]);\n previousCell = undefined;\n }\n return previousCell;\n}\n\n/**\n * Generate table end (and table body end).\n *\n * @param {Readonly<EditMap>} map\n * @param {Readonly<TokenizeContext>} context\n * @param {number} index\n * @param {Token} table\n * @param {Token | undefined} tableBody\n */\n// eslint-disable-next-line max-params\nfunction flushTableEnd(map, context, index, table, tableBody) {\n /** @type {Array<Event>} */\n const exits = [];\n const related = getPoint(context.events, index);\n if (tableBody) {\n tableBody.end = Object.assign({}, related);\n exits.push(['exit', tableBody, context]);\n }\n table.end = Object.assign({}, related);\n exits.push(['exit', table, context]);\n map.add(index + 1, 0, exits);\n}\n\n/**\n * @param {Readonly<Array<Event>>} events\n * @param {number} index\n * @returns {Readonly<Point>}\n */\nfunction getPoint(events, index) {\n const event = events[index];\n const side = event[0] === 'enter' ? 'start' : 'end';\n return event[1][side];\n}","/**\n * @import {Event} from 'micromark-util-types'\n */\n\n// Port of `edit_map.rs` from `markdown-rs`.\n// This should move to `markdown-js` later.\n\n// Deal with several changes in events, batching them together.\n//\n// Preferably, changes should be kept to a minimum.\n// Sometimes, it’s needed to change the list of events, because parsing can be\n// messy, and it helps to expose a cleaner interface of events to the compiler\n// and other users.\n// It can also help to merge many adjacent similar events.\n// And, in other cases, it’s needed to parse subcontent: pass some events\n// through another tokenizer and inject the result.\n\n/**\n * @typedef {[number, number, Array<Event>]} Change\n * @typedef {[number, number, number]} Jump\n */\n\n/**\n * Tracks a bunch of edits.\n */\nexport class EditMap {\n /**\n * Create a new edit map.\n */\n constructor() {\n /**\n * Record of changes.\n *\n * @type {Array<Change>}\n */\n this.map = [];\n }\n\n /**\n * Create an edit: a remove and/or add at a certain place.\n *\n * @param {number} index\n * @param {number} remove\n * @param {Array<Event>} add\n * @returns {undefined}\n */\n add(index, remove, add) {\n addImplementation(this, index, remove, add);\n }\n\n // To do: add this when moving to `micromark`.\n // /**\n // * Create an edit: but insert `add` before existing additions.\n // *\n // * @param {number} index\n // * @param {number} remove\n // * @param {Array<Event>} add\n // * @returns {undefined}\n // */\n // addBefore(index, remove, add) {\n // addImplementation(this, index, remove, add, true)\n // }\n\n /**\n * Done, change the events.\n *\n * @param {Array<Event>} events\n * @returns {undefined}\n */\n consume(events) {\n this.map.sort(function (a, b) {\n return a[0] - b[0];\n });\n\n /* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */\n if (this.map.length === 0) {\n return;\n }\n\n // To do: if links are added in events, like they are in `markdown-rs`,\n // this is needed.\n // // Calculate jumps: where items in the current list move to.\n // /** @type {Array<Jump>} */\n // const jumps = []\n // let index = 0\n // let addAcc = 0\n // let removeAcc = 0\n // while (index < this.map.length) {\n // const [at, remove, add] = this.map[index]\n // removeAcc += remove\n // addAcc += add.length\n // jumps.push([at, removeAcc, addAcc])\n // index += 1\n // }\n //\n // . shiftLinks(events, jumps)\n\n let index = this.map.length;\n /** @type {Array<Array<Event>>} */\n const vecs = [];\n while (index > 0) {\n index -= 1;\n vecs.push(events.slice(this.map[index][0] + this.map[index][1]), this.map[index][2]);\n\n // Truncate rest.\n events.length = this.map[index][0];\n }\n vecs.push(events.slice());\n events.length = 0;\n let slice = vecs.pop();\n while (slice) {\n for (const element of slice) {\n events.push(element);\n }\n slice = vecs.pop();\n }\n\n // Truncate everything.\n this.map.length = 0;\n }\n}\n\n/**\n * Create an edit.\n *\n * @param {EditMap} editMap\n * @param {number} at\n * @param {number} remove\n * @param {Array<Event>} add\n * @returns {undefined}\n */\nfunction addImplementation(editMap, at, remove, add) {\n let index = 0;\n\n /* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */\n if (remove === 0 && add.length === 0) {\n return;\n }\n while (index < editMap.map.length) {\n if (editMap.map[index][0] === at) {\n editMap.map[index][1] += remove;\n\n // To do: before not used by tables, use when moving to micromark.\n // if (before) {\n // add.push(...editMap.map[index][2])\n // editMap.map[index][2] = add\n // } else {\n editMap.map[index][2].push(...add);\n // }\n\n return;\n }\n index += 1;\n }\n editMap.map.push([at, remove, add]);\n}\n\n// /**\n// * Shift `previous` and `next` links according to `jumps`.\n// *\n// * This fixes links in case there are events removed or added between them.\n// *\n// * @param {Array<Event>} events\n// * @param {Array<Jump>} jumps\n// */\n// function shiftLinks(events, jumps) {\n// let jumpIndex = 0\n// let index = 0\n// let add = 0\n// let rm = 0\n\n// while (index < events.length) {\n// const rmCurr = rm\n\n// while (jumpIndex < jumps.length && jumps[jumpIndex][0] <= index) {\n// add = jumps[jumpIndex][2]\n// rm = jumps[jumpIndex][1]\n// jumpIndex += 1\n// }\n\n// // Ignore items that will be removed.\n// if (rm > rmCurr) {\n// index += rm - rmCurr\n// } else {\n// // ?\n// // if let Some(link) = &events[index].link {\n// // if let Some(next) = link.next {\n// // events[next].link.as_mut().unwrap().previous = Some(index + add - rm);\n// // while jumpIndex < jumps.len() && jumps[jumpIndex].0 <= next {\n// // add = jumps[jumpIndex].2;\n// // rm = jumps[jumpIndex].1;\n// // jumpIndex += 1;\n// // }\n// // events[index].link.as_mut().unwrap().next = Some(next + add - rm);\n// // index = next;\n// // continue;\n// // }\n// // }\n// index += 1\n// }\n// }\n// }","/**\n * @import {Event} from 'micromark-util-types'\n */\n\n/**\n * @typedef {'center' | 'left' | 'none' | 'right'} Align\n */\n\n/**\n * Figure out the alignment of a GFM table.\n *\n * @param {Readonly<Array<Event>>} events\n * List of events.\n * @param {number} index\n * Table enter event.\n * @returns {Array<Align>}\n * List of aligns.\n */\nexport function gfmTableAlign(events, index) {\n let inDelimiterRow = false;\n /** @type {Array<Align>} */\n const align = [];\n while (index < events.length) {\n const event = events[index];\n if (inDelimiterRow) {\n if (event[0] === 'enter') {\n // Start of alignment value: set a new column.\n // To do: `markdown-rs` uses `tableDelimiterCellValue`.\n if (event[1].type === 'tableContent') {\n align.push(events[index + 1][1].type === 'tableDelimiterMarker' ? 'left' : 'none');\n }\n }\n // Exits:\n // End of alignment value: change the column.\n // To do: `markdown-rs` uses `tableDelimiterCellValue`.\n else if (event[1].type === 'tableContent') {\n if (events[index - 1][1].type === 'tableDelimiterMarker') {\n const alignIndex = align.length - 1;\n align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right';\n }\n }\n // Done!\n else if (event[1].type === 'tableDelimiterRow') {\n break;\n }\n } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') {\n inDelimiterRow = true;\n }\n index += 1;\n }\n return align;\n}","/**\n * @import {Extension, State, TokenizeContext, Tokenizer} from 'micromark-util-types'\n */\n\nimport { factorySpace } from 'micromark-factory-space';\nimport { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace } from 'micromark-util-character';\nconst tasklistCheck = {\n name: 'tasklistCheck',\n tokenize: tokenizeTasklistCheck\n};\n\n/**\n * Create an HTML extension for `micromark` to support GFM task list items\n * syntax.\n *\n * @returns {Extension}\n * Extension for `micromark` that can be passed in `htmlExtensions` to\n * support GFM task list items when serializing to HTML.\n */\nexport function gfmTaskListItem() {\n return {\n text: {\n [91]: tasklistCheck\n }\n };\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeTasklistCheck(effects, ok, nok) {\n const self = this;\n return open;\n\n /**\n * At start of task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (\n // Exit if there’s stuff before.\n self.previous !== null ||\n // Exit if not in the first content that is the first child of a list\n // item.\n !self._gfmTasklistFirstContentOfListItem) {\n return nok(code);\n }\n effects.enter('taskListCheck');\n effects.enter('taskListCheckMarker');\n effects.consume(code);\n effects.exit('taskListCheckMarker');\n return inside;\n }\n\n /**\n * In task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n // Currently we match how GH works in files.\n // To match how GH works in comments, use `markdownSpace` (`[\\t ]`) instead\n // of `markdownLineEndingOrSpace` (`[\\t\\n\\r ]`).\n if (markdownLineEndingOrSpace(code)) {\n effects.enter('taskListCheckValueUnchecked');\n effects.consume(code);\n effects.exit('taskListCheckValueUnchecked');\n return close;\n }\n if (code === 88 || code === 120) {\n effects.enter('taskListCheckValueChecked');\n effects.consume(code);\n effects.exit('taskListCheckValueChecked');\n return close;\n }\n return nok(code);\n }\n\n /**\n * At close of task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function close(code) {\n if (code === 93) {\n effects.enter('taskListCheckMarker');\n effects.consume(code);\n effects.exit('taskListCheckMarker');\n effects.exit('taskListCheck');\n return after;\n }\n return nok(code);\n }\n\n /**\n * @type {State}\n */\n function after(code) {\n // EOL in paragraph means there must be something else after it.\n if (markdownLineEnding(code)) {\n return ok(code);\n }\n\n // Space or tab?\n // Check what comes after.\n if (markdownSpace(code)) {\n return effects.check({\n tokenize: spaceThenNonSpace\n }, ok, nok)(code);\n }\n\n // EOF, or non-whitespace, both wrong.\n return nok(code);\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction spaceThenNonSpace(effects, ok, nok) {\n return factorySpace(effects, after, \"whitespace\");\n\n /**\n * After whitespace, after task list item check.\n *\n * ```markdown\n * > | * [x] y.\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n // EOF means there was nothing, so bad.\n // EOL means there’s content after it, so good.\n // Impossible to have more spaces.\n // Anything else is good.\n return code === null ? nok(code) : ok(code);\n }\n}","/**\n * mdast transform plugin for Jinja if/elif/else/endif blocks.\n *\n * Three passes:\n * Pass 1 — Extract Jinja tags absorbed into list item text (Case B)\n * Pass 2 — Group standalone Jinja-tag paragraphs into jinjaIfBlockMdast nodes (Case A)\n * Pass 3 — Structure inline Jinja tags into jinjaIfInlineMdast nodes\n */\n\nconst MAX_DEPTH = 128;\n\n// Regex for a standalone Jinja tag paragraph (entire paragraph is one tag)\nconst JINJA_BLOCK_RE = /^\\s*\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}\\s*$/;\n\n// Regex for Jinja tags at line boundaries inside list item text\nconst JINJA_LINE_END_RE = /\\n\\s*(\\{%\\s*(?:if|elif|else|endif)\\s*[^%]*?\\s*%\\})\\s*$/;\nconst JINJA_LINE_START_RE = /^(\\{%\\s*(?:if|elif|else|endif)\\s*[^%]*?\\s*%\\})\\s*\\n/;\n\n// Regex for inline Jinja tags (non-greedy, captures tag type and condition)\nconst JINJA_INLINE_RE = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\ntype BranchType = 'if' | 'elif' | 'else';\n\nexport interface JinjaBranchMdast {\n branchType: BranchType;\n condition?: string;\n content: unknown[];\n}\n\nexport interface JinjaIfBlockMdastNode {\n type: 'jinjaIfBlockMdast';\n branches: JinjaBranchMdast[];\n}\n\nexport interface JinjaIfInlineMdastNode {\n type: 'jinjaIfInlineMdast';\n branches: JinjaBranchMdast[];\n}\n\ndeclare module 'mdast' {\n interface BlockContentMap {\n jinjaIfBlockMdast: JinjaIfBlockMdastNode;\n }\n interface PhrasingContentMap {\n jinjaIfInlineMdast: JinjaIfInlineMdastNode;\n }\n interface RootContentMap {\n jinjaIfBlockMdast: JinjaIfBlockMdastNode;\n }\n}\n\nfunction parseTag(text: string): { type: 'if' | 'elif' | 'else' | 'endif'; condition?: string } | null {\n const m = text.match(/^\\s*\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}\\s*$/);\n if (!m) return null;\n const type = m[1] as 'if' | 'elif' | 'else' | 'endif';\n const condition = m[2]?.trim() || undefined;\n return { type, condition };\n}\n\nfunction isTextOnlyParagraph(node: { type: string; children?: unknown[] }): string | null {\n if (node.type !== 'paragraph') return null;\n if (!node.children || node.children.length !== 1) return null;\n const child = node.children[0] as { type: string; value?: string };\n if (child.type !== 'text') return null;\n return child.value ?? null;\n}\n\n/**\n * Pass 1: Extract Jinja tags absorbed into list item text.\n * When there's no blank line between a Jinja tag and a list, mdast absorbs\n * the tag into the list item's text. We split these out.\n */\nfunction pass1ExtractFromLists(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse first\n for (const child of node.children) {\n pass1ExtractFromLists(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process list nodes\n if (node.type !== 'list') return;\n\n const list = node as { type: string; ordered?: boolean; start?: number; spread?: boolean; children: unknown[] };\n const items = list.children as Array<{ type: string; children: Array<{ type: string; children?: Array<{ type: string; value?: string }> }> }>;\n\n // Scan list items for Jinja tags at text boundaries\n type ExtractedPiece =\n | { kind: 'item'; item: unknown }\n | { kind: 'tag'; raw: string };\n\n const extracted: ExtractedPiece[] = [];\n let hadSplit = false;\n\n for (const item of items) {\n if (item.type !== 'listItem' || !item.children || item.children.length === 0) {\n extracted.push({ kind: 'item', item });\n continue;\n }\n\n // Check first paragraph for leading Jinja tag\n const firstChild = item.children[0];\n if (firstChild.type === 'paragraph' && firstChild.children && firstChild.children.length === 1 && firstChild.children[0].type === 'text') {\n const text = firstChild.children[0].value ?? '';\n const startMatch = text.match(JINJA_LINE_START_RE);\n if (startMatch) {\n hadSplit = true;\n extracted.push({ kind: 'tag', raw: startMatch[1] });\n const remainder = text.slice(startMatch[0].length);\n if (remainder.trim()) {\n firstChild.children[0] = { ...firstChild.children[0], value: remainder };\n extracted.push({ kind: 'item', item });\n } else if (item.children.length > 1) {\n item.children = item.children.slice(1);\n extracted.push({ kind: 'item', item });\n }\n continue;\n }\n }\n\n // Check last paragraph for trailing Jinja tag\n const lastChild = item.children[item.children.length - 1];\n if (lastChild.type === 'paragraph' && lastChild.children && lastChild.children.length === 1 && lastChild.children[0].type === 'text') {\n const text = lastChild.children[0].value ?? '';\n const endMatch = text.match(JINJA_LINE_END_RE);\n if (endMatch) {\n hadSplit = true;\n const remainder = text.slice(0, text.length - endMatch[0].length);\n if (remainder.trim()) {\n lastChild.children[0] = { ...lastChild.children[0], value: remainder };\n extracted.push({ kind: 'item', item });\n } else if (item.children.length > 1) {\n item.children = item.children.slice(0, -1);\n extracted.push({ kind: 'item', item });\n }\n extracted.push({ kind: 'tag', raw: endMatch[1] });\n continue;\n }\n }\n\n extracted.push({ kind: 'item', item });\n }\n\n if (!hadSplit) return;\n\n // Rebuild: replace parent's list node with a sequence of lists and tag paragraphs\n // We need to modify the parent's children. Since we're in the list node itself,\n // we'll reconstruct the list into segments.\n const parent = node as { type: string; children: unknown[] };\n\n // Actually, we need to replace this list node in its parent.\n // Instead, we mark the list with a special property to be expanded later.\n // Let's use a different approach: collect consecutive items into sub-lists,\n // interleaved with tag paragraphs.\n\n const result: unknown[] = [];\n let currentItems: unknown[] = [];\n let itemIndex = 0;\n\n function flushItems(): void {\n if (currentItems.length === 0) return;\n const startNum = list.ordered ? (list.start ?? 1) + itemIndex - currentItems.length : undefined;\n const subList = {\n type: 'list',\n ordered: list.ordered ?? false,\n spread: list.spread ?? false,\n ...(list.ordered ? { start: startNum } : {}),\n children: currentItems,\n };\n result.push(subList);\n currentItems = [];\n }\n\n for (const piece of extracted) {\n if (piece.kind === 'item') {\n currentItems.push(piece.item);\n itemIndex++;\n } else {\n flushItems();\n result.push({\n type: 'paragraph',\n children: [{ type: 'text', value: piece.raw }],\n });\n }\n }\n flushItems();\n\n // Mark this node for expansion in parent\n (node as { _jinjaExpanded?: unknown[] })._jinjaExpanded = result;\n}\n\n/**\n * After pass1, expand any list nodes that were marked with _jinjaExpanded.\n */\nfunction expandMarkedLists(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Process children first (bottom-up)\n for (const child of node.children) {\n expandMarkedLists(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n const newChildren: unknown[] = [];\n let changed = false;\n for (const child of node.children) {\n const c = child as { _jinjaExpanded?: unknown[] };\n if (c._jinjaExpanded) {\n newChildren.push(...c._jinjaExpanded);\n changed = true;\n } else {\n newChildren.push(child);\n }\n }\n if (changed) {\n node.children = newChildren;\n }\n}\n\n/**\n * Pass 2: Group standalone Jinja-tag paragraphs into jinjaIfBlockMdast nodes.\n * Works on children of root, blockquote, and listItem.\n */\nfunction pass2GroupBlocks(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse into children first\n for (const child of node.children) {\n pass2GroupBlocks(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process container nodes\n const containerTypes = new Set(['root', 'blockquote', 'listItem']);\n if (!containerTypes.has(node.type)) return;\n\n const children = node.children as Array<{ type: string; children?: unknown[] }>;\n const result: unknown[] = [];\n let i = 0;\n\n while (i < children.length) {\n const child = children[i];\n const text = isTextOnlyParagraph(child);\n const tag = text ? parseTag(text) : null;\n\n if (!tag || tag.type !== 'if') {\n result.push(child);\n i++;\n continue;\n }\n\n // Found {% if %} - use stack to find matching {% endif %}\n const ifParagraph = child; // save for position\n const branches: JinjaBranchMdast[] = [];\n let currentBranch: JinjaBranchMdast = {\n branchType: 'if',\n condition: tag.condition,\n content: [],\n };\n branches.push(currentBranch);\n\n let nestDepth = 1;\n i++; // skip the {% if %} paragraph\n\n let matched = false;\n let endifParagraph: { type: string; children?: unknown[]; position?: unknown } | null = null;\n while (i < children.length && nestDepth > 0) {\n const innerChild = children[i];\n const innerText = isTextOnlyParagraph(innerChild);\n const innerTag = innerText ? parseTag(innerText) : null;\n\n if (innerTag) {\n if (innerTag.type === 'if') {\n nestDepth++;\n if (nestDepth > 1) {\n currentBranch.content.push(innerChild);\n }\n } else if (innerTag.type === 'endif') {\n nestDepth--;\n if (nestDepth === 0) {\n matched = true;\n endifParagraph = innerChild;\n } else {\n currentBranch.content.push(innerChild);\n }\n } else if ((innerTag.type === 'elif' || innerTag.type === 'else') && nestDepth === 1) {\n currentBranch = {\n branchType: innerTag.type as BranchType,\n ...(innerTag.condition ? { condition: innerTag.condition } : {}),\n content: [],\n };\n branches.push(currentBranch);\n } else {\n currentBranch.content.push(innerChild);\n }\n } else {\n currentBranch.content.push(innerChild);\n }\n i++;\n }\n\n if (matched) {\n // Recursively process branch contents\n for (const branch of branches) {\n const wrapper = { type: node.type, children: branch.content };\n pass2GroupBlocks(wrapper, depth + 1);\n branch.content = wrapper.children as unknown[];\n }\n // Propagate position from {% if %} to {% endif %} for blank-line calculation\n const startPos = (ifParagraph as { position?: { start?: unknown } }).position?.start;\n const endPos = (endifParagraph as { position?: { end?: unknown } } | null)?.position?.end;\n const pos = startPos && endPos ? { position: { start: startPos, end: endPos } } : {};\n result.push({ type: 'jinjaIfBlockMdast', branches, ...pos });\n } else {\n // Unmatched {% if %} — restore as plain paragraph\n result.push({ type: 'paragraph', children: [{ type: 'text', value: text }] });\n // Rewind: the content we consumed needs to go back\n // Actually, we already advanced i, and the branches contain the consumed children.\n // We need to flatten them back.\n for (const branch of branches) {\n if (branch !== branches[0]) {\n // Re-emit the branch tag\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n result.push({ type: 'paragraph', children: [{ type: 'text', value: tagText }] });\n }\n result.push(...branch.content);\n }\n }\n }\n\n node.children = result;\n}\n\n/**\n * Pass 3: Structure inline Jinja tags within paragraph/heading text nodes.\n * Only processes direct text children (not inside marks like strong/emphasis).\n */\nfunction pass3InlineJinja(node: { type: string; children?: unknown[] }, depth: number): void {\n if (depth > MAX_DEPTH || !node.children) return;\n\n // Recurse into block-level children\n for (const child of node.children) {\n pass3InlineJinja(child as { type: string; children?: unknown[] }, depth + 1);\n }\n\n // Only process paragraph and heading\n if (node.type !== 'paragraph' && node.type !== 'heading') return;\n\n const children = node.children as Array<{ type: string; value?: string }>;\n\n // Check if any text child contains Jinja tags\n let hasJinja = false;\n for (const child of children) {\n if (child.type === 'text' && child.value) {\n JINJA_INLINE_RE.lastIndex = 0;\n if (JINJA_INLINE_RE.test(child.value)) {\n hasJinja = true;\n break;\n }\n }\n }\n if (!hasJinja) return;\n\n // Split text nodes on Jinja tags, then structure with stack\n const flatParts: Array<{ kind: 'node'; node: unknown } | { kind: 'tag'; tagType: 'if' | 'elif' | 'else' | 'endif'; condition?: string }> = [];\n\n for (const child of children) {\n if (child.type !== 'text' || !child.value) {\n flatParts.push({ kind: 'node', node: child });\n continue;\n }\n\n const text = child.value;\n JINJA_INLINE_RE.lastIndex = 0;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = JINJA_INLINE_RE.exec(text)) !== null) {\n if (match.index > lastIndex) {\n flatParts.push({ kind: 'node', node: { type: 'text', value: text.slice(lastIndex, match.index) } });\n }\n flatParts.push({\n kind: 'tag',\n tagType: match[1] as 'if' | 'elif' | 'else' | 'endif',\n condition: match[2]?.trim() || undefined,\n });\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n flatParts.push({ kind: 'node', node: { type: 'text', value: text.slice(lastIndex) } });\n }\n }\n\n // Stack-based structuring\n const result = structureInlineParts(flatParts);\n if (result) {\n node.children = result;\n }\n}\n\nfunction structureInlineParts(\n parts: Array<{ kind: 'node'; node: unknown } | { kind: 'tag'; tagType: 'if' | 'elif' | 'else' | 'endif'; condition?: string }>,\n): unknown[] | null {\n const output: unknown[] = [];\n let i = 0;\n\n while (i < parts.length) {\n const part = parts[i];\n if (part.kind === 'node') {\n output.push(part.node);\n i++;\n } else if (part.kind === 'tag' && part.tagType === 'if') {\n // Collect branches until matching endif\n const branches: JinjaBranchMdast[] = [];\n let currentBranch: JinjaBranchMdast = {\n branchType: 'if',\n condition: part.condition,\n content: [],\n };\n branches.push(currentBranch);\n i++;\n\n let nestDepth = 1;\n let matched = false;\n\n while (i < parts.length && nestDepth > 0) {\n const inner = parts[i];\n if (inner.kind === 'tag') {\n if (inner.tagType === 'if') {\n nestDepth++;\n if (nestDepth > 1) {\n // Nested if — emit as text for now\n currentBranch.content.push({ type: 'text', value: `{% if ${inner.condition ?? ''} %}`.trim() });\n }\n } else if (inner.tagType === 'endif') {\n nestDepth--;\n if (nestDepth === 0) {\n matched = true;\n } else {\n currentBranch.content.push({ type: 'text', value: '{% endif %}' });\n }\n } else if ((inner.tagType === 'elif' || inner.tagType === 'else') && nestDepth === 1) {\n currentBranch = {\n branchType: inner.tagType as BranchType,\n ...(inner.condition ? { condition: inner.condition } : {}),\n content: [],\n };\n branches.push(currentBranch);\n } else {\n // Nested elif/else\n const tagText = inner.tagType === 'else'\n ? '{% else %}'\n : `{% ${inner.tagType} ${inner.condition ?? ''} %}`.trim();\n currentBranch.content.push({ type: 'text', value: tagText });\n }\n } else {\n currentBranch.content.push(inner.node);\n }\n i++;\n }\n\n if (matched) {\n output.push({ type: 'jinjaIfInlineMdast', branches });\n } else {\n // Unmatched — restore as text\n output.push({ type: 'text', value: `{% if ${branches[0].condition ?? ''} %}`.trim() });\n for (const branch of branches) {\n if (branch !== branches[0]) {\n const tagText = branch.branchType === 'else'\n ? '{% else %}'\n : `{% ${branch.branchType} ${branch.condition ?? ''} %}`.trim();\n output.push({ type: 'text', value: tagText });\n }\n output.push(...branch.content);\n }\n }\n } else {\n // Stray elif/else/endif — keep as text\n const p = part as { tagType: string; condition?: string };\n const tagText = p.tagType === 'else'\n ? '{% else %}'\n : p.tagType === 'endif'\n ? '{% endif %}'\n : `{% ${p.tagType} ${p.condition ?? ''} %}`.trim();\n output.push({ type: 'text', value: tagText });\n i++;\n }\n }\n\n return output;\n}\n\n/**\n * Main transform: apply all three passes to an mdast tree.\n */\nexport function jinjaBlockTransform(tree: { type: string; children?: unknown[] }): void {\n // Pass 1: Extract Jinja tags from list item text\n pass1ExtractFromLists(tree, 0);\n expandMarkedLists(tree, 0);\n\n // Pass 2: Group block-level Jinja structures\n pass2GroupBlocks(tree, 0);\n\n // Pass 3: Structure inline Jinja\n pass3InlineJinja(tree, 0);\n}\n","import { parseMarkdown } from './parser';\nimport { serializeToMarkdown } from './serializer';\nimport type { AstNode, BlockNode, InlineNode, DocumentNode } from '../ast/types';\n\n/**\n * Serialize a list of AST nodes to markdown string (for clipboard).\n */\nexport function serializeFragment(nodes: AstNode[]): string {\n if (nodes.length === 0) return '';\n\n // Wrap in a doc for serialization\n const blocks: BlockNode[] = nodes.map((node) => {\n if (node.type === 'text' || node.type === 'resourceTag' || node.type === 'jumpPoint' || node.type === 'hardBreak') {\n return { type: 'paragraph', content: [node] };\n }\n if (node.type === 'doc') {\n // Flatten doc children\n return node.content;\n }\n return node as BlockNode;\n }).flat() as BlockNode[];\n\n const wrapper: DocumentNode = { type: 'doc', content: blocks };\n return serializeToMarkdown(wrapper);\n}\n\n/**\n * Parse a markdown string into a fragment (for clipboard paste).\n * Returns block nodes by default; if the markdown is a single paragraph,\n * returns its inline children.\n */\nexport function parseFragment(markdown: string): InlineNode[] | BlockNode[] {\n const doc = parseMarkdown(markdown);\n\n // If single paragraph, return inline content\n if (doc.content.length === 1 && doc.content[0].type === 'paragraph') {\n return doc.content[0].content as InlineNode[];\n }\n\n return doc.content as BlockNode[];\n}\n","/**\n * Pure text-based Jinja block scanner (no ProseMirror dependency).\n */\nimport type { JinjaBlock } from './types';\n\nconst JINJA_PATTERN = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\n/**\n * Scan all Jinja blocks from plain text.\n *\n * @param text - Plain text content\n * @returns All Jinja blocks sorted by position\n */\nexport function scanJinjaBlocks(text: string): JinjaBlock[] {\n const blocks: JinjaBlock[] = [];\n\n JINJA_PATTERN.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = JINJA_PATTERN.exec(text)) !== null) {\n const type = match[1] as JinjaBlock['type'];\n const conditionRaw = match[2].trim();\n const condition = type === 'if' || type === 'elif' ? conditionRaw : undefined;\n\n // Include trailing spaces after tag\n let endIndex = match.index + match[0].length;\n while (endIndex < text.length && text[endIndex] === ' ') {\n endIndex++;\n }\n\n blocks.push({\n type,\n condition,\n startIndex: match.index,\n endIndex,\n raw: match[0],\n });\n }\n\n return blocks.sort((a, b) => a.startIndex - b.startIndex);\n}\n","import type { JinjaBlock, JinjaIfStructure } from './types';\n\nfunction buildStructure(\n partial: { ifBlock: JinjaBlock; elifBlocks: JinjaBlock[]; elseBlock?: JinjaBlock },\n endifBlock: JinjaBlock,\n): JinjaIfStructure {\n const { ifBlock, elifBlocks, elseBlock } = partial;\n const contentRanges: JinjaIfStructure['contentRanges'] = [];\n\n // if branch content\n const ifContentEnd = elifBlocks[0]?.startIndex ?? elseBlock?.startIndex ?? endifBlock.startIndex;\n contentRanges.push({\n type: 'if',\n condition: ifBlock.condition!,\n startIndex: ifBlock.endIndex,\n endIndex: ifContentEnd,\n });\n\n // elif branches\n elifBlocks.forEach((elifBlock, idx) => {\n const nextBlock = elifBlocks[idx + 1] ?? elseBlock ?? endifBlock;\n contentRanges.push({\n type: 'elif',\n condition: elifBlock.condition!,\n startIndex: elifBlock.endIndex,\n endIndex: nextBlock.startIndex,\n });\n });\n\n // else branch\n if (elseBlock) {\n contentRanges.push({\n type: 'else',\n startIndex: elseBlock.endIndex,\n endIndex: endifBlock.startIndex,\n });\n }\n\n return {\n id: `jinja-${ifBlock.startIndex}-${endifBlock.endIndex}`,\n ifBlock,\n elifBlocks,\n elseBlock,\n endifBlock,\n contentRanges,\n };\n}\n\n/**\n * Structure scanned blocks into if~endif structures using stack-based approach.\n */\nexport function structureJinjaBlocks(blocks: JinjaBlock[]): JinjaIfStructure[] {\n const structures: JinjaIfStructure[] = [];\n const stack: Array<{\n ifBlock: JinjaBlock;\n elifBlocks: JinjaBlock[];\n elseBlock?: JinjaBlock;\n }> = [];\n\n for (const block of blocks) {\n switch (block.type) {\n case 'if':\n stack.push({ ifBlock: block, elifBlocks: [] });\n break;\n case 'elif':\n if (stack.length > 0) {\n stack[stack.length - 1].elifBlocks.push(block);\n }\n break;\n case 'else':\n if (stack.length > 0) {\n stack[stack.length - 1].elseBlock = block;\n }\n break;\n case 'endif': {\n const current = stack.pop();\n if (current) {\n structures.push(buildStructure(current, block));\n }\n break;\n }\n }\n }\n\n return structures;\n}\n","import type { DocumentNode } from '../ast/types';\nimport { textContent } from '../ast/traverse';\nimport { scanJinjaBlocks } from './scanner';\nimport { structureJinjaBlocks } from './structurer';\n\nexport interface JinjaVisualBranch {\n type: 'if' | 'elif' | 'else';\n condition?: string;\n blockStartIndex: number;\n blockEndIndex: number;\n tagBlockIndex: number;\n}\n\nexport interface JinjaVisualStructure {\n id: string;\n branches: JinjaVisualBranch[];\n ifTagBlockIndex: number;\n endifTagBlockIndex: number;\n}\n\n/**\n * Single pass: builds cumulative block-end offsets AND the full document text.\n * offsets[i] = exclusive end char index of block i.\n * Avoids calling textContent() twice (once for offsets, once for fullText).\n */\nfunction buildOffsetsAndText(doc: DocumentNode): { offsets: number[]; fullText: string } {\n const offsets: number[] = [];\n const parts: string[] = [];\n let cursor = 0;\n for (const block of doc.content) {\n const t = textContent(block);\n parts.push(t);\n cursor += t.length;\n offsets.push(cursor);\n }\n return { offsets, fullText: parts.join('') };\n}\n\n/**\n * Binary search: returns the block index that contains charIndex.\n * offsets[i] is the exclusive end of block i.\n */\nfunction charIndexToBlockIndex(offsets: number[], charIndex: number): number {\n if (offsets.length === 0) return 0;\n let lo = 0;\n let hi = offsets.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (offsets[mid] <= charIndex) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/**\n * Analyze a DocumentNode for Jinja if/elif/else/endif structures\n * and map them to block-level indices.\n */\nexport function analyzeJinjaBlocks(doc: DocumentNode): JinjaVisualStructure[] {\n if (doc.content.length === 0) return [];\n\n const { offsets, fullText } = buildOffsetsAndText(doc);\n\n const scanned = scanJinjaBlocks(fullText);\n if (scanned.length === 0) return [];\n\n const structures = structureJinjaBlocks(scanned);\n\n return structures.map((structure) => {\n const ifTagBlockIdx = charIndexToBlockIndex(offsets, structure.ifBlock.startIndex);\n const endifTagBlockIdx = charIndexToBlockIndex(offsets, structure.endifBlock.startIndex);\n\n const branches: JinjaVisualBranch[] = structure.contentRanges.map((range) => {\n // Find the tag block index for this branch\n let tagCharIndex: number;\n if (range.type === 'if') {\n tagCharIndex = structure.ifBlock.startIndex;\n } else if (range.type === 'elif') {\n const elifBlock = structure.elifBlocks.find((b) => b.condition === range.condition);\n tagCharIndex = elifBlock ? elifBlock.startIndex : range.startIndex;\n } else {\n tagCharIndex = structure.elseBlock!.startIndex;\n }\n\n const tagBlockIdx = charIndexToBlockIndex(offsets, tagCharIndex);\n\n // Content block range: from the block containing the content start\n // to the block containing the content end (exclusive)\n let contentStartBlock: number;\n let contentEndBlock: number;\n\n if (range.startIndex >= range.endIndex) {\n // Empty content range\n contentStartBlock = tagBlockIdx;\n contentEndBlock = tagBlockIdx;\n } else {\n contentStartBlock = charIndexToBlockIndex(offsets, range.startIndex);\n // If the content starts in the same block as the tag, the actual content blocks start after\n // But we keep the start as-is since the tag and content may share a block\n const lastContentChar = range.endIndex - 1;\n contentEndBlock = charIndexToBlockIndex(offsets, lastContentChar) + 1;\n }\n\n return {\n type: range.type,\n condition: range.condition,\n blockStartIndex: contentStartBlock,\n blockEndIndex: contentEndBlock,\n tagBlockIndex: tagBlockIdx,\n };\n });\n\n return {\n id: structure.id,\n branches,\n ifTagBlockIndex: ifTagBlockIdx,\n endifTagBlockIndex: endifTagBlockIdx,\n };\n });\n}\n","/**\n * Safe Jinja condition evaluator using recursive descent parsing.\n *\n * Supports:\n * Comparison: ==, !=, <, >, <=, >=\n * Logical: and, or, not\n * Identity: is, is not\n * Membership: in (value in identifier)\n * Literals: strings, numbers, booleans (True/False/true/false), None/null\n * Variables: dot-notation identifiers (e.g. context.planName)\n * Grouping: parentheses\n *\n * NO arbitrary code execution — only whitelisted operators and literal types.\n */\nimport type { VariableValue } from './types';\n\n// ── Tokenizer ──────────────────────────────────────────────────────\n\ntype TokenType =\n | 'STRING'\n | 'NUMBER'\n | 'BOOL'\n | 'NONE'\n | 'IDENT'\n | 'AND'\n | 'OR'\n | 'NOT'\n | 'IN'\n | 'IS'\n | 'EQ'\n | 'NEQ'\n | 'LT'\n | 'GT'\n | 'LTE'\n | 'GTE'\n | 'LPAREN'\n | 'RPAREN'\n | 'COMMA'\n | 'EOF';\n\ninterface Token {\n type: TokenType;\n value: string;\n}\n\nconst KEYWORDS: Record<string, TokenType> = {\n and: 'AND',\n or: 'OR',\n not: 'NOT',\n in: 'IN',\n is: 'IS',\n True: 'BOOL',\n False: 'BOOL',\n true: 'BOOL',\n false: 'BOOL',\n None: 'NONE',\n null: 'NONE',\n};\n\ninterface TokenizeResult {\n readonly tokens: Token[];\n readonly error?: string;\n}\n\nfunction tokenize(input: string): TokenizeResult {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < input.length) {\n // Skip whitespace\n if (/\\s/.test(input[i])) {\n i++;\n continue;\n }\n\n // String literals (single or double quoted)\n if (input[i] === '\"' || input[i] === \"'\") {\n const quote = input[i];\n let str = '';\n i++; // skip opening quote\n while (i < input.length && input[i] !== quote) {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n str += input[i + 1];\n i += 2;\n } else {\n str += input[i];\n i++;\n }\n }\n if (i >= input.length) return { tokens: [], error: 'Unterminated string literal' };\n i++; // skip closing quote\n tokens.push({ type: 'STRING', value: str });\n continue;\n }\n\n // Numbers (integer and float)\n if (/[0-9]/.test(input[i]) || (input[i] === '-' && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && (tokens.length === 0 || ['AND', 'OR', 'NOT', 'EQ', 'NEQ', 'LT', 'GT', 'LTE', 'GTE', 'LPAREN', 'IN', 'IS'].includes(tokens[tokens.length - 1].type)))) {\n let num = '';\n if (input[i] === '-') {\n num = '-';\n i++;\n }\n while (i < input.length && /[0-9]/.test(input[i])) {\n num += input[i];\n i++;\n }\n if (i < input.length && input[i] === '.') {\n num += '.';\n i++;\n while (i < input.length && /[0-9]/.test(input[i])) {\n num += input[i];\n i++;\n }\n }\n tokens.push({ type: 'NUMBER', value: num });\n continue;\n }\n\n // Identifiers and keywords\n if (/[a-zA-Z_]/.test(input[i])) {\n let ident = '';\n while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {\n ident += input[i];\n i++;\n }\n const kwType = KEYWORDS[ident];\n if (kwType) {\n tokens.push({ type: kwType, value: ident });\n } else {\n tokens.push({ type: 'IDENT', value: ident });\n }\n continue;\n }\n\n // Two-character operators\n if (i + 1 < input.length) {\n const two = input[i] + input[i + 1];\n if (two === '==') { tokens.push({ type: 'EQ', value: '==' }); i += 2; continue; }\n if (two === '!=') { tokens.push({ type: 'NEQ', value: '!=' }); i += 2; continue; }\n if (two === '<=') { tokens.push({ type: 'LTE', value: '<=' }); i += 2; continue; }\n if (two === '>=') { tokens.push({ type: 'GTE', value: '>=' }); i += 2; continue; }\n }\n\n // Single-character operators\n if (input[i] === '<') { tokens.push({ type: 'LT', value: '<' }); i++; continue; }\n if (input[i] === '>') { tokens.push({ type: 'GT', value: '>' }); i++; continue; }\n if (input[i] === '(') { tokens.push({ type: 'LPAREN', value: '(' }); i++; continue; }\n if (input[i] === ')') { tokens.push({ type: 'RPAREN', value: ')' }); i++; continue; }\n if (input[i] === ',') { tokens.push({ type: 'COMMA', value: ',' }); i++; continue; }\n\n // Unknown character → fail\n return { tokens: [], error: `Unexpected character: ${input[i]}` };\n }\n\n tokens.push({ type: 'EOF', value: '' });\n return { tokens };\n}\n\n// ── Evaluated value ────────────────────────────────────────────────\n\ntype Value = string | number | boolean | null | Value[];\n\n// ── Recursive descent parser + evaluator ───────────────────────────\n\nclass Parser {\n private pos = 0;\n private readonly tokens: Token[];\n private readonly variables: Map<string, VariableValue>;\n\n constructor(tokens: Token[], variables: Map<string, VariableValue>) {\n this.tokens = tokens;\n this.variables = variables;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: 'EOF', value: '' };\n }\n\n private advance(): Token {\n const t = this.tokens[this.pos];\n this.pos++;\n return t;\n }\n\n private expect(type: TokenType): Token {\n const t = this.peek();\n if (t.type !== type) {\n throw new Error(`Expected ${type}, got ${t.type}`);\n }\n return this.advance();\n }\n\n // Grammar (precedence low→high):\n // expr → or_expr\n // or_expr → and_expr ('or' and_expr)*\n // and_expr → not_expr ('and' not_expr)*\n // not_expr → 'not' not_expr | cmp_expr\n // cmp_expr → primary (('=='|'!='|'<'|'>'|'<='|'>='|'in'|'is'|'is not') primary)?\n // primary → STRING | NUMBER | BOOL | NONE | IDENT | '(' expr ')'\n\n evaluate(): Value {\n const result = this.orExpr();\n if (this.peek().type !== 'EOF') {\n throw new Error(`Unexpected token: ${this.peek().value}`);\n }\n return result;\n }\n\n private orExpr(): Value {\n let left = this.andExpr();\n while (this.peek().type === 'OR') {\n this.advance();\n const right = this.andExpr();\n left = isTruthy(left) || isTruthy(right);\n }\n return left;\n }\n\n private andExpr(): Value {\n let left = this.notExpr();\n while (this.peek().type === 'AND') {\n this.advance();\n const right = this.notExpr();\n left = isTruthy(left) && isTruthy(right);\n }\n return left;\n }\n\n private notExpr(): Value {\n if (this.peek().type === 'NOT') {\n this.advance();\n const val = this.notExpr();\n return !isTruthy(val);\n }\n return this.cmpExpr();\n }\n\n private cmpExpr(): Value {\n const left = this.primary();\n const op = this.peek().type;\n\n switch (op) {\n case 'EQ':\n this.advance();\n return looseEqual(left, this.primary());\n case 'NEQ':\n this.advance();\n return !looseEqual(left, this.primary());\n case 'LT':\n this.advance();\n return toNumber(left) < toNumber(this.primary());\n case 'GT':\n this.advance();\n return toNumber(left) > toNumber(this.primary());\n case 'LTE':\n this.advance();\n return toNumber(left) <= toNumber(this.primary());\n case 'GTE':\n this.advance();\n return toNumber(left) >= toNumber(this.primary());\n case 'IN': {\n this.advance();\n const collection = this.primary();\n if (Array.isArray(collection)) {\n return collection.some((item) => looseEqual(item, left));\n }\n if (typeof collection === 'string' && typeof left === 'string') {\n return collection.includes(left);\n }\n return false;\n }\n case 'IS': {\n this.advance();\n // \"is not\"\n if (this.peek().type === 'NOT') {\n this.advance();\n return !looseEqual(left, this.primary());\n }\n return looseEqual(left, this.primary());\n }\n default:\n return left;\n }\n }\n\n private primary(): Value {\n const t = this.peek();\n\n switch (t.type) {\n case 'STRING':\n this.advance();\n return t.value;\n case 'NUMBER':\n this.advance();\n return parseFloat(t.value);\n case 'BOOL':\n this.advance();\n return t.value === 'True' || t.value === 'true';\n case 'NONE':\n this.advance();\n return null;\n case 'IDENT': {\n this.advance();\n // Function/method call: ident(...) or obj.method(...)\n if (this.peek().type === 'LPAREN') {\n this.advance(); // consume '('\n // Parse arguments (may be empty)\n while (this.peek().type !== 'RPAREN' && this.peek().type !== 'EOF') {\n this.orExpr(); // evaluate and discard each argument\n if (this.peek().type === 'COMMA') {\n this.advance(); // consume ','\n }\n }\n this.expect('RPAREN');\n // Can't evaluate function calls — return null (falsy) for validation\n return null;\n }\n return this.resolveVariable(t.value);\n }\n case 'LPAREN': {\n this.advance();\n const val = this.orExpr();\n this.expect('RPAREN');\n return val;\n }\n default:\n throw new Error(`Unexpected token in primary: ${t.type} \"${t.value}\"`);\n }\n }\n\n private resolveVariable(name: string): Value {\n const entry = this.variables.get(name);\n if (entry === undefined) {\n // Check for partial dot-notation matches:\n // e.g., \"user.plan\" might be stored as \"user.plan\" directly\n // No match → treat as undefined (falsy)\n return null;\n }\n\n switch (entry.type) {\n case 'string':\n return String(entry.value);\n case 'number':\n return Number(entry.value);\n case 'boolean':\n return entry.value === true || entry.value === 'true';\n default:\n return String(entry.value);\n }\n }\n}\n\n// ── Helper functions ───────────────────────────────────────────────\n\nfunction isTruthy(v: Value): boolean {\n if (v === null || v === undefined) return false;\n if (typeof v === 'boolean') return v;\n if (typeof v === 'number') return v !== 0;\n if (typeof v === 'string') return v.length > 0;\n if (Array.isArray(v)) return v.length > 0;\n return true;\n}\n\nfunction looseEqual(a: Value, b: Value): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n\n // Coerce number↔string for Jinja compatibility\n if (typeof a === 'number' && typeof b === 'string') return a === parseFloat(b);\n if (typeof a === 'string' && typeof b === 'number') return parseFloat(a) === b;\n\n return false;\n}\n\nfunction toNumber(v: Value): number {\n if (typeof v === 'number') return v;\n if (typeof v === 'string') return parseFloat(v) || 0;\n if (typeof v === 'boolean') return v ? 1 : 0;\n return 0;\n}\n\n// ── Public API ─────────────────────────────────────────────────────\n\n/**\n * Safely evaluate a Jinja conditional expression.\n *\n * Uses a recursive-descent parser with a whitelist of allowed operators.\n * No `eval`, `new Function`, or arbitrary code execution.\n *\n * @returns true/false if evaluation succeeded, null if parsing/evaluation failed\n */\nexport function evaluateCondition(condition: string, variables: Map<string, VariableValue>): boolean | null {\n try {\n const { tokens, error } = tokenize(condition.trim());\n if (error || tokens.length === 0) return null;\n\n const parser = new Parser(tokens, variables);\n const result = parser.evaluate();\n return isTruthy(result);\n } catch {\n return null;\n }\n}\n\n// ── Condition validation ──────────────────────────────────────────\n\nexport interface ConditionValidationResult {\n readonly valid: boolean;\n readonly error?: string;\n}\n\n/**\n * Validate a Jinja conditional expression without evaluating it.\n * Returns a structured result with an error message on failure.\n */\nexport function validateCondition(condition: string): ConditionValidationResult {\n const trimmed = condition.trim();\n if (trimmed === '') return { valid: true };\n\n const { tokens, error: tokenError } = tokenize(trimmed);\n if (tokenError) return { valid: false, error: tokenError };\n if (tokens.length === 0) return { valid: false, error: 'Empty expression' };\n\n try {\n // Parse without evaluating — use an empty variable map\n const parser = new Parser(tokens, new Map());\n parser.evaluate();\n return { valid: true };\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Invalid expression';\n return { valid: false, error: msg };\n }\n}\n","/**\n * Extract a hierarchical tree structure from a DocumentNode for the preview tree view.\n *\n * Walks the AST and produces a tree of:\n * - Headings (H1/H2 as sections, H3-H6 as subsections)\n * - Jump points with their IDs\n * - Jinja if blocks with condition branches\n * - Resource tags (tool, handoff, etc.)\n */\nimport type { DocumentNode, BlockNode, InlineNode } from '../ast/types';\nimport { textContent } from '../ast/traverse';\nimport { analyzeJinjaBlocks } from '../jinja/analyzer';\n\nconst MAX_DEPTH = 128;\n\nexport type DocumentTreeNodeType =\n | 'heading'\n | 'jumpPoint'\n | 'jinjaIf'\n | 'jinjaBranch'\n | 'resourceTag'\n | 'noteBlock'\n | 'endAction';\n\nexport interface DocumentTreeNode {\n readonly type: DocumentTreeNodeType;\n readonly label: string;\n readonly blockIndex: number;\n readonly children: readonly DocumentTreeNode[];\n readonly meta?: Record<string, unknown>;\n}\n\n/** Resource IDs that represent \"end action\" tools (close conversation, etc.). */\nconst END_ACTION_RESOURCE_IDS = new Set([\n 'close-happy-tiger', // PredefinedToolKey.CloseConversation\n]);\n\n/** Text labels that indicate an end action (fallback when resourceId doesn't match). */\nconst END_ACTION_TEXTS = new Set([\n 'end conversation',\n 'end_conversation',\n]);\n\nfunction isEndActionTag(tagType: string, resourceId: string, text: string): boolean {\n return tagType === 'handoff'\n || END_ACTION_RESOURCE_IDS.has(resourceId)\n || END_ACTION_TEXTS.has(text.toLowerCase());\n}\n\nfunction extractInlineItems(\n content: readonly InlineNode[],\n blockIndex: number,\n): DocumentTreeNode[] {\n const items: DocumentTreeNode[] = [];\n for (const node of content) {\n if (node.type === 'jumpPoint') {\n items.push({\n type: 'jumpPoint',\n label: node.id,\n blockIndex,\n children: [],\n });\n } else if (node.type === 'resourceTag') {\n const endAction = isEndActionTag(node.tagType, node.resourceId, node.text);\n items.push({\n type: endAction ? 'endAction' : 'resourceTag',\n label: endAction ? `End ${node.text}` : node.text,\n blockIndex,\n children: [],\n meta: { tagType: node.tagType, resourceId: node.resourceId },\n });\n }\n }\n return items;\n}\n\nfunction extractBlockItems(\n blocks: readonly BlockNode[],\n startIndex: number,\n depth: number,\n): DocumentTreeNode[] {\n if (depth > MAX_DEPTH) return [];\n\n const items: DocumentTreeNode[] = [];\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const blockIndex = startIndex + i;\n\n switch (block.type) {\n case 'heading': {\n const label = textContent(block) || `Heading ${block.level}`;\n const inlineItems = extractInlineItems(block.content, blockIndex);\n items.push({\n type: 'heading',\n label,\n blockIndex,\n children: inlineItems,\n meta: { level: block.level },\n });\n break;\n }\n\n case 'paragraph': {\n const inlineItems = extractInlineItems(block.content, blockIndex);\n items.push(...inlineItems);\n break;\n }\n\n case 'jinjaIfBlock': {\n const branches: DocumentTreeNode[] = block.branches.map((branch, branchIdx) => {\n const branchLabel =\n branch.branchType === 'else'\n ? 'ELSE'\n : `${branch.branchType.toUpperCase()} ${branch.condition || ''}`.trim();\n const branchChildren = extractBlockItems(branch.content, blockIndex, depth + 1);\n return {\n type: 'jinjaBranch' as const,\n label: branchLabel,\n blockIndex,\n children: branchChildren,\n meta: { branchIndex: branchIdx },\n };\n });\n\n items.push({\n type: 'jinjaIf',\n label: 'Jinja if',\n blockIndex,\n children: branches,\n });\n break;\n }\n\n case 'noteBlock': {\n const noteContent = textContent(block);\n items.push({\n type: 'noteBlock',\n label: noteContent ? `Note: ${noteContent.slice(0, 30)}` : 'Note',\n blockIndex,\n children: [],\n });\n break;\n }\n\n case 'bulletList':\n case 'orderedList': {\n for (const li of block.content) {\n const childItems = extractBlockItems(li.content, blockIndex, depth + 1);\n items.push(...childItems);\n }\n break;\n }\n\n case 'blockquote': {\n const childItems = extractBlockItems(block.content, blockIndex, depth + 1);\n items.push(...childItems);\n break;\n }\n\n default:\n break;\n }\n }\n\n return items;\n}\n\n/**\n * Build a document outline tree from a DocumentNode.\n * Extracts both structured jinjaIfBlock nodes and text-based {% if %} patterns.\n */\nexport function buildDocumentTree(doc: DocumentNode): DocumentTreeNode[] {\n const items = extractBlockItems(doc.content, 0, 0);\n\n // Also detect text-based Jinja ({% if %} stored as plain text in paragraphs)\n try {\n const structures = analyzeJinjaBlocks(doc);\n if (structures.length > 0) {\n // Only add text-based Jinja if no structured jinjaIf was already found\n const hasStructuredJinja = items.some((n) => n.type === 'jinjaIf');\n if (!hasStructuredJinja) {\n for (const s of structures) {\n const branches: DocumentTreeNode[] = s.branches.map((b, branchIdx) => ({\n type: 'jinjaBranch' as const,\n label: b.type === 'else' ? 'ELSE' : `${b.type.toUpperCase()} ${b.condition || ''}`.trim(),\n blockIndex: b.tagBlockIndex,\n children: [],\n meta: { branchIndex: branchIdx },\n }));\n\n const jinjaNode: DocumentTreeNode = {\n type: 'jinjaIf',\n label: 'Jinja if',\n blockIndex: s.ifTagBlockIndex,\n children: branches,\n };\n\n // Insert at the correct position based on blockIndex\n let inserted = false;\n for (let i = 0; i < items.length; i++) {\n if (items[i].blockIndex > s.ifTagBlockIndex) {\n items.splice(i, 0, jinjaNode);\n inserted = true;\n break;\n }\n }\n if (!inserted) items.push(jinjaNode);\n }\n }\n }\n } catch {\n // analyzeJinjaBlocks may fail on some documents — don't break the tree\n }\n\n return items;\n}\n","/**\n * Jump-point adjacent decoration + edit plugins.\n *\n * Adjacent plugin: marks jumpPoint nodes near the cursor with a decoration\n * so the NodeView can show `^id^` raw syntax when the cursor is beside them.\n *\n * Edit plugin: tracks a \"raw range\" after ArrowLeft explodes a jumpPoint atom\n * to `^aa^` text. When the cursor moves outside that range the plugin\n * auto-reconverts the text back to a jumpPoint node (if it still matches\n * `^validId^` and the id has no duplicates elsewhere in the doc).\n *\n * Keymap:\n * Backspace — explode atom to `^aa` (closing `^` consumed), cursor at end\n * ArrowLeft — explode atom to `^aa^`, cursor before closing `^`\n */\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\n// ── Adjacent decoration plugin ────────────────────────────\n\nconst adjacentKey = new PluginKey<DecorationSet>('jumpPointAdjacent');\n\n/** Decoration spec set on a jumpPoint node when the cursor is adjacent. */\nexport const JUMP_POINT_ADJACENT_SPEC = { jumpPointAdjacent: true } as const;\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const { selection } = state;\n if (!selection.empty) return DecorationSet.empty;\n\n const cursorPos = selection.$from.pos;\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (node.type.name !== 'jumpPoint') return;\n const nodeEnd = pos + node.nodeSize;\n if (cursorPos === pos || cursorPos === nodeEnd) {\n decorations.push(Decoration.node(pos, nodeEnd, {}, JUMP_POINT_ADJACENT_SPEC));\n }\n });\n\n return DecorationSet.create(state.doc, decorations);\n}\n\n// ── Edit plugin (raw-range tracking + auto-reconvert) ─────\n\ninterface JumpPointEditState {\n rawRange: { from: number; to: number } | null;\n}\n\nexport const jumpPointEditKey = new PluginKey<JumpPointEditState>('jumpPointEdit');\n\n/** Matches the full `^validId^` pattern (letters, numbers, underscore, hyphen). */\nconst JUMP_POINT_FULL_RE = /^\\^([\\p{L}\\p{N}_-]+)\\^$/u;\n\nfunction createJumpPointEditPlugin(): Plugin<JumpPointEditState> {\n return new Plugin<JumpPointEditState>({\n key: jumpPointEditKey,\n\n state: {\n init: (): JumpPointEditState => ({ rawRange: null }),\n\n apply(tr, prev): JumpPointEditState {\n const meta = tr.getMeta(jumpPointEditKey) as\n | { from: number; to: number }\n | null\n | undefined;\n\n if (meta !== undefined) return { rawRange: meta };\n\n if (prev.rawRange) {\n // Use assoc=-1 for `from` so it stays at the range start when text\n // is inserted/replaced from that position (forward assoc would push\n // it to from+addLen, collapsing the range).\n const from = tr.mapping.map(prev.rawRange.from, -1);\n const to = tr.mapping.map(prev.rawRange.to, 1);\n if (from >= to) return { rawRange: null };\n return { rawRange: { from, to } };\n }\n\n return prev;\n },\n },\n\n appendTransaction(_, __, newState) {\n const pluginState = jumpPointEditKey.getState(newState);\n if (!pluginState?.rawRange) return null;\n\n const { from, to } = pluginState.rawRange;\n const cursor = newState.selection.anchor;\n\n // Still inside the raw region — nothing to do.\n // Use strict `< to` so cursor AT the end of `^aa^` is already \"outside\",\n // meaning a single ArrowRight press from `^aa|^` triggers reconversion.\n if (cursor >= from && cursor < to) return null;\n\n const docSize = newState.doc.content.size;\n const safeFrom = Math.min(from, docSize);\n const safeTo = Math.min(to, docSize);\n\n const reconvertTr = newState.tr;\n reconvertTr.setMeta(jumpPointEditKey, null); // always clear tracking\n\n if (safeFrom < safeTo) {\n const text = newState.doc.textBetween(safeFrom, safeTo);\n const match = JUMP_POINT_FULL_RE.exec(text);\n\n if (match) {\n const [, id] = match;\n const jumpPointType = newState.schema.nodes.jumpPoint;\n\n if (jumpPointType) {\n // Always reconvert — duplicates are allowed; validation plugin shows error state\n reconvertTr.replaceWith(safeFrom, safeTo, jumpPointType.create({ id }));\n const mappedCursor = reconvertTr.mapping.map(cursor);\n const clampedCursor = Math.min(mappedCursor, reconvertTr.doc.content.size);\n reconvertTr.setSelection(TextSelection.near(reconvertTr.doc.resolve(clampedCursor)));\n }\n }\n }\n\n return reconvertTr;\n },\n });\n}\n\n// ── Shared helpers ────────────────────────────────────────\n\n/** Find jumpPoint atom — either immediately before cursor (TextSelection)\n * or the selected atom itself (NodeSelection). */\nfunction jumpPointAtOrBefore(\n state: EditorState,\n): { id: string; nodeStart: number; nodeEnd: number } | null {\n const { selection } = state;\n\n // NodeSelection — atom itself is selected\n if ('node' in selection) {\n const node = (selection as any).node;\n if (node?.type?.name === 'jumpPoint') {\n return { id: node.attrs.id as string, nodeStart: selection.from, nodeEnd: selection.to };\n }\n return null;\n }\n\n // TextSelection — cursor immediately after atom\n if (!selection.empty) return null;\n const { $from } = selection;\n const nodeBefore = $from.nodeBefore;\n if (!nodeBefore || nodeBefore.type.name !== 'jumpPoint') return null;\n const nodeEnd = $from.pos;\n const nodeStart = nodeEnd - nodeBefore.nodeSize;\n return { id: nodeBefore.attrs.id as string, nodeStart, nodeEnd };\n}\n\n/**\n * Backspace on a jumpPoint atom → explode to `^aa` (no closing `^`).\n * Cursor lands at end: `^aa|`\n */\nfunction explodeOnBackspace(state: EditorState): Transaction | null {\n const info = jumpPointAtOrBefore(state);\n if (!info) return null;\n const { id, nodeStart, nodeEnd } = info;\n const rawText = `^${id}`;\n const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));\n const cursorPos = Math.min(nodeStart + rawText.length, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n return tr;\n}\n\n/**\n * ArrowLeft on a jumpPoint atom → explode to `^aa^`, cursor before closing `^`.\n * Sets jumpPointEditKey meta so auto-reconvert kicks in when cursor leaves.\n * Result: `^aa|^`\n */\nfunction explodeOnArrowLeft(state: EditorState): Transaction | null {\n const info = jumpPointAtOrBefore(state);\n if (!info) return null;\n const { id, nodeStart, nodeEnd } = info;\n const rawText = `^${id}^`;\n const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));\n // cursor before closing `^`\n const cursorPos = Math.min(nodeStart + 1 + id.length, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n // Track range so appendTransaction can reconvert on cursor-leave\n tr.setMeta(jumpPointEditKey, { from: nodeStart, to: nodeStart + rawText.length });\n return tr;\n}\n\n// ── Public factory ────────────────────────────────────────\n\nexport function createJumpPointAdjacentPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointAdjacent',\n keymap: () => ({\n Backspace: (state, dispatch) => {\n const tr = explodeOnBackspace(state);\n if (!tr) return false;\n if (dispatch) dispatch(tr);\n return true;\n },\n ArrowLeft: (state, dispatch) => {\n const tr = explodeOnArrowLeft(state);\n if (!tr) return false;\n if (dispatch) dispatch(tr);\n return true;\n },\n }),\n plugins: () => [\n createJumpPointEditPlugin(),\n new Plugin({\n key: adjacentKey,\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, old, _oldState, newState) {\n if (tr.selectionSet || tr.docChanged) {\n return buildDecorations(newState);\n }\n return old.map(tr.mapping, tr.doc);\n },\n },\n props: {\n decorations(state) {\n return adjacentKey.getState(state);\n },\n },\n }),\n ],\n };\n}\n","/**\n * React NodeView plugin for the `jumpPoint` node.\n *\n * Normal state: styled badge (anchor icon + id, yellow background)\n * Adjacent state: shows `^id^` raw syntax when cursor is immediately before or after\n * Duplicate state: red error badge with X button and hover tooltip\n */\nimport React, { useCallback, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { createReactNodeView } from '../nodeView/ReactNodeView';\nimport type { ReactNodeViewProps } from '../nodeView/ReactNodeView';\nimport type { ActionbookPlugin } from './types';\nimport { IconAnchor } from '../components/icons';\n\n/** Diamond-shaped alert icon (◆ with ! inside) for duplicate jumpPoint indicator. */\nfunction IconDiamondAlert({ size = 12, fill = '#D9352C' }: { size?: number; fill?: string }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.293 1.293a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 0-1.414l4-4Z\"\n fill={fill}\n />\n <path d=\"M6 3.5v3\" stroke=\"#fff\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"6\" cy=\"8.25\" r=\"0.625\" fill=\"#fff\" />\n </svg>\n );\n}\n\n// ── Styles (Figma spec) ──────────────────────────────────\n\nconst JUMP_POINT_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: '#FFF2B6',\n border: '1px solid #FFC233',\n color: '#AA5D04',\n userSelect: 'none',\n cursor: 'default',\n boxSizing: 'border-box',\n // height, padding, borderRadius, fontSize, lineHeight, overflow\n // are set via CSS class .ab-jump-point for heading-level overrides\n};\n\nconst JUMP_POINT_ADJACENT_STYLE: React.CSSProperties = {\n ...JUMP_POINT_STYLE,\n};\n\nconst JUMP_POINT_DUPLICATE_STYLE: React.CSSProperties = {\n ...JUMP_POINT_STYLE,\n backgroundColor: '#FFD9DD',\n borderColor: '#D9352C',\n color: '#9D091E',\n};\n\nconst LABEL_STYLE: React.CSSProperties = {\n whiteSpace: 'nowrap',\n // padding is set via CSS .ab-jp-label for heading-level overrides\n};\n\nconst CLOSE_BTN_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '16px',\n height: '16px',\n padding: 0,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: '1px',\n flexShrink: 0,\n color: 'inherit',\n fontSize: '10px',\n lineHeight: 1,\n};\n\nconst TOOLTIP_STYLE: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n alignSelf: 'stretch',\n padding: '16px 20px',\n backgroundColor: '#fff',\n border: '1px solid #CCC',\n borderRadius: '4px',\n boxShadow: '0 8px 10px rgba(13,13,13,0.12), 0 3px 14px rgba(13,13,13,0.08), 0 3px 5px rgba(13,13,13,0.04)',\n fontSize: '14px',\n lineHeight: '20px',\n color: '#0D0D0D',\n maxWidth: '240px',\n zIndex: 1100,\n pointerEvents: 'none',\n};\n\nconst TOOLTIP_ARROW_STYLE: React.CSSProperties = {\n position: 'absolute',\n bottom: '-6px',\n left: '50%',\n transform: 'translateX(-50%) rotate(45deg)',\n width: '10px',\n height: '10px',\n backgroundColor: '#fff',\n border: '1px solid #CCC',\n borderTop: 'none',\n borderLeft: 'none',\n};\n\n// ── Component ────────────────────────────────────────────\n\nfunction JumpPointNodeViewComponent({ node, decorations }: ReactNodeViewProps) {\n const id = node.attrs.id as string;\n const isAdjacent = decorations?.some((d) => (d as any).spec?.jumpPointAdjacent === true) ?? false;\n const isDuplicate = decorations?.some((d) => (d as any).spec?.jumpPointDuplicate === true) ?? false;\n const [showTooltip, setShowTooltip] = useState(false);\n const spanRef = useRef<HTMLSpanElement>(null);\n const [tooltipPos, setTooltipPos] = useState<{ top: number; left: number } | null>(null);\n\n const handleMouseEnter = useCallback(() => {\n if (!spanRef.current) return;\n const rect = spanRef.current.getBoundingClientRect();\n setTooltipPos({ top: rect.top - 8, left: rect.left + rect.width / 2 });\n setShowTooltip(true);\n }, []);\n\n if (isDuplicate) {\n return (\n <span\n ref={spanRef}\n className=\"ab-jump-point ab-jump-point-duplicate\"\n style={JUMP_POINT_DUPLICATE_STYLE}\n id={`jp-${id}`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={() => setShowTooltip(false)}\n >\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#9D091E\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{id}</span>\n <span style={{ ...CLOSE_BTN_STYLE, cursor: 'default' }}>\n <IconDiamondAlert size={12} fill=\"#D9352C\" />\n </span>\n {showTooltip && tooltipPos && createPortal(\n <span style={{ ...TOOLTIP_STYLE, top: tooltipPos.top, left: tooltipPos.left, transform: 'translate(-50%, -100%)' }}>\n &ldquo;{id}&rdquo; is already used as an anchor\n <span style={TOOLTIP_ARROW_STYLE} />\n </span>,\n document.body,\n )}\n </span>\n );\n }\n\n if (isAdjacent) {\n return (\n <span className=\"ab-jump-point ab-jump-point-adjacent\" style={JUMP_POINT_ADJACENT_STYLE} id={`jp-${id}`}>\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#AA5D04\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{`^${id}^`}</span>\n </span>\n );\n }\n\n return (\n <span className=\"ab-jump-point\" style={JUMP_POINT_STYLE} id={`jp-${id}`}>\n <span className=\"ab-jp-icon\"><IconAnchor size={12} fill=\"#AA5D04\" style={{ paddingLeft: '2px', flexShrink: 0 }} /></span>\n <span className=\"ab-jp-label\" style={LABEL_STYLE}>{id}</span>\n </span>\n );\n}\n\nexport function createJumpPointNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointNodeView',\n nodeViews: () => ({\n jumpPoint: createReactNodeView({ component: JumpPointNodeViewComponent, inline: true }),\n }),\n };\n}\n","/**\n * ProseMirror plugin that validates jumpPoint nodes and anchor references.\n *\n * 1. Attaches `jumpPointDuplicate` node decoration to jumpPoints with non-unique IDs.\n * 2. Attaches `brokenAnchorRef` inline decoration to link marks whose href=\"#ID\"\n * references a jumpPoint that doesn't exist in the document.\n * 3. Exports validation helpers for save-time checks.\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\nconst pluginKey = new PluginKey<DecorationSet>('jumpPointValidation');\n\n/** Collect all jumpPoint IDs in the document. */\nfunction collectJumpPointIds(state: EditorState): Set<string> {\n const ids = new Set<string>();\n state.doc.descendants((node) => {\n if (node.type.name === 'jumpPoint') {\n ids.add(node.attrs.id as string);\n }\n });\n return ids;\n}\n\nfunction findDuplicatePositions(state: EditorState): { pos: number; size: number }[] {\n const idCount = new Map<string, number>();\n const nodes: { id: string; pos: number; size: number }[] = [];\n\n state.doc.descendants((node, pos) => {\n if (node.type.name === 'jumpPoint') {\n const id = node.attrs.id as string;\n idCount.set(id, (idCount.get(id) ?? 0) + 1);\n nodes.push({ id, pos, size: node.nodeSize });\n }\n });\n\n return nodes.filter((n) => (idCount.get(n.id) ?? 0) > 1);\n}\n\n/** Find link marks with href=\"#ID\" where ID doesn't exist as a jumpPoint. */\nfunction findBrokenAnchorRefs(state: EditorState, existingIds: Set<string>): { from: number; to: number; refId: string }[] {\n const broken: { from: number; to: number; refId: string }[] = [];\n const linkMarkType = state.schema.marks.link;\n if (!linkMarkType) return broken;\n\n state.doc.descendants((node, pos) => {\n if (!node.isText) return;\n const linkMark = node.marks.find((m) => m.type === linkMarkType);\n if (!linkMark) return;\n\n const href = linkMark.attrs.href as string;\n if (!href || !href.startsWith('#')) return;\n\n const refId = href.slice(1); // strip \"#\"\n if (refId && !existingIds.has(refId)) {\n broken.push({ from: pos, to: pos + node.nodeSize, refId });\n }\n });\n\n return broken;\n}\n\n/**\n * Check whether the editor state contains duplicate jumpPoint IDs.\n */\nexport function hasDuplicateJumpPoints(state: EditorState): boolean {\n return findDuplicatePositions(state).length > 0;\n}\n\n/**\n * Check whether the editor state contains broken anchor references.\n */\nexport function hasBrokenAnchorRefs(state: EditorState): boolean {\n const ids = collectJumpPointIds(state);\n return findBrokenAnchorRefs(state, ids).length > 0;\n}\n\nexport function createJumpPointValidationPlugin(): ActionbookPlugin {\n return {\n name: 'jumpPointValidation',\n plugins: () => [\n new Plugin<DecorationSet>({\n key: pluginKey,\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, oldSet, _oldState, newState) {\n if (tr.docChanged) {\n return buildDecorations(newState);\n }\n return oldSet.map(tr.mapping, tr.doc);\n },\n },\n props: {\n decorations(state) {\n return pluginKey.getState(state) ?? DecorationSet.empty;\n },\n },\n }),\n ],\n };\n}\n\nfunction createBrokenRefIcon(refId: string): HTMLElement {\n const wrapper = document.createElement('span');\n wrapper.style.cssText = 'position: relative; display: inline-flex; align-items: center; cursor: help;';\n wrapper.contentEditable = 'false';\n\n // SVG diamond-alert icon\n const ns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(ns, 'svg');\n svg.setAttribute('width', '14');\n svg.setAttribute('height', '14');\n svg.setAttribute('viewBox', '0 0 16 16');\n svg.setAttribute('fill', 'none');\n const path = document.createElementNS(ns, 'path');\n path.setAttribute('fill-rule', 'evenodd');\n path.setAttribute('clip-rule', 'evenodd');\n path.setAttribute('d', 'M8.00002 0.666626L15.3334 7.99996L8.00002 15.3333L0.666687 7.99996L8.00002 0.666626ZM7.33335 8.66663V4.66663H8.66669V8.66663H7.33335ZM8.00002 11.3333C8.46026 11.3333 8.83335 10.9602 8.83335 10.5C8.83335 10.0397 8.46026 9.66663 8.00002 9.66663C7.53978 9.66663 7.16669 10.0397 7.16669 10.5C7.16669 10.9602 7.53978 11.3333 8.00002 11.3333Z');\n path.setAttribute('fill', '#D9352C');\n svg.appendChild(path);\n\n const iconSpan = document.createElement('span');\n iconSpan.style.cssText = 'display: inline-flex; margin-left: 2px; vertical-align: middle;';\n iconSpan.appendChild(svg);\n\n // Tooltip (appended to body on hover)\n const tooltip = document.createElement('span');\n tooltip.textContent = `Anchor \"${refId}\" no longer exists`;\n tooltip.style.cssText = [\n 'display:none', 'position:fixed', 'z-index:1100', 'pointer-events:none',\n 'padding:16px 20px', 'background:#fff', 'border:1px solid #CCC', 'border-radius:4px',\n 'box-shadow:0 8px 10px rgba(13,13,13,0.12),0 3px 14px rgba(13,13,13,0.08),0 3px 5px rgba(13,13,13,0.04)',\n 'font-size:14px', 'line-height:20px', 'color:#0D0D0D', 'max-width:240px', 'white-space:normal',\n ].join(';');\n\n const arrow = document.createElement('span');\n arrow.style.cssText = [\n 'position:absolute', 'bottom:-6px', 'left:50%', 'transform:translateX(-50%) rotate(45deg)',\n 'width:10px', 'height:10px', 'background:#fff', 'border:1px solid #CCC',\n 'border-top:none', 'border-left:none',\n ].join(';');\n tooltip.appendChild(arrow);\n\n wrapper.addEventListener('mouseenter', () => {\n const rect = wrapper.getBoundingClientRect();\n tooltip.style.left = `${rect.left + rect.width / 2}px`;\n tooltip.style.top = `${rect.top - 8}px`;\n tooltip.style.transform = 'translate(-50%, -100%)';\n tooltip.style.display = 'flex';\n tooltip.style.flexDirection = 'column';\n tooltip.style.alignItems = 'flex-start';\n document.body.appendChild(tooltip);\n });\n wrapper.addEventListener('mouseleave', () => {\n tooltip.style.display = 'none';\n if (tooltip.parentElement === document.body) document.body.removeChild(tooltip);\n });\n\n wrapper.appendChild(iconSpan);\n return wrapper;\n}\n\nfunction buildDecorations(state: EditorState): DecorationSet {\n const decos: Decoration[] = [];\n\n // 1. Duplicate jumpPoints\n const duplicates = findDuplicatePositions(state);\n for (const { pos, size } of duplicates) {\n decos.push(\n Decoration.node(pos, pos + size, { class: 'jump-point-duplicate' }, { jumpPointDuplicate: true }),\n );\n }\n\n // 2. Broken anchor references (link marks with href=\"#ID\" where ID doesn't exist)\n const existingIds = collectJumpPointIds(state);\n const brokenRefs = findBrokenAnchorRefs(state, existingIds);\n for (const { from, to, refId } of brokenRefs) {\n decos.push(\n Decoration.inline(from, to, {\n class: 'broken-anchor-ref',\n 'data-broken-ref': refId,\n spellcheck: 'false',\n style: 'color: #D9352C; font-weight: 500; text-decoration: none !important; text-decoration-line: none !important;',\n }),\n );\n decos.push(Decoration.widget(to, () => createBrokenRefIcon(refId), { side: -1 }));\n }\n\n if (decos.length === 0) return DecorationSet.empty;\n return DecorationSet.create(state.doc, decos);\n}\n","/**\n * React NodeView plugin for the `inlineToolTag` node.\n *\n * Renders a styled badge matching ActionbookRenderer's resourceTag output:\n * colored icon block + colored text label with border.\n */\nimport React from 'react';\nimport { createReactNodeView } from '../nodeView/ReactNodeView';\nimport type { ReactNodeViewProps } from '../nodeView/ReactNodeView';\nimport type { ActionbookPlugin } from './types';\nimport {\n IconTool,\n IconManual,\n IconMessageTemplate,\n IconHandoff,\n IconTimeDiff,\n IconStop,\n} from '../components/icons';\n\nconst RESOURCE_TAG_COLORS: Record<string, string> = {\n tool: '#027D69',\n manual: '#5959D3',\n agent_message_template: '#8012B3',\n handoff: '#D25309',\n time_diff: '#FB6B6B',\n};\nconst DEFAULT_COLOR = '#027D69';\n\ntype IconComponent = React.ComponentType<{ size?: number; fill?: string; style?: React.CSSProperties }>;\n\nconst RESOURCE_TAG_ICONS: Record<string, IconComponent> = {\n tool: IconTool,\n manual: IconManual,\n agent_message_template: IconMessageTemplate,\n handoff: IconHandoff,\n time_diff: IconTimeDiff,\n};\nconst DEFAULT_ICON = IconTool;\n\n// Per-resourceId overrides (Figma spec: End conversation uses black, not green)\nconst RESOURCE_ID_OVERRIDES: Record<string, { color: string; icon: IconComponent }> = {\n 'close-happy-tiger': { color: '#0D0D0D', icon: IconStop },\n};\n\nconst OUTER_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n padding: '2px',\n border: '1px solid #CCCCCC',\n borderRadius: '2px',\n alignItems: 'center',\n backgroundColor: 'white',\n userSelect: 'none',\n cursor: 'default',\n boxSizing: 'border-box',\n};\n\nconst ICON_BLOCK_BASE: React.CSSProperties = {\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '16px',\n height: '16px',\n borderRadius: '2px',\n flexShrink: 0,\n};\n\nconst LABEL_BASE: React.CSSProperties = {\n padding: '0 4px',\n fontSize: '12px',\n lineHeight: '16px',\n userSelect: 'none',\n};\n\nfunction InlineToolTagNodeViewComponent({ node, selected }: ReactNodeViewProps) {\n const type = node.attrs.type as string;\n const text = node.attrs.text as string;\n const resourceId = node.attrs.resourceId as string;\n const override = RESOURCE_ID_OVERRIDES[resourceId];\n const color = override?.color ?? RESOURCE_TAG_COLORS[type] ?? DEFAULT_COLOR;\n const Icon = override?.icon ?? RESOURCE_TAG_ICONS[type] ?? DEFAULT_ICON;\n\n const style: React.CSSProperties = selected\n ? { ...OUTER_STYLE, boxShadow: `inset 0 0 0 1px ${color}` }\n : OUTER_STYLE;\n\n return (\n <span style={style} data-type={type} data-resource-id={node.attrs.resourceId as string}>\n <span style={{ ...ICON_BLOCK_BASE, backgroundColor: color }}>\n <Icon size={9} fill=\"white\" />\n </span>\n <span style={{ ...LABEL_BASE, color }}>{text}</span>\n </span>\n );\n}\n\nexport function createInlineToolTagNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'inlineToolTagNodeView',\n nodeViews: () => ({\n inlineToolTag: createReactNodeView({ component: InlineToolTagNodeViewComponent, inline: true }),\n }),\n };\n}\n","import { Plugin, PluginKey } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { fromProseMirrorJSON, type JSONContent } from '../../compat/prosemirror';\nimport { analyzeJinjaBlocks } from '../../jinja/analyzer';\nimport type { ActionbookPlugin } from './types';\n\nconst jinjaPluginKey = new PluginKey('jinjaDecoration');\n\nconst JINJA_TAG_RE = /\\{%\\s*(if|elif|else|endif)\\s*([^%]*?)\\s*%\\}/g;\n\ninterface BlockPosInfo {\n index: number;\n from: number;\n to: number;\n}\n\nfunction getBlockPositions(doc: PMNode): BlockPosInfo[] {\n const blocks: BlockPosInfo[] = [];\n let index = 0;\n doc.forEach((node, offset) => {\n blocks.push({ index, from: offset, to: offset + node.nodeSize });\n index++;\n });\n return blocks;\n}\n\nfunction addInlineChipDecorations(doc: PMNode, decorations: Decoration[]) {\n doc.descendants((node, pos) => {\n if (!node.isText) return;\n const text = node.text!;\n JINJA_TAG_RE.lastIndex = 0;\n let match;\n while ((match = JINJA_TAG_RE.exec(text)) !== null) {\n const from = pos + match.index;\n const to = from + match[0].length;\n const keyword = match[1]; // if | elif | else | endif\n decorations.push(\n Decoration.inline(from, to, {\n class: `jinja-chip jinja-chip-${keyword}`,\n }),\n );\n }\n });\n}\n\nfunction addStructureBorderDecorations(\n doc: PMNode,\n blocks: BlockPosInfo[],\n decorations: Decoration[],\n) {\n const json = doc.toJSON() as JSONContent;\n let ast;\n try {\n ast = fromProseMirrorJSON(json);\n } catch {\n return;\n }\n\n const structures = analyzeJinjaBlocks(ast);\n\n for (const structure of structures) {\n // Build a map: blockIndex → branch type for every block in this structure\n // Tag lines (if/elif/else/endif) get the type of the branch they start\n // Content blocks get the type of their enclosing branch\n const blockBranchType = new Map<number, 'if' | 'elif' | 'else'>();\n\n for (const branch of structure.branches) {\n // The tag line itself\n blockBranchType.set(branch.tagBlockIndex, branch.type);\n // Content blocks under this branch\n for (let i = branch.blockStartIndex; i < branch.blockEndIndex; i++) {\n // Don't overwrite tag lines of subsequent branches\n if (!blockBranchType.has(i)) {\n blockBranchType.set(i, branch.type);\n }\n }\n }\n // endif tag line: use the last branch's type\n const lastBranch = structure.branches[structure.branches.length - 1];\n if (lastBranch && !blockBranchType.has(structure.endifTagBlockIndex)) {\n blockBranchType.set(structure.endifTagBlockIndex, lastBranch.type);\n }\n\n // Now emit decorations per contiguous run of same branch type\n const first = structure.ifTagBlockIndex;\n const last = structure.endifTagBlockIndex;\n\n for (let i = first; i <= last; i++) {\n const block = blocks[i];\n if (!block) continue;\n\n const branchType = blockBranchType.get(i) || 'if';\n const prevType = i > first ? blockBranchType.get(i - 1) : undefined;\n const nextType = i < last ? blockBranchType.get(i + 1) : undefined;\n\n const classes = ['jinja-bar', `jinja-bar-${branchType}`];\n // Segment boundaries: start/end of a contiguous same-color run\n if (i === first || prevType !== branchType) classes.push('jinja-bar-first');\n if (i === last || nextType !== branchType) classes.push('jinja-bar-last');\n\n decorations.push(Decoration.node(block.from, block.to, { class: classes.join(' ') }));\n }\n }\n}\n\n/** Quick scan: does the document contain any jinja tags at all? */\nfunction hasJinjaTags(doc: PMNode): boolean {\n let found = false;\n doc.descendants((node) => {\n if (found) return false; // stop early\n if (node.isText && node.text!.includes('{%')) {\n found = true;\n return false;\n }\n });\n return found;\n}\n\nfunction buildDecorations(doc: PMNode): DecorationSet {\n // Fast path: skip entirely when no jinja tags present\n if (!hasJinjaTags(doc)) return DecorationSet.empty;\n\n const blocks = getBlockPositions(doc);\n const decorations: Decoration[] = [];\n\n addInlineChipDecorations(doc, decorations);\n addStructureBorderDecorations(doc, blocks, decorations);\n\n if (decorations.length === 0) return DecorationSet.empty;\n return DecorationSet.create(doc, decorations);\n}\n\nexport function createJinjaDecorationPlugin(): ActionbookPlugin {\n return {\n name: 'jinjaDecoration',\n plugins: () => [\n new Plugin({\n key: jinjaPluginKey,\n state: {\n init(_, state) {\n return buildDecorations(state.doc);\n },\n apply(tr, oldDecos) {\n if (!tr.docChanged) return oldDecos;\n return buildDecorations(tr.doc);\n },\n },\n props: {\n decorations(state) {\n return jinjaPluginKey.getState(state) as DecorationSet;\n },\n },\n }),\n ],\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type { Node as PMNode, Schema } from 'prosemirror-model';\nimport { Plugin, TextSelection } from 'prosemirror-state';\nimport type { EditorView, NodeView, ViewMutationRecord } from 'prosemirror-view';\nimport { tokenizeCondition } from '../../jinja/conditionHighlighter';\nimport { validateCondition } from '../../jinja/evaluator';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\ntype BranchType = 'if' | 'elif' | 'else';\n\ninterface BranchContext {\n readonly blockNode: PMNode;\n readonly blockPos: number;\n readonly branchNode: PMNode;\n readonly branchPos: number;\n readonly branchIndex: number;\n}\n\ninterface PopupMenuItem {\n readonly label: string;\n readonly disabled?: boolean;\n readonly onSelect: () => void;\n}\n\ninterface MenuPosition {\n readonly top: number;\n readonly left?: number;\n readonly right?: number;\n}\n\ninterface JinjaBranchHeaderProps {\n readonly branchType: BranchType;\n readonly condition: string;\n readonly editable?: boolean;\n readonly isBodyEmpty: boolean;\n readonly isBodyTouched: boolean;\n readonly onConditionChange: (value: string) => void;\n readonly onDelete: () => void;\n readonly onAddBranch: (branchType: Exclude<BranchType, 'if'>) => void;\n readonly isLastBranch: boolean;\n readonly hasElseBranch: boolean;\n}\n\ninterface ConditionDisplayProps {\n readonly branchType: BranchType;\n readonly condition: string;\n readonly editable?: boolean;\n readonly onConditionChange: (value: string) => void;\n readonly onBackspaceEmpty?: () => void;\n readonly onConditionBlur?: () => void;\n}\n\ninterface BranchPopupMenuProps {\n readonly items: readonly PopupMenuItem[];\n readonly position: MenuPosition;\n}\n\nconst PLACEHOLDER_TEXT = 'Describe what AI agent should do when this condition is met';\nconst CONDITION_PLACEHOLDER = 'Write a condition in natural language';\nconst STYLE_ID = 'ab-jinja-if-block-styles';\n\nconst JINJA_STYLES = `\n.jinja-if-block {\n margin: 8px 0;\n}\n\n.jinja-branch {\n position: relative;\n display: grid;\n grid-template-areas:\n \"header\"\n \"error\"\n \"body\"\n \"body-error\"\n \"footer\";\n gap: 0;\n}\n\n.jinja-branch-controls {\n display: contents;\n}\n\n.jinja-branch-header {\n grid-area: header;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px;\n border: 1px solid #E0E0E0;\n border-radius: 4px;\n background: #FFFFFF;\n}\n\n.jinja-branch-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 32px;\n padding: 0 8px;\n border-radius: 4px;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n font-weight: 700;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.jinja-branch-badge-if,\n.jinja-branch-badge-elif {\n background: #E7F1FF;\n color: #0D0D0D;\n}\n\n.jinja-branch-badge-else {\n background: #F7F7F7;\n color: #424242;\n}\n\n.jinja-branch-condition {\n flex: 1;\n min-width: 0;\n min-height: 20px;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n width: 100%;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n color: #0D0D0D;\n cursor: text;\n text-align: left;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n white-space: nowrap;\n}\n\n.jinja-branch-condition:focus-visible,\n.jinja-ghost-btn:focus-visible,\n.jinja-popup-item:focus-visible {\n outline: 2px solid rgba(98, 16, 204, 0.28);\n outline-offset: 2px;\n}\n\n.jinja-condition-placeholder {\n color: #A6A6A6;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-branch-header-invalid {\n border: 1px solid #D9352C;\n border-radius: 4px;\n}\n\n.jinja-condition-error {\n grid-area: error;\n display: flex;\n align-items: center;\n padding: 4px 0 4px 52px;\n color: #D9352C;\n font-size: 12px;\n line-height: 16px;\n}\n\n.jinja-body-error {\n grid-area: body-error;\n display: flex;\n align-items: center;\n padding: 0 0 4px 52px;\n color: #D9352C;\n font-size: 12px;\n line-height: 16px;\n}\n\n.jinja-token-variable {\n color: #4141B2;\n}\n\n.jinja-token-operator {\n color: #858585;\n}\n\n.jinja-token-value {\n color: #0D0D0D;\n}\n\n.jinja-token-punctuation {\n color: #858585;\n}\n\n.jinja-otherwise {\n flex: 1;\n color: #858585;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-branch-actions,\n.jinja-add-footer-actions {\n position: relative;\n display: inline-flex;\n align-items: center;\n}\n\n.jinja-branch-body {\n grid-area: body;\n display: flex;\n gap: 12px;\n padding: 0 8px;\n min-height: 52px;\n}\n\n.jinja-branch-divider-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n justify-content: center;\n}\n\n.jinja-branch-divider {\n width: 1px;\n background: #E0E0E0;\n}\n\n/* L-shaped divider for the last branch (ELSE) */\n.jinja-branch-last .jinja-branch-divider-col {\n align-items: flex-start;\n padding-left: 16px;\n}\n\n.jinja-branch-last .jinja-branch-divider {\n width: 16px;\n height: 28px;\n background: none;\n border-left: 1px solid #E0E0E0;\n border-bottom: 1px solid #E0E0E0;\n border-bottom-left-radius: 8px;\n}\n\n.jinja-branch-content {\n position: relative;\n flex: 1;\n min-width: 0;\n padding: 16px 0;\n}\n\n.jinja-branch-content.jinja-branch-content-empty::before {\n content: attr(data-placeholder);\n position: absolute;\n top: 16px;\n left: 0;\n color: #A6A6A6;\n font-size: 14px;\n line-height: 20px;\n pointer-events: none;\n}\n\n.jinja-add-footer {\n grid-area: footer;\n display: flex;\n padding: 8px;\n}\n\n.jinja-add-footer .jinja-add-footer-col {\n width: 32px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.jinja-ghost-btn {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: #858585;\n cursor: pointer;\n}\n\n.jinja-ghost-btn:hover:not(:disabled) {\n background: rgba(13, 13, 13, 0.04);\n}\n\n.jinja-ghost-btn.jinja-add-btn {\n color: #5E5E5E;\n}\n\n.jinja-ghost-btn.jinja-add-btn.active {\n background: #DCDBFF;\n color: #6210CC;\n}\n\n.jinja-ghost-btn:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.jinja-popup-menu {\n position: absolute;\n z-index: 20;\n min-width: 200px;\n padding: 8px 0;\n background: #FFFFFF;\n border-radius: 4px;\n box-shadow: 0px 8px 10px 0px rgba(13,13,13,0.12), 0px 3px 14px 0px rgba(13,13,13,0.08), 0px 3px 5px 0px rgba(13,13,13,0.04);\n}\n\n.jinja-popup-item {\n width: 100%;\n display: block;\n padding: 6px 16px;\n border: none;\n background: transparent;\n color: #0D0D0D;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: -0.1px;\n}\n\n.jinja-popup-item:hover:not(:disabled) {\n background: rgba(13, 13, 13, 0.04);\n}\n\n.jinja-popup-item:disabled {\n color: #A6A6A6;\n cursor: default;\n}\n\n.jinja-condition-input {\n width: 100%;\n min-width: 0;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n background: transparent;\n color: #0D0D0D;\n caret-color: #6210CC;\n font-family: \"Roboto Mono\", monospace;\n font-size: 13px;\n line-height: 20px;\n letter-spacing: -0.3px;\n}\n\n.jinja-condition-input::placeholder {\n color: #A6A6A6;\n}\n`;\n\nclass StyleManager {\n private static refCount = 0;\n private static styleEl: HTMLStyleElement | null = null;\n\n static acquire(): void {\n if (this.refCount++ > 0) return;\n\n const existing = document.getElementById(STYLE_ID);\n if (existing instanceof HTMLStyleElement) {\n this.styleEl = existing;\n return;\n }\n\n this.styleEl = document.createElement('style');\n this.styleEl.id = STYLE_ID;\n this.styleEl.textContent = JINJA_STYLES;\n document.head.appendChild(this.styleEl);\n }\n\n static release(): void {\n if (this.refCount === 0) return;\n if (--this.refCount > 0) return;\n\n if (this.styleEl?.parentNode) {\n this.styleEl.remove();\n }\n this.styleEl = null;\n }\n}\n\nfunction getBranchContext(view: EditorView, nodePos: number): BranchContext | null {\n try {\n const { doc } = view.state;\n const resolved = doc.resolve(nodePos);\n let blockDepth = -1;\n\n for (let depth = resolved.depth; depth >= 0; depth--) {\n if (resolved.node(depth).type.name === 'jinjaIfBlock') {\n blockDepth = depth;\n break;\n }\n }\n\n if (blockDepth < 0) {\n return null;\n }\n\n const blockNode = resolved.node(blockDepth);\n const blockPos = blockDepth === 0 ? 0 : resolved.before(blockDepth);\n\n let branchOffset = blockPos + 1;\n for (let index = 0; index < blockNode.childCount; index++) {\n const branchNode = blockNode.child(index);\n if (branchOffset === nodePos) {\n return {\n blockNode,\n blockPos,\n branchNode,\n branchPos: branchOffset,\n branchIndex: index,\n };\n }\n branchOffset += branchNode.nodeSize;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction isBranchBodyEmpty(node: PMNode): boolean {\n if (node.childCount !== 1) return false;\n const firstChild = node.firstChild;\n return firstChild?.type.name === 'paragraph' && firstChild.content.size === 0;\n}\n\nfunction isBranchNode(node: PMNode | null | undefined): node is PMNode {\n return node?.type.name === 'jinjaIfBranch';\n}\n\nfunction createBranchNode(schema: Schema, branchType: Exclude<BranchType, 'if'>, condition: string): PMNode | null {\n const branchNodeType = schema.nodes.jinjaIfBranch;\n const paragraphNode = schema.nodes.paragraph?.createAndFill();\n\n if (!branchNodeType || !paragraphNode) {\n return null;\n }\n\n return branchNodeType.create(\n {\n branchType,\n condition: branchType === 'else' ? '' : condition,\n },\n paragraphNode,\n );\n}\n\nfunction getLastBranchOfBlock(view: EditorView, nodePos: number): { index: number; node: PMNode } | null {\n const context = getBranchContext(view, nodePos);\n if (!context || context.blockNode.childCount === 0) {\n return null;\n }\n\n const index = context.blockNode.childCount - 1;\n return {\n index,\n node: context.blockNode.child(index),\n };\n}\n\nfunction getLastNonElseBranchIndex(view: EditorView, nodePos: number): number {\n const context = getBranchContext(view, nodePos);\n if (!context) return -1;\n for (let i = context.blockNode.childCount - 1; i >= 0; i--) {\n if ((context.blockNode.child(i).attrs.branchType as BranchType) !== 'else') return i;\n }\n return -1;\n}\n\nfunction getElseBranch(view: EditorView, nodePos: number): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n\n for (let index = 0; index < context.blockNode.childCount; index++) {\n if ((context.blockNode.child(index).attrs.branchType as BranchType) === 'else') {\n return true;\n }\n }\n\n return false;\n}\n\nfunction deleteBlock(view: EditorView, blockPos: number): boolean {\n const blockNode = view.state.doc.nodeAt(blockPos);\n if (blockNode?.type.name !== 'jinjaIfBlock') {\n return false;\n }\n\n view.dispatch(view.state.tr.delete(blockPos, blockPos + blockNode.nodeSize).scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction insertNewBranch(\n view: EditorView,\n nodePos: number,\n branchType: Exclude<BranchType, 'if'>,\n condition = '',\n): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n if ((context.branchNode.attrs.branchType as BranchType) === 'else') return false;\n\n const lastBranch = getLastBranchOfBlock(view, nodePos);\n if (!lastBranch) return false;\n\n if (branchType === 'else') {\n if (getElseBranch(view, nodePos)) return false;\n if (lastBranch.index !== context.branchIndex) return false;\n }\n\n const newBranch = createBranchNode(view.state.schema, branchType, condition);\n if (!newBranch) return false;\n\n const insertPos = context.branchPos + context.branchNode.nodeSize;\n const tr = view.state.tr.insert(insertPos, newBranch);\n // Move cursor into the new branch's content (branch > paragraph)\n const cursorPos = insertPos + 2; // +1 into branch, +1 into paragraph\n if (cursorPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.near(tr.doc.resolve(cursorPos)));\n }\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction deleteBranch(view: EditorView, nodePos: number, branchType: BranchType): boolean {\n const context = getBranchContext(view, nodePos);\n if (!context) return false;\n\n const { branchNode, branchPos, branchIndex, blockNode, blockPos } = context;\n\n if (branchType === 'if') {\n // Delete entire jinja block, replace with empty paragraph\n const tr = view.state.tr;\n tr.replaceWith(blockPos, blockPos + blockNode.nodeSize, view.state.schema.nodes.paragraph.create());\n tr.setSelection(TextSelection.near(tr.doc.resolve(blockPos)));\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n }\n\n // ELIF or ELSE → delete only this branch\n const tr = view.state.tr;\n tr.delete(branchPos, branchPos + branchNode.nodeSize);\n tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(branchPos)), -1));\n view.dispatch(tr.scrollIntoView());\n view.focus();\n return true;\n}\n\nfunction renderCondition(condition: string) {\n const tokens = tokenizeCondition(condition);\n const rendered: JSX.Element[] = [];\n\n for (let index = 0; index < tokens.length; index++) {\n const token = tokens[index];\n // Skip whitespace-only gaps — CSS gap handles spacing between tokens\n rendered.push(\n <span key={`token-${index}-${token.start}`} className={`jinja-token-${token.category}`}>\n {token.text}\n </span>,\n );\n }\n\n return rendered;\n}\n\nfunction ConditionDisplay({\n branchType,\n condition,\n editable = true,\n onConditionChange,\n onBackspaceEmpty,\n onConditionBlur,\n}: ConditionDisplayProps) {\n const [isEditing, setIsEditing] = useState(false);\n const [draftValue, setDraftValue] = useState(condition);\n const inputRef = useRef<HTMLInputElement>(null);\n const autoFocusedRef = useRef(false);\n\n useEffect(() => {\n if (!isEditing) {\n setDraftValue(condition);\n }\n }, [condition, isEditing]);\n\n useEffect(() => {\n if (isEditing) {\n inputRef.current?.focus();\n inputRef.current?.select();\n }\n }, [isEditing]);\n\n // Auto-enter edit mode once when condition is empty (newly inserted)\n useEffect(() => {\n if (editable && !condition && !autoFocusedRef.current) {\n autoFocusedRef.current = true;\n setIsEditing(true);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (branchType === 'else') {\n return <span className=\"jinja-otherwise\">Otherwise</span>;\n }\n\n const commit = () => {\n // Dispatch the value change BEFORE leaving edit mode.\n // If setIsEditing(false) runs first, ProseMirror regains focus and\n // triggers a re-render with stale node.attrs, losing the draft.\n if (draftValue !== condition) {\n onConditionChange(draftValue);\n }\n setIsEditing(false);\n onConditionBlur?.();\n };\n\n const cancel = () => {\n setDraftValue(condition);\n setIsEditing(false);\n };\n\n if (isEditing && editable) {\n return (\n <input\n ref={inputRef}\n className=\"jinja-condition-input\"\n value={draftValue}\n placeholder={CONDITION_PLACEHOLDER}\n onChange={(event) => setDraftValue(event.target.value)}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commit();\n }\n\n if (event.key === 'Escape') {\n event.preventDefault();\n cancel();\n }\n\n if (event.key === 'Backspace' && draftValue === '' && onBackspaceEmpty) {\n event.preventDefault();\n onBackspaceEmpty();\n }\n }}\n />\n );\n }\n\n return (\n <button\n type=\"button\"\n className=\"jinja-branch-condition\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (editable) {\n setDraftValue(condition);\n setIsEditing(true);\n }\n }}\n >\n {condition.length > 0 ? (\n condition.trim().length > 0 ? renderCondition(condition) : <span className=\"jinja-token-identifier\">{condition}</span>\n ) : (\n <span className=\"jinja-condition-placeholder\">{CONDITION_PLACEHOLDER}</span>\n )}\n </button>\n );\n}\n\nfunction BranchPopupMenu({ items, position }: BranchPopupMenuProps) {\n return (\n <div\n className=\"jinja-popup-menu\"\n style={{\n top: position.top,\n left: position.left,\n right: position.right,\n }}\n role=\"menu\"\n >\n {items.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n className=\"jinja-popup-item\"\n disabled={item.disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (!item.disabled) {\n item.onSelect();\n }\n }}\n role=\"menuitem\"\n >\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n\nfunction JinjaBranchHeader({\n branchType,\n condition,\n editable = true,\n isBodyEmpty,\n isBodyTouched,\n onConditionChange,\n onDelete,\n onAddBranch,\n isLastBranch,\n hasElseBranch,\n}: JinjaBranchHeaderProps) {\n const [menuSource, setMenuSource] = useState<'kebab' | 'footer' | null>(null);\n const kebabRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!menuSource) return;\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (kebabRef.current?.contains(target) || footerRef.current?.contains(target)) {\n return;\n }\n setMenuSource(null);\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setMenuSource(null);\n }\n };\n\n document.addEventListener('pointerdown', handlePointerDown, true);\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown, true);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [menuSource]);\n\n const menuItems: PopupMenuItem[] = [];\n\n if (editable) {\n if (!hasElseBranch) {\n menuItems.push({\n label: 'Else if',\n onSelect: () => onAddBranch('elif'),\n });\n menuItems.push({\n label: 'Else',\n onSelect: () => onAddBranch('else'),\n });\n }\n menuItems.push({\n label: 'Delete',\n onSelect: onDelete,\n });\n }\n\n const canOpenFooterMenu = editable && isLastBranch && branchType !== 'else';\n const isMenuOpen = (source: 'kebab' | 'footer') => menuSource === source && menuItems.length > 0;\n\n // Track whether the condition input has been blurred at least once\n const [conditionTouched, setConditionTouched] = useState(false);\n\n // Condition validation — show error after blur:\n // - empty condition after touch → \"This field is required.\"\n // - non-empty invalid syntax → parser error message\n const conditionError = (() => {\n if (branchType === 'else') return null;\n if (condition.length === 0) {\n return conditionTouched ? 'This field is required.' : null;\n }\n const result = validateCondition(condition);\n return result.valid ? null : (result.error || 'Invalid condition');\n })();\n\n return (\n <>\n <div className={`jinja-branch-header${conditionError ? ' jinja-branch-header-invalid' : ''}`}>\n <span className={`jinja-branch-badge jinja-branch-badge-${branchType}`}>\n {branchType === 'elif' ? 'ELSE IF' : branchType.toUpperCase()}\n </span>\n <ConditionDisplay\n branchType={branchType}\n condition={condition}\n editable={editable}\n onConditionChange={onConditionChange}\n onBackspaceEmpty={onDelete}\n onConditionBlur={() => setConditionTouched(true)}\n />\n {editable ? (\n <div className=\"jinja-branch-actions\" ref={kebabRef}>\n <button\n type=\"button\"\n className=\"jinja-ghost-btn\"\n aria-label={`${branchType} branch options`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (menuItems.length > 0) {\n setMenuSource((current) => (current === 'kebab' ? null : 'kebab'));\n }\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\"><circle cx=\"8\" cy=\"3\" r=\"1.5\"/><circle cx=\"8\" cy=\"8\" r=\"1.5\"/><circle cx=\"8\" cy=\"13\" r=\"1.5\"/></svg>\n </button>\n {isMenuOpen('kebab') ? (\n <BranchPopupMenu\n position={{ top: 28, right: 0 }}\n items={menuItems\n .filter((item) => item.label === 'Delete')\n .map((item) => ({\n ...item,\n label: branchType === 'if' ? 'Delete all' : 'Delete',\n onSelect: () => {\n setMenuSource(null);\n item.onSelect();\n },\n }))}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n\n {conditionError && <div className=\"jinja-condition-error\">{conditionError}</div>}\n\n {isBodyEmpty && isBodyTouched && editable && (\n <div className=\"jinja-body-error\">This field is required.</div>\n )}\n\n {isLastBranch && editable ? (\n <div className=\"jinja-add-footer\">\n <div className=\"jinja-add-footer-col\">\n <div className=\"jinja-add-footer-actions\" ref={footerRef}>\n <button\n type=\"button\"\n className={`jinja-ghost-btn jinja-add-btn${menuSource === 'footer' ? ' active' : ''}`}\n aria-label=\"Add branch\"\n disabled={!canOpenFooterMenu}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n if (canOpenFooterMenu && menuItems.length > 0) {\n setMenuSource((current) => (current === 'footer' ? null : 'footer'));\n }\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7.33337 11L7.33337 8.66666L5.00004 8.66666V7.33333L7.33337 7.33333V4.99999H8.66671V7.33333H11V8.66666H8.66671L8.66671 11H7.33337Z\" fill=\"currentColor\"/>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M8.00004 14.6667C11.6819 14.6667 14.6667 11.6819 14.6667 7.99999C14.6667 4.3181 11.6819 1.33333 8.00004 1.33333C4.31814 1.33333 1.33337 4.3181 1.33337 7.99999C1.33337 11.6819 4.31814 14.6667 8.00004 14.6667ZM13.3334 7.99999C13.3334 10.9455 10.9456 13.3333 8.00004 13.3333C5.05452 13.3333 2.66671 10.9455 2.66671 7.99999C2.66671 5.05448 5.05452 2.66666 8.00004 2.66666C10.9456 2.66666 13.3334 5.05448 13.3334 7.99999Z\" fill=\"currentColor\"/>\n </svg>\n </button>\n {isMenuOpen('footer') ? (\n <BranchPopupMenu\n position={{ top: 28, left: 0 }}\n items={menuItems\n .filter((item) => item.label === 'Else if' || item.label === 'Else')\n .map((item) => ({\n ...item,\n onSelect: () => {\n setMenuSource(null);\n item.onSelect();\n },\n }))}\n />\n ) : null}\n </div>\n </div>\n </div>\n ) : null}\n </>\n );\n}\n\nclass JinjaIfBlockView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n constructor() {\n this.dom = document.createElement('div');\n this.dom.className = 'jinja-if-block';\n this.dom.setAttribute('data-jinja-if-block', '');\n this.contentDOM = this.dom;\n // Deferred: notify children to re-render after all siblings are mounted\n requestAnimationFrame(() => this.notifyChildren());\n }\n\n private notifyChildren() {\n this.dom.querySelectorAll('.jinja-branch').forEach((el) => {\n el.dispatchEvent(new CustomEvent('jinja-siblings-changed', { bubbles: false }));\n });\n }\n\n update(node: PMNode): boolean {\n if (node.type.name !== 'jinjaIfBlock') return false;\n requestAnimationFrame(() => this.notifyChildren());\n return true;\n }\n}\n\nclass JinjaIfBranchView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n\n private headerContainer: HTMLElement;\n private root: Root;\n private node: PMNode;\n private view: EditorView;\n private getPos: () => number | undefined;\n private bodyTouched = false;\n\n constructor(node: PMNode, view: EditorView, getPos: () => number | undefined) {\n this.node = node;\n this.view = view;\n this.getPos = getPos;\n\n StyleManager.acquire();\n\n this.dom = document.createElement('div');\n this.headerContainer = document.createElement('div');\n const body = document.createElement('div');\n const dividerColumn = document.createElement('div');\n const divider = document.createElement('div');\n\n this.dom.appendChild(this.headerContainer);\n this.dom.appendChild(body);\n\n this.headerContainer.className = 'jinja-branch-controls';\n this.headerContainer.contentEditable = 'false';\n\n body.className = 'jinja-branch-body';\n dividerColumn.className = 'jinja-branch-divider-col';\n dividerColumn.contentEditable = 'false';\n divider.className = 'jinja-branch-divider';\n dividerColumn.appendChild(divider);\n\n this.contentDOM = document.createElement('div');\n this.contentDOM.className = 'jinja-branch-content';\n this.contentDOM.setAttribute('data-placeholder', PLACEHOLDER_TEXT);\n\n body.appendChild(dividerColumn);\n body.appendChild(this.contentDOM);\n\n // Track body blur — show \"required\" error when body is empty after losing focus\n this.contentDOM.addEventListener('focusout', () => {\n if (!this.bodyTouched && isBranchBodyEmpty(this.node)) {\n this.bodyTouched = true;\n this.render();\n }\n });\n\n this.root = createRoot(this.headerContainer);\n\n // Listen for sibling changes (dispatched by parent JinjaIfBlockView)\n this._onSiblingsChanged = () => this.render();\n this.dom.addEventListener('jinja-siblings-changed', this._onSiblingsChanged);\n\n // Listen for editable changes (dispatched by the editable-watcher plugin)\n this._onEditableChanged = () => this.render();\n this.dom.addEventListener('jinja-editable-changed', this._onEditableChanged);\n\n this.syncDOM();\n this.render();\n }\n\n private _onSiblingsChanged: (() => void) | null = null;\n private _onEditableChanged: (() => void) | null = null;\n\n private syncDOM(): void {\n const branchType = this.node.attrs.branchType as BranchType;\n this.dom.className = `jinja-branch jinja-branch-${branchType}`;\n this.dom.setAttribute('data-jinja-branch', '');\n this.dom.setAttribute('data-branch-type', branchType);\n this.dom.setAttribute('data-condition', String(this.node.attrs.condition ?? ''));\n\n this.contentDOM.classList.toggle('jinja-branch-content-empty', isBranchBodyEmpty(this.node));\n }\n\n private render(): void {\n const nodePos = this.getPos();\n\n let context: BranchContext | null = null;\n let lastBranch: { index: number } | null = null;\n if (nodePos != null) {\n context = getBranchContext(this.view, nodePos);\n lastBranch = getLastBranchOfBlock(this.view, nodePos);\n\n // Set data-branch-index\n let branchIdx = context?.branchIndex ?? -1;\n if (branchIdx < 0 && this.dom.parentElement) {\n const siblings = this.dom.parentElement.querySelectorAll(':scope > [data-jinja-branch]');\n branchIdx = Array.prototype.indexOf.call(siblings, this.dom);\n }\n if (branchIdx >= 0) {\n this.dom.setAttribute('data-branch-index', String(branchIdx));\n }\n }\n\n const branchType = this.node.attrs.branchType as BranchType;\n const condition = String(this.node.attrs.condition ?? '');\n\n // Use safe defaults when context is unavailable (e.g. right after insertion)\n const isLast = context && lastBranch ? lastBranch.index === context.branchIndex : true;\n const lastNonElseIdx = context ? getLastNonElseBranchIndex(this.view, nodePos!) : 0;\n const showAddButton = context ? context.branchIndex === lastNonElseIdx : true;\n\n // Add/remove last-branch class for L-shaped divider\n this.dom.classList.toggle('jinja-branch-last', isLast);\n\n this.root.render(\n <JinjaBranchHeader\n branchType={branchType}\n condition={condition}\n editable={this.view.editable && this.view.dom.getAttribute('contenteditable') !== 'false'}\n isBodyEmpty={isBranchBodyEmpty(this.node)}\n isBodyTouched={this.bodyTouched}\n isLastBranch={showAddButton}\n hasElseBranch={context && nodePos != null ? getElseBranch(this.view, nodePos) : false}\n onConditionChange={(value) => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n\n const tr = this.view.state.tr.setNodeMarkup(currentPos, undefined, {\n ...this.node.attrs,\n condition: value,\n });\n // Move cursor into the branch's content (first paragraph)\n // Branch structure: branchNode > paragraph > ...\n // Content starts at currentPos + 1 (inside branch) + 1 (inside first child)\n const contentPos = currentPos + 2;\n if (contentPos <= tr.doc.content.size) {\n tr.setSelection(TextSelection.near(tr.doc.resolve(contentPos)));\n }\n this.view.dispatch(tr.scrollIntoView());\n this.view.focus();\n }}\n onDelete={() => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n deleteBranch(this.view, currentPos, branchType);\n }}\n onAddBranch={(nextBranchType) => {\n const currentPos = this.getPos();\n if (currentPos == null) return;\n insertNewBranch(this.view, currentPos, nextBranchType, '');\n }}\n />,\n );\n }\n\n update(node: PMNode): boolean {\n if (!isBranchNode(node)) return false;\n\n this.node = node;\n this.syncDOM();\n this.render();\n return true;\n }\n\n stopEvent(event: Event): boolean {\n const target = event.target as Node | null;\n return target != null && this.headerContainer.contains(target);\n }\n\n ignoreMutation(mutation: ViewMutationRecord): boolean {\n // Must also ignore mutations on this.dom itself — syncDOM() and render()\n // modify className/attributes on the NodeView root element. Without this,\n // ProseMirror's DOMObserver re-parses the DOM on every attribute change,\n // triggering update() → syncDOM() → attribute change → re-parse → infinite loop.\n return mutation.target === this.dom || this.headerContainer.contains(mutation.target);\n }\n\n destroy(): void {\n if (this._onSiblingsChanged) {\n this.dom.removeEventListener('jinja-siblings-changed', this._onSiblingsChanged);\n }\n if (this._onEditableChanged) {\n this.dom.removeEventListener('jinja-editable-changed', this._onEditableChanged);\n }\n StyleManager.release();\n setTimeout(() => this.root.unmount(), 0);\n }\n}\n\n/**\n * ProseMirror plugin that watches for `view.editable` changes and notifies\n * JinjaIfBranchView NodeViews so they can re-render edit-only controls.\n *\n * ProseMirror does NOT trigger NodeView.update() when `editable` changes\n * (only when the document node changes). Without this plugin, stale UI\n * (e.g. the \"+\" add-branch button) persists after switching to view mode.\n */\nfunction createEditableWatcherPlugin(): Plugin {\n let lastEditable: boolean | null = null;\n\n return new Plugin({\n view(editorView) {\n lastEditable = editorView.editable;\n return {\n update(view) {\n const currentEditable = view.editable;\n if (lastEditable !== null && lastEditable !== currentEditable) {\n // Notify all jinja branch NodeViews to re-render\n const event = new Event('jinja-editable-changed', { bubbles: true });\n view.dom.querySelectorAll('[data-jinja-branch]').forEach((el) => {\n el.dispatchEvent(event);\n });\n }\n lastEditable = currentEditable;\n },\n };\n },\n });\n}\n\nexport function createJinjaIfBlockPlugin(): ActionbookPlugin {\n return {\n name: 'jinjaIfBlock',\n plugins: () => [createEditableWatcherPlugin()],\n nodeViews: () => ({\n jinjaIfBlock: (() => new JinjaIfBlockView()) as NodeViewFactory,\n jinjaIfBranch: ((node: PMNode, view: EditorView, getPos: () => number | undefined) => (\n new JinjaIfBranchView(node, view, getPos)\n )) as NodeViewFactory,\n }),\n };\n}\n","/**\n * Link editing plugin for the Actionbook editor.\n *\n * UX flow:\n * 1. `[aa](#aa)` is rendered as a clickable \"aa\" link mark.\n * 2. Pressing Backspace while cursor is inside or just after the link\n * \"explodes\" it to raw markdown `[aa](#aa)` for editing.\n * 3. While the cursor stays inside the raw text, normal editing applies.\n * 4. When the cursor leaves the raw region:\n * - If the text still matches `[label](href)` → reconverts to link mark.\n * - Otherwise → stays as plain text (user intentionally broke the link).\n * 5. Completing the markdown syntax by typing `)` triggers the input rule\n * and immediately converts to a link mark.\n */\n\nimport { InputRule, inputRules } from 'prosemirror-inputrules';\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport type { Mark, MarkType, ResolvedPos } from 'prosemirror-model';\nimport type { ActionbookPlugin } from './types';\n\n// ── Regexes ──────────────────────────────────────────────────────────────────\n\n/** Matches a fully typed `[label](href)` or `[label](href \"title\")` at end of input. */\n// Match [label](href) — also handles escaped brackets \\[ \\]\nconst LINK_INPUT_RE = /\\\\?\\[([^\\]]*?)\\\\?\\]\\(([^)\\s]*?)(?:\\s+\"([^\"]*)\")?\\)$/;\n\n/**\n * Matches raw link text that spans the entire string.\n * Used to validate/reconvert after cursor leaves the raw editing region.\n */\n// Match [label](href) — also handles escaped brackets \\[ \\] from markdown roundtrip\nconst LINK_FULL_RE = /^\\\\?\\[([^\\]]*?)\\\\?\\]\\(([^)\\s]*?)(?:\\s+\"([^\"]*)\")?\\)$/;\n\n// ── Plugin state ──────────────────────────────────────────────────────────────\n\ninterface LinkEditState {\n /** Absolute positions of the raw `[label](href)` text currently being edited. */\n rawRange: { from: number; to: number } | null;\n}\n\nconst linkEditKey = new PluginKey<LinkEditState>('linkEdit');\n\n// ── Utilities ─────────────────────────────────────────────────────────────────\n\n/**\n * Find the contiguous extent of a mark type around a resolved position.\n *\n * Handles `inclusive: false` marks (like `link`) correctly: when cursor is\n * placed just AFTER the mark text, the last node of the mark span is found\n * via `childBefore` and the full range is returned.\n */\nfunction getMarkRange(\n $pos: ResolvedPos,\n type: MarkType,\n): { from: number; to: number; mark: Mark } | null {\n const { parentOffset } = $pos;\n\n let child = $pos.parent.childAfter(parentOffset);\n\n // When cursor is exactly at a node boundary, also try the node ending here.\n if (parentOffset === child.offset && child.offset !== 0) {\n child = $pos.parent.childBefore(parentOffset);\n }\n\n if (!child.node) return null;\n\n const mark = child.node.marks.find((m) => m.type === type);\n if (!mark) return null;\n\n const parentStart = $pos.start();\n let { index: startIndex } = child;\n let startPos = parentStart + child.offset;\n let endIndex = startIndex + 1;\n let endPos = startPos + child.node.nodeSize;\n\n while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {\n startIndex -= 1;\n startPos -= $pos.parent.child(startIndex).nodeSize;\n }\n\n while (\n endIndex < $pos.parent.childCount &&\n mark.isInSet($pos.parent.child(endIndex).marks)\n ) {\n endPos += $pos.parent.child(endIndex).nodeSize;\n endIndex += 1;\n }\n\n return { from: startPos, to: endPos, mark };\n}\n\n/**\n * Replace a link mark span with its raw markdown text `[label](href)`.\n *\n * Cursor placement after explosion: maps the cursor offset within the link\n * label to the same relative position in the raw text (adding 1 for the\n * leading `[`). For cursor at the end of the label, this positions just\n * before `]`, which is natural for continued editing.\n *\n * Returns `null` when the cursor is not at/inside a link mark.\n */\nfunction explodeLinkToRaw(state: EditorState): Transaction | null {\n const { selection, doc, schema } = state;\n if (!selection.empty) return null;\n\n const linkMarkType = schema.marks.link;\n if (!linkMarkType) return null;\n\n const $pos = doc.resolve(selection.from);\n const range = getMarkRange($pos, linkMarkType);\n if (!range) return null;\n\n const { from, to, mark } = range;\n const label = doc.textBetween(from, to);\n const { href, title } = mark.attrs as { href: string; title: string | null };\n const titlePart = title ? ` \"${title}\"` : '';\n const rawText = `[${label}](${href}${titlePart})`;\n\n // +1 for the leading `[`, clamped to label length\n const cursorOffset = Math.min(selection.from - from, label.length);\n const rawCursorOffset = cursorOffset + 1;\n\n const tr = state.tr;\n tr.replaceWith(from, to, schema.text(rawText));\n\n const newPos = Math.min(from + rawCursorOffset, tr.doc.content.size);\n tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));\n tr.setMeta(linkEditKey, { from, to: from + rawText.length });\n\n return tr;\n}\n\n// ── Auto-reconvert plugin ─────────────────────────────────────────────────────\n\n/**\n * Tracks the raw editing region after a link explosion and reconverts it back\n * to a link mark when the cursor moves outside that region.\n */\nfunction createLinkEditPlugin(): Plugin<LinkEditState> {\n return new Plugin<LinkEditState>({\n key: linkEditKey,\n\n state: {\n init: (): LinkEditState => ({ rawRange: null }),\n\n apply(tr, prev): LinkEditState {\n const meta = tr.getMeta(linkEditKey) as\n | { from: number; to: number }\n | null\n | undefined;\n\n if (meta !== undefined) return { rawRange: meta };\n\n if (prev.rawRange) {\n const from = tr.mapping.map(prev.rawRange.from, -1);\n const to = tr.mapping.map(prev.rawRange.to, -1);\n if (from >= to) return { rawRange: null };\n return { rawRange: { from, to } };\n }\n\n return prev;\n },\n },\n\n appendTransaction(_, __, newState) {\n const pluginState = linkEditKey.getState(newState);\n if (!pluginState?.rawRange) return null;\n\n const { from, to } = pluginState.rawRange;\n\n // Still inside — nothing to do (strict < to so cursor AT the end triggers reconvert)\n if (newState.selection.anchor >= from && newState.selection.anchor < to) {\n return null;\n }\n\n const docSize = newState.doc.content.size;\n const safeFrom = Math.min(from, docSize);\n const safeTo = Math.min(to, docSize);\n\n const reconvertTr = newState.tr;\n reconvertTr.setMeta(linkEditKey, null);\n\n if (safeFrom < safeTo) {\n const text = newState.doc.textBetween(safeFrom, safeTo);\n const match = LINK_FULL_RE.exec(text);\n\n if (match) {\n const [, label, href, title] = match;\n const linkMarkType = newState.schema.marks.link;\n\n // Empty label → delete the entire raw link text (no invisible markup left)\n if (!label) {\n reconvertTr.delete(safeFrom, safeTo);\n } else if (linkMarkType && href) {\n const attrs = title ? { href, title: title.trim() } : { href };\n reconvertTr.delete(safeFrom, safeTo);\n reconvertTr.insertText(label, safeFrom);\n reconvertTr.addMark(\n safeFrom,\n safeFrom + label.length,\n linkMarkType.create(attrs),\n );\n }\n }\n }\n\n return reconvertTr;\n },\n });\n}\n\n// ── Input rule ────────────────────────────────────────────────────────────────\n\n/**\n * When the user completes `[label](href)` by typing `)`, immediately convert\n * the matched text to a link mark. Works both for fresh typing and for\n * finalising an edited raw-exploded link.\n */\nfunction createLinkInputRule(): InputRule {\n return new InputRule(\n LINK_INPUT_RE,\n (state, match, start, end) => {\n const [, label, href, title] = match;\n const linkMarkType = state.schema.marks.link;\n if (!linkMarkType) return null;\n\n const { tr } = state;\n\n // Empty label → delete the entire link syntax (no invisible [](url) left)\n if (!label) {\n tr.delete(start, end);\n tr.setMeta(linkEditKey, null);\n return tr;\n }\n\n if (!href) return null;\n\n const attrs = title ? { href, title: title.trim() } : { href };\n tr.replaceWith(start, end, state.schema.text(label));\n tr.addMark(start, start + label.length, linkMarkType.create(attrs));\n tr.setMeta(linkEditKey, null);\n\n return tr;\n },\n );\n}\n\n// ── Click handler (anchor navigation) ────────────────────────────────────────\n\nfunction createLinkClickPlugin(): Plugin {\n return new Plugin({\n key: new PluginKey('linkClick'),\n props: {\n handleDOMEvents: {\n click: (_view, event) => {\n const target = event.target as HTMLElement;\n if (target.tagName !== 'A') return false;\n\n const href = (target as HTMLAnchorElement).getAttribute('href');\n if (!href) return false;\n\n // Internal jump-point links (#section) — scroll instead of navigate\n if (href.startsWith('#')) {\n event.preventDefault();\n const targetId = `jp-${href.slice(1)}`;\n const el = document.getElementById(targetId);\n if (el) {\n el.scrollIntoView({ block: 'end' });\n el.focus();\n if (el.parentElement) {\n el.parentElement.style.outline = '2px solid #6213cc';\n setTimeout(() => {\n (el.parentElement as HTMLElement).style.outline = 'none';\n }, 500);\n }\n }\n return true;\n }\n\n return false;\n },\n },\n },\n });\n}\n\n// ── Public factory ────────────────────────────────────────────────────────────\n\n/**\n * Creates the link editing `ActionbookPlugin`.\n *\n * Bundles:\n * - Backspace → explode to raw markdown\n * - `appendTransaction` auto-reconvert on cursor leave\n * - Input rule for `[label](href)` → link mark\n * - Click handler for internal `#anchor` links\n */\nexport function createLinkPlugin(): ActionbookPlugin {\n return {\n name: 'link',\n plugins: () => [\n createLinkEditPlugin(),\n createLinkClickPlugin(),\n inputRules({ rules: [createLinkInputRule()] }),\n ],\n keymap: () => ({\n Backspace: (state, dispatch) => {\n if (!state.selection.empty) return false;\n\n // Already in raw-edit mode — let normal Backspace through\n if (linkEditKey.getState(state)?.rawRange) return false;\n\n const tr = explodeLinkToRaw(state);\n if (!tr) return false;\n\n if (dispatch) dispatch(tr);\n return true;\n },\n }),\n };\n}\n","/**\n * Drag handle plugin v2 — enterprise-grade block reordering.\n *\n * Key improvements over v1:\n * - Diff-based handle updates (no full DOM rebuild per transaction)\n * - Pointer Events API (unified mouse/touch/pen)\n * - Auto-scroll during drag\n * - Keyboard accessibility (Alt+Arrow, ARIA)\n * - CSS custom properties for theming\n * - Proper style cleanup via adopted stylesheets / ref-count\n * - Class-based state management for testability\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorView } from 'prosemirror-view';\nimport type { Node as PMNode, ResolvedPos } from 'prosemirror-model';\nimport type { Transaction, EditorState, Command } from 'prosemirror-state';\nimport type { ActionbookPlugin } from './types';\n\n// ────────────────────────────────────────────────────────────\n// Constants\n// ────────────────────────────────────────────────────────────\n\nconst PLUGIN_KEY = new PluginKey('dragHandle');\n\nconst GRIP_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 12 12\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"4\" cy=\"2.5\" r=\"1.2\"/><circle cx=\"8\" cy=\"2.5\" r=\"1.2\"/>\n <circle cx=\"4\" cy=\"6\" r=\"1.2\"/><circle cx=\"8\" cy=\"6\" r=\"1.2\"/>\n <circle cx=\"4\" cy=\"9.5\" r=\"1.2\"/><circle cx=\"8\" cy=\"9.5\" r=\"1.2\"/>\n</svg>`;\n\nconst AUTO_SCROLL_ZONE = 40;\nconst AUTO_SCROLL_MAX_SPEED = 8;\nconst HANDLE_GAP = 4;\nexport const DRAG_THRESHOLD = 5;\n\n// ────────────────────────────────────────────────────────────\n// Styles (CSS custom properties for theming)\n// ────────────────────────────────────────────────────────────\n\nconst STYLES = /* css */ `\n.ab-drag-handle-layer {\n --ab-dh-color-idle: transparent;\n --ab-dh-color-hover: #c4c4c4;\n --ab-dh-color-visible: #8b8b8b;\n --ab-dh-color-accent: rgba(1,156,110,0.8);\n --ab-dh-bg-hover: rgba(13,13,13,0.04);\n --ab-dh-bg-active: rgba(13,13,13,0.04);\n --ab-dh-dragging-opacity: 0.4;\n --ab-dh-handle-size: 24px;\n --ab-dh-handle-radius: 4px;\n --ab-dh-transition-duration: 0.15s;\n\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n pointer-events: none;\n overflow: visible;\n}\n.ab-drag-handle {\n position: absolute;\n width: var(--ab-dh-handle-size);\n height: var(--ab-dh-handle-size);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: grab;\n color: transparent;\n border-radius: var(--ab-dh-handle-radius);\n transition: none;\n user-select: none;\n pointer-events: auto;\n touch-action: none;\n opacity: 0;\n pointer-events: none;\n overflow: visible;\n}\n.ab-drag-handle.ab-dh-active {\n opacity: 1;\n pointer-events: auto;\n color: var(--ab-dh-color-visible);\n}\n.ab-drag-handle:hover {\n color: var(--ab-dh-color-visible) !important;\n background: var(--ab-dh-bg-hover);\n}\n.ab-drag-handle:hover::after {\n content: 'Drag to move';\n position: absolute;\n bottom: calc(100% + 4px);\n left: 0;\n background: #2e2e2e;\n color: #fff;\n font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 400;\n line-height: 16px;\n padding: 4px 8px;\n border-radius: 4px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 30;\n}\n.ab-drag-handle:hover::before {\n content: '';\n position: absolute;\n bottom: calc(100% + 0px);\n left: 8px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 5px solid #2e2e2e;\n pointer-events: none;\n z-index: 31;\n}\n.ab-drag-handle.dragging::after,\n.ab-drag-handle.dragging::before {\n display: none;\n}\n.ab-dh-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: #fff;\n border-radius: 4px;\n box-shadow: 0px 8px 10px 1px rgba(13,13,13,0.12), 0px 3px 14px 2px rgba(13,13,13,0.08), 0px 3px 5px -3px rgba(13,13,13,0.04);\n padding: 8px 0;\n z-index: 40;\n min-width: 120px;\n}\n.ab-dh-menu-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 6px 16px;\n border: none;\n background: #fff;\n cursor: pointer;\n font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n letter-spacing: -0.1px;\n color: #0d0d0d;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.ab-dh-menu-item:hover {\n background: rgba(0,0,0,0.04);\n}\n.ab-drag-handle:active, .ab-drag-handle.dragging {\n cursor: grabbing;\n color: var(--ab-dh-color-accent) !important;\n background: var(--ab-dh-bg-active);\n}\n.ab-drop-indicator {\n position: absolute;\n left: 0; right: 0;\n height: 4px;\n background: rgba(1,156,110,0.4);\n border: 1px solid rgba(1,156,110,0.6);\n border-radius: 12px;\n pointer-events: none;\n z-index: 20;\n box-sizing: border-box;\n transition: top 60ms ease-out;\n}\n.ab-block-dragging {\n opacity: var(--ab-dh-dragging-opacity, 0.4);\n}\n@keyframes ab-block-flash {\n from { background: rgba(1,156,110,0.08); }\n to { background: transparent; }\n}\n.ab-block-just-moved {\n animation: ab-block-flash 0.4s ease-out;\n}\n.ab-sr-only {\n position: absolute;\n width: 1px; height: 1px;\n padding: 0; margin: -1px;\n overflow: hidden;\n clip: rect(0,0,0,0);\n white-space: nowrap;\n border: 0;\n}\n`;\n\n// ────────────────────────────────────────────────────────────\n// Style Manager (ref-counted, leak-free)\n// ────────────────────────────────────────────────────────────\n\nclass StyleManager {\n private static refCount = 0;\n private static sheet: CSSStyleSheet | null = null;\n private static styleEl: HTMLStyleElement | null = null;\n\n static acquire(): void {\n if (this.refCount++ > 0) return;\n\n if (typeof CSSStyleSheet !== 'undefined' && 'replaceSync' in CSSStyleSheet.prototype) {\n this.sheet = new CSSStyleSheet();\n this.sheet.replaceSync(STYLES);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, this.sheet];\n } else {\n // Fallback for older browsers\n this.styleEl = document.createElement('style');\n this.styleEl.id = 'ab-drag-handle-styles';\n this.styleEl.textContent = STYLES;\n document.head.appendChild(this.styleEl);\n }\n }\n\n static release(): void {\n if (--this.refCount > 0) return;\n\n if (this.sheet) {\n document.adoptedStyleSheets = document.adoptedStyleSheets.filter(s => s !== this.sheet);\n this.sheet = null;\n }\n if (this.styleEl) {\n this.styleEl.remove();\n this.styleEl = null;\n }\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Types\n// ────────────────────────────────────────────────────────────\n\ninterface BlockInfo {\n offset: number;\n nodeSize: number;\n dom: HTMLElement;\n}\n\ninterface HandleEntry {\n el: HTMLElement;\n block: BlockInfo;\n topPx: number;\n listenerCleanup: () => void;\n}\n\ninterface DragState {\n fromIndex: number;\n handle: HTMLElement;\n blockDom: HTMLElement;\n dropTargetIndex: number;\n pointerY: number;\n pointerId: number;\n startX: number;\n startY: number;\n activated: boolean;\n ghost: HTMLElement | null;\n}\n\n// ────────────────────────────────────────────────────────────\n// Pure helpers (exported for testing)\n// ────────────────────────────────────────────────────────────\n\n/**\n * Build a PM transaction that moves the top-level block at `fromIndex`\n * to `toIndex` (insert-before semantics: toIndex is counted in the\n * original ordering).\n *\n * Returns null if the move is a no-op or out of bounds.\n */\nexport function buildMoveTransaction(\n state: EditorState,\n fromIndex: number,\n toIndex: number,\n): Transaction | null {\n const { doc } = state;\n if (fromIndex === toIndex || fromIndex + 1 === toIndex) return null;\n if (fromIndex < 0 || fromIndex >= doc.childCount) return null;\n if (toIndex < 0 || toIndex > doc.childCount) return null;\n\n const node = doc.child(fromIndex);\n\n // Collect offsets of each top-level block\n const offsets: number[] = [];\n doc.forEach((_child, offset) => { offsets.push(offset); });\n\n const nodeStart = offsets[fromIndex];\n const nodeEnd = nodeStart + node.nodeSize;\n\n let tr = state.tr;\n\n if (toIndex > fromIndex) {\n // Moving down: insert first, then delete (keeps positions valid)\n const targetEnd = offsets[toIndex - 1] + doc.child(toIndex - 1).nodeSize;\n tr = tr.insert(targetEnd, node);\n tr = tr.delete(tr.mapping.map(nodeStart), tr.mapping.map(nodeEnd));\n } else {\n // Moving up: delete first, then insert\n const insertPos = offsets[toIndex];\n tr = tr.delete(nodeStart, nodeEnd);\n tr = tr.insert(tr.mapping.map(insertPos), node);\n }\n\n return tr;\n}\n\n/**\n * Given a list of block bounding rects (top/bottom relative to container),\n * determine which gap the pointer is closest to.\n * Returns an index in [0, blocks.length] (insert-before semantics).\n */\nexport function findDropTarget(\n blockRects: Array<{ top: number; bottom: number }>,\n pointerY: number,\n): number {\n if (blockRects.length === 0) return 0;\n\n let bestIndex = 0;\n let bestDist = Infinity;\n\n for (let i = 0; i <= blockRects.length; i++) {\n let gapY: number;\n if (i === 0) {\n gapY = blockRects[0].top;\n } else if (i === blockRects.length) {\n gapY = blockRects[blockRects.length - 1].bottom;\n } else {\n gapY = (blockRects[i - 1].bottom + blockRects[i].top) / 2;\n }\n const dist = Math.abs(pointerY - gapY);\n if (dist < bestDist) {\n bestDist = dist;\n bestIndex = i;\n }\n }\n\n return bestIndex;\n}\n\n/**\n * Compute auto-scroll speed based on pointer proximity to container edges.\n * Returns pixels-per-frame (negative = up, positive = down, 0 = no scroll).\n */\nexport function computeAutoScrollSpeed(\n pointerY: number,\n containerTop: number,\n containerBottom: number,\n): number {\n if (pointerY < containerTop + AUTO_SCROLL_ZONE) {\n const ratio = Math.max(0, (pointerY - containerTop) / AUTO_SCROLL_ZONE);\n return -AUTO_SCROLL_MAX_SPEED * (1 - ratio);\n }\n if (pointerY > containerBottom - AUTO_SCROLL_ZONE) {\n const ratio = Math.max(0, (containerBottom - pointerY) / AUTO_SCROLL_ZONE);\n return AUTO_SCROLL_MAX_SPEED * (1 - ratio);\n }\n return 0;\n}\n\n/**\n * Compare two block lists and return which indices need create/remove/reposition.\n * A block is \"same\" if its offset and nodeSize match.\n */\nexport function diffBlockList(\n prev: Array<{ offset: number; nodeSize: number }>,\n next: Array<{ offset: number; nodeSize: number }>,\n): { added: number[]; removed: number[]; kept: Array<{ prevIdx: number; nextIdx: number }> } {\n const prevMap = new Map<string, number>();\n prev.forEach((b, i) => prevMap.set(`${b.offset}:${b.nodeSize}`, i));\n\n const added: number[] = [];\n const kept: Array<{ prevIdx: number; nextIdx: number }> = [];\n const usedPrev = new Set<number>();\n\n next.forEach((b, i) => {\n const key = `${b.offset}:${b.nodeSize}`;\n const prevIdx = prevMap.get(key);\n if (prevIdx !== undefined && !usedPrev.has(prevIdx)) {\n kept.push({ prevIdx, nextIdx: i });\n usedPrev.add(prevIdx);\n } else {\n added.push(i);\n }\n });\n\n const removed: number[] = [];\n prev.forEach((_, i) => {\n if (!usedPrev.has(i)) removed.push(i);\n });\n\n return { added, removed, kept };\n}\n\n// ────────────────────────────────────────────────────────────\n// DragHandleController\n// ────────────────────────────────────────────────────────────\n\nclass DragHandleController {\n private view: EditorView;\n private layer: HTMLElement;\n private liveRegion: HTMLElement;\n private handles: HandleEntry[] = [];\n private prevBlocks: BlockInfo[] = [];\n private drag: DragState | null = null;\n private dropIndicator: HTMLElement | null = null;\n private scrollRAF: number | null = null;\n private updateRAF: number | null = null;\n private pendingUpdate = false;\n private scrollContainer: HTMLElement;\n private scrollSyncRAF: number | null = null;\n private resizeObserver: ResizeObserver | null = null;\n\n // Hover state\n private hoverBound: { enter: () => void; leave: () => void } | null = null;\n\n // Global fallback handlers active during drag\n private globalCleanup: (() => void) | null = null;\n\n constructor(view: EditorView) {\n this.view = view;\n StyleManager.acquire();\n\n const parent = view.dom.parentNode as HTMLElement;\n const pos = getComputedStyle(parent).position;\n if (pos === 'static' || pos === '') parent.style.position = 'relative';\n\n // Create overlay layer\n this.layer = document.createElement('div');\n this.layer.className = 'ab-drag-handle-layer';\n parent.insertBefore(this.layer, view.dom.nextSibling);\n\n // ARIA live region for announcements\n this.liveRegion = document.createElement('div');\n this.liveRegion.className = 'ab-sr-only';\n this.liveRegion.setAttribute('aria-live', 'assertive');\n this.liveRegion.setAttribute('aria-atomic', 'true');\n parent.appendChild(this.liveRegion);\n\n // Hover listeners removed — handle visibility is now based on cursor block position.\n // Kept hoverBound for cleanup compatibility.\n this.hoverBound = { enter: () => {}, leave: () => {} };\n\n // Find scroll container\n this.scrollContainer = this.findScrollContainer(view.dom);\n\n // Scroll listener — reposition handles when container scrolls\n this.scrollContainer.addEventListener('scroll', this.onScroll, { passive: true });\n\n // Resize observer — recompute when editor dimensions change\n this.resizeObserver = new ResizeObserver(() => this.scheduleUpdate());\n this.resizeObserver.observe(view.dom);\n\n // Hide in non-editable mode\n if (!view.editable) {\n this.layer.style.display = 'none';\n }\n\n // Initial render\n this.rebuildHandles();\n }\n\n update(view: EditorView, prevState: EditorState): void {\n this.view = view;\n\n // Hide all handles in non-editable mode\n if (!view.editable) {\n this.layer.style.display = 'none';\n return;\n }\n this.layer.style.display = '';\n\n // Skip updates during drag — flush when drag ends\n if (this.drag) {\n this.pendingUpdate = true;\n return;\n }\n\n // Recompute when doc structure changes\n if (!view.state.doc.eq(prevState.doc)) {\n this.scheduleUpdate();\n }\n\n // Update active handle when selection changes\n if (!view.state.selection.eq(prevState.selection) || !view.state.doc.eq(prevState.doc)) {\n this.updateActiveHandle();\n }\n }\n\n /** Show only the handle for the block containing the cursor. */\n private updateActiveHandle(): void {\n const { $from } = this.view.state.selection;\n // Find the top-level block index that contains the cursor\n const cursorBlockOffset = $from.start(1) - 1; // offset of the top-level block\n\n for (const h of this.handles) {\n if (h.block.offset === cursorBlockOffset) {\n h.el.classList.add('ab-dh-active');\n } else {\n h.el.classList.remove('ab-dh-active');\n }\n }\n }\n\n destroy(): void {\n this.cancelDrag();\n\n if (this.updateRAF !== null) cancelAnimationFrame(this.updateRAF);\n if (this.scrollSyncRAF !== null) cancelAnimationFrame(this.scrollSyncRAF);\n this.scrollContainer.removeEventListener('scroll', this.onScroll);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n\n // Remove handles and their listeners\n for (const h of this.handles) {\n h.listenerCleanup();\n h.el.remove();\n }\n this.handles = [];\n\n // Remove hover listeners\n if (this.hoverBound) {\n const parent = this.view.dom.parentNode as HTMLElement | null;\n if (parent) {\n parent.removeEventListener('mouseenter', this.hoverBound.enter);\n parent.removeEventListener('mouseleave', this.hoverBound.leave);\n }\n }\n\n this.liveRegion.remove();\n this.layer.remove();\n StyleManager.release();\n }\n\n // ── Private: update pipeline ──\n\n private scheduleUpdate(): void {\n if (this.updateRAF !== null) return;\n this.updateRAF = requestAnimationFrame(() => {\n this.updateRAF = null;\n this.rebuildHandles();\n });\n }\n\n private onScroll = (): void => {\n if (this.scrollSyncRAF !== null) return;\n this.scrollSyncRAF = requestAnimationFrame(() => {\n this.scrollSyncRAF = null;\n if (!this.drag) this.syncHandlePositions();\n });\n };\n\n private collectBlocks(): BlockInfo[] {\n const blocks: BlockInfo[] = [];\n\n this.view.state.doc.forEach((node, offset) => {\n // nodeDOM returns the outermost DOM node for the block at this offset.\n // This is more reliable than domAtPos(offset + 1) which can resolve to\n // the wrong element for leaf blocks (e.g. horizontalRule with nodeSize=1).\n const dom = this.view.nodeDOM(offset);\n if (dom instanceof HTMLElement) {\n blocks.push({ offset, nodeSize: node.nodeSize, dom });\n }\n });\n\n return blocks;\n }\n\n private rebuildHandles(): void {\n const newBlocks = this.collectBlocks();\n const diff = diffBlockList(\n this.prevBlocks.map(b => ({ offset: b.offset, nodeSize: b.nodeSize })),\n newBlocks.map(b => ({ offset: b.offset, nodeSize: b.nodeSize })),\n );\n\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n const handleSize = parseInt(getComputedStyle(this.layer).getPropertyValue('--ab-dh-handle-size') || '22', 10);\n const handleLeft = editorRect.left - parentRect.left - handleSize - HANDLE_GAP;\n\n // Build new handles array preserving kept entries\n const newHandles: HandleEntry[] = new Array(newBlocks.length);\n\n // Reuse kept handles (reposition if needed)\n for (const { prevIdx, nextIdx } of diff.kept) {\n const entry = this.handles[prevIdx];\n entry.block = newBlocks[nextIdx];\n const blockRect = entry.block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(entry.block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n entry.topPx = topPx;\n entry.el.style.top = `${topPx}px`;\n entry.el.style.left = `${handleLeft}px`;\n // Update the index in the pointerdown closure\n this.rebindHandleIndex(entry, nextIdx);\n newHandles[nextIdx] = entry;\n }\n\n // Remove obsolete handles\n for (const idx of diff.removed) {\n const entry = this.handles[idx];\n entry.listenerCleanup();\n entry.el.remove();\n }\n\n // Create new handles\n for (const idx of diff.added) {\n const block = newBlocks[idx];\n const blockRect = block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n\n const el = document.createElement('div');\n el.className = 'ab-drag-handle';\n el.setAttribute('data-ab-float', '');\n el.setAttribute('role', 'button');\n el.setAttribute('aria-roledescription', 'drag handle');\n el.setAttribute('aria-label', `블록 ${idx + 1} 이동`);\n // Tooltip is shown via CSS ::after pseudo-element (no native title to avoid double tooltip)\n el.setAttribute('tabindex', '-1');\n el.innerHTML = GRIP_SVG;\n el.style.left = `${handleLeft}px`;\n el.style.top = `${topPx}px`;\n this.layer.appendChild(el);\n\n const cleanup = this.bindHandleEvents(el, idx);\n newHandles[idx] = { el, block, topPx, listenerCleanup: cleanup };\n }\n\n this.handles = newHandles;\n this.prevBlocks = newBlocks;\n\n // Set initial active handle based on cursor position\n this.updateActiveHandle();\n }\n\n private activeMenu: HTMLElement | null = null;\n private activeMenuCleanup: (() => void) | null = null;\n\n private dismissMenu() {\n if (this.activeMenu) {\n this.activeMenu.remove();\n this.activeMenu = null;\n }\n if (this.activeMenuCleanup) {\n this.activeMenuCleanup();\n this.activeMenuCleanup = null;\n }\n }\n\n private showMenu(el: HTMLElement, blockIndex: number) {\n this.dismissMenu();\n\n const menu = document.createElement('div');\n menu.className = 'ab-dh-menu';\n\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'ab-dh-menu-item';\n deleteBtn.textContent = 'Delete';\n\n deleteBtn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.deleteBlock(blockIndex);\n this.dismissMenu();\n });\n\n menu.appendChild(deleteBtn);\n el.appendChild(menu);\n this.activeMenu = menu;\n\n // Close on outside click\n const onOutside = (e: MouseEvent) => {\n if (!menu.contains(e.target as Node)) {\n this.dismissMenu();\n }\n };\n setTimeout(() => document.addEventListener('mousedown', onOutside, true), 0);\n this.activeMenuCleanup = () => document.removeEventListener('mousedown', onOutside, true);\n }\n\n private deleteBlock(blockIndex: number) {\n const blocks = this.collectBlocks();\n if (blockIndex >= blocks.length) return;\n const block = blocks[blockIndex];\n const from = block.offset;\n const to = block.offset + block.nodeSize;\n const tr = this.view.state.tr;\n tr.replaceWith(from, to, this.view.state.schema.nodes.paragraph.create());\n this.view.dispatch(tr);\n this.view.focus();\n }\n\n private bindHandleEvents(el: HTMLElement, index: number): () => void {\n let currentIndex = index;\n let downX = 0;\n let downY = 0;\n let didDrag = false;\n\n let menuWasOpen = false;\n\n const onPointerDown = (e: PointerEvent) => {\n // If clicking inside the menu, let the menu handle it\n if (this.activeMenu && this.activeMenu.contains(e.target as Node)) return;\n\n e.preventDefault();\n if (!this.view.editable) return;\n\n menuWasOpen = !!this.activeMenu;\n this.dismissMenu();\n\n downX = e.clientX;\n downY = e.clientY;\n didDrag = false;\n el.setPointerCapture(e.pointerId);\n this.prevBlocks = this.collectBlocks();\n this.syncHandlePositions();\n this.startDrag(currentIndex, el, e);\n };\n const onPointerMove = (e: PointerEvent) => {\n if (Math.abs(e.clientX - downX) > 3 || Math.abs(e.clientY - downY) > 3) {\n didDrag = true;\n }\n this.onPointerMove(e);\n };\n const onPointerUp = (e: PointerEvent) => {\n this.onPointerUp(e);\n // Toggle menu: if it was open before this click, don't reopen\n if (!didDrag && !menuWasOpen) {\n this.showMenu(el, currentIndex);\n }\n };\n const onLostCapture = () => this.cancelDrag();\n const onPointerCancel = () => this.cancelDrag();\n\n el.addEventListener('pointerdown', onPointerDown);\n el.addEventListener('pointermove', onPointerMove);\n el.addEventListener('pointerup', onPointerUp);\n el.addEventListener('pointercancel', onPointerCancel);\n el.addEventListener('lostpointercapture', onLostCapture);\n\n const cleanup = () => {\n el.removeEventListener('pointerdown', onPointerDown);\n el.removeEventListener('pointermove', onPointerMove);\n el.removeEventListener('pointerup', onPointerUp);\n el.removeEventListener('pointercancel', onPointerCancel);\n el.removeEventListener('lostpointercapture', onLostCapture);\n };\n\n (el as any).__abUpdateIndex = (newIdx: number) => { currentIndex = newIdx; };\n\n return cleanup;\n }\n\n private rebindHandleIndex(entry: HandleEntry, newIndex: number): void {\n const fn = (entry.el as any).__abUpdateIndex;\n if (fn) fn(newIndex);\n entry.el.setAttribute('aria-label', `블록 ${newIndex + 1} 이동`);\n }\n\n private syncHandlePositions(): void {\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n const handleSize = parseInt(getComputedStyle(this.layer).getPropertyValue('--ab-dh-handle-size') || '22', 10);\n const handleLeft = editorRect.left - parentRect.left - handleSize - HANDLE_GAP;\n\n for (const entry of this.handles) {\n if (!entry) continue;\n const blockRect = entry.block.dom.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(entry.block.dom).lineHeight) || 24;\n const verticalOffset = Math.max(0, (lineHeight - handleSize) / 2);\n const topPx = blockRect.top - parentRect.top + parent.scrollTop + verticalOffset;\n entry.topPx = topPx;\n entry.el.style.top = `${topPx}px`;\n entry.el.style.left = `${handleLeft}px`;\n }\n }\n\n // ── Private: drag lifecycle ──\n\n private startDrag(index: number, handle: HTMLElement, e: PointerEvent): void {\n const block = this.prevBlocks[index];\n if (!block) return;\n\n // Guard: clean up any existing drag first (e.g. multi-touch edge case)\n if (this.drag) {\n this.cleanupDragState();\n }\n\n this.drag = {\n fromIndex: index,\n handle,\n blockDom: block.dom,\n dropTargetIndex: index,\n pointerY: e.clientY,\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n activated: false,\n ghost: null,\n };\n\n // Global fallback handlers: catch pointerup/pointercancel even when\n // pointer capture is lost or events don't reach the handle element\n this.addGlobalDragListeners(e.pointerId);\n }\n\n private activateDrag(): void {\n if (!this.drag) return;\n\n this.drag.activated = true;\n this.drag.handle.classList.add('dragging');\n this.drag.blockDom.classList.add('ab-block-dragging');\n\n // Create ghost element — semi-transparent clone following cursor\n const blockRect = this.drag.blockDom.getBoundingClientRect();\n const ghost = this.drag.blockDom.cloneNode(true) as HTMLElement;\n ghost.className = 'ab-drag-ghost';\n ghost.style.cssText = `\n position: fixed;\n top: ${blockRect.top}px;\n left: ${blockRect.left}px;\n width: ${blockRect.width}px;\n opacity: 0.4;\n pointer-events: none;\n z-index: 9999;\n transition: none;\n `;\n document.body.appendChild(ghost);\n this.drag.ghost = ghost;\n // Store initial offset so ghost follows cursor smoothly\n (this.drag as any)._ghostOffsetY = this.drag.startY - blockRect.top;\n\n // Create drop indicator\n const parent = this.view.dom.parentNode as HTMLElement;\n this.dropIndicator = document.createElement('div');\n this.dropIndicator.className = 'ab-drop-indicator';\n this.dropIndicator.style.display = 'none';\n parent.appendChild(this.dropIndicator);\n\n // Re-detect scroll container at drag time (content may have grown since init)\n this.scrollContainer = this.findScrollContainer(this.view.dom);\n\n // Start auto-scroll loop\n this.tickAutoScroll();\n }\n\n private addGlobalDragListeners(pointerId: number): void {\n const onDocPointerUp = (e: PointerEvent) => {\n if (e.pointerId === pointerId) this.onPointerUp(e);\n };\n const onDocPointerCancel = (e: PointerEvent) => {\n if (e.pointerId === pointerId) this.cancelDrag();\n };\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') this.cancelDrag();\n };\n\n document.addEventListener('pointerup', onDocPointerUp);\n document.addEventListener('pointercancel', onDocPointerCancel);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n this.globalCleanup = () => {\n document.removeEventListener('pointerup', onDocPointerUp);\n document.removeEventListener('pointercancel', onDocPointerCancel);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.drag || e.pointerId !== this.drag.pointerId) return;\n if (!this.view.editable) { this.cancelDrag(); return; }\n\n // Threshold check — only activate drag after moving 5px\n if (!this.drag.activated) {\n const dx = e.clientX - this.drag.startX;\n const dy = e.clientY - this.drag.startY;\n if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) return;\n this.activateDrag();\n }\n\n this.drag.pointerY = e.clientY;\n\n // Move ghost to follow cursor\n if (this.drag.ghost) {\n const offsetY = (this.drag as any)._ghostOffsetY ?? 0;\n this.drag.ghost.style.top = `${e.clientY - offsetY}px`;\n }\n\n this.updateDropTarget();\n }\n\n private updateDropTarget(): void {\n if (!this.drag || !this.dropIndicator) return;\n\n const parent = this.view.dom.parentNode as HTMLElement;\n const parentRect = parent.getBoundingClientRect();\n const editorRect = this.view.dom.getBoundingClientRect();\n\n // Build block rects relative to viewport\n const blockRects = this.prevBlocks.map(b => {\n const r = b.dom.getBoundingClientRect();\n return { top: r.top, bottom: r.bottom };\n });\n\n const targetIndex = findDropTarget(blockRects, this.drag.pointerY);\n this.drag.dropTargetIndex = targetIndex;\n\n // Compute indicator position\n let indicatorY: number;\n if (targetIndex === 0) {\n indicatorY = (blockRects[0]?.top ?? parentRect.top) - parentRect.top + parent.scrollTop - 1;\n } else if (targetIndex >= blockRects.length) {\n const last = blockRects[blockRects.length - 1];\n indicatorY = (last?.bottom ?? parentRect.bottom) - parentRect.top + parent.scrollTop + 1;\n } else {\n const above = blockRects[targetIndex - 1].bottom;\n const below = blockRects[targetIndex].top;\n indicatorY = ((above + below) / 2) - parentRect.top + parent.scrollTop;\n }\n\n // Hide when drop position equals source (no-op)\n const isSamePos = targetIndex === this.drag.fromIndex || targetIndex === this.drag.fromIndex + 1;\n this.dropIndicator.style.display = isSamePos ? 'none' : '';\n this.dropIndicator.style.top = `${indicatorY}px`;\n this.dropIndicator.style.left = `${editorRect.left - parentRect.left}px`;\n this.dropIndicator.style.width = `${editorRect.width}px`;\n }\n\n private onPointerUp(e: PointerEvent): void {\n if (!this.drag || e.pointerId !== this.drag.pointerId) return;\n\n // If threshold was never met, cancel without moving\n if (!this.drag.activated) {\n this.cleanupDragState();\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n return;\n }\n\n const fromIndex = this.drag.fromIndex;\n const toIndex = this.drag.dropTargetIndex;\n\n this.cleanupDragState();\n\n // Execute the move\n if (fromIndex !== toIndex && fromIndex + 1 !== toIndex) {\n const tr = buildMoveTransaction(this.view.state, fromIndex, toIndex);\n if (tr) {\n this.view.dispatch(tr.scrollIntoView());\n this.view.focus();\n this.flashMovedBlock(toIndex > fromIndex ? toIndex - 1 : toIndex);\n this.announce(`블록이 위치 ${(toIndex > fromIndex ? toIndex : toIndex + 1)}(으)로 이동됨`);\n }\n }\n\n // Flush pending update\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n }\n\n cancelDrag(): void {\n if (!this.drag) return;\n this.cleanupDragState();\n\n if (this.pendingUpdate) {\n this.pendingUpdate = false;\n this.scheduleUpdate();\n }\n }\n\n private cleaningUp = false;\n\n private cleanupDragState(): void {\n if (!this.drag || this.cleaningUp) return;\n this.cleaningUp = true;\n\n this.drag.handle.classList.remove('dragging');\n this.drag.blockDom.classList.remove('ab-block-dragging');\n\n // Remove ghost element\n if (this.drag.ghost) {\n this.drag.ghost.remove();\n this.drag.ghost = null;\n }\n\n // Try to release pointer capture (may already be released).\n // releasePointerCapture can fire lostpointercapture synchronously,\n // so the cleaningUp guard prevents re-entrant calls.\n try {\n this.drag.handle.releasePointerCapture(this.drag.pointerId);\n } catch { /* already released */ }\n\n this.dropIndicator?.remove();\n this.dropIndicator = null;\n\n // Remove global fallback listeners\n if (this.globalCleanup) {\n this.globalCleanup();\n this.globalCleanup = null;\n }\n\n if (this.scrollRAF !== null) {\n cancelAnimationFrame(this.scrollRAF);\n this.scrollRAF = null;\n }\n\n this.drag = null;\n this.cleaningUp = false;\n // Restore hover state based on actual pointer position\n delete this.layer.dataset.hover;\n }\n\n // ── Private: auto-scroll ──\n\n private tickAutoScroll(): void {\n if (!this.drag) return;\n\n const rect = this.scrollContainer.getBoundingClientRect();\n const speed = computeAutoScrollSpeed(this.drag.pointerY, rect.top, rect.bottom);\n\n if (speed !== 0) {\n this.scrollContainer.scrollBy(0, speed);\n this.syncHandlePositions();\n this.updateDropTarget();\n }\n\n this.scrollRAF = requestAnimationFrame(() => this.tickAutoScroll());\n }\n\n private findScrollContainer(el: HTMLElement): HTMLElement {\n let current = el.parentElement;\n while (current) {\n const overflow = getComputedStyle(current).overflowY;\n if (overflow === 'auto' || overflow === 'scroll') return current;\n // PerfectScrollbar uses overflow:hidden + .ps class\n if (overflow === 'hidden' && (current.classList.contains('ps') || current.scrollHeight > current.clientHeight + 1)) return current;\n current = current.parentElement;\n }\n return el.parentElement ?? el;\n }\n\n // ── Private: feedback ──\n\n private flashMovedBlock(blockIndex: number): void {\n // Re-collect after transaction so we get the new DOM\n requestAnimationFrame(() => {\n const blocks = this.collectBlocks();\n const block = blocks[blockIndex];\n if (!block) return;\n block.dom.classList.add('ab-block-just-moved');\n const onEnd = () => {\n block.dom.classList.remove('ab-block-just-moved');\n block.dom.removeEventListener('animationend', onEnd);\n };\n block.dom.addEventListener('animationend', onEnd);\n });\n }\n\n private announce(message: string): void {\n this.liveRegion.textContent = '';\n // Force screen reader to re-read by clearing then setting\n requestAnimationFrame(() => {\n this.liveRegion.textContent = message;\n });\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Keyboard commands\n// ────────────────────────────────────────────────────────────\n\nfunction moveBlockCommand(direction: -1 | 1): Command {\n return (state, dispatch) => {\n const $from = state.selection.$from;\n // Resolve to top-level block\n const blockIndex = $from.index(0);\n const toIndex = direction === -1 ? blockIndex - 1 : blockIndex + 2;\n\n if (toIndex < 0 || toIndex > state.doc.childCount) return false;\n\n if (dispatch) {\n const tr = buildMoveTransaction(state, blockIndex, toIndex);\n if (tr) {\n dispatch(tr.scrollIntoView());\n } else {\n return false;\n }\n }\n return true;\n };\n}\n\n// ────────────────────────────────────────────────────────────\n// Plugin factory (public API — unchanged signature)\n// ────────────────────────────────────────────────────────────\n\nexport function createDragHandlePlugin(): ActionbookPlugin {\n return {\n name: 'dragHandle',\n\n plugins: () => {\n let controller: DragHandleController | null = null;\n\n return [\n new Plugin({\n key: PLUGIN_KEY,\n view(editorView) {\n controller = new DragHandleController(editorView);\n return {\n update(view, prevState) {\n controller?.update(view, prevState);\n },\n destroy() {\n controller?.destroy();\n controller = null;\n },\n };\n },\n }),\n ];\n },\n\n keymap: () => ({\n 'Alt-ArrowUp': moveBlockCommand(-1),\n 'Alt-ArrowDown': moveBlockCommand(1),\n }),\n };\n}\n","/**\n * NodeView plugin for todo/checkbox list items.\n * Renders a clickable checkbox when listItem.attrs.checked !== null.\n */\nimport React from 'react';\nimport type { NodeView, EditorView } from 'prosemirror-view';\nimport type { Node as PMNode } from 'prosemirror-model';\nimport { Plugin } from 'prosemirror-state';\nimport type { EditorState, Transaction } from 'prosemirror-state';\nimport type { ActionbookPlugin, NodeViewFactory } from './types';\n\nfunction createCheckboxDOM(checked: boolean): HTMLElement {\n const el = document.createElement('span');\n el.contentEditable = 'false';\n el.style.cssText = `\n display: inline-flex; align-items: center; justify-content: center;\n width: 18px; height: 18px; margin-right: 6px;\n cursor: pointer; border-radius: 4px;\n user-select: none; flex-shrink: 0; vertical-align: middle;\n position: relative; top: -1px; font-size: 12px; font-weight: 700;\n ${checked\n ? 'background: #6366f1; color: #fff; border: none;'\n : 'background: transparent; color: transparent; border: 2px solid #d1d5db;'\n }\n `;\n el.textContent = checked ? '✓' : '';\n return el;\n}\n\nclass TodoListItemView implements NodeView {\n dom: HTMLElement;\n contentDOM: HTMLElement;\n private checkbox: HTMLElement;\n\n constructor(\n private node: PMNode,\n private view: EditorView,\n private getPos: () => number | undefined,\n ) {\n const checked = node.attrs.checked as boolean;\n\n this.dom = document.createElement('li');\n this.dom.className = 'todo-item';\n this.dom.dataset.checked = String(checked);\n this.dom.style.display = 'flex';\n this.dom.style.alignItems = 'flex-start';\n\n this.checkbox = createCheckboxDOM(checked);\n this.checkbox.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const pos = this.getPos();\n if (pos == null) return;\n this.view.dispatch(\n this.view.state.tr.setNodeMarkup(pos, undefined, {\n ...this.node.attrs,\n checked: !this.node.attrs.checked,\n }),\n );\n });\n\n this.contentDOM = document.createElement('div');\n this.contentDOM.style.flex = '1';\n if (checked) {\n this.contentDOM.style.textDecoration = 'line-through';\n this.contentDOM.style.opacity = '0.6';\n }\n\n this.dom.appendChild(this.checkbox);\n this.dom.appendChild(this.contentDOM);\n }\n\n update(node: PMNode): boolean {\n if (node.type !== this.node.type) return false;\n // If checked changed from/to null, refuse update (different rendering)\n if ((node.attrs.checked == null) !== (this.node.attrs.checked == null)) return false;\n if (node.attrs.checked == null) return false;\n\n this.node = node;\n const checked = node.attrs.checked as boolean;\n this.dom.dataset.checked = String(checked);\n\n // Update checkbox\n const newCb = createCheckboxDOM(checked);\n newCb.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const pos = this.getPos();\n if (pos == null) return;\n this.view.dispatch(\n this.view.state.tr.setNodeMarkup(pos, undefined, {\n ...this.node.attrs,\n checked: !this.node.attrs.checked,\n }),\n );\n });\n this.dom.replaceChild(newCb, this.checkbox);\n this.checkbox = newCb;\n\n // Update content styling\n if (checked) {\n this.contentDOM.style.textDecoration = 'line-through';\n this.contentDOM.style.opacity = '0.6';\n } else {\n this.contentDOM.style.textDecoration = '';\n this.contentDOM.style.opacity = '';\n }\n\n return true;\n }\n}\n\n/**\n * appendTransaction: when splitListItem creates a new listItem,\n * the new item inherits the parent's `value` attr. Reset it to null\n * so it auto-increments from the previous item.\n */\nfunction createListItemValueResetPlugin() {\n return new Plugin({\n appendTransaction(trs: readonly Transaction[], oldState: EditorState, newState: EditorState) {\n if (!trs.some((tr) => tr.docChanged)) return null;\n\n const oldCount = oldState.doc.childCount;\n let hasNewListItems = false;\n\n // Quick check: did any transaction add list items?\n newState.doc.descendants((node: PMNode) => {\n if (hasNewListItems) return false;\n if (node.type.name === 'listItem' && node.attrs.value != null) {\n hasNewListItems = true;\n }\n });\n if (!hasNewListItems) return null;\n\n // Find listItems with value attrs that are inside orderedLists\n // and reset value to null for items that weren't explicitly set by the user\n // Strategy: if two consecutive items have the same value, the second one was inherited\n let tr = newState.tr;\n let changed = false;\n\n newState.doc.descendants((node: PMNode, pos: number) => {\n if (node.type.name !== 'orderedList') return;\n let prevValue: number | null = null;\n node.forEach((li: PMNode, offset: number) => {\n const liValue = li.attrs.value as number | null;\n if (liValue != null && liValue === prevValue) {\n // Duplicate value → this was inherited from splitListItem, reset it\n const liPos = pos + 1 + offset; // +1 for orderedList opening\n tr = tr.setNodeMarkup(liPos, undefined, { ...li.attrs, value: null });\n changed = true;\n }\n prevValue = liValue;\n });\n });\n\n return changed ? tr : null;\n },\n });\n}\n\nexport function createTodoNodeViewPlugin(): ActionbookPlugin {\n return {\n name: 'todoNodeView',\n plugins: () => [createListItemValueResetPlugin()],\n nodeViews: () => ({\n listItem: ((node: PMNode, view: EditorView, getPos: () => number | undefined): NodeView => {\n // Only use custom node view for todo items (checked !== null)\n if (node.attrs.checked == null) {\n const li = document.createElement('li');\n // Sync value attribute for per-item ordered list numbering\n if (node.attrs.value != null) {\n li.value = node.attrs.value as number;\n }\n return {\n dom: li,\n contentDOM: li,\n update(updatedNode: PMNode) {\n if (updatedNode.type.name !== 'listItem') return false;\n // If it became a todo item, let PM recreate with TodoListItemView\n if (updatedNode.attrs.checked != null) return false;\n // Sync value attribute\n if (updatedNode.attrs.value != null) {\n li.value = updatedNode.attrs.value as number;\n } else {\n li.removeAttribute('value');\n }\n return true;\n },\n };\n }\n return new TodoListItemView(node, view, getPos);\n }) as NodeViewFactory,\n }),\n };\n}\n","/**\n * Placeholder plugin — shows hint text in empty paragraphs.\n *\n * Uses a node decoration with CSS ::before and ::after pseudo-elements\n * to render \"Type to start writing, or press [/] to insert an action.\"\n * where [/] is a styled keycap badge.\n *\n * Only the paragraph that currently has the cursor gets the placeholder.\n */\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\n\nconst pluginKey = new PluginKey<DecorationSet>('placeholder');\n\nfunction buildDecorations(state: import('prosemirror-state').EditorState): DecorationSet {\n const { doc, selection } = state;\n if (!selection.empty) return DecorationSet.empty;\n\n const $from = selection.$from;\n const parent = $from.parent;\n\n // Only show placeholder in empty paragraphs\n if (parent.type.name !== 'paragraph' || parent.content.size !== 0) {\n return DecorationSet.empty;\n }\n\n // Don't show placeholder inside noteBlock or blockquote (system prompt)\n const EXCLUDED_ANCESTORS = new Set(['noteBlock', 'blockquote', 'jinjaIfBranch']);\n for (let d = $from.depth - 1; d > 0; d--) {\n if (EXCLUDED_ANCESTORS.has($from.node(d).type.name)) {\n return DecorationSet.empty;\n }\n }\n\n const pos = $from.before($from.depth);\n const deco = Decoration.node(pos, pos + parent.nodeSize, {\n class: 'ab-empty-paragraph',\n 'data-placeholder': 'Type to start writing, or press / to insert an action.',\n });\n\n return DecorationSet.create(doc, [deco]);\n}\n\nexport function createPlaceholderPlugin(): ActionbookPlugin {\n let isEditable = true;\n\n return {\n name: 'placeholder',\n plugins: () => [\n new Plugin<DecorationSet>({\n key: pluginKey,\n view(editorView) {\n isEditable = editorView.editable;\n return {\n update(view) {\n isEditable = view.editable;\n },\n };\n },\n state: {\n init(_, state) {\n return buildDecorations(state);\n },\n apply(tr, oldSet, _oldState, newState) {\n if (tr.docChanged || tr.selectionSet) {\n return buildDecorations(newState);\n }\n return oldSet;\n },\n },\n props: {\n decorations(state) {\n if (!isEditable) return DecorationSet.empty;\n return pluginKey.getState(state) ?? DecorationSet.empty;\n },\n },\n }),\n ],\n };\n}\n","/**\n * SlashCommandMenu — injectable floating slash-command picker.\n *\n * Usage:\n * ```tsx\n * // Define items (inject from outside)\n * const items: SlashCommandItem[] = [\n * {\n * id: 'heading1',\n * title: 'Heading 1',\n * description: 'Large section heading',\n * icon: <span>H1</span>,\n * command({ view, range }) {\n * const { state, dispatch } = view;\n * const tr = state.tr.delete(range.from, range.to);\n * setBlockType(heading, { level: 1 })(\n * state.apply(tr),\n * (newTr) => dispatch(tr.steps.length ? tr : newTr),\n * );\n * },\n * },\n * ];\n *\n * // In your editor component:\n * const [editorState, setEditorState] = useState<EditorState | null>(null);\n * const handle = useEditorView({ ..., onTransaction: setEditorState });\n *\n * return (\n * <>\n * <EditorShell ref={handle.viewRef} />\n * <SlashCommandMenu\n * view={handle.view}\n * editorState={editorState}\n * items={items}\n * />\n * </>\n * );\n * ```\n *\n * The `command` callback receives the editor view and the range of the\n * `/query` trigger text. It is responsible for deleting the trigger and\n * inserting whatever content it wants.\n */\n\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { EditorView } from 'prosemirror-view';\nimport type { EditorState } from 'prosemirror-state';\nimport { slashCommandKey } from '../plugin/slashCommandPlugin';\nimport type { SlashCommandState } from '../plugin/slashCommandPlugin';\n\n// ── Public types ──────────────────────────────────────────\n\nexport interface SlashCommandItem {\n /** Unique key; falls back to `title` if omitted. */\n id?: string;\n title: string;\n description?: string;\n /** Optional icon node rendered to the left of the title. */\n icon?: React.ReactNode;\n /** Optional group name. When present, items are visually grouped with a header. */\n group?: string;\n /** Optional shortcut symbol displayed on the right side (e.g. \"#\", \"##\", \"---\"). */\n shortcut?: string;\n /**\n * Execute this command.\n *\n * @param view - Live EditorView; use `view.state` / `view.dispatch`.\n * @param range - Positions of the full `/query` text in the document.\n * Delete this range before inserting your content.\n */\n command: (props: { view: EditorView; range: { from: number; to: number } }) => void;\n}\n\nexport interface SlashCommandMenuProps {\n view: EditorView | null;\n editorState: EditorState | null;\n /** Full item list. Filtered by the current query automatically. */\n items: SlashCommandItem[];\n}\n\n// ── Filtering ─────────────────────────────────────────────\n\nfunction filterItems(items: SlashCommandItem[], query: string): SlashCommandItem[] {\n if (!query) return items;\n // Support 2-depth queries: \"Prefix:search\" → filter by \"search\" only\n const colonIdx = query.indexOf(':');\n const searchPart = colonIdx >= 0 ? query.slice(colonIdx + 1).trim() : query;\n if (!searchPart) return items;\n const words = searchPart.toLowerCase().split(/\\s+/);\n const filtered = items.filter(\n ({ title, description }) => {\n const hay = (title + ' ' + (description ?? '')).toLowerCase();\n return words.every((w) => hay.includes(w));\n },\n );\n // Fallback: if nothing matches, show all items (same pattern as legacy editor)\n return filtered.length > 0 ? filtered : items;\n}\n\n// ── Scrollbar CSS (webkit) ────────────────────────────────\n\nconst SCROLLBAR_STYLE_ID = 'ab-slash-menu-scrollbar';\n\nfunction injectScrollbarStyle() {\n if (document.getElementById(SCROLLBAR_STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = SCROLLBAR_STYLE_ID;\n style.textContent = `\n.ab-slash-menu::-webkit-scrollbar { display: none; }\n.ab-slash-menu { scrollbar-width: none; }\n`;\n document.head.appendChild(style);\n}\n\n// ── Shared styles ─────────────────────────────────────────\n\nconst POPUP_SHADOW =\n '0 3px 5px -3px rgba(13,13,13,0.04), 0 3px 14px 2px rgba(13,13,13,0.08), 0 8px 10px 1px rgba(13,13,13,0.12)';\n\nconst BTN_RESET: React.CSSProperties = {\n border: 'none',\n padding: 0,\n margin: 0,\n background: 'transparent',\n fontFamily: 'inherit',\n cursor: 'pointer',\n lineHeight: 1,\n textAlign: 'left',\n width: '100%',\n};\n\nconst VPORT_MARGIN = 8;\nconst MENU_WIDTH = 440;\nconst MAX_MENU_H = 400;\n\n// ── Menu component ────────────────────────────────────────\n\nexport function SlashCommandMenu({ view, editorState, items }: SlashCommandMenuProps) {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const listRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => { injectScrollbarStyle(); }, []);\n\n // Read plugin state\n const pluginState = editorState\n ? (slashCommandKey.getState(editorState) as SlashCommandState | undefined)\n : undefined;\n\n const active = pluginState?.active ?? false;\n const range = pluginState?.range ?? null;\n const query = pluginState?.query ?? '';\n\n const filtered = filterItems(items, query);\n\n // Reset selection when query or active state changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [query, active]);\n\n // Scroll selected item into view\n useEffect(() => {\n const list = listRef.current;\n if (!list) return;\n const item = list.querySelector(`[data-slash-index=\"${selectedIndex}\"]`) as HTMLElement | null;\n item?.scrollIntoView({ block: 'nearest' });\n }, [selectedIndex]);\n\n // Keyboard handler — captures Arrow/Enter before ProseMirror sees them\n // Only active when there are items to show (empty items = no menu, no key capture)\n useEffect(() => {\n if (!active || !view || filtered.length === 0) return;\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n setSelectedIndex((i) => Math.min(i + 1, filtered.length - 1));\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n setSelectedIndex((i) => Math.max(i - 1, 0));\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n if (filtered[selectedIndex] && range) {\n filtered[selectedIndex].command({ view, range });\n view.focus();\n }\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n // Delete the /query text to close the menu — user can type / again to reopen\n if (range) {\n view.dispatch(view.state.tr.delete(range.from, range.to));\n }\n view.focus();\n }\n };\n\n document.addEventListener('keydown', onKeyDown, true);\n return () => document.removeEventListener('keydown', onKeyDown, true);\n }, [active, view, filtered, selectedIndex, range]);\n\n // Compute position after DOM update via useLayoutEffect\n const [menuPos, setMenuPos] = useState<{ top: number; left: number } | null>(null);\n\n const menuRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!active || !view || !range || filtered.length === 0) {\n setMenuPos(null);\n return;\n }\n try {\n const coords = view.coordsAtPos(range.to);\n let left = coords.left;\n left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - MENU_WIDTH - VPORT_MARGIN));\n\n // Use actual menu height if rendered, otherwise estimate\n const menuHeight = menuRef.current?.offsetHeight ?? MAX_MENU_H;\n let top = coords.bottom + 4;\n if (top + menuHeight > window.innerHeight - VPORT_MARGIN) {\n top = coords.top - menuHeight - 4;\n }\n setMenuPos({ top, left });\n } catch {\n // coordsAtPos can fail if view is not attached\n }\n });\n\n if (!active || !view || !range || filtered.length === 0 || !menuPos) return null;\n\n return createPortal(\n <div\n ref={menuRef}\n className=\"ab-slash-menu\"\n style={{\n position: 'fixed',\n top: menuPos.top,\n left: menuPos.left,\n width: MENU_WIDTH,\n maxHeight: MAX_MENU_H,\n overflowY: 'auto',\n background: '#fff',\n borderRadius: 4,\n boxShadow: POPUP_SHADOW,\n padding: '8px 0',\n zIndex: 1100,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div ref={listRef}>\n {filtered.map((item, i) => {\n const prevGroup = i > 0 ? filtered[i - 1].group : undefined;\n const showGroupHeader = item.group && item.group !== prevGroup;\n return (\n <React.Fragment key={item.id ?? item.title}>\n {showGroupHeader && (\n <>\n <div\n style={{\n padding: '16px 16px 4px',\n fontSize: 12,\n fontWeight: 600,\n lineHeight: '12px',\n color: '#858585',\n }}\n >\n {item.group}\n </div>\n </>\n )}\n <SlashMenuItem\n item={item}\n index={i}\n selected={i === selectedIndex}\n onMouseEnter={() => setSelectedIndex(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n if (range) {\n item.command({ view, range });\n view.focus();\n }\n }}\n />\n </React.Fragment>\n );\n })}\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── SlashMenuItem ─────────────────────────────────────────\n\ninterface SlashMenuItemProps {\n item: SlashCommandItem;\n index: number;\n selected: boolean;\n onMouseEnter: () => void;\n onMouseDown: (e: React.MouseEvent) => void;\n}\n\nfunction SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }: SlashMenuItemProps) {\n return (\n <button\n data-slash-index={index}\n style={{\n ...BTN_RESET,\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n padding: '6px 16px',\n background: selected ? 'rgba(13, 13, 13, 0.04)' : 'transparent',\n transition: 'background 0.08s',\n }}\n onMouseEnter={onMouseEnter}\n onMouseDown={onMouseDown}\n >\n <span\n style={{\n flex: '1 0 0',\n fontSize: 14,\n fontWeight: 400,\n lineHeight: '20px',\n letterSpacing: '-0.1px',\n color: '#0d0d0d',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n minWidth: 0,\n }}\n >\n {item.title}\n </span>\n\n {/* Description or shortcut (right-aligned) */}\n {(item.description || item.shortcut) && (\n <span\n style={{\n fontSize: 12,\n lineHeight: '16px',\n color: '#5e5e5e',\n whiteSpace: 'nowrap',\n flexShrink: 0,\n textAlign: 'right',\n }}\n >\n {item.shortcut ?? item.description}\n </span>\n )}\n </button>\n );\n}\n","import React, { useState, type ReactElement } from 'react';\nimport type { DocumentNode } from '../../ast/types';\nimport { textContent } from '../../ast/traverse';\nimport { analyzeJinjaBlocks, type JinjaVisualStructure, type JinjaVisualBranch } from '../../jinja/analyzer';\n\nexport interface JinjaTreeViewProps {\n doc: DocumentNode;\n className?: string;\n}\n\nconst BRANCH_COLORS: Record<string, string> = {\n if: '#6366f1',\n elif: '#f59e0b',\n else: '#8b5cf6',\n};\n\nfunction getBlockPreview(doc: DocumentNode, startIdx: number, endIdx: number): string {\n const blocks = doc.content.slice(startIdx, endIdx);\n const text = blocks.map((b) => textContent(b)).join(' ').trim();\n return text.length > 40 ? text.slice(0, 40) + '...' : text;\n}\n\nfunction BranchNode({\n branch,\n doc,\n isLast,\n}: {\n branch: JinjaVisualBranch;\n doc: DocumentNode;\n isLast: boolean;\n}): ReactElement {\n const color = BRANCH_COLORS[branch.type] || '#6366f1';\n const blockCount = branch.blockEndIndex - branch.blockStartIndex;\n const preview = getBlockPreview(doc, branch.blockStartIndex, branch.blockEndIndex);\n const connector = isLast ? '\\u2514\\u2500' : '\\u251C\\u2500';\n\n return (\n <div className=\"jinja-tree-branch\">\n <span className=\"jinja-tree-connector\">{connector} </span>\n <span className=\"jinja-tree-badge\" style={{ color, borderColor: color }}>\n [{branch.type}]\n </span>\n {branch.condition && (\n <span className=\"jinja-tree-condition\"> {branch.condition}</span>\n )}\n <span className=\"jinja-tree-meta\">\n {' '}{blockCount} block{blockCount !== 1 ? 's' : ''}\n {preview && `: \"${preview}\"`}\n </span>\n </div>\n );\n}\n\nfunction StructureNode({ structure, doc }: { structure: JinjaVisualStructure; doc: DocumentNode }): ReactElement {\n const [expanded, setExpanded] = useState(true);\n const firstBranch = structure.branches[0];\n const label = firstBranch?.condition ? `if ${firstBranch.condition}` : 'if';\n\n return (\n <div className=\"jinja-tree-structure\">\n <button\n className=\"jinja-tree-toggle\"\n onClick={() => setExpanded(!expanded)}\n type=\"button\"\n >\n <span className=\"jinja-tree-arrow\">{expanded ? '\\u25BC' : '\\u25B6'}</span>\n <span className=\"jinja-tree-label\">{label}</span>\n </button>\n {expanded && (\n <div className=\"jinja-tree-branches\">\n {structure.branches.map((branch, i) => (\n <BranchNode\n key={`${structure.id}-${i}`}\n branch={branch}\n doc={doc}\n isLast={i === structure.branches.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function JinjaTreeView({ doc, className }: JinjaTreeViewProps): ReactElement | null {\n const structures = analyzeJinjaBlocks(doc);\n if (structures.length === 0) return null;\n\n return (\n <div className={`jinja-tree ${className || ''}`}>\n {structures.map((structure) => (\n <StructureNode key={structure.id} structure={structure} doc={doc} />\n ))}\n </div>\n );\n}\n","/**\n * DocumentTreeView — lightweight React tree component for document outline.\n * Shows headings, jump points, jinja if blocks, resource tags, end actions, and note blocks.\n * Supports selected item highlight (purple background like Figma).\n */\nimport { useState, type ReactElement } from 'react';\nimport type { DocumentNode } from '../../ast/types';\nimport { buildDocumentTree, type DocumentTreeNode } from '../../tree/documentTree';\n\nexport interface DocumentTreeViewProps {\n doc: DocumentNode;\n className?: string;\n onNavigate?: (blockIndex: number) => void;\n}\n\nconst ICONS: Record<string, string> = {\n heading: 'H',\n jumpPoint: '\\u2299',\n jinjaIf: '\\u2325',\n jinjaBranch: '\\u2387',\n resourceTag: '\\u229B',\n noteBlock: '\\u270D',\n endAction: '\\u2192',\n};\n\nconst COLORS: Record<string, string> = {\n heading: '#333',\n jumpPoint: '#d97706',\n jinjaIf: '#6366f1',\n jinjaBranch: '#8b5cf6',\n resourceTag: '#059669',\n noteBlock: '#999',\n endAction: '#059669',\n};\n\nfunction TreeNodeItem({\n node,\n onNavigate,\n depth,\n selectedPath,\n onSelect,\n path,\n}: {\n node: DocumentTreeNode;\n onNavigate?: (blockIndex: number) => void;\n depth: number;\n selectedPath: string | null;\n onSelect: (path: string) => void;\n path: string;\n}): ReactElement {\n const [collapsed, setCollapsed] = useState(false);\n const hasChildren = node.children.length > 0;\n const icon = ICONS[node.type] || '\\u2022';\n const color = COLORS[node.type] || '#666';\n const isSelected = selectedPath === path;\n\n const headingLevel = node.meta?.level as number | undefined;\n const headingLabel = headingLevel ? `H${headingLevel}` : icon;\n\n return (\n <div style={{ paddingLeft: depth > 0 ? 16 : 0 }}>\n <div\n className=\"doc-tree-node\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '3px 6px',\n borderRadius: 4,\n cursor: onNavigate ? 'pointer' : 'default',\n fontSize: 13,\n lineHeight: '1.5',\n background: isSelected ? 'rgba(99, 102, 241, 0.1)' : 'transparent',\n transition: 'background 0.12s ease',\n }}\n onClick={(e) => {\n e.stopPropagation();\n if (hasChildren) setCollapsed(!collapsed);\n onSelect(path);\n onNavigate?.(node.blockIndex);\n }}\n onMouseEnter={(e) => {\n if (!isSelected) (e.currentTarget as HTMLElement).style.background = '#f3f4f6';\n }}\n onMouseLeave={(e) => {\n if (!isSelected) (e.currentTarget as HTMLElement).style.background = 'transparent';\n }}\n >\n {hasChildren && (\n <span\n style={{\n width: 14,\n textAlign: 'center',\n fontSize: 10,\n color: '#999',\n flexShrink: 0,\n userSelect: 'none',\n }}\n >\n {collapsed ? '\\u25B8' : '\\u25BE'}\n </span>\n )}\n {!hasChildren && <span style={{ width: 14, flexShrink: 0 }} />}\n\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 22,\n height: 18,\n borderRadius: 3,\n fontSize: 10,\n fontWeight: 700,\n color: isSelected ? '#6366f1' : color,\n background: isSelected ? 'rgba(99, 102, 241, 0.15)' : `${color}11`,\n border: `1px solid ${isSelected ? 'rgba(99, 102, 241, 0.3)' : `${color}33`}`,\n flexShrink: 0,\n }}\n >\n {node.type === 'heading' ? headingLabel : icon}\n </span>\n\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: isSelected\n ? '#6366f1'\n : node.type === 'noteBlock'\n ? '#999'\n : node.type === 'endAction'\n ? '#059669'\n : '#333',\n fontStyle: node.type === 'noteBlock' ? 'italic' : 'normal',\n fontWeight: isSelected\n ? 600\n : node.type === 'heading' && headingLevel && headingLevel <= 2\n ? 600\n : 400,\n }}\n >\n {node.label}\n </span>\n\n {node.meta?.tagType != null && (\n <span\n style={{\n fontSize: 10,\n padding: '1px 5px',\n borderRadius: 999,\n background: node.type === 'endAction' ? 'rgba(5, 150, 105, 0.1)' : 'rgba(0, 0, 0, 0.04)',\n color: node.type === 'endAction' ? '#059669' : '#999',\n fontWeight: 500,\n }}\n >\n {String(node.meta.tagType)}\n </span>\n )}\n </div>\n\n {hasChildren && !collapsed && (\n <div>\n {node.children.map((child, i) => (\n <TreeNodeItem\n key={`${child.type}-${child.blockIndex}-${i}`}\n node={child}\n onNavigate={onNavigate}\n depth={depth + 1}\n selectedPath={selectedPath}\n onSelect={onSelect}\n path={`${path}/${i}`}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function DocumentTreeView({ doc, className, onNavigate }: DocumentTreeViewProps): ReactElement {\n const tree = buildDocumentTree(doc);\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n\n if (tree.length === 0) {\n return (\n <div className={className} style={{ color: '#999', fontSize: 13, padding: 16 }}>\n No document structure to display.\n </div>\n );\n }\n\n return (\n <div className={className} style={{ padding: '8px 0', fontFamily: 'Inter, sans-serif' }}>\n {tree.map((node, i) => (\n <TreeNodeItem\n key={`${node.type}-${node.blockIndex}-${i}`}\n node={node}\n onNavigate={onNavigate}\n depth={0}\n selectedPath={selectedPath}\n onSelect={setSelectedPath}\n path={`${i}`}\n />\n ))}\n </div>\n );\n}\n","/**\n * Floating UI for the Actionbook editor.\n *\n * Two interaction patterns:\n *\n * 1. SelectionToolbar — appears above a non-empty text selection.\n * Buttons: Bold · Italic · Underline · Strikethrough · Code · Link · ─ · Block type ▾\n *\n * 2. EmptyParaHandle — appears to the left of an empty paragraph/heading\n * after the cursor has dwelled there for DWELL_MS (600 ms).\n * A small \"+\" button opens a block-type picker menu.\n *\n * Both are rendered into document.body via React portals so they never\n * get clipped by overflow:hidden ancestors.\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { Mark, MarkType, ResolvedPos } from 'prosemirror-model';\nimport type { EditorView } from 'prosemirror-view';\nimport { TextSelection } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { setBlockType, toggleMark, wrapIn } from 'prosemirror-commands';\nimport { wrapInList } from 'prosemirror-schema-list';\nimport { actionbookSchema } from '../schema';\n\n// ── Schema refs ───────────────────────────────────────────\n\nconst { paragraph, heading, bulletList, orderedList, blockquote } = actionbookSchema.nodes;\nconst {\n bold,\n italic,\n underline,\n strikethrough,\n code,\n link: linkMark,\n} = actionbookSchema.marks;\n\n// ── Constants ─────────────────────────────────────────────\n\nconst DWELL_MS = 600;\nconst TOOLBAR_H = 36;\nconst TOOLBAR_GAP = 8;\nconst VPORT_MARGIN = 8;\n// attribute used to detect clicks inside any floating element\nconst FLOAT_ATTR = 'data-ab-float';\n\n// ── Editor state helpers ──────────────────────────────────\n\nfunction hasMark(state: EditorState, type: typeof bold): boolean {\n const { from, to, empty } = state.selection;\n if (empty) return false;\n return state.doc.rangeHasMark(from, to, type);\n}\n\nfunction getMarkRange(\n $pos: ResolvedPos,\n type: MarkType,\n): { from: number; to: number; mark: Mark } | null {\n const { parentOffset } = $pos;\n\n let child = $pos.parent.childAfter(parentOffset);\n\n if (parentOffset === child.offset && child.offset !== 0) {\n child = $pos.parent.childBefore(parentOffset);\n }\n\n if (!child.node) return null;\n\n const mark = child.node.marks.find((candidate) => candidate.type === type);\n if (!mark) return null;\n\n const parentStart = $pos.start();\n let { index: startIndex } = child;\n let startPos = parentStart + child.offset;\n let endIndex = startIndex + 1;\n let endPos = startPos + child.node.nodeSize;\n\n while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {\n startIndex -= 1;\n startPos -= $pos.parent.child(startIndex).nodeSize;\n }\n\n while (\n endIndex < $pos.parent.childCount &&\n mark.isInSet($pos.parent.child(endIndex).marks)\n ) {\n endPos += $pos.parent.child(endIndex).nodeSize;\n endIndex += 1;\n }\n\n return { from: startPos, to: endPos, mark };\n}\n\ninterface LinkAtCursor {\n href: string;\n text: string;\n from: number;\n to: number;\n}\n\nfunction getLinkAtCursor(state: EditorState): LinkAtCursor | null {\n const { selection, doc } = state;\n if (!selection.empty) return null;\n\n const range = getMarkRange(doc.resolve(selection.from), linkMark);\n if (!range) return null;\n\n return {\n href: (range.mark.attrs.href as string) || '',\n text: doc.textBetween(range.from, range.to),\n from: range.from,\n to: range.to,\n };\n}\n\nfunction normalizeLinkHref(href: string): string {\n const trimmedHref = href.trim();\n if (!trimmedHref) return '';\n return trimmedHref.startsWith('#') || trimmedHref.startsWith('/') || /^https?:\\/\\//i.test(trimmedHref)\n ? trimmedHref\n : `https://${trimmedHref}`;\n}\n\nfunction getNonLinkMarksInRange(state: EditorState, from: number, to: number): readonly Mark[] {\n let marks: readonly Mark[] = [];\n state.doc.nodesBetween(from, to, (node) => {\n if (!node.isText) return;\n marks = node.marks.filter((mark) => mark.type !== linkMark);\n return false;\n });\n return marks;\n}\n\nfunction activeHeadingLevel(state: EditorState): number | null {\n const { $from } = state.selection;\n const node = $from.parent;\n if (node.type === heading) return node.attrs.level as number;\n return null;\n}\n\n/** Returns 'bullet' | 'ordered' | null depending on whether the cursor is inside a list. */\nfunction activeListType(state: EditorState): 'bullet' | 'ordered' | null {\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n const t = $from.node(d).type;\n if (t === bulletList) return 'bullet';\n if (t === orderedList) return 'ordered';\n }\n return null;\n}\n\n/** Convert the nearest ancestor list to `toType`. */\nfunction convertList(\n state: EditorState,\n dispatch: EditorView['dispatch'] | undefined,\n toType: typeof bulletList | typeof orderedList,\n): boolean {\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n const node = $from.node(d);\n if (node.type === bulletList || node.type === orderedList) {\n if (node.type === toType) return false;\n if (dispatch) {\n dispatch(state.tr.setNodeMarkup($from.before(d), toType, node.attrs));\n }\n return true;\n }\n }\n return false;\n}\n\nfunction currentBlockLabel(state: EditorState): string {\n const hl = activeHeadingLevel(state);\n if (hl) return `H${hl}`;\n const lt = activeListType(state);\n if (lt === 'bullet') return '• List';\n if (lt === 'ordered') return '1. List';\n const { $from } = state.selection;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type === blockquote) return 'Quote';\n }\n return 'Text';\n}\n\nfunction emptyBlockCursorPos(state: EditorState): number | null {\n const { selection } = state;\n if (!selection.empty) return null;\n const { $from } = selection;\n const parent = $from.parent;\n if (\n (parent.type === paragraph || parent.type === heading) &&\n parent.content.size === 0\n ) {\n return selection.from;\n }\n return null;\n}\n\n/** Get the bounding rect of the current DOM selection (viewport-relative). */\nfunction getSelectionDOMRect(): DOMRect | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return null;\n const rect = sel.getRangeAt(0).getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return null;\n return rect;\n}\n\n// ── Shared styles ─────────────────────────────────────────\n\nconst POPUP_SHADOW =\n '0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)';\n\nconst BTN_RESET: React.CSSProperties = {\n border: 'none',\n padding: 0,\n background: 'transparent',\n fontFamily: 'inherit',\n cursor: 'pointer',\n lineHeight: 1,\n};\n\n// ── ToolbarButton ─────────────────────────────────────────\n\ninterface TBtnProps {\n children: React.ReactNode;\n active?: boolean;\n title?: string;\n onMouseDown: (e: React.MouseEvent) => void;\n style?: React.CSSProperties;\n}\n\nfunction TBtn({ children, active, title, onMouseDown, style }: TBtnProps) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n title={title}\n onMouseDown={(e) => { e.preventDefault(); onMouseDown(e); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n width: 28, height: 28, borderRadius: 6,\n fontSize: 13, fontWeight: 600, color: active ? '#6210CC' : '#0D0D0D',\n background: active\n ? 'rgba(98,16,204,0.08)'\n : hover ? 'rgba(0,0,0,0.05)' : 'transparent',\n transition: 'background 0.1s, color 0.1s',\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n\n// ── Divider ───────────────────────────────────────────────\n\nfunction Divider() {\n return (\n <div style={{ width: 1, height: 18, background: 'rgba(0,0,0,0.07)', margin: '0 2px', flexShrink: 0 }} />\n );\n}\n\n// ── BlockTypeDropdown ─────────────────────────────────────\n\ninterface BlockTypeDropdownProps {\n view: EditorView;\n state: EditorState;\n label: string;\n}\n\nfunction BlockTypeDropdown({ view, state, label }: BlockTypeDropdownProps) {\n const [open, setOpen] = useState(false);\n const btnRef = useRef<HTMLButtonElement>(null);\n const [hover, setHover] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [open]);\n\n const headingLevel = activeHeadingLevel(state);\n const listType = activeListType(state);\n\n const items: { label: string; shortLabel: string; active: boolean; run: () => void }[] = [\n { label: 'Text', shortLabel: '¶', active: !headingLevel && !listType, run: () => { setBlockType(paragraph)(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 1', shortLabel: 'H1', active: headingLevel === 1, run: () => { setBlockType(heading, { level: 1 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 2', shortLabel: 'H2', active: headingLevel === 2, run: () => { setBlockType(heading, { level: 2 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Heading 3', shortLabel: 'H3', active: headingLevel === 3, run: () => { setBlockType(heading, { level: 3 })(view.state, view.dispatch); view.focus(); } },\n { label: 'Bullet List', shortLabel: '•', active: listType === 'bullet', run: () => {\n if (listType === 'bullet') return;\n if (listType === 'ordered') { convertList(view.state, view.dispatch, bulletList); }\n else { wrapInList(bulletList)(view.state, view.dispatch); }\n view.focus();\n }},\n { label: 'Ordered List', shortLabel: '1.', active: listType === 'ordered', run: () => {\n if (listType === 'ordered') return;\n if (listType === 'bullet') { convertList(view.state, view.dispatch, orderedList); }\n else { wrapInList(orderedList)(view.state, view.dispatch); }\n view.focus();\n }},\n { label: 'Quote', shortLabel: '>', active: false, run: () => {\n // Block inside listItem\n const { $from } = view.state.selection;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === 'listItem') return;\n }\n wrapIn(blockquote)(view.state, view.dispatch); view.focus();\n }},\n ];\n\n const btnRect = btnRef.current?.getBoundingClientRect();\n\n return (\n <>\n <button\n ref={btnRef}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); setOpen((v) => !v); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 3,\n height: 28, padding: '0 6px', borderRadius: 6,\n fontSize: 11, fontWeight: 600, color: open ? '#6210CC' : '#0D0D0D',\n background: open ? 'rgba(98,16,204,0.08)' : hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s, color 0.1s',\n whiteSpace: 'nowrap',\n }}\n >\n {label}\n <span style={{ fontSize: 8, opacity: 0.6 }}>▾</span>\n </button>\n {open && btnRect && createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed', zIndex: 1001,\n left: btnRect.left, top: btnRect.bottom + 4,\n background: '#fff', borderRadius: 8, boxShadow: POPUP_SHADOW,\n padding: 4, minWidth: 168,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {items.map((item) => (\n <DropdownItem key={item.label} item={item} onRun={() => setOpen(false)} />\n ))}\n </div>,\n document.body,\n )}\n </>\n );\n}\n\nfunction DropdownItem({ item, onRun }: { item: { label: string; shortLabel: string; active: boolean; run: () => void }; onRun: () => void }) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); item.run(); onRun(); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 10,\n width: '100%', padding: '6px 8px',\n borderRadius: 4, textAlign: 'left',\n fontSize: 13, color: item.active ? '#6210CC' : '#0D0D0D',\n fontWeight: item.active ? 600 : 400,\n background: hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s',\n }}\n >\n <span style={{ width: 24, flexShrink: 0, textAlign: 'center', fontWeight: 700, fontSize: 12, fontFamily: 'monospace', color: item.active ? '#6210CC' : '#666' }}>\n {item.shortLabel}\n </span>\n {item.label}\n </button>\n );\n}\n\n// ── SelectionToolbar ──────────────────────────────────────\n\ninterface SelectionToolbarProps {\n view: EditorView;\n state: EditorState;\n selectionRect: DOMRect;\n}\n\nfunction SelectionToolbar({ view, state, selectionRect }: SelectionToolbarProps) {\n const [linkMode, setLinkMode] = useState(false);\n const [linkHref, setLinkHref] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Derived state\n const isBold = hasMark(state, bold);\n const isItalic = hasMark(state, italic);\n const isUnderline = hasMark(state, underline);\n const isStrike = hasMark(state, strikethrough);\n const isCode = hasMark(state, code);\n const isLink = hasMark(state, linkMark);\n const blockLabel = currentBlockLabel(state);\n\n const toolbarW = linkMode ? 300 : 380;\n const toolbarH = TOOLBAR_H;\n\n let left = selectionRect.left + selectionRect.width / 2 - toolbarW / 2;\n let top = selectionRect.top - toolbarH - TOOLBAR_GAP;\n // Flip below selection when there's no space above\n if (top < VPORT_MARGIN) top = selectionRect.bottom + TOOLBAR_GAP;\n // Clamp to viewport\n left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - toolbarW - VPORT_MARGIN));\n top = Math.max(VPORT_MARGIN, Math.min(top, window.innerHeight - toolbarH - VPORT_MARGIN));\n\n const run = useCallback(\n (cmd: (s: EditorState, d?: typeof view.dispatch) => boolean) => {\n cmd(view.state, view.dispatch);\n view.focus();\n },\n [view],\n );\n\n const openLinkInput = () => {\n // Pre-fill with the first href found in the selection (if any)\n const { from, to } = view.state.selection;\n let existingHref = '';\n view.state.doc.nodesBetween(from, to, (node) => {\n if (!existingHref) {\n const lm = node.marks.find((m) => m.type === linkMark);\n if (lm) existingHref = lm.attrs.href as string;\n }\n });\n setLinkHref(existingHref);\n setLinkMode(true);\n setTimeout(() => inputRef.current?.focus(), 0);\n };\n\n const applyLink = () => {\n const href = linkHref.trim();\n if (href) {\n const finalHref =\n href.startsWith('#') || href.startsWith('/') || /^https?:\\/\\//i.test(href)\n ? href\n : `https://${href}`;\n const { from, to } = view.state.selection;\n const tr = view.state.tr.addMark(from, to, linkMark.create({ href: finalHref }));\n view.dispatch(tr);\n }\n view.focus();\n setLinkMode(false);\n setLinkHref('');\n };\n\n const removeLink = () => {\n const { from, to } = view.state.selection;\n view.dispatch(view.state.tr.removeMark(from, to, linkMark));\n view.focus();\n };\n\n return (\n <div\n {...{ [FLOAT_ATTR]: 'selection-toolbar' }}\n style={{\n position: 'fixed', left, top, width: toolbarW, height: toolbarH,\n zIndex: 1000,\n display: 'flex', alignItems: 'center', gap: 2, padding: '0 6px',\n background: '#fff', borderRadius: 8, boxShadow: POPUP_SHADOW,\n userSelect: 'none',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {linkMode ? (\n /* ── Link input mode ── */\n <>\n <span style={{ fontSize: 13, color: '#9ca3af', paddingLeft: 4, flexShrink: 0 }}>↗</span>\n <input\n ref={inputRef}\n value={linkHref}\n onChange={(e) => setLinkHref(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyLink(); }\n if (e.key === 'Escape') { e.preventDefault(); setLinkMode(false); view.focus(); }\n }}\n placeholder=\"Paste link...\"\n style={{\n flex: 1, border: 'none', outline: 'none',\n fontSize: 13, fontFamily: 'inherit', color: '#171717',\n padding: '0 6px', background: 'transparent',\n minWidth: 0,\n }}\n />\n <TBtn\n title=\"Apply (Enter)\"\n onMouseDown={(e) => { e.preventDefault(); applyLink(); }}\n style={{ color: '#6210CC', width: 24, fontSize: 14 }}\n >↵</TBtn>\n <TBtn\n title=\"Cancel (Esc)\"\n onMouseDown={(e) => { e.preventDefault(); setLinkMode(false); view.focus(); }}\n style={{ color: '#9ca3af', width: 24, fontSize: 14 }}\n >✕</TBtn>\n </>\n ) : (\n /* ── Normal toolbar mode ── */\n <>\n {/* Marks */}\n <TBtn active={isBold} title=\"Bold (Cmd+B)\" onMouseDown={() => run(toggleMark(bold))}\n style={{ fontWeight: 700 }}>B</TBtn>\n <TBtn active={isItalic} title=\"Italic (Cmd+I)\" onMouseDown={() => run(toggleMark(italic))}\n style={{ fontStyle: 'italic' }}>I</TBtn>\n <TBtn active={isUnderline} title=\"Underline (Cmd+U)\" onMouseDown={() => run(toggleMark(underline))}\n style={{ textDecoration: 'underline' }}>U</TBtn>\n <TBtn active={isStrike} title=\"Strikethrough (Cmd+Shift+X)\" onMouseDown={() => run(toggleMark(strikethrough))}\n style={{ textDecoration: 'line-through' }}>S</TBtn>\n <TBtn active={isCode} title=\"Code (Cmd+E)\" onMouseDown={() => run(toggleMark(code))}\n style={{ fontFamily: 'monospace', fontSize: 11 }}>`·`</TBtn>\n <TBtn active={isLink} title={isLink ? 'Remove link' : 'Add link (Cmd+K)'}\n onMouseDown={() => isLink ? removeLink() : openLinkInput()}\n style={{ fontSize: 14 }}>↗</TBtn>\n\n <Divider />\n\n {/* Block type dropdown */}\n <BlockTypeDropdown view={view} state={state} label={blockLabel} />\n </>\n )}\n </div>\n );\n}\n\n// ── LinkHoverTooltip ──────────────────────────────────────\n\ninterface LinkHoverTooltipProps {\n view: EditorView;\n link: LinkAtCursor;\n onEdit: (link: LinkAtCursor) => void;\n}\n\nfunction LinkHoverTooltip({ view, link, onEdit }: LinkHoverTooltipProps) {\n const [hover, setHover] = useState(false);\n\n const startCoords = view.coordsAtPos(link.from);\n const endCoords = view.coordsAtPos(link.to);\n const anchorTop = Math.min(startCoords.top, endCoords.top);\n const linkLeft = Math.min(startCoords.left, endCoords.left);\n const linkRight = Math.max(startCoords.right, endCoords.right);\n const tooltipHalfW = Math.min(174, Math.max(0, (window.innerWidth - VPORT_MARGIN * 2) / 2));\n const safeCenterX = Math.max(\n VPORT_MARGIN + tooltipHalfW,\n Math.min((linkLeft + linkRight) / 2, window.innerWidth - VPORT_MARGIN - tooltipHalfW),\n );\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left: safeCenterX,\n top: Math.max(64, anchorTop - 4),\n transform: 'translate(-50%, -100%)',\n zIndex: 1000,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n animation: 'ab-float-in 0.12s ease',\n pointerEvents: 'auto',\n }}\n >\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n minHeight: 28,\n maxWidth: 'min(348px, calc(100vw - 16px))',\n padding: '6px 8px',\n background: '#2E2E2E',\n borderRadius: 4,\n boxSizing: 'border-box',\n }}\n >\n <span\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n color: '#FFFFFF',\n fontSize: 12,\n lineHeight: '16px',\n fontFamily: '\"SF Pro Text\", \"SF Pro\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n whiteSpace: 'normal',\n wordBreak: 'break-word',\n overflowWrap: 'anywhere',\n maxWidth: 300,\n }}\n >\n {link.href}\n </span>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n width: 1,\n height: 16,\n background: '#424242',\n flexShrink: 0,\n }}\n />\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n onEdit(link);\n }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n padding: '0 2px',\n color: '#FFFFFF',\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n fontFamily: '\"SF Pro Text\", \"SF Pro\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n opacity: hover ? 0.78 : 1,\n flexShrink: 0,\n }}\n >\n Edit\n </button>\n </div>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n width: 0,\n height: 0,\n borderLeft: '6px solid transparent',\n borderRight: '6px solid transparent',\n borderTop: '6px solid #2E2E2E',\n marginTop: -1,\n }}\n />\n </div>,\n document.body,\n );\n}\n\n// ── LinkEditDialog ────────────────────────────────────────\n\ninterface LinkEditDialogProps {\n view: EditorView;\n link: LinkAtCursor;\n onClose: () => void;\n}\n\nfunction LinkEditDialog({ view, link, onClose }: LinkEditDialogProps) {\n const [textValue, setTextValue] = useState(link.text);\n const [hrefValue, setHrefValue] = useState(link.href);\n const textInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setTextValue(link.text);\n setHrefValue(link.href);\n }, [link.from, link.href, link.text, link.to]);\n\n useEffect(() => {\n setTimeout(() => textInputRef.current?.focus(), 0);\n }, [link.from, link.to]);\n\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [onClose]);\n\n const startCoords = view.coordsAtPos(link.from);\n const endCoords = view.coordsAtPos(link.to);\n const anchorTop = Math.min(startCoords.top, endCoords.top);\n const anchorBottom = Math.max(startCoords.bottom, endCoords.bottom);\n const linkLeft = Math.min(startCoords.left, endCoords.left);\n const linkRight = Math.max(startCoords.right, endCoords.right);\n const dialogW = 280;\n const estimatedDialogH = 188;\n const centerX = (linkLeft + linkRight) / 2;\n const left = Math.max(\n VPORT_MARGIN,\n Math.min(centerX - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN),\n );\n let top = anchorTop - estimatedDialogH - 12;\n if (top < VPORT_MARGIN) {\n top = Math.min(anchorBottom + 12, window.innerHeight - estimatedDialogH - VPORT_MARGIN);\n }\n\n const finalHref = normalizeLinkHref(hrefValue);\n const finalText = textValue.trim() ? textValue : '';\n // Allow save when: label emptied (will delete link), or href/text changed\n const canSave = !textValue.trim()\n || (Boolean(finalHref) && (finalHref !== link.href || finalText !== link.text));\n\n const currentLink = () => {\n const activeLink = getLinkAtCursor(view.state);\n if (activeLink && activeLink.from === link.from && activeLink.to === link.to) {\n return activeLink;\n }\n return link;\n };\n\n const saveLink = () => {\n const activeLink = currentLink();\n const nextHref = normalizeLinkHref(hrefValue);\n\n // If label is completely empty, delete the entire link (text + mark)\n if (!textValue.trim()) {\n const tr = view.state.tr.delete(activeLink.from, activeLink.to);\n view.dispatch(tr);\n onClose();\n view.focus();\n return;\n }\n\n const nextText = textValue;\n if (!nextHref) return;\n if (nextHref === activeLink.href && nextText === activeLink.text) return;\n\n const cursorOffset = Math.max(0, view.state.selection.from - activeLink.from);\n const tr = view.state.tr;\n\n if (nextText === activeLink.text) {\n tr.removeMark(activeLink.from, activeLink.to, linkMark);\n tr.addMark(activeLink.from, activeLink.to, linkMark.create({ href: nextHref }));\n const nextCursor = Math.min(activeLink.from + cursorOffset, activeLink.to);\n tr.setSelection(TextSelection.near(tr.doc.resolve(nextCursor)));\n } else {\n const preservedMarks = getNonLinkMarksInRange(view.state, activeLink.from, activeLink.to);\n tr.insertText(nextText, activeLink.from, activeLink.to);\n const nextTo = activeLink.from + nextText.length;\n tr.removeMark(activeLink.from, nextTo, linkMark);\n for (const mark of preservedMarks) {\n tr.addMark(activeLink.from, nextTo, mark);\n }\n tr.addMark(activeLink.from, nextTo, linkMark.create({ href: nextHref }));\n const nextCursor = Math.min(activeLink.from + cursorOffset, nextTo);\n tr.setSelection(TextSelection.near(tr.doc.resolve(nextCursor)));\n }\n\n view.dispatch(tr);\n onClose();\n view.focus();\n };\n\n const removeLink = () => {\n const activeLink = currentLink();\n view.dispatch(view.state.tr.removeMark(activeLink.from, activeLink.to, linkMark));\n onClose();\n view.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n view.focus();\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n saveLink();\n }\n };\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left,\n top,\n zIndex: 1001,\n width: dialogW,\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n background: '#FFFFFF',\n borderRadius: 8,\n boxShadow: '0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)',\n boxSizing: 'border-box',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Text <span style={{ color: '#858585' }}>(optional)</span>\n </div>\n <input\n ref={textInputRef}\n {...{ [FLOAT_ATTR]: '' }}\n value={textValue}\n onChange={(e) => setTextValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n fontSize: 12,\n lineHeight: '16px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Link\n </div>\n <input\n {...{ [FLOAT_ATTR]: '' }}\n value={hrefValue}\n onChange={(e) => setHrefValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n }}\n >\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n removeLink();\n }}\n style={{\n ...BTN_RESET,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Remove link\n </button>\n\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n onClose();\n view.focus();\n }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n disabled={!canSave}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => {\n e.preventDefault();\n if (!canSave) return;\n saveLink();\n }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n background: canSave ? '#6210CC' : '#ECECEC',\n color: canSave ? '#FFFFFF' : '#A6A6A6',\n cursor: canSave ? 'pointer' : 'default',\n }}\n >\n Save\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── Link Insert Dialog (new link at cursor) ─────────────────────────────────\n\n/** Custom event name for triggering the insert-link dialog from outside. */\nexport const INSERT_LINK_EVENT = 'ab-insert-link';\n\ninterface LinkInsertDialogProps {\n view: EditorView;\n cursorPos: number;\n onClose: () => void;\n}\n\nfunction LinkInsertDialog({ view, cursorPos, onClose }: LinkInsertDialogProps) {\n const [textValue, setTextValue] = useState('');\n const [hrefValue, setHrefValue] = useState('');\n const textInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setTimeout(() => textInputRef.current?.focus(), 0);\n }, []);\n\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [onClose]);\n\n let coords: { top: number; bottom: number; left: number };\n try {\n coords = view.coordsAtPos(cursorPos);\n } catch {\n onClose();\n return null;\n }\n\n const dialogW = 280;\n const left = Math.max(\n VPORT_MARGIN,\n Math.min(coords.left - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN),\n );\n const top = Math.min(coords.bottom + 8, window.innerHeight - 220 - VPORT_MARGIN);\n\n const finalHref = normalizeLinkHref(hrefValue);\n const canSave = Boolean(finalHref);\n\n const saveLink = () => {\n if (!finalHref) return;\n const displayText = textValue.trim() || finalHref;\n const tr = view.state.tr;\n const linkMarkType = view.state.schema.marks.link;\n if (!linkMarkType) return;\n\n tr.insertText(displayText, cursorPos);\n tr.addMark(cursorPos, cursorPos + displayText.length, linkMarkType.create({ href: finalHref }));\n view.dispatch(tr);\n onClose();\n view.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n view.focus();\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n saveLink();\n }\n };\n\n return createPortal(\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed',\n left,\n top,\n zIndex: 1001,\n width: dialogW,\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n background: '#FFFFFF',\n borderRadius: 8,\n boxShadow: POPUP_SHADOW,\n boxSizing: 'border-box',\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ fontSize: 12, lineHeight: '16px', fontWeight: 600, color: '#0D0D0D' }}>\n Text <span style={{ color: '#858585' }}>(optional)</span>\n </div>\n <input\n ref={textInputRef}\n {...{ [FLOAT_ATTR]: '' }}\n value={textValue}\n placeholder=\"\"\n onChange={(e) => setTextValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ fontSize: 12, lineHeight: '16px', fontWeight: 600, color: '#0D0D0D' }}>\n Link\n </div>\n <input\n {...{ [FLOAT_ATTR]: '' }}\n value={hrefValue}\n onChange={(e) => setHrefValue(e.target.value)}\n onKeyDown={handleKeyDown}\n style={{\n height: 32,\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n padding: '0 16px',\n fontSize: 14,\n color: '#0D0D0D',\n outline: 'none',\n boxSizing: 'border-box',\n }}\n />\n </div>\n <div {...{ [FLOAT_ATTR]: '' }} style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 8 }}>\n <button\n type=\"button\"\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); onClose(); view.focus(); }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n border: '1px solid #CCCCCC',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n color: '#0D0D0D',\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n disabled={!canSave}\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); if (canSave) saveLink(); }}\n style={{\n ...BTN_RESET,\n height: 32,\n padding: '0 13px',\n borderRadius: 4,\n fontSize: 14,\n lineHeight: '20px',\n fontWeight: 600,\n background: canSave ? '#6210CC' : '#ECECEC',\n color: canSave ? '#FFFFFF' : '#A6A6A6',\n cursor: canSave ? 'pointer' : 'default',\n }}\n >\n Save\n </button>\n </div>\n </div>,\n document.body,\n );\n}\n\n// ── Block menu items ──────────────────────────────────────\n\ninterface BlockItem {\n shortLabel: string;\n label: string;\n run: (view: EditorView) => void;\n}\n\nconst BLOCK_ITEMS: BlockItem[] = [\n {\n shortLabel: '¶',\n label: 'Text',\n run: (v) => { setBlockType(paragraph)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H1',\n label: 'Heading 1',\n run: (v) => { setBlockType(heading, { level: 1 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H2',\n label: 'Heading 2',\n run: (v) => { setBlockType(heading, { level: 2 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: 'H3',\n label: 'Heading 3',\n run: (v) => { setBlockType(heading, { level: 3 })(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '•',\n label: 'Bullet List',\n run: (v) => { wrapInList(bulletList)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '1.',\n label: 'Ordered List',\n run: (v) => { wrapInList(orderedList)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '☐',\n label: 'Todo List',\n run: (v) => {\n const { listItem: liType, bulletList: blType, paragraph: pType } = actionbookSchema.nodes;\n const li = liType.create({ checked: false }, pType.create());\n const list = blType.create(null, li);\n v.dispatch(v.state.tr.replaceSelectionWith(list));\n v.focus();\n },\n },\n {\n shortLabel: '❝',\n label: 'Quote',\n run: (v) => { wrapIn(blockquote)(v.state, v.dispatch); v.focus(); },\n },\n {\n shortLabel: '▦',\n label: 'Table',\n run: (v) => {\n const { table: tblType, tableRow: trType, tableHeader: thType, tableCell: tdType } = actionbookSchema.nodes;\n const headerCells = [thType.create(), thType.create(), thType.create()];\n const bodyCells = [tdType.create(), tdType.create(), tdType.create()];\n const headerRow = trType.create(null, headerCells);\n const bodyRow = trType.create(null, bodyCells);\n const tbl = tblType.create(null, [headerRow, bodyRow]);\n v.dispatch(v.state.tr.replaceSelectionWith(tbl));\n v.focus();\n },\n },\n];\n\n// ── EmptyParaHandle ───────────────────────────────────────\n\ninterface EmptyParaHandleProps {\n view: EditorView;\n cursorPos: number;\n}\n\nfunction EmptyParaHandle({ view, cursorPos }: EmptyParaHandleProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n const coords = view.coordsAtPos(cursorPos);\n const lineH = Math.max(coords.bottom - coords.top, 18);\n const btnSize = 22;\n const btnLeft = coords.left - btnSize - 32;\n const btnTop = coords.top + (lineH - btnSize) / 2;\n const menuLeft = Math.max(VPORT_MARGIN, btnLeft);\n const menuTop = btnTop + btnSize + 4;\n\n // Close block menu when clicking outside floating elements\n useEffect(() => {\n if (!menuOpen) return;\n const onDown = (e: MouseEvent) => {\n if (!(e.target as HTMLElement).closest(`[${FLOAT_ATTR}]`)) {\n setMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onDown, true);\n return () => document.removeEventListener('mousedown', onDown, true);\n }, [menuOpen]);\n\n return (\n <>\n {/* + button */}\n <button\n {...{ [FLOAT_ATTR]: '' }}\n title=\"Add block\"\n onMouseDown={(e) => { e.preventDefault(); setMenuOpen((v) => !v); }}\n style={{\n ...BTN_RESET,\n position: 'fixed', zIndex: 999,\n left: btnLeft < VPORT_MARGIN ? VPORT_MARGIN : btnLeft,\n top: btnTop,\n width: btnSize, height: btnSize,\n border: '1px solid rgba(0,0,0,0.1)',\n borderRadius: 5,\n background: menuOpen ? 'rgba(98,16,204,0.08)' : '#fff',\n boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n color: menuOpen ? '#6210CC' : '#9ca3af',\n fontSize: 16,\n animation: 'ab-float-in 0.15s ease',\n transition: 'color 0.1s, background 0.1s, border-color 0.1s',\n }}\n >\n +\n </button>\n\n {/* Block picker menu */}\n {menuOpen && (\n <div\n {...{ [FLOAT_ATTR]: '' }}\n style={{\n position: 'fixed', zIndex: 1000,\n left: menuLeft, top: menuTop,\n background: '#fff',\n borderRadius: 8,\n boxShadow: POPUP_SHADOW,\n padding: 4,\n minWidth: 168,\n animation: 'ab-float-in 0.12s ease',\n }}\n >\n {BLOCK_ITEMS.map((item) => (\n <BlockMenuItem\n key={item.label}\n item={item}\n view={view}\n onRun={() => setMenuOpen(false)}\n />\n ))}\n </div>\n )}\n </>\n );\n}\n\nfunction BlockMenuItem({\n item,\n view,\n onRun,\n}: {\n item: BlockItem;\n view: EditorView;\n onRun: () => void;\n}) {\n const [hover, setHover] = useState(false);\n return (\n <button\n {...{ [FLOAT_ATTR]: '' }}\n onMouseDown={(e) => { e.preventDefault(); item.run(view); onRun(); }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n ...BTN_RESET,\n display: 'flex', alignItems: 'center', gap: 10,\n width: '100%', padding: '6px 8px',\n borderRadius: 6, textAlign: 'left',\n fontSize: 13, color: '#0D0D0D',\n background: hover ? 'rgba(0,0,0,0.04)' : 'transparent',\n transition: 'background 0.1s',\n }}\n >\n <span\n style={{\n width: 24, flexShrink: 0, textAlign: 'center',\n fontWeight: 700, fontSize: 12,\n fontFamily: 'monospace',\n color: '#6210CC',\n }}\n >\n {item.shortLabel}\n </span>\n {item.label}\n </button>\n );\n}\n\n// ── FloatingMenu (root) ───────────────────────────────────\n\nexport interface FloatingMenuProps {\n view: EditorView | null;\n editorState: EditorState | null;\n}\n\nexport function FloatingMenu({ view, editorState }: FloatingMenuProps) {\n // ── Dwell timer for empty paragraph ──\n const [showEmptyHandle, setShowEmptyHandle] = useState(false);\n const [editingLink, setEditingLink] = useState<LinkAtCursor | null>(null);\n const [insertLinkPos, setInsertLinkPos] = useState<number | null>(null);\n const dwellTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastEmptyPosRef = useRef<number | null>(null);\n\n // Listen for insert-link events from toolbar/slash command\n useEffect(() => {\n const dom = view?.dom;\n if (!dom) return;\n const handler = () => {\n const pos = view.state.selection.from;\n setInsertLinkPos(pos);\n };\n dom.addEventListener(INSERT_LINK_EVENT, handler);\n return () => dom.removeEventListener(INSERT_LINK_EVENT, handler);\n }, [view]);\n\n // ── Re-render on editor container scroll (position recalculation) ──\n const [, setScrollTick] = useState(0);\n useEffect(() => {\n const editorDom = view?.dom;\n if (!editorDom) return;\n const container = editorDom.closest('.editor-shell') ?? editorDom.parentElement;\n if (!container) return;\n const onScroll = () => setScrollTick((n) => n + 1);\n container.addEventListener('scroll', onScroll, { passive: true });\n return () => container.removeEventListener('scroll', onScroll);\n }, [view]);\n\n // ── Inject keyframe animation once ──\n useEffect(() => {\n const id = 'ab-float-keyframes';\n if (document.getElementById(id)) return;\n const style = document.createElement('style');\n style.id = id;\n style.textContent = `\n @keyframes ab-float-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `;\n document.head.appendChild(style);\n }, []);\n\n const emptyPos = editorState ? emptyBlockCursorPos(editorState) : null;\n const hasSelection = editorState ? !editorState.selection.empty : false;\n const linkAtCursor = editorState && !hasSelection ? getLinkAtCursor(editorState) : null;\n\n useEffect(() => {\n if (!editingLink) return;\n if (!linkAtCursor || linkAtCursor.from !== editingLink.from || linkAtCursor.to !== editingLink.to) {\n setEditingLink(null);\n }\n }, [editingLink, linkAtCursor]);\n\n if (!view || !editorState) return null;\n\n // Manage dwell timer\n if (emptyPos !== lastEmptyPosRef.current) {\n lastEmptyPosRef.current = emptyPos;\n\n if (dwellTimerRef.current) {\n clearTimeout(dwellTimerRef.current);\n dwellTimerRef.current = null;\n }\n\n if (emptyPos !== null) {\n dwellTimerRef.current = setTimeout(() => setShowEmptyHandle(true), DWELL_MS);\n } else {\n setShowEmptyHandle(false);\n }\n }\n\n const selectionRect = hasSelection ? getSelectionDOMRect() : null;\n\n return createPortal(\n <>\n {/* Selection toolbar */}\n {hasSelection && selectionRect && (\n <SelectionToolbar\n view={view}\n state={editorState}\n selectionRect={selectionRect}\n />\n )}\n\n {!hasSelection && linkAtCursor && !editingLink && (\n <LinkHoverTooltip\n view={view}\n link={linkAtCursor}\n onEdit={(link) => setEditingLink(link)}\n />\n )}\n\n {!hasSelection && editingLink && (\n <LinkEditDialog\n view={view}\n link={editingLink}\n onClose={() => setEditingLink(null)}\n />\n )}\n\n {/* Insert new link dialog */}\n {insertLinkPos !== null && (\n <LinkInsertDialog\n view={view}\n cursorPos={insertLinkPos}\n onClose={() => setInsertLinkPos(null)}\n />\n )}\n\n {/* Empty paragraph handle */}\n {!hasSelection && !linkAtCursor && !insertLinkPos && showEmptyHandle && emptyPos !== null && (\n <EmptyParaHandle view={view} cursorPos={emptyPos} />\n )}\n </>,\n document.body,\n );\n}\n","/**\n * Inline suggestion (ghost text) plugin.\n *\n * Debounces after the cursor stops moving, calls an LLM endpoint via a\n * user-supplied `InlineSuggestProvider`, then renders the response as gray\n * ghost text after the cursor using a ProseMirror widget decoration.\n *\n * Accepts:\n * Tab → insert the suggestion at the cursor\n * Escape → dismiss the suggestion\n *\n * Fully detachable: just omit `createInlineSuggestPlugin()` from the plugins\n * array to disable the feature entirely.\n */\n\nimport { Plugin, PluginKey } from 'prosemirror-state';\nimport type { EditorState } from 'prosemirror-state';\nimport { Decoration, DecorationSet } from 'prosemirror-view';\nimport type { EditorView } from 'prosemirror-view';\nimport type { ActionbookPlugin } from './types';\nimport type { LlmCompletionEndpoint } from '../../lint/types';\n\n// ── Public types ──────────────────────────────────────────\n\n/**\n * Cursor context passed to the provider's `buildPrompt`.\n */\nexport type InlineSuggestContext = {\n /** Text before the cursor — current paragraph plus up to 2 preceding paragraphs. */\n textBefore: string;\n /** Text in the current paragraph after the cursor (up to 100 chars). */\n textAfter: string;\n};\n\n/**\n * Extensible provider interface, analogous to `LlmLintRule`.\n *\n * Implement this to customize what gets sent to the LLM and how the\n * response is parsed into a suggestion string.\n */\nexport type InlineSuggestProvider = {\n /** Unique identifier for this provider. */\n id: string;\n /**\n * Build the prompt string sent to the LLM endpoint.\n * Return an empty string to suppress the request entirely.\n */\n buildPrompt: (ctx: InlineSuggestContext) => string;\n /**\n * Parse the raw LLM response into the text to insert at the cursor.\n * Return an empty string to suppress the decoration.\n * `ctx` is the same context that was passed to `buildPrompt`.\n */\n parseResponse: (response: string, ctx: InlineSuggestContext) => string;\n};\n\nexport interface InlineSuggestState {\n /** Ghost text currently shown, or null if nothing is active. */\n suggestion: string | null;\n /** Document position the suggestion is anchored to. */\n anchorPos: number | null;\n}\n\nexport const inlineSuggestKey = new PluginKey<InlineSuggestState>('inlineSuggest');\n\n// ── Constants ─────────────────────────────────────────────\n\nconst DEBOUNCE_MS = 600;\nconst CONTEXT_CHARS = 500;\n\n// ── Factory ───────────────────────────────────────────────\n\nexport function createInlineSuggestPlugin(\n provider: InlineSuggestProvider,\n endpoint: LlmCompletionEndpoint,\n options?: {\n /**\n * Called when the user accepts a suggestion (Tab) or the cursor moves to\n * a new context. Use this to pre-create a fresh completion session so it's\n * ready by the time the next debounce fires.\n */\n onContextChange?: () => void;\n },\n): ActionbookPlugin {\n const { onContextChange } = options ?? {};\n return {\n name: 'inlineSuggest',\n\n plugins: () => [\n new Plugin<InlineSuggestState>({\n key: inlineSuggestKey,\n\n state: {\n init: (): InlineSuggestState => ({ suggestion: null, anchorPos: null }),\n\n apply(tr, prev): InlineSuggestState {\n const meta = tr.getMeta(inlineSuggestKey) as InlineSuggestState | null | undefined;\n if (meta !== undefined) return meta ?? { suggestion: null, anchorPos: null };\n // Any document edit or cursor move clears the current ghost text\n if (tr.docChanged || tr.selectionSet) {\n return { suggestion: null, anchorPos: null };\n }\n return prev;\n },\n },\n\n props: {\n decorations(state: EditorState) {\n const ps = inlineSuggestKey.getState(state);\n if (!ps?.suggestion || !state.selection.empty) return DecorationSet.empty;\n\n const ghost = document.createElement('span');\n ghost.textContent = ps.suggestion;\n ghost.style.cssText =\n 'color: rgba(0,0,0,0.3); pointer-events: none; user-select: none;';\n ghost.setAttribute('aria-hidden', 'true');\n\n return DecorationSet.create(state.doc, [\n Decoration.widget(state.selection.from, ghost, {\n side: 1,\n key: 'inline-suggest',\n }),\n ]);\n },\n },\n\n view(editorView: EditorView) {\n // Capture Tab / Escape before the browser handles them (Tab moves\n // focus, Escape might bubble to parent dialogs).\n function onKeydown(event: KeyboardEvent) {\n if (event.key !== 'Tab' && event.key !== 'Escape') return;\n const ps = inlineSuggestKey.getState(editorView.state);\n console.debug('[inline-suggest] key pressed:', event.key, 'suggestion:', ps?.suggestion);\n if (!ps?.suggestion) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (event.key === 'Tab') {\n // Context changes after accept — pre-clone now so the next\n // fetch gets a fresh session without waiting for clone().\n onContextChange?.();\n const tr = editorView.state.tr.insertText(\n ps.suggestion,\n editorView.state.selection.from,\n );\n tr.setMeta(inlineSuggestKey, { suggestion: null, anchorPos: null });\n editorView.dispatch(tr);\n } else {\n const tr = editorView.state.tr;\n tr.setMeta(inlineSuggestKey, { suggestion: null, anchorPos: null });\n editorView.dispatch(tr);\n }\n }\n\n editorView.dom.addEventListener('keydown', onKeydown, { capture: true });\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let abortController: AbortController | null = null;\n\n function cancel() {\n if (debounceTimer != null) {\n clearTimeout(debounceTimer);\n debounceTimer = null;\n }\n abortController?.abort();\n abortController = null;\n }\n\n function schedule(view: EditorView) {\n cancel();\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n void fetchSuggestion(view);\n }, DEBOUNCE_MS);\n }\n\n async function fetchSuggestion(view: EditorView) {\n const { state } = view;\n if (!state.selection.empty) return;\n\n const cursorPos = state.selection.from;\n const $from = state.doc.resolve(cursorPos);\n const paraStart = $from.start();\n const paraEnd = $from.end();\n\n // Collect up to 3 block nodes ending at the cursor's block.\n const nearbyStart = (() => {\n const $cursor = state.doc.resolve(cursorPos);\n const depth = $cursor.depth; // depth of the paragraph node\n let blockStart = $cursor.before(depth); // pos of current block's opening token\n let count = 1;\n while (count < 3 && blockStart > 0) {\n const $prev = state.doc.resolve(blockStart - 1);\n blockStart = $prev.before($prev.depth);\n count++;\n }\n return blockStart;\n })();\n\n const textBefore = state.doc.textBetween(nearbyStart, cursorPos, '\\n', '');\n const textAfter = state.doc.textBetween(\n cursorPos,\n Math.min(paraEnd, cursorPos + 100),\n '\\n',\n '',\n );\n\n if (!textBefore.trim()) return;\n\n const ctx = { textBefore, textAfter };\n const prompt = provider.buildPrompt(ctx);\n if (!prompt) return;\n\n console.debug(`[inline-suggest] fetching (provider=${provider.id}) prompt=`, prompt);\n\n abortController = new AbortController();\n try {\n const response = await endpoint(prompt, { signal: abortController.signal });\n console.debug(`[inline-suggest] response=`, response);\n\n const suggestion = provider.parseResponse(response, ctx).trimEnd();\n console.debug(`[inline-suggest] parsed suggestion=`, JSON.stringify(suggestion));\n\n if (!suggestion) {\n console.debug('[inline-suggest] empty suggestion — skipping');\n return;\n }\n\n // Discard if cursor moved while we were waiting\n if (!view.state.selection.empty) return;\n if (view.state.selection.from !== cursorPos) {\n console.debug('[inline-suggest] cursor moved — discarding');\n return;\n }\n\n const tr = view.state.tr;\n tr.setMeta(inlineSuggestKey, { suggestion, anchorPos: cursorPos });\n view.dispatch(tr);\n console.debug('[inline-suggest] suggestion applied');\n } catch (err) {\n if ((err as Error)?.name === 'AbortError') {\n console.debug('[inline-suggest] request aborted');\n } else {\n console.warn('[inline-suggest] endpoint error:', err);\n }\n }\n }\n\n return {\n update(view: EditorView, prevState: EditorState) {\n const docChanged = view.state.doc !== prevState.doc;\n const selChanged = view.state.selection !== prevState.selection;\n if (!docChanged && !selChanged) return;\n\n // A suggestion was just set (meta transaction) — don't reschedule\n const ps = inlineSuggestKey.getState(view.state);\n if (ps?.suggestion) return;\n\n if (!view.state.selection.empty) {\n cancel();\n return;\n }\n\n // Context changed — pre-clone before the debounce fires so the\n // session is fresh and ready when the fetch runs.\n onContextChange?.();\n schedule(view);\n },\n\n destroy() {\n cancel();\n editorView.dom.removeEventListener('keydown', onKeydown, { capture: true });\n },\n };\n },\n }),\n ],\n };\n}\n","import type { EditorState } from 'prosemirror-state';\nimport { validateCondition } from '../../jinja/evaluator';\n\n/**\n * Check if any jinjaIfBranch in the editor has an invalid (non-empty) condition.\n * Used to block save when conditions have syntax errors.\n */\nexport function hasInvalidJinjaConditions(state: EditorState): boolean {\n let found = false;\n state.doc.descendants((node) => {\n if (found) return false;\n if (node.type.name === 'jinjaIfBranch') {\n const condition = String(node.attrs.condition ?? '');\n if (condition && !validateCondition(condition).valid) {\n found = true;\n }\n return false;\n }\n });\n return found;\n}\n\n/**\n * Check if any jinjaIfBranch has an empty body (single empty paragraph).\n * Used to block save when branch bodies have no content.\n */\nexport function hasEmptyJinjaBranches(state: EditorState): boolean {\n let found = false;\n state.doc.descendants((node) => {\n if (found) return false;\n if (node.type.name === 'jinjaIfBranch') {\n if (node.childCount === 1) {\n const first = node.firstChild;\n if (first?.type.name === 'paragraph' && first.content.size === 0) {\n found = true;\n }\n }\n return false;\n }\n });\n return found;\n}\n"],"mappings":"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","names":["key","text","jsx","jsxs","key","text","doc","jsx","EditorShell","text","textContent","blocks","defaultHandlers","exit","exit","table","row","sizes","columnIndex","code","exit","defaultHandlers","text","text","MAX_DEPTH","ALLOWED_URL_PROTOCOLS","linkMark","doc","defaultHandlers","doc","ALLOWED_URL_PROTOCOLS","convertInline","convertBlock","convertBlock","doc","doc","derived","JUMP_POINT_RE","liDepth","liIndex","tr","textContent","keymap","Plugin","TextSelection","keymap","TextSelection","text","Plugin","doc","keymap","Plugin","PluginKey","MAX_DEPTH","MAX_DEPTH","code","code","constructs","ok","code","markdownSpace","ok","code","markdownLineEndingOrSpace","ok","code","markdownLineEndingOrSpace","strikethrough","text","ok","code","markdownLineEnding","markdownLineEndingOrSpace","markdownSpace","ok","code","markdownLineEnding","markdownSpace","markdownLineEndingOrSpace","map","table","markdownLineEnding","markdownLineEndingOrSpace","markdownSpace","ok","code","MAX_DEPTH","text","MAX_DEPTH","MAX_DEPTH","doc","text","doc","KEYWORDS","MAX_DEPTH","text","doc","PluginKey","doc","text","Plugin","linkMark","slice","Plugin","PluginKey","TextSelection","Decoration","DecorationSet","text","useCallback","useRef","useState","jsx","jsxs","useState","useRef","useCallback","Plugin","PluginKey","Decoration","DecorationSet","linkMark","buildDecorations","jsx","jsxs","RESOURCE_TAG_COLORS","RESOURCE_TAG_ICONS","text","Plugin","PluginKey","Decoration","DecorationSet","PluginKey","JINJA_TAG_RE","doc","text","Decoration","buildDecorations","DecorationSet","Plugin","useEffect","useRef","useState","createRoot","Plugin","TextSelection","Fragment","jsx","jsxs","doc","TextSelection","tr","jsx","useState","useRef","useEffect","jsxs","Fragment","createRoot","Plugin","InputRule","inputRules","Plugin","PluginKey","TextSelection","doc","text","Plugin","PluginKey","StyleManager","doc","key","Plugin","tr","Plugin","PluginKey","Decoration","DecorationSet","pluginKey","buildDecorations","doc","React","useEffect","useRef","useState","createPortal","Fragment","jsx","jsxs","useState","useRef","useEffect","createPortal","React","useState","jsx","jsxs","doc","text","useState","useState","jsx","jsxs","useState","doc","useCallback","useEffect","useRef","useState","createPortal","TextSelection","setBlockType","toggleMark","wrapInList","Fragment","jsx","jsxs","paragraph","heading","bulletList","orderedList","blockquote","bold","italic","underline","strikethrough","code","VPORT_MARGIN","getMarkRange","doc","POPUP_SHADOW","BTN_RESET","useState","useRef","useEffect","setBlockType","wrapInList","createPortal","useCallback","toggleMark","link","tr","TextSelection","Plugin","PluginKey","Decoration","DecorationSet","Plugin","DecorationSet","Decoration"]}