@notectl/core 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1816 -0
- package/dist/notectl-core.js +1046 -2792
- package/dist/notectl-core.js.map +1 -1
- package/dist/notectl-core.mjs +7886 -0
- package/dist/notectl-core.mjs.map +1 -0
- package/package.json +31 -55
- package/dist/notectl-core.umd.cjs +0 -117
- package/dist/notectl-core.umd.cjs.map +0 -1
- package/dist/types/index.d.ts +0 -1469
package/dist/notectl-core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notectl-core.js","sources":["../src/schema/Schema.ts","../src/schema/NodeFactory.ts","../src/state/EditorState.ts","../src/constants.ts","../src/plugins/PluginManager.ts","../../../node_modules/dompurify/dist/purify.es.mjs","../src/utils/security.ts","../src/utils/accessibility.ts","../src/editor/NotectlEditor.ts","../src/plugins/Plugin.ts","../src/delta/Delta.ts","../src/delta/Operations.ts","../src/delta/Transform.ts","../src/utils/helpers.ts","../src/index.ts"],"sourcesContent":["/**\n * Document schema definition for Notectl\n * Defines the structure and validation rules for the document model\n */\n\nimport type { NodeType, BlockNode, TextNode, Node, Mark } from '../types/index.js';\n\n/**\n * Node specification in the schema\n */\nexport interface NodeSpec {\n type: NodeType;\n group?: 'block' | 'inline' | 'table';\n content?: string; // Content expression (e.g., \"block+\", \"inline*\", \"text*\")\n marks?: string; // Allowed marks (e.g., \"_\", \"strong em\")\n attrs?: Record<string, AttributeSpec>;\n defining?: boolean; // Node defines its content boundaries\n isolating?: boolean; // Node isolates content from surroundings\n toDOM?: (node: Node) => HTMLElement | [string, Record<string, string>, ...unknown[]];\n parseDOM?: Array<{\n tag?: string;\n attrs?: Record<string, unknown>;\n }>;\n}\n\n/**\n * Attribute specification\n */\nexport interface AttributeSpec {\n default?: unknown;\n validate?: (value: unknown) => boolean;\n required?: boolean;\n}\n\n/**\n * Mark specification in the schema\n */\nexport interface MarkSpec {\n type: string;\n attrs?: Record<string, AttributeSpec>;\n inclusive?: boolean;\n excludes?: string; // Marks that cannot coexist\n group?: string;\n spanning?: boolean;\n toDOM?: (mark: Mark) => [string, Record<string, string>];\n parseDOM?: Array<{\n tag?: string;\n style?: string;\n attrs?: Record<string, unknown>;\n }>;\n}\n\n/**\n * Document schema\n */\nexport class Schema {\n nodes: Map<NodeType, NodeSpec>;\n marks: Map<string, MarkSpec>;\n topNode: NodeType;\n\n constructor(config: { nodes: NodeSpec[]; marks: MarkSpec[]; topNode?: NodeType }) {\n this.nodes = new Map(config.nodes.map((spec) => [spec.type, spec]));\n this.marks = new Map(config.marks.map((spec) => [spec.type, spec]));\n this.topNode = config.topNode || 'paragraph';\n }\n\n /**\n * Get node specification\n */\n node(type: NodeType): NodeSpec | undefined {\n return this.nodes.get(type);\n }\n\n /**\n * Get mark specification\n */\n mark(type: string): MarkSpec | undefined {\n return this.marks.get(type);\n }\n\n /**\n * Validate if a node conforms to the schema\n */\n validateNode(node: Node): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n if ('text' in node) {\n // Text node validation\n const textNode = node as TextNode;\n if (typeof textNode.text !== 'string') {\n errors.push('Text node must have a string text property');\n }\n if (textNode.marks) {\n for (const mark of textNode.marks) {\n if (!this.marks.has(mark.type)) {\n errors.push(`Unknown mark type: ${mark.type}`);\n }\n }\n }\n } else {\n // Block node validation\n const blockNode = node as BlockNode;\n const spec = this.nodes.get(blockNode.type);\n \n if (!spec) {\n errors.push(`Unknown node type: ${blockNode.type}`);\n return { valid: false, errors };\n }\n\n // Validate required attributes\n if (spec.attrs) {\n for (const [attrName, attrSpec] of Object.entries(spec.attrs)) {\n if (attrSpec.required && (!blockNode.attrs || !(attrName in blockNode.attrs))) {\n errors.push(`Required attribute missing: ${attrName}`);\n }\n if (blockNode.attrs?.[attrName] && attrSpec.validate) {\n if (!attrSpec.validate(blockNode.attrs[attrName])) {\n errors.push(`Invalid attribute value: ${attrName}`);\n }\n }\n }\n }\n\n // Validate children if present\n if (blockNode.children) {\n for (const child of blockNode.children) {\n const childValidation = this.validateNode(child);\n errors.push(...childValidation.errors);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Check if a mark is allowed on a node\n */\n markAllowedOn(markType: string, nodeType: NodeType): boolean {\n const nodeSpec = this.nodes.get(nodeType);\n if (!nodeSpec || !nodeSpec.marks) {\n return false;\n }\n \n if (nodeSpec.marks === '_') {\n return true; // All marks allowed\n }\n \n return nodeSpec.marks.split(' ').includes(markType);\n }\n\n /**\n * Check if two marks can coexist\n */\n marksCompatible(markA: string, markB: string): boolean {\n const specA = this.marks.get(markA);\n const specB = this.marks.get(markB);\n \n if (specA?.excludes && specA.excludes.split(' ').includes(markB)) {\n return false;\n }\n if (specB?.excludes && specB.excludes.split(' ').includes(markA)) {\n return false;\n }\n \n return true;\n }\n}\n\n/**\n * Create default Notectl schema\n */\nexport function createDefaultSchema(): Schema {\n return new Schema({\n nodes: [\n {\n type: 'paragraph',\n group: 'block',\n content: 'inline*',\n marks: '_',\n },\n {\n type: 'heading',\n group: 'block',\n content: 'inline*',\n marks: '_',\n attrs: {\n level: {\n default: 1,\n validate: (val) => typeof val === 'number' && val >= 1 && val <= 6,\n },\n },\n },\n {\n type: 'list',\n group: 'block',\n content: 'list_item+',\n },\n {\n type: 'list_item',\n content: 'paragraph block*',\n defining: true,\n },\n {\n type: 'table',\n group: 'block',\n content: 'table_row+',\n isolating: true,\n },\n {\n type: 'table_row',\n content: 'table_cell+',\n },\n {\n type: 'table_cell',\n content: 'block+',\n isolating: true,\n },\n {\n type: 'image',\n group: 'inline',\n attrs: {\n src: { required: true },\n alt: { default: '' },\n decorative: { default: false },\n },\n },\n {\n type: 'code_block',\n group: 'block',\n content: 'text*',\n marks: '',\n },\n {\n type: 'text',\n group: 'inline',\n },\n ],\n marks: [\n { type: 'bold', excludes: '' },\n { type: 'italic', excludes: '' },\n { type: 'underline', excludes: '' },\n { type: 'strikethrough', excludes: '' },\n { type: 'code', excludes: 'link' },\n {\n type: 'link',\n attrs: {\n href: { required: true },\n title: { default: '' },\n },\n excludes: 'code',\n },\n ],\n topNode: 'paragraph',\n });\n}\n","/**\n * Factory for creating document nodes\n */\n\nimport type { BlockNode, TextNode, BlockId, NodeType, Mark, BlockAttrs } from '../types/index.js';\nimport { Schema } from './Schema.js';\n\n/**\n * Generate a unique block ID\n */\nexport function generateBlockId(): BlockId {\n // Simple UUID v4 implementation\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Node factory for creating valid nodes\n */\nexport class NodeFactory {\n constructor(private schema: Schema) {}\n\n /**\n * Create a text node\n */\n text(text: string, marks?: Mark[]): TextNode {\n return {\n type: 'text',\n text,\n marks: marks || [],\n };\n }\n\n /**\n * Create a paragraph node\n */\n paragraph(content?: TextNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'paragraph',\n attrs,\n children: content || [],\n };\n }\n\n /**\n * Create a heading node\n */\n heading(level: number, content?: TextNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'heading',\n attrs: { ...attrs, level },\n children: content || [],\n };\n }\n\n /**\n * Create a list node\n */\n list(items: BlockNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'list',\n attrs,\n children: items,\n };\n }\n\n /**\n * Create a list item node\n */\n listItem(content: BlockNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'list_item',\n attrs,\n children: content,\n };\n }\n\n /**\n * Create a table node\n */\n table(rows: BlockNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'table',\n attrs,\n children: rows,\n };\n }\n\n /**\n * Create a table row node\n */\n tableRow(cells: BlockNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'table_row',\n attrs,\n children: cells,\n };\n }\n\n /**\n * Create a table cell node\n */\n tableCell(content: BlockNode[], attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'table_cell',\n attrs,\n children: content,\n };\n }\n\n /**\n * Create an image node\n */\n image(src: string, alt?: string, attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'image',\n attrs: { src, alt: alt || '', decorative: !alt, ...attrs },\n children: [],\n };\n }\n\n /**\n * Create a code block node\n */\n codeBlock(content: string, attrs?: BlockAttrs): BlockNode {\n return {\n id: generateBlockId(),\n type: 'code_block',\n attrs,\n children: [this.text(content)],\n };\n }\n\n /**\n * Create a generic block node\n */\n block(type: NodeType, attrs?: BlockAttrs, children?: (TextNode | BlockNode)[]): BlockNode {\n const spec = this.schema.node(type);\n if (!spec) {\n throw new Error(`Unknown node type: ${type}`);\n }\n\n return {\n id: generateBlockId(),\n type,\n attrs,\n children,\n };\n }\n\n /**\n * Create a mark\n */\n mark(type: string, attrs?: Record<string, unknown>): Mark {\n const spec = this.schema.mark(type);\n if (!spec) {\n throw new Error(`Unknown mark type: ${type}`);\n }\n\n return {\n type,\n attrs,\n };\n }\n\n /**\n * Clone a node with new children\n */\n cloneNode(node: BlockNode, children?: (TextNode | BlockNode)[]): BlockNode {\n return {\n ...node,\n id: generateBlockId(), // Generate new ID for cloned node\n children: children !== undefined ? children : node.children,\n };\n }\n}\n\n/**\n * Create a node factory with the given schema\n */\nexport function createNodeFactory(schema: Schema): NodeFactory {\n return new NodeFactory(schema);\n}\n","/**\n * Editor state management\n * Maintains the document state and provides methods for querying and updating\n */\n\nimport type { Document, Selection, BlockNode, BlockId, Node } from '../types/index.js';\nimport { Schema, createDefaultSchema } from '../schema/Schema.js';\nimport { NodeFactory, createNodeFactory } from '../schema/NodeFactory.js';\nimport type { Delta } from '../delta/Delta.js';\nimport type { Operation } from '../delta/Operations.js';\n\n/**\n * History entry for undo/redo\n */\ninterface HistoryEntry {\n delta: Delta;\n inverseOps: Operation[];\n timestamp: number;\n}\n\n/**\n * Editor state class\n */\nexport class EditorState {\n private document: Document;\n private selection: Selection | null = null;\n private history: HistoryEntry[] = [];\n private historyIndex: number = -1;\n private maxHistoryDepth: number;\n \n readonly schema: Schema;\n readonly nodeFactory: NodeFactory;\n\n constructor(\n initialDoc?: Document,\n schema?: Schema,\n options?: { maxHistoryDepth?: number }\n ) {\n this.schema = schema || createDefaultSchema();\n this.nodeFactory = createNodeFactory(this.schema);\n this.maxHistoryDepth = options?.maxHistoryDepth || 100;\n\n this.document = initialDoc || {\n version: 0,\n schemaVersion: '1.0.0',\n children: [this.nodeFactory.paragraph()],\n };\n }\n\n /**\n * Get current document\n */\n getDocument(): Document {\n return this.document;\n }\n\n /**\n * Get document version\n */\n getVersion(): number {\n return this.document.version;\n }\n\n /**\n * Get current selection\n */\n getSelection(): Selection | null {\n return this.selection;\n }\n\n /**\n * Set selection\n */\n setSelection(selection: Selection | null): void {\n this.selection = selection;\n }\n\n /**\n * Apply a delta to the state\n */\n applyDelta(delta: Delta): void {\n // Validate delta version\n if (delta.baseVersion !== this.document.version) {\n throw new Error(\n `Delta version mismatch: expected ${this.document.version}, got ${delta.baseVersion}`\n );\n }\n\n // Store in history (only if not a selection update)\n const hasContentOps = delta.ops.some((op) => op.op !== 'update_selection');\n if (hasContentOps) {\n this.addToHistory(delta);\n }\n\n // Apply each operation\n for (const op of delta.ops) {\n this.applyOperation(op);\n }\n\n // Increment version\n this.document.version++;\n }\n\n /**\n * Apply a single operation\n */\n private applyOperation(op: Operation): void {\n switch (op.op) {\n case 'insert_text':\n this.applyInsertText(op);\n break;\n case 'delete_range':\n this.applyDeleteRange(op);\n break;\n case 'apply_mark':\n this.applyMark(op);\n break;\n case 'insert_block_after':\n this.applyInsertBlockAfter(op);\n break;\n case 'insert_block_before':\n this.applyInsertBlockBefore(op);\n break;\n case 'delete_block':\n this.applyDeleteBlock(op);\n break;\n case 'set_attrs':\n this.applySetAttrs(op);\n break;\n case 'update_selection':\n this.selection = {\n anchor: op.selection.anchor,\n head: op.selection.head,\n };\n break;\n // Table operations would be implemented here\n default:\n console.warn('Unhandled operation type:', (op as Operation).op);\n }\n }\n\n /**\n * Apply insert text operation\n */\n private applyInsertText(op: Extract<Operation, { op: 'insert_text' }>): void {\n const block = this.findBlock(op.target.blockId);\n if (!block || !block.children) return;\n\n // Find text node at offset and insert text\n // Simplified implementation - would need proper offset handling\n const textNode = block.children.find((n): n is Extract<Node, { type: 'text' }> => 'text' in n);\n if (textNode) {\n const before = textNode.text.slice(0, op.target.offset);\n const after = textNode.text.slice(op.target.offset);\n textNode.text = before + op.text + after;\n if (op.marks && op.marks.length > 0) {\n textNode.marks = op.marks;\n }\n }\n }\n\n /**\n * Apply delete range operation\n */\n private applyDeleteRange(op: Extract<Operation, { op: 'delete_range' }>): void {\n const block = this.findBlock(op.range.start.blockId);\n if (!block || !block.children) return;\n\n const textNode = block.children.find((n): n is Extract<Node, { type: 'text' }> => 'text' in n);\n if (textNode) {\n const before = textNode.text.slice(0, op.range.start.offset);\n const after = textNode.text.slice(op.range.end.offset);\n textNode.text = before + after;\n }\n }\n\n /**\n * Apply mark operation\n */\n private applyMark(op: Extract<Operation, { op: 'apply_mark' }>): void {\n const block = this.findBlock(op.range.start.blockId);\n if (!block || !block.children) return;\n\n const textNode = block.children.find((n): n is Extract<Node, { type: 'text' }> => 'text' in n);\n if (textNode) {\n if (op.add) {\n textNode.marks = textNode.marks || [];\n if (!textNode.marks.some((m) => m.type === op.mark.type)) {\n textNode.marks.push(op.mark);\n }\n } else {\n textNode.marks = textNode.marks?.filter((m) => m.type !== op.mark.type);\n }\n }\n }\n\n /**\n * Apply insert block after operation\n */\n private applyInsertBlockAfter(op: Extract<Operation, { op: 'insert_block_after' }>): void {\n const index = this.document.children.findIndex((b) => b.id === op.after);\n if (index !== -1) {\n this.document.children.splice(index + 1, 0, op.block);\n }\n }\n\n /**\n * Apply insert block before operation\n */\n private applyInsertBlockBefore(op: Extract<Operation, { op: 'insert_block_before' }>): void {\n const index = this.document.children.findIndex((b) => b.id === op.before);\n if (index !== -1) {\n this.document.children.splice(index, 0, op.block);\n }\n }\n\n /**\n * Apply delete block operation\n */\n private applyDeleteBlock(op: Extract<Operation, { op: 'delete_block' }>): void {\n const index = this.document.children.findIndex((b) => b.id === op.target.blockId);\n if (index !== -1) {\n this.document.children.splice(index, 1);\n }\n }\n\n /**\n * Apply set attributes operation\n */\n private applySetAttrs(op: Extract<Operation, { op: 'set_attrs' }>): void {\n const block = this.findBlock(op.target.blockId);\n if (block) {\n block.attrs = { ...block.attrs, ...op.attrs };\n }\n }\n\n /**\n * Find a block by ID\n */\n findBlock(blockId: BlockId): BlockNode | undefined {\n const search = (nodes: BlockNode[]): BlockNode | undefined => {\n for (const node of nodes) {\n if (node.id === blockId) {\n return node;\n }\n if (node.children) {\n const blockChildren = node.children.filter((n): n is BlockNode => 'id' in n);\n const found = search(blockChildren);\n if (found) return found;\n }\n }\n return undefined;\n };\n\n return search(this.document.children);\n }\n\n /**\n * Add delta to history\n */\n private addToHistory(delta: Delta): void {\n // Remove any redo entries\n if (this.historyIndex < this.history.length - 1) {\n this.history = this.history.slice(0, this.historyIndex + 1);\n }\n\n // Add to history\n this.history.push({\n delta,\n inverseOps: delta.inverseOps || [],\n timestamp: Date.now(),\n });\n\n // Maintain max depth\n if (this.history.length > this.maxHistoryDepth) {\n this.history.shift();\n } else {\n this.historyIndex++;\n }\n }\n\n /**\n * Undo last change\n */\n canUndo(): boolean {\n return this.historyIndex >= 0;\n }\n\n undo(): Delta | null {\n if (!this.canUndo()) return null;\n\n const entry = this.history[this.historyIndex];\n this.historyIndex--;\n\n // Create undo delta with inverse operations\n return {\n txnId: `undo-${entry.delta.txnId}`,\n clientId: entry.delta.clientId,\n timestamp: new Date().toISOString(),\n baseVersion: this.document.version,\n ltime: Date.now(),\n intent: 'edit',\n ops: entry.inverseOps,\n };\n }\n\n /**\n * Redo last undone change\n */\n canRedo(): boolean {\n return this.historyIndex < this.history.length - 1;\n }\n\n redo(): Delta | null {\n if (!this.canRedo()) return null;\n\n this.historyIndex++;\n const entry = this.history[this.historyIndex];\n\n return entry.delta;\n }\n\n /**\n * Export state as JSON\n */\n toJSON(): Document {\n return this.document;\n }\n\n /**\n * Create state from JSON\n */\n static fromJSON(json: Document, schema?: Schema): EditorState {\n return new EditorState(json, schema);\n }\n}\n","/**\n * Constants for Notectl Editor\n * Exported to avoid magic numbers and improve maintainability\n */\n\n/**\n * Timeout in milliseconds to wait for editor's connectedCallback to complete\n * and render the DOM structure including plugin containers.\n *\n * This is needed when registering plugins immediately after appending the editor\n * to the DOM, as the connectedCallback runs asynchronously.\n *\n * @example\n * ```typescript\n * const editor = document.createElement('notectl-editor');\n * container.appendChild(editor);\n * await new Promise(resolve => setTimeout(resolve, EDITOR_READY_TIMEOUT));\n * await editor.registerPlugin(new ToolbarPlugin());\n * ```\n */\nexport const EDITOR_READY_TIMEOUT = 100; // ms\n\n/**\n * Default timeout for screen reader announcements\n * Used to clear and reset the aria-live region\n */\nexport const ARIA_ANNOUNCEMENT_DELAY = 100; // ms\n\n/**\n * Default maximum number of history entries to keep\n */\nexport const DEFAULT_MAX_HISTORY_DEPTH = 100;\n\n/**\n * Default minimum height for the editor content area\n */\nexport const DEFAULT_MIN_HEIGHT = 200; // px\n\n/**\n * Error codes for structured error handling\n */\nexport const ErrorCodes = {\n // Plugin-related errors\n PLUGIN_ALREADY_REGISTERED: 'PLUGIN_ALREADY_REGISTERED',\n PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n PLUGIN_INVALID_CONFIG: 'PLUGIN_INVALID_CONFIG',\n PLUGIN_INIT_FAILED: 'PLUGIN_INIT_FAILED',\n PLUGIN_DESTROY_FAILED: 'PLUGIN_DESTROY_FAILED',\n PLUGIN_DEPENDENCY_CONFLICT: 'PLUGIN_DEPENDENCY_CONFLICT',\n\n // Editor state errors\n EDITOR_NOT_MOUNTED: 'EDITOR_NOT_MOUNTED',\n EDITOR_NOT_INITIALIZED: 'EDITOR_NOT_INITIALIZED',\n EDITOR_DESTROYED: 'EDITOR_DESTROYED',\n\n // Command errors\n COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',\n COMMAND_ALREADY_REGISTERED: 'COMMAND_ALREADY_REGISTERED',\n COMMAND_EXECUTION_FAILED: 'COMMAND_EXECUTION_FAILED',\n COMMAND_INVALID_ARGS: 'COMMAND_INVALID_ARGS',\n\n // Content errors\n INVALID_CONTENT: 'INVALID_CONTENT',\n INVALID_DELTA: 'INVALID_DELTA',\n INVALID_DOCUMENT: 'INVALID_DOCUMENT',\n SANITIZATION_FAILED: 'SANITIZATION_FAILED',\n\n // Security errors\n XSS_DETECTED: 'XSS_DETECTED',\n UNSAFE_OPERATION: 'UNSAFE_OPERATION',\n\n // General errors\n INVALID_OPERATION: 'INVALID_OPERATION',\n INTERNAL_ERROR: 'INTERNAL_ERROR',\n} as const;\n\n/**\n * Type for error codes\n */\nexport type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];\n\n/**\n * Structured error class for Notectl\n */\nexport class NotectlError extends Error {\n constructor(\n public code: ErrorCode,\n message: string,\n public details?: unknown\n ) {\n super(message);\n this.name = 'NotectlError';\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, NotectlError);\n }\n }\n\n /**\n * Convert to JSON-serializable format\n */\n toJSON() {\n return {\n error: {\n code: this.code,\n message: this.message,\n details: this.details,\n }\n };\n }\n}\n\n/**\n * Validation constraints for document structure\n */\nexport const ValidationConstraints = {\n NO_DANGLING_REFS: 'noDanglingRefs',\n TABLE_GRID_CONSISTENT: 'tableGridConsistent',\n ALT_OR_DECORATIVE: 'altOrDecorative',\n RTL_INTEGRITY: 'rtlIntegrity',\n} as const;\n","/**\n * Plugin manager for registering and managing plugins\n */\n\nimport type { Plugin, PluginContext } from './Plugin.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Delta } from '../delta/Delta.js';\nimport { ErrorCodes, NotectlError } from '../constants.js';\n\n/**\n * Plugin manager class\n */\nexport class PluginManager {\n private plugins: Map<string, Plugin> = new Map();\n private initializationOrder: string[] = [];\n\n constructor() {}\n\n /**\n * Register a plugin\n *\n * @param plugin - The plugin to register\n * @param context - Plugin context with editor APIs\n * @throws {NotectlError} If plugin validation fails or initialization errors occur\n *\n * @example\n * ```typescript\n * const toolbarPlugin = new ToolbarPlugin();\n * await pluginManager.register(toolbarPlugin, context);\n * ```\n */\n async register(plugin: Plugin, context: PluginContext): Promise<void> {\n // Validate plugin object\n if (!plugin) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INVALID_CONFIG,\n 'Cannot register null or undefined plugin'\n );\n }\n\n if (!plugin.id || typeof plugin.id !== 'string') {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INVALID_CONFIG,\n 'Plugin must have a valid string \"id\" property',\n { plugin }\n );\n }\n\n if (!plugin.name || typeof plugin.name !== 'string') {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INVALID_CONFIG,\n `Plugin \"${plugin.id}\" must have a valid string \"name\" property`,\n { pluginId: plugin.id }\n );\n }\n\n if (!plugin.version || typeof plugin.version !== 'string') {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INVALID_CONFIG,\n `Plugin \"${plugin.id}\" must have a valid string \"version\" property`,\n { pluginId: plugin.id, pluginName: plugin.name }\n );\n }\n\n if (typeof plugin.init !== 'function') {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INVALID_CONFIG,\n `Plugin \"${plugin.id}\" must have an \"init\" method`,\n { pluginId: plugin.id, pluginName: plugin.name }\n );\n }\n\n // Check if already registered\n if (this.plugins.has(plugin.id)) {\n const existing = this.plugins.get(plugin.id)!;\n throw new NotectlError(\n ErrorCodes.PLUGIN_ALREADY_REGISTERED,\n `Plugin \"${plugin.id}\" is already registered (version: ${existing.version})`,\n { pluginId: plugin.id, existingVersion: existing.version, newVersion: plugin.version }\n );\n }\n\n // Check dependencies\n if (plugin.dependencies && plugin.dependencies.length > 0) {\n const missingDeps: string[] = [];\n\n for (const depId of plugin.dependencies) {\n if (!this.plugins.has(depId)) {\n missingDeps.push(depId);\n }\n }\n\n if (missingDeps.length > 0) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_MISSING_DEPENDENCY,\n `Plugin \"${plugin.id}\" (${plugin.name}) cannot be registered because the following dependencies are missing: ${missingDeps.join(', ')}. Please register these plugins first.`,\n {\n pluginId: plugin.id,\n pluginName: plugin.name,\n missingDependencies: missingDeps,\n registeredPlugins: Array.from(this.plugins.keys())\n }\n );\n }\n }\n\n // Initialize plugin\n try {\n await plugin.init(context);\n } catch (error) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_INIT_FAILED,\n `Failed to initialize plugin \"${plugin.id}\" (${plugin.name}): ${error instanceof Error ? error.message : String(error)}`,\n {\n pluginId: plugin.id,\n pluginName: plugin.name,\n originalError: error\n }\n );\n }\n\n // Store plugin\n this.plugins.set(plugin.id, plugin);\n this.initializationOrder.push(plugin.id);\n\n // Emit event\n context.emit('plugin-registered', { pluginId: plugin.id, plugin });\n }\n\n /**\n * Unregister a plugin\n *\n * @param pluginId - ID of the plugin to unregister\n * @param context - Plugin context for event emission\n * @throws {NotectlError} If plugin is not found or has dependents\n *\n * @example\n * ```typescript\n * await pluginManager.unregister('toolbar-plugin', context);\n * ```\n */\n async unregister(pluginId: string, context: PluginContext): Promise<void> {\n // Validate plugin ID\n if (!pluginId || typeof pluginId !== 'string') {\n throw new NotectlError(\n ErrorCodes.PLUGIN_NOT_FOUND,\n 'Plugin ID must be a non-empty string',\n { pluginId }\n );\n }\n\n // Check if plugin exists\n const plugin = this.plugins.get(pluginId);\n if (!plugin) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_NOT_FOUND,\n `Plugin \"${pluginId}\" is not registered and cannot be unregistered`,\n {\n pluginId,\n registeredPlugins: Array.from(this.plugins.keys())\n }\n );\n }\n\n // Check if other plugins depend on this one\n const dependentPlugins: string[] = [];\n for (const [id, p] of this.plugins.entries()) {\n if (p.dependencies?.includes(pluginId)) {\n dependentPlugins.push(`${id} (${p.name})`);\n }\n }\n\n if (dependentPlugins.length > 0) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_DEPENDENCY_CONFLICT,\n `Cannot unregister plugin \"${pluginId}\" (${plugin.name}) because the following plugins depend on it: ${dependentPlugins.join(', ')}. Please unregister dependent plugins first.`,\n {\n pluginId,\n pluginName: plugin.name,\n dependentPlugins: dependentPlugins\n }\n );\n }\n\n // Destroy plugin\n if (plugin.destroy) {\n try {\n await plugin.destroy();\n } catch (error) {\n throw new NotectlError(\n ErrorCodes.PLUGIN_DESTROY_FAILED,\n `Failed to destroy plugin \"${pluginId}\" (${plugin.name}): ${error instanceof Error ? error.message : String(error)}`,\n {\n pluginId,\n pluginName: plugin.name,\n originalError: error\n }\n );\n }\n }\n\n // Remove plugin\n this.plugins.delete(pluginId);\n this.initializationOrder = this.initializationOrder.filter((id) => id !== pluginId);\n\n // Emit event\n context.emit('plugin-unregistered', { pluginId });\n }\n\n /**\n * Get a plugin by ID\n */\n get(pluginId: string): Plugin | undefined {\n return this.plugins.get(pluginId);\n }\n\n /**\n * Check if a plugin is registered\n */\n has(pluginId: string): boolean {\n return this.plugins.has(pluginId);\n }\n\n /**\n * Get all registered plugins\n */\n getAll(): Plugin[] {\n return this.initializationOrder.map((id) => this.plugins.get(id)!);\n }\n\n /**\n * Notify plugins of state update\n */\n notifyStateUpdate(oldState: EditorState, newState: EditorState): void {\n for (const pluginId of this.initializationOrder) {\n const plugin = this.plugins.get(pluginId);\n if (plugin?.onStateUpdate) {\n try {\n plugin.onStateUpdate(oldState, newState);\n } catch (error) {\n console.error(`Error in plugin ${pluginId} onStateUpdate:`, error);\n }\n }\n }\n }\n\n /**\n * Notify plugins of delta application\n */\n notifyDeltaApplied(delta: Delta): void {\n for (const pluginId of this.initializationOrder) {\n const plugin = this.plugins.get(pluginId);\n if (plugin?.onDeltaApplied) {\n try {\n plugin.onDeltaApplied(delta);\n } catch (error) {\n console.error(`Error in plugin ${pluginId} onDeltaApplied:`, error);\n }\n }\n }\n }\n\n /**\n * Destroy all plugins\n */\n async destroyAll(): Promise<void> {\n // Destroy in reverse order\n const pluginIds = [...this.initializationOrder].reverse();\n \n for (const pluginId of pluginIds) {\n const plugin = this.plugins.get(pluginId);\n if (plugin?.destroy) {\n try {\n await plugin.destroy();\n } catch (error) {\n console.error(`Error destroying plugin ${pluginId}:`, error);\n }\n }\n }\n\n this.plugins.clear();\n this.initializationOrder = [];\n }\n}\n","/*! @license DOMPurify 3.2.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.7/LICENSE */\n\nconst {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n} = Object;\nlet {\n freeze,\n seal,\n create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n apply,\n construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(func, thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return func.apply(thisArg, args);\n };\n}\nif (!construct) {\n construct = function construct(Func) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(Func) {\n return function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return construct(Func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'slot', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*/gm); // eslint-disable-line unicorn/better-regex\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.2.7';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either <annotation-xml> or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n remove(node);\n }\n };\n /**\n * _removeAttribute\n *\n * @param name an Attribute name\n * @param element a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, element) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: element.getAttributeNode(name),\n from: element\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: element\n });\n }\n element.removeAttribute(name);\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * _isClobbered\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n };\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param value object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n const _isNode = function _isNode(value) {\n return typeof Node === 'function' && value instanceof Node;\n };\n function _executeHooks(hooks, currentNode, data) {\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* Detect mXSS attempts abusing namespace confusion */\n if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\\w!]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const {\n attributes\n } = currentNode;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes || _isClobbered(currentNode)) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n const initValue = attrValue;\n let value = name === 'value' ? initValue : stringTrim(initValue);\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title|textarea)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Make sure we cannot easily use animated hrefs, even if animations are allowed */\n if (lcName === 'attributename' && stringMatch(value, 'href')) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n /* Handle invalid data-* attribute set by try-catching it */\n if (value !== initValue) {\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {\n _removeAttribute(name, currentNode);\n }\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n _sanitizeElements(shadowNode);\n /* Check attributes next */\n _sanitizeAttributes(shadowNode);\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n _sanitizeElements(currentNode);\n /* Check attributes next */\n _sanitizeAttributes(currentNode);\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint, hookFunction) {\n if (hookFunction !== undefined) {\n const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n }\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","/**\n * Security utilities for XSS prevention and content sanitization\n */\n\nimport DOMPurify from 'dompurify';\nimport type { Delta } from '../delta/Delta.js';\nimport type { Config } from 'dompurify';\n\n/**\n * DOMPurify configuration for editor content\n */\nconst EDITOR_SANITIZE_CONFIG: Config = {\n ALLOWED_TAGS: [\n 'p', 'br', 'strong', 'em', 'u', 's', 'code', 'pre',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li',\n 'blockquote',\n 'a', 'img',\n 'table', 'thead', 'tbody', 'tr', 'th', 'td',\n 'div', 'span'\n ],\n ALLOWED_ATTR: [\n 'href', 'src', 'alt', 'title', 'class', 'id',\n 'style', 'data-*',\n 'role', 'aria-*'\n ],\n ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i,\n KEEP_CONTENT: true,\n SANITIZE_DOM: true,\n SAFE_FOR_TEMPLATES: true,\n};\n\n/**\n * Strict DOMPurify configuration for untrusted content\n */\nconst STRICT_SANITIZE_CONFIG: Config = {\n ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'u', 'code'],\n ALLOWED_ATTR: [],\n KEEP_CONTENT: true,\n SANITIZE_DOM: true,\n SAFE_FOR_TEMPLATES: true,\n};\n\n/**\n * Sanitize HTML content using DOMPurify\n * @param html - HTML content to sanitize\n * @param strict - Use strict configuration (default: false)\n * @returns Sanitized HTML\n */\nexport function sanitizeHTML(html: string, strict: boolean = false): string {\n const config = strict ? STRICT_SANITIZE_CONFIG : EDITOR_SANITIZE_CONFIG;\n return DOMPurify.sanitize(html, config) as string;\n}\n\n/**\n * Sanitize user content (text and HTML)\n * @param content - Content to sanitize\n * @param allowHTML - Allow HTML tags (default: true)\n * @returns Sanitized content\n */\nexport function sanitizeContent(content: string, allowHTML: boolean = true): string {\n if (!allowHTML) {\n // Escape all HTML\n return escapeHTML(content);\n }\n\n // Sanitize HTML while preserving allowed tags\n return sanitizeHTML(content);\n}\n\n/**\n * Escape HTML entities\n * @param text - Text to escape\n * @returns Escaped text\n */\nexport function escapeHTML(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\n/**\n * Unescape HTML entities\n * @param html - HTML to unescape\n * @returns Unescaped text\n */\nexport function unescapeHTML(html: string): string {\n const div = document.createElement('div');\n div.innerHTML = html;\n return div.textContent || '';\n}\n\n/**\n * Validate delta operations for potential XSS\n * @param delta - Delta to validate\n * @returns True if delta is safe\n */\nexport function validateDelta(delta: Delta): boolean {\n try {\n // Check if delta has required structure\n if (!delta || typeof delta !== 'object') {\n return false;\n }\n\n // Validate operations array\n if (!Array.isArray(delta.ops)) {\n return false;\n }\n\n // Check each operation\n for (const op of delta.ops) {\n // Validate insert operations\n if ('insert' in op) {\n const insert = op.insert;\n\n // Check for script injection in strings\n if (typeof insert === 'string') {\n const sanitized = sanitizeHTML(insert);\n if (sanitized !== insert && insert.includes('<script')) {\n return false;\n }\n }\n\n // Check for dangerous attributes\n if (typeof insert === 'object' && insert !== null) {\n const insertObj = insert as Record<string, unknown>;\n if ('script' in insertObj || 'onerror' in insertObj || 'onclick' in insertObj) {\n return false;\n }\n }\n }\n\n // Validate attributes\n if ('attributes' in op && op.attributes) {\n const attrs = op.attributes as Record<string, unknown>;\n\n // Check for event handlers\n for (const key in attrs) {\n if (key.startsWith('on') || key.toLowerCase().includes('script')) {\n return false;\n }\n }\n }\n }\n\n return true;\n } catch (error) {\n console.error('Error validating delta:', error);\n return false;\n }\n}\n\n/**\n * Prevent XSS in URLs\n * @param url - URL to validate\n * @returns Sanitized URL or empty string if invalid\n */\nexport function sanitizeURL(url: string): string {\n try {\n const trimmed = url.trim();\n\n // Block javascript: and data: URLs\n if (\n trimmed.toLowerCase().startsWith('javascript:') ||\n trimmed.toLowerCase().startsWith('data:') ||\n trimmed.toLowerCase().startsWith('vbscript:')\n ) {\n return '';\n }\n\n // Validate URL format\n const urlObj = new URL(trimmed, window.location.origin);\n\n // Only allow http, https, mailto, tel protocols\n const allowedProtocols = ['http:', 'https:', 'mailto:', 'tel:'];\n if (!allowedProtocols.includes(urlObj.protocol)) {\n return '';\n }\n\n return urlObj.href;\n } catch {\n // Invalid URL\n return '';\n }\n}\n\n/**\n * Create a safe HTML string with sanitization\n * @param strings - Template strings\n * @param values - Template values\n * @returns Sanitized HTML\n */\nexport function safeHTML(strings: TemplateStringsArray, ...values: unknown[]): string {\n let html = strings[0];\n\n for (let i = 0; i < values.length; i++) {\n const value = values[i];\n const escaped = typeof value === 'string' ? escapeHTML(value) : String(value);\n html += escaped + strings[i + 1];\n }\n\n return sanitizeHTML(html);\n}\n\n/**\n * Remove dangerous attributes from an element\n * @param element - Element to clean\n */\nexport function removeDangerousAttributes(element: Element): void {\n const dangerousAttrs = [\n 'onerror', 'onload', 'onclick', 'onmouseover', 'onfocus', 'onblur',\n 'onchange', 'onsubmit', 'onkeydown', 'onkeyup', 'onkeypress'\n ];\n\n dangerousAttrs.forEach(attr => {\n if (element.hasAttribute(attr)) {\n element.removeAttribute(attr);\n }\n });\n\n // Check all attributes for javascript:\n Array.from(element.attributes).forEach(attr => {\n if (attr.value.toLowerCase().includes('javascript:')) {\n element.removeAttribute(attr.name);\n }\n });\n}\n\n/**\n * Sanitize DOM element and its children\n * @param element - Element to sanitize\n */\nexport function sanitizeElement(element: Element): void {\n // Remove dangerous attributes from current element\n removeDangerousAttributes(element);\n\n // Recursively sanitize children\n Array.from(element.children).forEach(child => {\n sanitizeElement(child);\n });\n}\n\n/**\n * Check if content contains potential XSS\n * @param content - Content to check\n * @returns True if potentially dangerous\n */\nexport function containsXSS(content: string): boolean {\n const dangerous = [\n '<script',\n 'javascript:',\n 'onerror=',\n 'onclick=',\n 'onload=',\n '<iframe',\n '<object',\n '<embed',\n 'data:text/html'\n ];\n\n const lower = content.toLowerCase();\n return dangerous.some(pattern => lower.includes(pattern));\n}\n","/**\n * Accessibility utilities for ARIA attributes and screen reader support\n */\n\n/**\n * ARIA live region politeness levels\n */\nexport type AriaLive = 'off' | 'polite' | 'assertive';\n\n/**\n * Keyboard shortcut configuration\n */\nexport interface KeyboardShortcut {\n key: string;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n altKey?: boolean;\n description: string;\n action: () => void;\n}\n\n/**\n * Focus trap configuration\n */\nexport interface FocusTrapConfig {\n container: HTMLElement;\n initialFocus?: HTMLElement;\n returnFocus?: HTMLElement;\n escapeDeactivates?: boolean;\n}\n\n/**\n * Announce message to screen readers\n * @param message - Message to announce\n * @param politeness - ARIA live politeness level\n */\nexport function announceToScreenReader(\n message: string,\n politeness: AriaLive = 'polite'\n): void {\n // Create or get existing live region\n let liveRegion = document.getElementById('notectl-sr-live');\n\n if (!liveRegion) {\n liveRegion = document.createElement('div');\n liveRegion.id = 'notectl-sr-live';\n liveRegion.setAttribute('role', 'status');\n liveRegion.setAttribute('aria-live', politeness);\n liveRegion.setAttribute('aria-atomic', 'true');\n liveRegion.style.position = 'absolute';\n liveRegion.style.left = '-10000px';\n liveRegion.style.width = '1px';\n liveRegion.style.height = '1px';\n liveRegion.style.overflow = 'hidden';\n document.body.appendChild(liveRegion);\n } else {\n liveRegion.setAttribute('aria-live', politeness);\n }\n\n // Clear and set message (ensures announcement)\n liveRegion.textContent = '';\n setTimeout(() => {\n liveRegion!.textContent = message;\n }, 100);\n}\n\n/**\n * Get all focusable elements within a container\n * @param container - Container element\n * @returns Array of focusable elements\n */\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n const selector = [\n 'a[href]',\n 'button:not([disabled])',\n 'textarea:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n ].join(',');\n\n return Array.from(container.querySelectorAll<HTMLElement>(selector)).filter(\n el => {\n // Check if element is visible\n return el.offsetParent !== null &&\n getComputedStyle(el).visibility !== 'hidden' &&\n !el.hasAttribute('hidden');\n }\n );\n}\n\n/**\n * Trap focus within a container\n * @param config - Focus trap configuration\n * @returns Cleanup function\n */\nexport function trapFocus(config: FocusTrapConfig): () => void {\n const { container, initialFocus, returnFocus, escapeDeactivates = true } = config;\n\n const focusableElements = getFocusableElements(container);\n if (focusableElements.length === 0) {\n console.warn('No focusable elements found in container');\n return () => {};\n }\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n // Focus initial element\n if (initialFocus && focusableElements.includes(initialFocus)) {\n initialFocus.focus();\n } else {\n firstElement.focus();\n }\n\n // Handle keyboard events\n const handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n // Shift+Tab\n if (document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n }\n } else {\n // Tab\n if (document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n } else if (escapeDeactivates && event.key === 'Escape') {\n event.preventDefault();\n deactivate();\n }\n };\n\n // Deactivate focus trap\n const deactivate = (): void => {\n document.removeEventListener('keydown', handleKeyDown);\n if (returnFocus) {\n returnFocus.focus();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n\n return deactivate;\n}\n\n/**\n * Generate ARIA label for editor actions\n * @param action - Action name\n * @param state - Current state description\n * @returns ARIA label\n */\nexport function getAriaLabel(action: string, state?: string): string {\n const labels: Record<string, string> = {\n bold: 'Toggle bold formatting',\n italic: 'Toggle italic formatting',\n underline: 'Toggle underline formatting',\n strikethrough: 'Toggle strikethrough formatting',\n code: 'Toggle code formatting',\n heading1: 'Format as heading level 1',\n heading2: 'Format as heading level 2',\n heading3: 'Format as heading level 3',\n bulletList: 'Create bullet list',\n orderedList: 'Create numbered list',\n blockquote: 'Create blockquote',\n codeBlock: 'Create code block',\n link: 'Insert link',\n image: 'Insert image',\n undo: 'Undo last action',\n redo: 'Redo last action',\n clear: 'Clear formatting'\n };\n\n const baseLabel = labels[action] || action;\n return state ? `${baseLabel} (${state})` : baseLabel;\n}\n\n/**\n * Get keyboard shortcut description\n * @param shortcut - Keyboard shortcut\n * @returns Human-readable description\n */\nexport function getShortcutDescription(shortcut: KeyboardShortcut): string {\n const parts: string[] = [];\n\n const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n\n if (shortcut.ctrlKey || shortcut.metaKey) {\n parts.push(isMac ? 'Cmd' : 'Ctrl');\n }\n if (shortcut.shiftKey) {\n parts.push('Shift');\n }\n if (shortcut.altKey) {\n parts.push(isMac ? 'Option' : 'Alt');\n }\n\n parts.push(shortcut.key.toUpperCase());\n\n return `${parts.join('+')} - ${shortcut.description}`;\n}\n\n/**\n * Register keyboard shortcuts with announcements\n * @param shortcuts - Array of keyboard shortcuts\n * @param container - Container element to attach listeners\n * @returns Cleanup function\n */\nexport function registerKeyboardShortcuts(\n shortcuts: KeyboardShortcut[],\n container: HTMLElement\n): () => void {\n const handleKeyDown = (event: KeyboardEvent): void => {\n for (const shortcut of shortcuts) {\n const ctrlMatch = shortcut.ctrlKey ? event.ctrlKey : true;\n const metaMatch = shortcut.metaKey ? event.metaKey : true;\n const shiftMatch = shortcut.shiftKey ? event.shiftKey : !event.shiftKey;\n const altMatch = shortcut.altKey ? event.altKey : !event.altKey;\n\n if (\n event.key.toLowerCase() === shortcut.key.toLowerCase() &&\n ctrlMatch &&\n metaMatch &&\n shiftMatch &&\n altMatch\n ) {\n event.preventDefault();\n shortcut.action();\n announceToScreenReader(shortcut.description);\n break;\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n };\n}\n\n/**\n * Set ARIA attributes for an element\n * @param element - Element to update\n * @param attributes - ARIA attributes\n */\nexport function setAriaAttributes(\n element: HTMLElement,\n attributes: Record<string, string | boolean | number>\n): void {\n for (const [key, value] of Object.entries(attributes)) {\n const attrName = key.startsWith('aria-') ? key : `aria-${key}`;\n element.setAttribute(attrName, String(value));\n }\n}\n\n/**\n * Create a visually hidden element (accessible to screen readers)\n * @param text - Text content\n * @returns Visually hidden element\n */\nexport function createVisuallyHidden(text: string): HTMLElement {\n const element = document.createElement('span');\n element.textContent = text;\n element.style.position = 'absolute';\n element.style.left = '-10000px';\n element.style.width = '1px';\n element.style.height = '1px';\n element.style.overflow = 'hidden';\n element.setAttribute('aria-hidden', 'false');\n return element;\n}\n\n/**\n * Update ARIA live region\n * @param id - Live region ID\n * @param message - Message to announce\n * @param politeness - Politeness level\n */\nexport function updateAriaLive(\n id: string,\n message: string,\n politeness: AriaLive = 'polite'\n): void {\n let liveRegion = document.getElementById(id);\n\n if (!liveRegion) {\n liveRegion = document.createElement('div');\n liveRegion.id = id;\n liveRegion.setAttribute('role', 'status');\n liveRegion.setAttribute('aria-live', politeness);\n liveRegion.setAttribute('aria-atomic', 'true');\n liveRegion.style.position = 'absolute';\n liveRegion.style.left = '-10000px';\n liveRegion.style.width = '1px';\n liveRegion.style.height = '1px';\n liveRegion.style.overflow = 'hidden';\n document.body.appendChild(liveRegion);\n }\n\n liveRegion.textContent = message;\n}\n\n/**\n * Check if reduced motion is preferred\n * @returns True if reduced motion is preferred\n */\nexport function prefersReducedMotion(): boolean {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Check if high contrast is enabled\n * @returns True if high contrast is enabled\n */\nexport function prefersHighContrast(): boolean {\n return window.matchMedia('(prefers-contrast: high)').matches;\n}\n\n/**\n * Get accessible color contrast ratio\n * @param foreground - Foreground color (hex)\n * @param background - Background color (hex)\n * @returns Contrast ratio\n */\nexport function getContrastRatio(foreground: string, background: string): number {\n const getLuminance = (color: string): number => {\n const rgb = parseInt(color.slice(1), 16);\n const r = ((rgb >> 16) & 0xff) / 255;\n const g = ((rgb >> 8) & 0xff) / 255;\n const b = (rgb & 0xff) / 255;\n\n const [rs, gs, bs] = [r, g, b].map(c => {\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n });\n\n return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;\n };\n\n const l1 = getLuminance(foreground);\n const l2 = getLuminance(background);\n\n const lighter = Math.max(l1, l2);\n const darker = Math.min(l1, l2);\n\n return (lighter + 0.05) / (darker + 0.05);\n}\n","/**\n * NotectlEditor Web Component\n * Framework-agnostic rich text editor\n */\n\nimport { EditorState } from '../state/EditorState.js';\nimport { PluginManager } from '../plugins/PluginManager.js';\nimport type { Plugin, PluginContext, CommandHandler } from '../plugins/Plugin.js';\nimport type { Delta } from '../delta/Delta.js';\nimport type { EditorConfig, EditorEvent, EditorEventCallback, Document } from '../types/index.js';\nimport { createDefaultSchema } from '../schema/Schema.js';\nimport { sanitizeHTML, sanitizeContent, validateDelta } from '../utils/security.js';\nimport {\n announceToScreenReader,\n registerKeyboardShortcuts,\n setAriaAttributes,\n type KeyboardShortcut\n} from '../utils/accessibility.js';\n\n/**\n * NotectlEditor custom element\n */\nexport class NotectlEditor extends HTMLElement {\n private state: EditorState;\n private pluginManager: PluginManager;\n private eventListeners: Map<string, Set<EditorEventCallback>> = new Map();\n private commands: Map<string, CommandHandler> = new Map();\n private contentElement: HTMLDivElement | null = null;\n private pluginContainerTop: HTMLDivElement | null = null;\n private pluginContainerBottom: HTMLDivElement | null = null;\n private config: EditorConfig;\n private keyboardShortcutCleanup?: () => void;\n private ariaLiveRegion: HTMLDivElement | null = null;\n\n // Plugin queue system for pre-mount registration\n private pendingPlugins: Plugin[] = [];\n private readyPromise: Promise<void>;\n private readyResolve?: () => void;\n private isReady: boolean = false;\n\n constructor() {\n super();\n\n // Default config\n this.config = {\n placeholder: 'Start typing...',\n readonly: false,\n autofocus: false,\n sanitizeHTML: true,\n maxHistoryDepth: 100,\n };\n\n // Initialize state\n const schema = createDefaultSchema();\n this.state = new EditorState(undefined, schema, {\n maxHistoryDepth: this.config.maxHistoryDepth,\n });\n\n // Initialize plugin manager\n this.pluginManager = new PluginManager();\n\n // Initialize ready promise\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n // Attach shadow DOM\n this.attachShadow({ mode: 'open' });\n }\n\n /**\n * Observed attributes for the web component\n */\n static get observedAttributes(): string[] {\n return ['placeholder', 'readonly', 'autofocus'];\n }\n\n /**\n * Called when element is connected to DOM\n */\n async connectedCallback(): Promise<void> {\n this.render();\n this.attachEventListeners();\n this.setupAccessibility();\n this.setupKeyboardShortcuts();\n\n // Mark editor as ready\n this.isReady = true;\n\n // Process pending plugins that were registered before mounting\n if (this.pendingPlugins.length > 0) {\n const plugins = [...this.pendingPlugins];\n this.pendingPlugins = [];\n\n for (const plugin of plugins) {\n try {\n await this.pluginManager.register(plugin, this.createPluginContext());\n } catch (error) {\n console.error(`Failed to register pending plugin ${plugin.id}:`, error);\n }\n }\n }\n\n // Resolve the ready promise\n if (this.readyResolve) {\n this.readyResolve();\n }\n\n // Emit ready event\n this.emit('ready', { editor: this });\n\n if (this.config.autofocus) {\n this.focus();\n }\n }\n\n /**\n * Called when element is disconnected from DOM\n */\n disconnectedCallback(): void {\n this.detachEventListeners();\n this.pluginManager.destroyAll();\n if (this.keyboardShortcutCleanup) {\n this.keyboardShortcutCleanup();\n }\n if (this.ariaLiveRegion && this.ariaLiveRegion.parentNode) {\n this.ariaLiveRegion.parentNode.removeChild(this.ariaLiveRegion);\n }\n\n // Reset ready state for potential re-mounting\n this.isReady = false;\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n }\n\n /**\n * Called when attributes change\n */\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n switch (name) {\n case 'placeholder':\n this.config.placeholder = newValue || '';\n this.updatePlaceholder();\n break;\n case 'readonly':\n this.config.readonly = newValue !== null;\n this.updateReadonly();\n break;\n case 'autofocus':\n this.config.autofocus = newValue !== null;\n break;\n }\n }\n\n /**\n * Render the editor UI\n */\n private render(): void {\n if (!this.shadowRoot) return;\n\n this.shadowRoot.innerHTML = `\n <style>\n :host {\n display: block;\n position: relative;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 16px;\n line-height: 1.5;\n }\n\n .notectl-container {\n display: flex;\n flex-direction: column;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: white;\n }\n\n .notectl-plugin-container {\n display: block;\n background: transparent;\n }\n\n .notectl-plugin-container[data-position=\"top\"] {\n order: -1;\n }\n\n .notectl-plugin-container[data-position=\"bottom\"] {\n order: 1;\n }\n\n .notectl-editor-wrapper {\n position: relative;\n flex: 1;\n }\n\n .notectl-editor {\n min-height: 200px;\n padding: 1rem;\n outline: none;\n background: white;\n }\n\n .notectl-container:focus-within {\n border-color: #2196F3;\n box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.1);\n }\n\n .notectl-editor[data-readonly=\"true\"] {\n background: #f5f5f5;\n cursor: not-allowed;\n }\n\n .notectl-editor table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .notectl-editor table td,\n .notectl-editor table th {\n border: 1px solid #ddd;\n padding: 8px;\n min-width: 100px;\n }\n\n .notectl-placeholder {\n position: absolute;\n top: 1rem;\n left: 1rem;\n color: #9e9e9e;\n pointer-events: none;\n user-select: none;\n }\n\n .notectl-placeholder.hidden {\n display: none;\n }\n\n .visually-hidden {\n position: absolute;\n left: -10000px;\n width: 1px;\n height: 1px;\n overflow: hidden;\n }\n </style>\n\n <div class=\"notectl-container\">\n <div class=\"notectl-plugin-container\" data-position=\"top\"></div>\n <div class=\"notectl-editor-wrapper\">\n <div class=\"notectl-placeholder\" aria-hidden=\"true\">${this.config.placeholder}</div>\n <div\n class=\"notectl-editor\"\n contenteditable=\"${!this.config.readonly}\"\n data-readonly=\"${this.config.readonly}\"\n role=\"textbox\"\n aria-label=\"Rich text editor\"\n aria-multiline=\"true\"\n aria-describedby=\"notectl-help-text\"\n tabindex=\"0\"\n ></div>\n </div>\n <div class=\"notectl-plugin-container\" data-position=\"bottom\"></div>\n </div>\n <div id=\"notectl-help-text\" class=\"visually-hidden\">\n Use arrow keys to navigate. Press Ctrl+B for bold, Ctrl+I for italic, Ctrl+U for underline.\n Press Ctrl+Z to undo, Ctrl+Shift+Z to redo.\n </div>\n <div id=\"notectl-aria-live\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"visually-hidden\"></div>\n `;\n\n this.contentElement = this.shadowRoot.querySelector('.notectl-editor');\n this.pluginContainerTop = this.shadowRoot.querySelector('.notectl-plugin-container[data-position=\"top\"]');\n this.pluginContainerBottom = this.shadowRoot.querySelector('.notectl-plugin-container[data-position=\"bottom\"]');\n this.ariaLiveRegion = this.shadowRoot.querySelector('#notectl-aria-live');\n this.renderContent();\n }\n\n /**\n * Render document content\n */\n private renderContent(): void {\n if (!this.contentElement) return;\n\n const doc = this.state.getDocument();\n const html = this.documentToHTML(doc);\n\n // Sanitize HTML before rendering\n this.contentElement.innerHTML = this.config.sanitizeHTML\n ? sanitizeHTML(html)\n : html;\n }\n\n /**\n * Convert document to HTML\n */\n private documentToHTML(doc: Document): string {\n return doc.children.map((block) => this.blockToHTML(block)).join('');\n }\n\n /**\n * Convert block to HTML (simplified)\n */\n private blockToHTML(block: any): string {\n switch (block.type) {\n case 'paragraph':\n return `<p>${this.childrenToHTML(block.children || [])}</p>`;\n case 'heading':\n const level = block.attrs?.level || 1;\n return `<h${level}>${this.childrenToHTML(block.children || [])}</h${level}>`;\n case 'table':\n return this.tableToHTML(block);\n default:\n return `<div>${this.childrenToHTML(block.children || [])}</div>`;\n }\n }\n\n /**\n * Convert children to HTML\n */\n private childrenToHTML(children: any[]): string {\n return children\n .map((child) => {\n if (child.type === 'text') {\n let html = this.escapeHTML(child.text);\n if (child.marks) {\n for (const mark of child.marks) {\n html = this.applyMarkHTML(html, mark);\n }\n }\n return html;\n }\n return this.blockToHTML(child);\n })\n .join('');\n }\n\n /**\n * Apply mark as HTML\n */\n private applyMarkHTML(text: string, mark: any): string {\n switch (mark.type) {\n case 'bold':\n return `<strong>${text}</strong>`;\n case 'italic':\n return `<em>${text}</em>`;\n case 'underline':\n return `<u>${text}</u>`;\n case 'strikethrough':\n return `<s>${text}</s>`;\n case 'code':\n return `<code>${text}</code>`;\n default:\n return text;\n }\n }\n\n /**\n * Escape HTML\n */\n private escapeHTML(text: string): string {\n if (!this.config.sanitizeHTML) return text;\n\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n private tableToHTML(block: any): string {\n const tableData = block.attrs?.table;\n const tableId = block.id || crypto.randomUUID();\n const attrParts: string[] = [\n 'data-node-type=\"table\"',\n `data-block-id=\"${tableId}\"`,\n ];\n\n if (block.attrs?.style) {\n const styleString = this.styleObjectToString(block.attrs.style);\n if (styleString) {\n attrParts.push(`style=\"${styleString}\"`);\n }\n }\n\n let bodyHTML = '';\n const rows = Array.isArray(tableData?.rows) ? tableData.rows : [];\n\n if (rows.length === 0) {\n const fallbackCellId = crypto.randomUUID();\n const fallbackRowId = crypto.randomUUID();\n bodyHTML = `\n <tr data-node-type=\"table_row\" data-row=\"0\" data-block-id=\"${fallbackRowId}\">\n <td data-node-type=\"table_cell\" data-row=\"0\" data-col=\"0\" data-block-id=\"${fallbackCellId}\"><br></td>\n </tr>\n `;\n } else {\n bodyHTML = rows\n .map((row: any, rowIndex: number) => this.tableRowToHTML(row, rowIndex))\n .join('');\n }\n\n return `<table ${attrParts.join(' ')}><tbody>${bodyHTML}</tbody></table>`;\n }\n\n private tableRowToHTML(row: any, rowIndex: number): string {\n const rowId = row.id || crypto.randomUUID();\n const attrs: string[] = [\n 'data-node-type=\"table_row\"',\n `data-row=\"${rowIndex}\"`,\n `data-block-id=\"${rowId}\"`,\n ];\n\n if (row.attrs?.style) {\n const style = this.styleObjectToString(row.attrs.style);\n if (style) {\n attrs.push(`style=\"${style}\"`);\n }\n }\n\n const cells = Array.isArray(row.cells) ? row.cells : [];\n\n const cellsHTML = cells\n .map((cell: any, colIndex: number) => this.tableCellToHTML(cell, rowIndex, colIndex))\n .join('');\n\n return `<tr ${attrs.join(' ')}>${cellsHTML}</tr>`;\n }\n\n private tableCellToHTML(cell: any, rowIndex: number, colIndex: number): string {\n const cellId = cell.id || crypto.randomUUID();\n const attrs: string[] = [\n 'data-node-type=\"table_cell\"',\n `data-row=\"${rowIndex}\"`,\n `data-col=\"${colIndex}\"`,\n `data-block-id=\"${cellId}\"`,\n ];\n\n const rowSpan = Number(cell.rowSpan) || 1;\n const colSpan = Number(cell.colSpan) || 1;\n if (rowSpan > 1) {\n attrs.push(`rowspan=\"${rowSpan}\"`);\n }\n if (colSpan > 1) {\n attrs.push(`colspan=\"${colSpan}\"`);\n }\n\n if (cell.attrs?.style) {\n const style = this.styleObjectToString(cell.attrs.style);\n if (style) {\n attrs.push(`style=\"${style}\"`);\n }\n }\n\n const content = typeof cell.content === 'string' ? this.escapeHTML(cell.content) : '';\n const inner = content || '<br>';\n\n return `<td ${attrs.join(' ')}>${inner}</td>`;\n }\n\n private styleObjectToString(style: Record<string, unknown>): string {\n return Object.entries(style)\n .map(([key, value]) => {\n if (value === undefined || value === null || value === '') {\n return null;\n }\n const cssKey = key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\n return `${cssKey}: ${String(value)}`;\n })\n .filter(Boolean)\n .join('; ');\n }\n\n /**\n * Setup accessibility features\n */\n private setupAccessibility(): void {\n if (!this.contentElement) return;\n\n // Set comprehensive ARIA attributes\n setAriaAttributes(this.contentElement, {\n 'role': 'textbox',\n 'aria-multiline': true,\n 'aria-label': 'Rich text editor',\n 'aria-describedby': 'notectl-help-text',\n 'aria-autocomplete': 'none'\n });\n\n // Update ARIA attributes based on readonly state\n if (this.config.readonly) {\n this.contentElement.setAttribute('aria-readonly', 'true');\n }\n }\n\n /**\n * Setup keyboard shortcuts with screen reader announcements\n */\n private setupKeyboardShortcuts(): void {\n if (!this.contentElement) return;\n\n const shortcuts: KeyboardShortcut[] = [\n {\n key: 'b',\n ctrlKey: true,\n description: 'Bold formatting applied',\n action: () => this.toggleFormat('bold')\n },\n {\n key: 'i',\n ctrlKey: true,\n description: 'Italic formatting applied',\n action: () => this.toggleFormat('italic')\n },\n {\n key: 'u',\n ctrlKey: true,\n description: 'Underline formatting applied',\n action: () => this.toggleFormat('underline')\n },\n {\n key: 'z',\n ctrlKey: true,\n description: 'Action undone',\n action: () => this.undo()\n },\n {\n key: 'z',\n ctrlKey: true,\n shiftKey: true,\n description: 'Action redone',\n action: () => this.redo()\n }\n ];\n\n this.keyboardShortcutCleanup = registerKeyboardShortcuts(shortcuts, this.contentElement);\n }\n\n /**\n * Toggle formatting\n */\n private toggleFormat(format: string): void {\n // Get current selection\n const selection = window.getSelection();\n if (!selection || !this.contentElement) return;\n\n // Apply formatting via execCommand (will be replaced with Delta operations)\n try {\n switch (format) {\n case 'bold':\n document.execCommand('bold', false);\n break;\n case 'italic':\n document.execCommand('italic', false);\n break;\n case 'underline':\n document.execCommand('underline', false);\n break;\n case 'strikethrough':\n document.execCommand('strikeThrough', false);\n break;\n case 'code':\n // Wrap selection in <code> tag\n const code = document.createElement('code');\n if (selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n code.appendChild(range.extractContents());\n range.insertNode(code);\n }\n break;\n }\n\n this.announceToScreenReader(`${format} formatting applied`);\n this.emit('change', { state: this.state });\n } catch (error) {\n console.error(`Failed to apply ${format} formatting:`, error);\n this.announceToScreenReader(`Failed to apply ${format} formatting`);\n }\n }\n\n /**\n * Insert table at current selection\n */\n insertTable(rows: number = 3, cols: number = 3): void {\n if (!this.contentElement) return;\n\n try {\n // Focus the editor if not already focused\n this.contentElement.focus();\n\n // Create table element\n const table = document.createElement('table');\n table.setAttribute('data-notectl-table', 'true');\n\n // Create tbody\n const tbody = document.createElement('tbody');\n\n // Generate rows - all cells are equal, user can style as needed\n for (let i = 0; i < rows; i++) {\n const tr = document.createElement('tr');\n\n for (let j = 0; j < cols; j++) {\n const cell = document.createElement('td');\n cell.textContent = ''; // Empty cells - user fills them\n tr.appendChild(cell);\n }\n\n tbody.appendChild(tr);\n }\n\n table.appendChild(tbody);\n\n // Get the current selection\n const selection = window.getSelection();\n let insertPosition = this.contentElement.childNodes.length;\n\n // Try to find the cursor position\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n\n // Check if the range is inside contentElement\n if (this.contentElement.contains(range.commonAncestorContainer)) {\n // Find the position in childNodes\n let node = range.startContainer;\n\n // If it's a text node, get its parent\n if (node.nodeType === Node.TEXT_NODE) {\n node = node.parentNode as Node;\n }\n\n // Find position among contentElement's children\n if (node === this.contentElement) {\n insertPosition = range.startOffset;\n } else {\n // Find the index of the node or its ancestor\n let child = node;\n while (child.parentNode && child.parentNode !== this.contentElement) {\n child = child.parentNode;\n }\n if (child.parentNode === this.contentElement) {\n insertPosition = Array.from(this.contentElement.childNodes).indexOf(child as ChildNode) + 1;\n }\n }\n }\n }\n\n // Add a paragraph after the table\n const p = document.createElement('p');\n p.innerHTML = '<br>';\n\n // Insert at the correct position\n if (insertPosition >= this.contentElement.childNodes.length) {\n this.contentElement.appendChild(table);\n this.contentElement.appendChild(p);\n } else {\n const refNode = this.contentElement.childNodes[insertPosition];\n this.contentElement.insertBefore(table, refNode);\n this.contentElement.insertBefore(p, refNode);\n }\n\n // Set cursor in the new paragraph\n if (selection) {\n const range = document.createRange();\n range.setStart(p, 0);\n range.setEnd(p, 0);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n // Update placeholder visibility (content is no longer empty)\n this.updatePlaceholder();\n\n // Force sync to state\n this.syncContentToState();\n\n this.announceToScreenReader(`Table with ${rows} rows and ${cols} columns inserted`);\n this.emit('change', { state: this.state });\n } catch (error) {\n console.error('Failed to insert table:', error);\n this.announceToScreenReader('Failed to insert table');\n }\n }\n\n /**\n * Announce message to screen readers\n */\n private announceToScreenReader(message: string): void {\n if (this.ariaLiveRegion) {\n this.ariaLiveRegion.textContent = '';\n setTimeout(() => {\n if (this.ariaLiveRegion) {\n this.ariaLiveRegion.textContent = message;\n }\n }, 100);\n } else {\n announceToScreenReader(message);\n }\n }\n\n /**\n * Attach event listeners\n */\n private attachEventListeners(): void {\n if (!this.contentElement) return;\n\n this.contentElement.addEventListener('input', this.handleInput);\n this.contentElement.addEventListener('keydown', this.handleKeydown);\n this.contentElement.addEventListener('focus', this.handleFocus);\n this.contentElement.addEventListener('blur', this.handleBlur);\n this.contentElement.addEventListener('contextmenu', this.handleContextMenu);\n }\n\n /**\n * Detach event listeners\n */\n private detachEventListeners(): void {\n if (!this.contentElement) return;\n\n this.contentElement.removeEventListener('input', this.handleInput);\n this.contentElement.removeEventListener('keydown', this.handleKeydown);\n this.contentElement.removeEventListener('focus', this.handleFocus);\n this.contentElement.removeEventListener('blur', this.handleBlur);\n this.contentElement.removeEventListener('contextmenu', this.handleContextMenu);\n }\n\n /**\n * Handle input event\n */\n private handleInput = (event: Event): void => {\n this.updatePlaceholder();\n\n // Skip syncing if input originates inside a managed table to avoid\n // clobbering the plugin-driven document state until table syncing is\n // fully implemented.\n const target = event.target as HTMLElement | null;\n if (!target?.closest('[data-node-type=\"table\"]')) {\n this.syncContentToState();\n }\n\n this.emit('change', { state: this.state });\n };\n\n /**\n * Handle keydown event\n */\n private handleKeydown = (event: KeyboardEvent): void => {\n this.emit('keydown', event);\n if (event.defaultPrevented) {\n return;\n }\n\n // Handle undo/redo\n if ((event.ctrlKey || event.metaKey) && event.key === 'z') {\n event.preventDefault();\n if (event.shiftKey) {\n this.redo();\n this.announceToScreenReader('Action redone');\n } else {\n this.undo();\n this.announceToScreenReader('Action undone');\n }\n }\n\n // Announce navigation\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {\n if (event.ctrlKey || event.metaKey) {\n this.announceToScreenReader(`Navigating ${event.key.replace('Arrow', '').toLowerCase()}`);\n }\n }\n };\n\n /**\n * Handle focus event\n */\n private handleFocus = (): void => {\n this.emit('focus', { state: this.state });\n };\n\n /**\n * Handle blur event\n */\n private handleBlur = (): void => {\n this.emit('blur', { state: this.state });\n };\n\n private handleContextMenu = (event: MouseEvent): void => {\n this.emit('contextmenu', event);\n };\n\n /**\n * Update placeholder visibility\n */\n private updatePlaceholder(): void {\n if (!this.shadowRoot) return;\n\n const placeholder = this.shadowRoot.querySelector('.notectl-placeholder');\n const isEmpty = !this.contentElement?.textContent?.trim();\n\n if (placeholder) {\n placeholder.classList.toggle('hidden', !isEmpty);\n }\n }\n\n /**\n * Sync content from DOM to state\n */\n private syncContentToState(): void {\n if (!this.contentElement) return;\n\n try {\n const doc = this.htmlToDocument(this.contentElement.innerHTML);\n this.state = EditorState.fromJSON(doc, this.state.schema);\n } catch (error) {\n console.error('Failed to sync content to state:', error);\n }\n }\n\n /**\n * Convert HTML to document structure\n */\n private htmlToDocument(html: string): Document {\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n const body = doc.body;\n\n const children: any[] = [];\n\n // Parse child nodes\n Array.from(body.childNodes).forEach((node) => {\n const block = this.nodeToBlock(node);\n if (block) {\n children.push(block);\n }\n });\n\n // If no children, create empty paragraph\n if (children.length === 0) {\n children.push({\n id: crypto.randomUUID(),\n type: 'paragraph',\n children: [],\n });\n }\n\n return {\n version: this.state.getDocument().version + 1,\n schemaVersion: '1.0.0',\n children,\n };\n }\n\n /**\n * Convert DOM node to block\n */\n private nodeToBlock(node: Node): any {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n if (!text.trim()) return null;\n return {\n type: 'text',\n text,\n marks: [],\n };\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n\n // Block elements\n if (tagName === 'p') {\n return {\n id: crypto.randomUUID(),\n type: 'paragraph',\n children: this.parseChildren(element),\n };\n }\n\n if (['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tagName)) {\n const level = parseInt(tagName.charAt(1), 10);\n return {\n id: crypto.randomUUID(),\n type: 'heading',\n attrs: { level },\n children: this.parseChildren(element),\n };\n }\n\n // Inline elements - extract text with marks\n return this.parseInlineElement(element);\n }\n\n return null;\n }\n\n /**\n * Parse children nodes\n */\n private parseChildren(element: Element): any[] {\n const children: any[] = [];\n\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n if (text) {\n children.push({\n type: 'text',\n text,\n marks: [],\n });\n }\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const childElement = node as Element;\n const result = this.parseInlineElement(childElement);\n if (result) {\n if (Array.isArray(result)) {\n children.push(...result);\n } else {\n children.push(result);\n }\n }\n }\n });\n\n return children;\n }\n\n /**\n * Parse inline element with marks\n */\n private parseInlineElement(element: Element): any {\n const tagName = element.tagName.toLowerCase();\n const marks: any[] = [];\n\n // Determine mark type\n if (tagName === 'strong' || tagName === 'b') {\n marks.push({ type: 'bold' });\n } else if (tagName === 'em' || tagName === 'i') {\n marks.push({ type: 'italic' });\n } else if (tagName === 'u') {\n marks.push({ type: 'underline' });\n } else if (tagName === 's' || tagName === 'strike') {\n marks.push({ type: 'strikethrough' });\n } else if (tagName === 'code') {\n marks.push({ type: 'code' });\n }\n\n // Get text content and nested marks\n const children: any[] = [];\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n if (text) {\n children.push({\n type: 'text',\n text,\n marks,\n });\n }\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const childElement = node as Element;\n const childResult = this.parseInlineElement(childElement);\n if (childResult) {\n // Merge marks\n if (childResult.type === 'text') {\n childResult.marks = [...marks, ...(childResult.marks || [])];\n children.push(childResult);\n } else if (Array.isArray(childResult)) {\n childResult.forEach((item: any) => {\n if (item.type === 'text') {\n item.marks = [...marks, ...(item.marks || [])];\n }\n children.push(item);\n });\n }\n }\n }\n });\n\n return children.length === 1 ? children[0] : children;\n }\n\n /**\n * Update readonly state\n */\n private updateReadonly(): void {\n if (this.contentElement) {\n this.contentElement.contentEditable = String(!this.config.readonly);\n this.contentElement.setAttribute('data-readonly', String(this.config.readonly));\n }\n }\n\n /**\n * Register a plugin\n *\n * Plugins can be registered before or after the editor is mounted.\n * If registered before mounting, they will be queued and initialized\n * automatically when the editor connects to the DOM.\n *\n * @param plugin - The plugin to register\n * @returns Promise that resolves when the plugin is registered\n */\n async registerPlugin(plugin: Plugin): Promise<void> {\n // If editor is not yet connected to DOM, queue the plugin\n if (!this.isReady) {\n this.pendingPlugins.push(plugin);\n return;\n }\n\n // Editor is ready, register immediately\n const context = this.createPluginContext();\n await this.pluginManager.register(plugin, context);\n }\n\n /**\n * Unregister a plugin\n */\n async unregisterPlugin(pluginId: string): Promise<void> {\n const context = this.createPluginContext();\n await this.pluginManager.unregister(pluginId, context);\n }\n\n /**\n * Wait for the editor to be ready\n *\n * Returns a Promise that resolves when the editor has been mounted\n * and all pending plugins have been initialized. This is useful when\n * you need to ensure the editor is fully initialized before performing\n * operations that depend on the editor being mounted.\n *\n * @returns Promise that resolves when the editor is ready\n * @example\n * ```typescript\n * const editor = document.createElement('notectl-editor');\n * container.appendChild(editor);\n * await editor.whenReady();\n * // Editor is now fully initialized\n * ```\n */\n async whenReady(): Promise<void> {\n return this.readyPromise;\n }\n\n // ===== Plugin Context Helper Methods =====\n\n /**\n * Get the block containing the current selection\n */\n private getSelectedBlock(): import('../types/index.js').BlockNode | null {\n const selection = this.state.getSelection();\n if (!selection) return null;\n\n return this.state.findBlock(selection.anchor.blockId) || null;\n }\n\n /**\n * Find all blocks of a specific type\n */\n private findBlocksByType(type: string): import('../types/index.js').BlockNode[] {\n const results: import('../types/index.js').BlockNode[] = [];\n const doc = this.state.getDocument();\n\n const search = (nodes: import('../types/index.js').BlockNode[]): void => {\n for (const node of nodes) {\n if (node.type === type) {\n results.push(node);\n }\n if (node.children) {\n const blockChildren = node.children.filter(\n (n): n is import('../types/index.js').BlockNode => 'id' in n\n );\n search(blockChildren);\n }\n }\n };\n\n search(doc.children);\n return results;\n }\n\n /**\n * Find parent block of a given block\n */\n private findParentBlock(block: import('../types/index.js').BlockNode): import('../types/index.js').BlockNode | null {\n const doc = this.state.getDocument();\n\n const search = (\n nodes: import('../types/index.js').BlockNode[],\n parent: import('../types/index.js').BlockNode | null = null\n ): import('../types/index.js').BlockNode | null => {\n for (const node of nodes) {\n if (node.id === block.id) {\n return parent;\n }\n if (node.children) {\n const blockChildren = node.children.filter(\n (n): n is import('../types/index.js').BlockNode => 'id' in n\n );\n const found = search(blockChildren, node);\n if (found) return found;\n }\n }\n return null;\n };\n\n return search(doc.children);\n }\n\n /**\n * Get block at current cursor position\n */\n private getBlockAtCursor(): import('../types/index.js').BlockNode | null {\n return this.getSelectedBlock();\n }\n\n /**\n * Insert a block after another block (Delta-based)\n */\n private insertBlockAfter(block: import('../types/index.js').BlockNode, afterId?: import('../types/index.js').BlockId): void {\n const doc = this.state.getDocument();\n const targetId = afterId || (doc.children[doc.children.length - 1]?.id);\n\n if (!targetId) {\n // Document is empty, just add the block\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'edit',\n ops: [\n {\n op: 'insert_block_after',\n after: '',\n block,\n },\n ],\n };\n this.applyDelta(delta);\n return;\n }\n\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'edit',\n ops: [\n {\n op: 'insert_block_after',\n after: targetId,\n block,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Insert a block before another block (Delta-based)\n */\n private insertBlockBefore(block: import('../types/index.js').BlockNode, beforeId?: import('../types/index.js').BlockId): void {\n const doc = this.state.getDocument();\n const targetId = beforeId || doc.children[0]?.id;\n\n if (!targetId) {\n // Document is empty, just add the block\n this.insertBlockAfter(block);\n return;\n }\n\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'edit',\n ops: [\n {\n op: 'insert_block_before',\n before: targetId,\n block,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Update block attributes (Delta-based)\n */\n private updateBlockAttrs(blockId: import('../types/index.js').BlockId, attrs: Record<string, unknown>): void {\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'edit',\n ops: [\n {\n op: 'set_attrs',\n target: { blockId },\n attrs,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Delete a block (Delta-based)\n */\n private deleteBlockById(blockId: import('../types/index.js').BlockId): void {\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'edit',\n ops: [\n {\n op: 'delete_block',\n target: { blockId },\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Add mark to current selection (Delta-based)\n */\n private addMarkToSelection(mark: import('../types/index.js').Mark): void {\n const selection = this.state.getSelection();\n if (!selection) return;\n\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'format',\n ops: [\n {\n op: 'apply_mark',\n range: {\n start: selection.anchor,\n end: selection.head,\n },\n mark,\n add: true,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Remove mark from current selection (Delta-based)\n */\n private removeMarkFromSelection(markType: string): void {\n const selection = this.state.getSelection();\n if (!selection) return;\n\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'format',\n ops: [\n {\n op: 'apply_mark',\n range: {\n start: selection.anchor,\n end: selection.head,\n },\n mark: { type: markType },\n add: false,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Toggle mark on current selection (Delta-based)\n */\n private toggleMarkOnSelection(markType: string): void {\n const selection = this.state.getSelection();\n if (!selection) return;\n\n const block = this.state.findBlock(selection.anchor.blockId);\n if (!block || !block.children) return;\n\n // Check if mark already exists in selection\n const textNode = block.children.find((n): n is import('../types/index.js').TextNode => 'text' in n);\n const hasMark = textNode?.marks?.some((m) => m.type === markType) || false;\n\n const delta: Delta = {\n txnId: crypto.randomUUID(),\n clientId: 'editor',\n timestamp: new Date().toISOString(),\n baseVersion: this.state.getVersion(),\n ltime: Date.now(),\n intent: 'format',\n ops: [\n {\n op: 'apply_mark',\n range: {\n start: selection.anchor,\n end: selection.head,\n },\n mark: { type: markType },\n add: !hasMark,\n },\n ],\n };\n\n this.applyDelta(delta);\n }\n\n /**\n * Create plugin context\n */\n private createPluginContext(): PluginContext {\n return {\n // Core state and delta operations\n getState: () => this.state,\n applyDelta: (delta: Delta) => this.applyDelta(delta),\n\n // Selection helpers\n getSelection: () => this.state.getSelection(),\n setSelection: (selection) => {\n this.state.setSelection(selection);\n this.emit('selection-change', { selection });\n },\n getSelectedBlock: () => this.getSelectedBlock(),\n\n // Node queries\n findBlocksByType: (type: string) => this.findBlocksByType(type),\n findBlockById: (blockId) => this.state.findBlock(blockId),\n findParentBlock: (block) => this.findParentBlock(block),\n getBlockAtCursor: () => this.getBlockAtCursor(),\n\n // Block mutations\n insertBlockAfter: (block, afterId) => this.insertBlockAfter(block, afterId),\n insertBlockBefore: (block, beforeId) => this.insertBlockBefore(block, beforeId),\n updateBlockAttrs: (blockId, attrs) => this.updateBlockAttrs(blockId, attrs),\n deleteBlock: (blockId) => this.deleteBlockById(blockId),\n\n // Mark utilities\n addMark: (mark) => this.addMarkToSelection(mark),\n removeMark: (markType) => this.removeMarkFromSelection(markType),\n toggleMark: (markType) => this.toggleMarkOnSelection(markType),\n\n // Events\n on: (event: string, callback: (data: unknown) => void) => this.on(event as EditorEvent, callback),\n off: (event: string, callback: (data: unknown) => void) => this.off(event as EditorEvent, callback),\n emit: (event: string, data?: unknown) => this.emit(event, data),\n\n // Commands\n registerCommand: (name: string, handler: CommandHandler) => this.registerCommand(name, handler),\n executeCommand: (name: string, ...args: unknown[]) => this.executeCommand(name, ...args),\n\n // DOM access (deprecated)\n getContainer: () => this.contentElement!,\n getPluginContainer: (position: 'top' | 'bottom') => {\n if (position === 'top') {\n return this.pluginContainerTop!;\n }\n return this.pluginContainerBottom!;\n },\n };\n }\n\n /**\n * Apply a delta\n */\n applyDelta(delta: Delta): void {\n // Validate delta for security\n if (!validateDelta(delta)) {\n console.error('Invalid or unsafe delta rejected');\n this.announceToScreenReader('Action blocked due to security validation');\n return;\n }\n\n this.state.applyDelta(delta);\n this.renderContent();\n this.pluginManager.notifyDeltaApplied(delta);\n this.emit('change', { delta, state: this.state });\n }\n\n /**\n * Register event listener\n */\n on(event: EditorEvent, callback: EditorEventCallback): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback);\n }\n\n /**\n * Unregister event listener\n */\n off(event: EditorEvent, callback: EditorEventCallback): void {\n this.eventListeners.get(event)?.delete(callback);\n }\n\n /**\n * Emit event\n */\n private emit(event: string, data?: unknown): void {\n this.eventListeners.get(event)?.forEach((callback) => {\n try {\n callback(data);\n } catch (error) {\n console.error(`Error in event listener for ${event}:`, error);\n }\n });\n }\n\n /**\n * Register command\n */\n registerCommand(name: string, handler: CommandHandler): void {\n this.commands.set(name, handler);\n }\n\n /**\n * Execute command\n */\n executeCommand(name: string, ...args: unknown[]): unknown {\n const handler = this.commands.get(name);\n if (!handler) {\n throw new Error(`Command not found: ${name}`);\n }\n return handler(...args);\n }\n\n /**\n * Undo last change\n */\n undo(): void {\n const undoDelta = this.state.undo();\n if (undoDelta) {\n this.renderContent();\n this.announceToScreenReader('Undo performed');\n this.emit('change', { delta: undoDelta, state: this.state });\n } else {\n this.announceToScreenReader('Nothing to undo');\n }\n }\n\n /**\n * Redo last undone change\n */\n redo(): void {\n const redoDelta = this.state.redo();\n if (redoDelta) {\n this.renderContent();\n this.announceToScreenReader('Redo performed');\n this.emit('change', { delta: redoDelta, state: this.state });\n } else {\n this.announceToScreenReader('Nothing to redo');\n }\n }\n\n /**\n * Configure editor options\n * @param config - Configuration options to apply\n */\n configure(config: EditorConfig): void {\n this.config = { ...this.config, ...config };\n\n // Apply configuration changes\n if (config.readonly !== undefined) {\n this.updateReadonly();\n }\n\n if (config.placeholder !== undefined && this.shadowRoot) {\n const placeholder = this.shadowRoot.querySelector('.notectl-placeholder');\n if (placeholder) {\n placeholder.textContent = config.placeholder;\n }\n }\n\n if (config.initialContent) {\n if (typeof config.initialContent === 'object') {\n this.setJSON(config.initialContent);\n }\n }\n\n if (config.content) {\n if (typeof config.content === 'string') {\n this.setContent(config.content);\n } else {\n this.setJSON(config.content as Document);\n }\n }\n }\n\n /**\n * Destroy the editor and clean up resources\n */\n destroy(): void {\n this.detachEventListeners();\n this.pluginManager.destroyAll();\n\n if (this.keyboardShortcutCleanup) {\n this.keyboardShortcutCleanup();\n }\n\n if (this.ariaLiveRegion && this.ariaLiveRegion.parentNode) {\n this.ariaLiveRegion.parentNode.removeChild(this.ariaLiveRegion);\n }\n\n this.eventListeners.clear();\n this.commands.clear();\n }\n\n /**\n * Get current content as string or JSON\n * @returns Current document content\n */\n getContent(): Document | string {\n return this.getJSON();\n }\n\n /**\n * Get current state\n */\n getState(): EditorState {\n return this.state;\n }\n\n /**\n * Get document as JSON\n */\n getJSON(): Document {\n return this.state.toJSON();\n }\n\n /**\n * Set document from JSON\n */\n setJSON(doc: Document): void {\n this.state = EditorState.fromJSON(doc, this.state.schema);\n this.renderContent();\n }\n\n /**\n * Get HTML content (sanitized)\n */\n getHTML(): string {\n const html = this.documentToHTML(this.state.getDocument());\n return this.config.sanitizeHTML ? sanitizeHTML(html) : html;\n }\n\n /**\n * Set HTML content (with sanitization)\n * @param html - HTML content to set\n */\n setHTML(html: string): void {\n const sanitized = this.config.sanitizeHTML ? sanitizeHTML(html) : html;\n if (this.contentElement) {\n this.contentElement.innerHTML = sanitized;\n this.announceToScreenReader('Content updated');\n }\n }\n\n /**\n * Set content from string (with sanitization)\n * @param content - Content to set\n * @param allowHTML - Allow HTML tags\n */\n setContent(content: string, allowHTML: boolean = true): void {\n const sanitized = this.config.sanitizeHTML\n ? sanitizeContent(content, allowHTML)\n : content;\n\n if (this.contentElement) {\n this.contentElement.innerHTML = sanitized;\n this.announceToScreenReader('Content updated');\n }\n }\n\n /**\n * Export HTML content (sanitized)\n * @returns Sanitized HTML\n */\n exportHTML(): string {\n return this.getHTML();\n }\n\n /**\n * Focus the editor\n */\n focus(): void {\n this.contentElement?.focus();\n }\n\n /**\n * Blur the editor\n */\n blur(): void {\n this.contentElement?.blur();\n }\n}\n\n/**\n * Register custom element\n */\nif (!customElements.get('notectl-editor')) {\n customElements.define('notectl-editor', NotectlEditor);\n}\n","/**\n * Plugin interface and types for Notectl\n */\n\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Delta } from '../delta/Delta.js';\nimport type { Selection, BlockNode, Mark, BlockId } from '../types/index.js';\n\n/**\n * Plugin context provided to plugins\n */\nexport interface PluginContext {\n // === Core State & Delta Operations ===\n\n /**\n * Get current editor state\n */\n getState(): EditorState;\n\n /**\n * Apply a delta to the editor\n */\n applyDelta(delta: Delta): void;\n\n // === Selection Helpers ===\n\n /**\n * Get current selection\n */\n getSelection(): Selection | null;\n\n /**\n * Set selection\n */\n setSelection(selection: Selection): void;\n\n /**\n * Get the block containing the current cursor/selection\n */\n getSelectedBlock(): BlockNode | null;\n\n // === Node Queries ===\n\n /**\n * Find all blocks of a specific type\n * @param type - Block type to search for (e.g., 'table', 'heading', 'paragraph')\n * @returns Array of matching blocks\n */\n findBlocksByType(type: string): BlockNode[];\n\n /**\n * Find a block by its ID\n * @param blockId - Block identifier\n * @returns Block or undefined if not found\n */\n findBlockById(blockId: BlockId): BlockNode | undefined;\n\n /**\n * Find parent block of a given block\n * @param block - Child block\n * @returns Parent block or null if block is at root level\n */\n findParentBlock(block: BlockNode): BlockNode | null;\n\n /**\n * Get block at current cursor position\n */\n getBlockAtCursor(): BlockNode | null;\n\n // === Block Mutations (Delta-based) ===\n\n /**\n * Insert a block after another block\n * @param block - Block to insert\n * @param afterId - ID of block to insert after (if undefined, appends to end)\n */\n insertBlockAfter(block: BlockNode, afterId?: BlockId): void;\n\n /**\n * Insert a block before another block\n * @param block - Block to insert\n * @param beforeId - ID of block to insert before (if undefined, prepends to start)\n */\n insertBlockBefore(block: BlockNode, beforeId?: BlockId): void;\n\n /**\n * Update block attributes\n * @param blockId - Block to update\n * @param attrs - Attributes to merge\n */\n updateBlockAttrs(blockId: BlockId, attrs: Record<string, unknown>): void;\n\n /**\n * Delete a block\n * @param blockId - Block to delete\n */\n deleteBlock(blockId: BlockId): void;\n\n // === Mark Utilities ===\n\n /**\n * Add mark to current selection\n * @param mark - Mark to add\n */\n addMark(mark: Mark): void;\n\n /**\n * Remove mark from current selection\n * @param markType - Type of mark to remove\n */\n removeMark(markType: string): void;\n\n /**\n * Toggle mark on current selection\n * @param markType - Type of mark to toggle\n */\n toggleMark(markType: string): void;\n\n // === Events ===\n\n /**\n * Register event listener\n */\n on(event: string, callback: (data: unknown) => void): void;\n\n /**\n * Unregister event listener\n */\n off(event: string, callback: (data: unknown) => void): void;\n\n /**\n * Emit an event\n */\n emit(event: string, data?: unknown): void;\n\n // === Commands ===\n\n /**\n * Register a command\n */\n registerCommand(name: string, handler: CommandHandler): void;\n\n /**\n * Execute a command\n */\n executeCommand(name: string, ...args: unknown[]): unknown;\n\n // === DOM Access (discouraged, use Delta operations instead) ===\n\n /**\n * Access DOM container (editable area)\n * @deprecated Prefer using Delta operations instead of direct DOM manipulation\n */\n getContainer(): HTMLElement;\n\n /**\n * Access plugin container for UI elements (toolbar, etc.)\n * @param position - 'top' or 'bottom'\n */\n getPluginContainer(position: 'top' | 'bottom'): HTMLElement;\n}\n\n/**\n * Command handler function\n */\nexport type CommandHandler = (...args: unknown[]) => unknown;\n\n/**\n * Plugin interface\n */\nexport interface Plugin {\n /**\n * Unique plugin identifier\n */\n id: string;\n\n /**\n * Plugin name\n */\n name: string;\n\n /**\n * Plugin version\n */\n version: string;\n\n /**\n * Plugin dependencies (optional)\n */\n dependencies?: string[];\n\n /**\n * Initialize the plugin\n */\n init(context: PluginContext): Promise<void> | void;\n\n /**\n * Cleanup the plugin\n */\n destroy?(): Promise<void> | void;\n\n /**\n * Handle state updates (optional)\n */\n onStateUpdate?(oldState: EditorState, newState: EditorState): void;\n\n /**\n * Handle delta application (optional)\n */\n onDeltaApplied?(delta: Delta): void;\n}\n\n/**\n * Plugin factory function type\n */\nexport type PluginFactory<TConfig = unknown> = (config?: TConfig) => Plugin;\n\n/**\n * Base plugin class for convenience\n */\nexport abstract class BasePlugin implements Plugin {\n abstract id: string;\n abstract name: string;\n abstract version: string;\n dependencies?: string[];\n\n protected context?: PluginContext;\n\n async init(context: PluginContext): Promise<void> {\n this.context = context;\n }\n\n async destroy(): Promise<void> {\n this.context = undefined;\n }\n\n protected getContext(): PluginContext {\n if (!this.context) {\n throw new Error('Plugin not initialized');\n }\n return this.context;\n }\n}\n","/**\n * Delta envelope - transactional container for operations\n */\n\nimport type { Operation } from './Operations.js';\nimport type { ValidationConstraint } from '../types/index.js';\n\n/**\n * Validation metadata for delta\n */\nexport interface DeltaValidation {\n requiresSchemaVersion: string;\n constraints: ValidationConstraint[];\n}\n\n/**\n * Delta envelope containing operations and metadata\n */\nexport interface Delta {\n txnId: string;\n clientId: string;\n timestamp: string;\n baseVersion: number;\n ltime: number;\n intent: 'edit' | 'comment' | 'format' | 'import' | string;\n undoGroup?: string;\n ops: Operation[];\n inverseOps?: Operation[];\n validation?: DeltaValidation;\n}\n\n/**\n * Delta class for creating and managing deltas\n */\nexport class DeltaBuilder {\n private delta: Partial<Delta>;\n private operations: Operation[] = [];\n\n constructor(clientId: string, baseVersion: number) {\n this.delta = {\n txnId: this.generateTxnId(),\n clientId,\n timestamp: new Date().toISOString(),\n baseVersion,\n ltime: Date.now(),\n ops: [],\n };\n }\n\n /**\n * Set the intent of this delta\n */\n setIntent(intent: Delta['intent']): this {\n this.delta.intent = intent;\n return this;\n }\n\n /**\n * Set the undo group for batch operations\n */\n setUndoGroup(group: string): this {\n this.delta.undoGroup = group;\n return this;\n }\n\n /**\n * Add an operation to this delta\n */\n addOperation(op: Operation): this {\n this.operations.push(op);\n return this;\n }\n\n /**\n * Add multiple operations\n */\n addOperations(ops: Operation[]): this {\n this.operations.push(...ops);\n return this;\n }\n\n /**\n * Set inverse operations for fast undo\n */\n setInverseOps(inverseOps: Operation[]): this {\n this.delta.inverseOps = inverseOps;\n return this;\n }\n\n /**\n * Set validation constraints\n */\n setValidation(validation: DeltaValidation): this {\n this.delta.validation = validation;\n return this;\n }\n\n /**\n * Build the final delta\n */\n build(): Delta {\n if (this.operations.length === 0) {\n throw new Error('Delta must contain at least one operation');\n }\n\n return {\n ...this.delta,\n ops: this.operations,\n } as Delta;\n }\n\n /**\n * Generate a unique transaction ID\n */\n private generateTxnId(): string {\n // Simple UUID v4 implementation\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Utility function to create a delta builder\n */\nexport function createDelta(clientId: string, baseVersion: number): DeltaBuilder {\n return new DeltaBuilder(clientId, baseVersion);\n}\n\n/**\n * Compute inverse operations for undo\n * This is a simplified implementation - full implementation would inspect document state\n */\nexport function computeInverse(delta: Delta): Operation[] {\n // In a real implementation, this would:\n // 1. Examine each operation\n // 2. Query the document state to determine the inverse\n // 3. Return the inverse operations in reverse order\n \n // For now, return empty array (inverse ops should be provided explicitly)\n return delta.inverseOps || [];\n}\n\n/**\n * Validate a delta against constraints\n */\nexport function validateDelta(delta: Delta): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n if (!delta.txnId) {\n errors.push('Delta must have a transaction ID');\n }\n\n if (!delta.clientId) {\n errors.push('Delta must have a client ID');\n }\n\n if (delta.ops.length === 0) {\n errors.push('Delta must contain at least one operation');\n }\n\n if (delta.baseVersion < 0) {\n errors.push('Base version must be non-negative');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Delta operation definitions for Notectl\n * Implements the operations specified in the Delta Design document\n */\n\nimport type { BlockId, Position, Range, Mark, BlockNode, BlockAttrs } from '../types/index.js';\n\n/**\n * Base operation interface\n */\nexport interface BaseOperation {\n op: string;\n}\n\n/**\n * Insert text at a position\n */\nexport interface InsertTextOp extends BaseOperation {\n op: 'insert_text';\n target: Position;\n text: string;\n marks?: Mark[];\n}\n\n/**\n * Delete text across a range\n */\nexport interface DeleteRangeOp extends BaseOperation {\n op: 'delete_range';\n range: Range;\n}\n\n/**\n * Apply or remove a mark across a range\n */\nexport interface ApplyMarkOp extends BaseOperation {\n op: 'apply_mark';\n range: Range;\n mark: Mark;\n add: boolean;\n}\n\n/**\n * Insert a block before another block\n */\nexport interface InsertBlockBeforeOp extends BaseOperation {\n op: 'insert_block_before';\n before: BlockId;\n block: BlockNode;\n}\n\n/**\n * Insert a block after another block\n */\nexport interface InsertBlockAfterOp extends BaseOperation {\n op: 'insert_block_after';\n after: BlockId;\n block: BlockNode;\n}\n\n/**\n * Delete a block\n */\nexport interface DeleteBlockOp extends BaseOperation {\n op: 'delete_block';\n target: { blockId: BlockId };\n}\n\n/**\n * Set attributes on a block\n */\nexport interface SetAttrsOp extends BaseOperation {\n op: 'set_attrs';\n target: { blockId: BlockId };\n attrs: BlockAttrs;\n}\n\n/**\n * Wrap blocks in a container\n */\nexport interface WrapInOp extends BaseOperation {\n op: 'wrap_in';\n blockIds: BlockId[];\n wrapperType: string;\n wrapperAttrs?: BlockAttrs;\n}\n\n/**\n * Lift blocks out of their container\n */\nexport interface LiftOutOp extends BaseOperation {\n op: 'lift_out';\n blockIds: BlockId[];\n}\n\n/**\n * Table operation: insert row\n */\nexport interface TableInsertRowOp extends BaseOperation {\n op: 'table_insert_row';\n target: { tableId: BlockId; rowIndex: number };\n row: BlockNode;\n}\n\n/**\n * Table operation: delete row\n */\nexport interface TableDeleteRowOp extends BaseOperation {\n op: 'table_delete_row';\n target: { tableId: BlockId; rowIndex: number };\n}\n\n/**\n * Table operation: insert column\n */\nexport interface TableInsertColOp extends BaseOperation {\n op: 'table_insert_col';\n target: { tableId: BlockId; colIndex: number };\n}\n\n/**\n * Table operation: delete column\n */\nexport interface TableDeleteColOp extends BaseOperation {\n op: 'table_delete_col';\n target: { tableId: BlockId; colIndex: number };\n}\n\n/**\n * Table operation: merge cells\n */\nexport interface TableMergeCellsOp extends BaseOperation {\n op: 'table_merge_cells';\n target: { tableId: BlockId; cells: BlockId[] };\n}\n\n/**\n * Table operation: split cell\n */\nexport interface TableSplitCellOp extends BaseOperation {\n op: 'table_split_cell';\n target: { tableId: BlockId; cellId: BlockId };\n}\n\n/**\n * Update selection/cursor\n */\nexport interface UpdateSelectionOp extends BaseOperation {\n op: 'update_selection';\n actorId: string;\n selection: {\n anchor: Position;\n head: Position;\n };\n}\n\n/**\n * Union of all operation types\n */\nexport type Operation =\n | InsertTextOp\n | DeleteRangeOp\n | ApplyMarkOp\n | InsertBlockBeforeOp\n | InsertBlockAfterOp\n | DeleteBlockOp\n | SetAttrsOp\n | WrapInOp\n | LiftOutOp\n | TableInsertRowOp\n | TableDeleteRowOp\n | TableInsertColOp\n | TableDeleteColOp\n | TableMergeCellsOp\n | TableSplitCellOp\n | UpdateSelectionOp;\n\n/**\n * Type guard for operation types\n */\nexport function isTextOperation(op: Operation): op is InsertTextOp | DeleteRangeOp | ApplyMarkOp {\n return op.op === 'insert_text' || op.op === 'delete_range' || op.op === 'apply_mark';\n}\n\nexport function isBlockOperation(\n op: Operation\n): op is InsertBlockBeforeOp | InsertBlockAfterOp | DeleteBlockOp | SetAttrsOp {\n return (\n op.op === 'insert_block_before' ||\n op.op === 'insert_block_after' ||\n op.op === 'delete_block' ||\n op.op === 'set_attrs'\n );\n}\n\nexport function isTableOperation(op: Operation): boolean {\n return op.op.startsWith('table_');\n}\n\nexport function isSelectionOperation(op: Operation): op is UpdateSelectionOp {\n return op.op === 'update_selection';\n}\n","/**\n * Operational Transformation (OT) logic for concurrent editing\n */\n\nimport type { Operation } from './Operations.js';\nimport type { Delta } from './Delta.js';\n\n/**\n * Transform operation A against operation B\n * Returns transformed version of A that can be applied after B\n */\nexport function transformOperation(opA: Operation, opB: Operation, side: 'left' | 'right'): Operation {\n // This is a simplified OT implementation\n // Full OT would require detailed transformation rules for each operation pair\n \n // For text operations, we need to adjust positions\n if (opA.op === 'insert_text' && opB.op === 'insert_text') {\n return transformInsertInsert(opA, opB, side);\n }\n \n if (opA.op === 'insert_text' && opB.op === 'delete_range') {\n return transformInsertDelete(opA, opB);\n }\n \n if (opA.op === 'delete_range' && opB.op === 'insert_text') {\n return transformDeleteInsert(opA, opB);\n }\n \n if (opA.op === 'delete_range' && opB.op === 'delete_range') {\n return transformDeleteDelete(opA, opB, side);\n }\n \n // For other operations, return as-is (naive approach)\n // A full implementation would handle all operation pairs\n return opA;\n}\n\n/**\n * Transform two concurrent insert operations\n */\nfunction transformInsertInsert(\n opA: Extract<Operation, { op: 'insert_text' }>,\n opB: Extract<Operation, { op: 'insert_text' }>,\n side: 'left' | 'right'\n): Operation {\n // If insertions are in the same block\n if (opA.target.blockId === opB.target.blockId) {\n // If B inserted before A's position, adjust A's offset\n if (opB.target.offset <= opA.target.offset) {\n return {\n ...opA,\n target: {\n ...opA.target,\n offset: opA.target.offset + opB.text.length,\n },\n };\n }\n // If B inserted at same position, use side to determine order\n if (opB.target.offset === opA.target.offset && side === 'right') {\n return {\n ...opA,\n target: {\n ...opA.target,\n offset: opA.target.offset + opB.text.length,\n },\n };\n }\n }\n return opA;\n}\n\n/**\n * Transform insert against delete\n */\nfunction transformInsertDelete(\n opA: Extract<Operation, { op: 'insert_text' }>,\n opB: Extract<Operation, { op: 'delete_range' }>\n): Operation {\n // If insertion is in the deleted range, move it to start of range\n if (opA.target.blockId === opB.range.start.blockId) {\n if (opA.target.offset >= opB.range.start.offset) {\n const deleteLength = opB.range.end.offset - opB.range.start.offset;\n return {\n ...opA,\n target: {\n ...opA.target,\n offset: Math.max(opB.range.start.offset, opA.target.offset - deleteLength),\n },\n };\n }\n }\n return opA;\n}\n\n/**\n * Transform delete against insert\n */\nfunction transformDeleteInsert(\n opA: Extract<Operation, { op: 'delete_range' }>,\n opB: Extract<Operation, { op: 'insert_text' }>\n): Operation {\n // If insert is before delete range, adjust delete positions\n if (opA.range.start.blockId === opB.target.blockId) {\n if (opB.target.offset <= opA.range.start.offset) {\n return {\n ...opA,\n range: {\n start: {\n ...opA.range.start,\n offset: opA.range.start.offset + opB.text.length,\n },\n end: {\n ...opA.range.end,\n offset: opA.range.end.offset + opB.text.length,\n },\n },\n };\n }\n }\n return opA;\n}\n\n/**\n * Transform two concurrent delete operations\n */\nfunction transformDeleteDelete(\n opA: Extract<Operation, { op: 'delete_range' }>,\n opB: Extract<Operation, { op: 'delete_range' }>,\n _side: 'left' | 'right'\n): Operation {\n // If ranges overlap, need to adjust A's range\n if (opA.range.start.blockId === opB.range.start.blockId) {\n const aStart = opA.range.start.offset;\n const aEnd = opA.range.end.offset;\n const bStart = opB.range.start.offset;\n const bEnd = opB.range.end.offset;\n \n // If B's delete is completely before A\n if (bEnd <= aStart) {\n const bLength = bEnd - bStart;\n return {\n ...opA,\n range: {\n start: { ...opA.range.start, offset: aStart - bLength },\n end: { ...opA.range.end, offset: aEnd - bLength },\n },\n };\n }\n \n // If B's delete overlaps with A, adjust accordingly\n // This is complex - simplified version here\n if (bStart <= aStart && bEnd >= aEnd) {\n // B deletes all of A's range - A becomes no-op (delete zero chars)\n return {\n ...opA,\n range: {\n start: { ...opA.range.start, offset: bStart },\n end: { ...opA.range.end, offset: bStart },\n },\n };\n }\n }\n return opA;\n}\n\n/**\n * Transform a delta against another delta\n * Returns transformed version of deltaA that can be applied after deltaB\n */\nexport function transformDelta(deltaA: Delta, deltaB: Delta, side: 'left' | 'right' = 'left'): Delta {\n const transformedOps = deltaA.ops.map((opA) => {\n let transformed = opA;\n for (const opB of deltaB.ops) {\n transformed = transformOperation(transformed, opB, side);\n }\n return transformed;\n });\n\n return {\n ...deltaA,\n ops: transformedOps,\n baseVersion: deltaB.baseVersion + 1, // Update to new base\n };\n}\n\n/**\n * Compose two deltas into a single delta\n * Applies deltaB after deltaA\n */\nexport function composeDelta(deltaA: Delta, deltaB: Delta): Delta {\n // Compose operations - this is simplified\n // Full implementation would optimize/merge operations\n return {\n ...deltaB,\n ops: [...deltaA.ops, ...deltaB.ops],\n baseVersion: deltaA.baseVersion,\n };\n}\n\n/**\n * Check if two deltas can be safely composed\n */\nexport function canCompose(deltaA: Delta, deltaB: Delta): boolean {\n // DeltaB should be based on the version after deltaA\n return deltaB.baseVersion === deltaA.baseVersion || deltaB.clientId === deltaA.clientId;\n}\n","/**\n * Helper utilities for selection, blocks, and node operations\n */\n\nimport type {\n Selection,\n Position,\n BlockNode,\n TextNode,\n Node as NotectlNode,\n SelectionHelpers,\n BlockHelpers,\n} from '../types/index.js';\n\n/**\n * Selection helper implementation\n */\nexport const selectionHelpers: SelectionHelpers = {\n /**\n * Check if selection is collapsed (cursor)\n */\n isCollapsed(selection: Selection): boolean {\n return (\n selection.anchor.blockId === selection.head.blockId &&\n selection.anchor.offset === selection.head.offset\n );\n },\n\n /**\n * Check if selection spans multiple blocks\n */\n isMultiBlock(selection: Selection): boolean {\n return selection.anchor.blockId !== selection.head.blockId;\n },\n\n /**\n * Get the direction of selection (forward/backward)\n */\n getDirection(selection: Selection): 'forward' | 'backward' | 'none' {\n if (this.isCollapsed(selection)) {\n return 'none';\n }\n\n if (selection.anchor.blockId === selection.head.blockId) {\n return selection.anchor.offset < selection.head.offset ? 'forward' : 'backward';\n }\n\n // For multi-block selections, would need document order comparison\n // Simplified: assume forward\n return 'forward';\n },\n\n /**\n * Create a collapsed selection at a position\n */\n createCollapsed(position: Position): Selection {\n return {\n anchor: position,\n head: position,\n };\n },\n\n /**\n * Create a selection range\n */\n createRange(start: Position, end: Position): Selection {\n return {\n anchor: start,\n head: end,\n };\n },\n};\n\n/**\n * Block helper implementation\n */\nexport const blockHelpers: BlockHelpers = {\n /**\n * Check if a node is a text node\n */\n isTextNode(node: NotectlNode): node is TextNode {\n return 'text' in node && node.type === 'text';\n },\n\n /**\n * Check if a node is a block node\n */\n isBlockNode(node: NotectlNode): node is BlockNode {\n return 'id' in node && 'type' in node;\n },\n\n /**\n * Get all text content from a block\n */\n getTextContent(block: BlockNode): string {\n if (!block.children) {\n return '';\n }\n\n return block.children\n .map((child) => {\n if (this.isTextNode(child)) {\n return child.text;\n } else if (this.isBlockNode(child)) {\n return this.getTextContent(child);\n }\n return '';\n })\n .join('');\n },\n\n /**\n * Check if block is empty\n */\n isEmpty(block: BlockNode): boolean {\n if (!block.children || block.children.length === 0) {\n return true;\n }\n\n return this.getTextContent(block).trim() === '';\n },\n};\n","/**\n * Notectl Core - Framework-agnostic rich text editor\n * @packageDocumentation\n */\n\n// Main editor\nexport { NotectlEditor } from './editor/NotectlEditor.js';\nimport { NotectlEditor } from './editor/NotectlEditor.js';\n\n// State management\nexport { EditorState } from './state/EditorState.js';\n\n// Schema\nexport { Schema, createDefaultSchema } from './schema/Schema.js';\nexport type { NodeSpec, MarkSpec, AttributeSpec } from './schema/Schema.js';\n\n// Node factory\nexport { NodeFactory, createNodeFactory, generateBlockId } from './schema/NodeFactory.js';\n\n// Plugin system\nexport { PluginManager } from './plugins/PluginManager.js';\nexport { BasePlugin } from './plugins/Plugin.js';\nexport type {\n Plugin,\n PluginContext,\n PluginFactory,\n CommandHandler,\n} from './plugins/Plugin.js';\n\n// Delta system\nexport { DeltaBuilder, createDelta, computeInverse, validateDelta } from './delta/Delta.js';\nexport type { Delta, DeltaValidation } from './delta/Delta.js';\n\n// Operations\nexport type {\n Operation,\n InsertTextOp,\n DeleteRangeOp,\n ApplyMarkOp,\n InsertBlockBeforeOp,\n InsertBlockAfterOp,\n DeleteBlockOp,\n SetAttrsOp,\n WrapInOp,\n LiftOutOp,\n TableInsertRowOp,\n TableDeleteRowOp,\n TableInsertColOp,\n TableDeleteColOp,\n TableMergeCellsOp,\n TableSplitCellOp,\n UpdateSelectionOp,\n} from './delta/Operations.js';\nexport {\n isTextOperation,\n isBlockOperation,\n isTableOperation,\n isSelectionOperation,\n} from './delta/Operations.js';\n\n// Transformation\nexport { transformOperation, transformDelta, composeDelta, canCompose } from './delta/Transform.js';\n\n// Core types\nexport type {\n BlockId,\n Position,\n Range,\n Mark,\n NodeType,\n TextNode,\n BlockNode,\n BlockAttrs,\n Node,\n Document,\n Selection,\n EditorEvent,\n EditorEventCallback,\n EditorConfig,\n EditorAPI,\n ValidationConstraint,\n ErrorEnvelope,\n CommandRegistry,\n CommandDefinition,\n SelectionHelpers,\n BlockHelpers,\n TableData,\n TableRow,\n TableCell,\n} from './types/index.js';\nimport type { EditorConfig } from './types/index.js';\n\n// Utility helpers\nexport { selectionHelpers, blockHelpers } from './utils/helpers.js';\n\n// Constants and error handling\nexport {\n EDITOR_READY_TIMEOUT,\n ARIA_ANNOUNCEMENT_DELAY,\n DEFAULT_MAX_HISTORY_DEPTH,\n DEFAULT_MIN_HEIGHT,\n ErrorCodes,\n ValidationConstraints,\n NotectlError,\n} from './constants.js';\nexport type { ErrorCode } from './constants.js';\n\n// Utility function to initialize editor\nexport function createEditor(container: HTMLElement, config?: EditorConfig) {\n const editor = new NotectlEditor();\n\n // Apply configuration if provided\n if (config) {\n // Config would be applied here\n }\n\n container.appendChild(editor);\n return editor;\n}\n\n// Version\nexport const VERSION = '0.0.1';\n"],"names":["Schema","config","spec","type","node","errors","textNode","mark","blockNode","attrName","attrSpec","child","childValidation","markType","nodeType","nodeSpec","markA","markB","specA","specB","createDefaultSchema","val","generateBlockId","c","r","NodeFactory","schema","text","marks","content","attrs","level","items","rows","cells","src","alt","children","createNodeFactory","EditorState","initialDoc","options","selection","delta","op","block","n","before","after","m","index","b","blockId","search","nodes","blockChildren","found","entry","json","EDITOR_READY_TIMEOUT","ARIA_ANNOUNCEMENT_DELAY","DEFAULT_MAX_HISTORY_DEPTH","DEFAULT_MIN_HEIGHT","ErrorCodes","NotectlError","code","message","details","ValidationConstraints","PluginManager","plugin","context","existing","missingDeps","depId","error","pluginId","dependentPlugins","id","p","oldState","newState","pluginIds","entries","setPrototypeOf","isFrozen","getPrototypeOf","getOwnPropertyDescriptor","freeze","seal","create","apply","construct","x","func","thisArg","_len","args","_key","Func","_len2","_key2","arrayForEach","unapply","arrayLastIndexOf","arrayPop","arrayPush","arraySplice","stringToLowerCase","stringToString","stringMatch","stringReplace","stringIndexOf","stringTrim","objectHasOwnProperty","regExpTest","typeErrorCreate","unconstruct","_len3","_key3","_len4","_key4","addToSet","set","array","transformCaseFunc","l","element","lcElement","cleanArray","clone","object","newObject","property","value","lookupGetter","prop","desc","fallbackValue","html$1","svg$1","svgFilters","svgDisallowed","mathMl$1","mathMlDisallowed","html","svg","mathMl","xml","MUSTACHE_EXPR","ERB_EXPR","TMPLIT_EXPR","DATA_ATTR","ARIA_ATTR","IS_ALLOWED_URI","IS_SCRIPT_OR_DATA","ATTR_WHITESPACE","DOCTYPE_NAME","CUSTOM_ELEMENT","EXPRESSIONS","NODE_TYPE","getGlobal","_createTrustedTypesPolicy","trustedTypes","purifyHostElement","suffix","ATTR_NAME","policyName","scriptUrl","_createHooksMap","createDOMPurify","window","DOMPurify","root","document","originalDocument","currentScript","DocumentFragment","HTMLTemplateElement","Node","Element","NodeFilter","NamedNodeMap","HTMLFormElement","DOMParser","ElementPrototype","cloneNode","remove","getNextSibling","getChildNodes","getParentNode","template","trustedTypesPolicy","emptyHTML","implementation","createNodeIterator","createDocumentFragment","getElementsByTagName","importNode","hooks","IS_ALLOWED_URI$1","ALLOWED_TAGS","DEFAULT_ALLOWED_TAGS","ALLOWED_ATTR","DEFAULT_ALLOWED_ATTR","CUSTOM_ELEMENT_HANDLING","FORBID_TAGS","FORBID_ATTR","ALLOW_ARIA_ATTR","ALLOW_DATA_ATTR","ALLOW_UNKNOWN_PROTOCOLS","ALLOW_SELF_CLOSE_IN_ATTR","SAFE_FOR_TEMPLATES","SAFE_FOR_XML","WHOLE_DOCUMENT","SET_CONFIG","FORCE_BODY","RETURN_DOM","RETURN_DOM_FRAGMENT","RETURN_TRUSTED_TYPE","SANITIZE_DOM","SANITIZE_NAMED_PROPS","SANITIZE_NAMED_PROPS_PREFIX","KEEP_CONTENT","IN_PLACE","USE_PROFILES","FORBID_CONTENTS","DEFAULT_FORBID_CONTENTS","DATA_URI_TAGS","DEFAULT_DATA_URI_TAGS","URI_SAFE_ATTRIBUTES","DEFAULT_URI_SAFE_ATTRIBUTES","MATHML_NAMESPACE","SVG_NAMESPACE","HTML_NAMESPACE","NAMESPACE","IS_EMPTY_INPUT","ALLOWED_NAMESPACES","DEFAULT_ALLOWED_NAMESPACES","MATHML_TEXT_INTEGRATION_POINTS","HTML_INTEGRATION_POINTS","COMMON_SVG_AND_HTML_ELEMENTS","PARSER_MEDIA_TYPE","SUPPORTED_PARSER_MEDIA_TYPES","DEFAULT_PARSER_MEDIA_TYPE","CONFIG","formElement","isRegexOrFunction","testValue","_parseConfig","cfg","ALL_SVG_TAGS","ALL_MATHML_TAGS","_checkValidNamespace","parent","tagName","parentTagName","_forceRemove","_removeAttribute","name","_initDocument","dirty","doc","leadingWhitespace","matches","dirtyPayload","body","_createNodeIterator","_isClobbered","_isNode","_executeHooks","currentNode","data","hook","_sanitizeElements","_isBasicCustomElement","parentNode","childNodes","childCount","i","childClone","expr","_isValidAttribute","lcTag","lcName","_sanitizeAttributes","attributes","hookEvent","attr","namespaceURI","attrValue","initValue","_sanitizeShadowDOM","fragment","shadowNode","shadowIterator","importedNode","returnNode","nodeIterator","serializedHTML","tag","entryPoint","hookFunction","purify","EDITOR_SANITIZE_CONFIG","STRICT_SANITIZE_CONFIG","sanitizeHTML","strict","sanitizeContent","allowHTML","escapeHTML","div","validateDelta","insert","insertObj","key","announceToScreenReader","politeness","liveRegion","registerKeyboardShortcuts","shortcuts","container","handleKeyDown","event","shortcut","ctrlMatch","metaMatch","shiftMatch","altMatch","setAriaAttributes","NotectlEditor","resolve","plugins","oldValue","newValue","tableData","attrParts","styleString","bodyHTML","fallbackCellId","row","rowIndex","rowId","style","cellsHTML","cell","colIndex","cellId","rowSpan","colSpan","inner","match","format","range","cols","table","tbody","tr","j","insertPosition","refNode","placeholder","isEmpty","childElement","result","childResult","item","results","afterId","targetId","beforeId","hasMark","callback","handler","position","undoDelta","redoDelta","sanitized","BasePlugin","DeltaBuilder","clientId","baseVersion","intent","group","ops","inverseOps","validation","createDelta","computeInverse","isTextOperation","isBlockOperation","isTableOperation","isSelectionOperation","transformOperation","opA","opB","side","transformInsertInsert","transformInsertDelete","transformDeleteInsert","transformDeleteDelete","deleteLength","_side","aStart","aEnd","bStart","bEnd","bLength","transformDelta","deltaA","deltaB","transformedOps","transformed","composeDelta","canCompose","selectionHelpers","start","end","blockHelpers","createEditor","editor","VERSION"],"mappings":"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","x_google_ignoreList":[5]}
|
|
1
|
+
{"version":3,"file":"notectl-core.js","sources":["../src/model/Document.ts","../src/model/Selection.ts","../src/model/Schema.ts","../src/model/TypeBrands.ts","../src/model/AttrRegistry.ts","../src/model/NodeSpec.ts","../src/model/SchemaRegistry.ts","../src/model/NodeResolver.ts","../src/model/ContentModel.ts","../src/model/BuiltinSpecs.ts","../src/state/StepApplication.ts","../src/state/Transaction.ts","../src/state/EditorState.ts","../src/state/History.ts","../src/commands/Commands.ts","../src/input/KeyboardHandler.ts","../src/plugins/Plugin.ts","../src/plugins/EventBus.ts","../src/decorations/PositionMapping.ts","../src/decorations/Decoration.ts","../src/plugins/PluginManager.ts","../src/plugins/toolbar/ToolbarPlugin.ts","../src/plugins/toolbar/ToolbarItem.ts","../src/plugins/text-formatting/TextFormattingPlugin.ts","../src/plugins/heading/HeadingPlugin.ts","../src/plugins/link/LinkPlugin.ts","../src/plugins/list/ListPlugin.ts","../src/plugins/blockquote/BlockquotePlugin.ts","../src/plugins/strikethrough/StrikethroughPlugin.ts","../src/plugins/text-color/TextColorPlugin.ts","../src/plugins/horizontal-rule/HorizontalRulePlugin.ts","../src/plugins/text-alignment/TextAlignmentPlugin.ts","../src/plugins/font/FontPlugin.ts","../src/plugins/font-size/FontSizePlugin.ts","../src/plugins/font/StarterFonts.ts","../src/plugins/table/TableHelpers.ts","../src/plugins/table/TableCommands.ts","../src/plugins/table/TableNavigation.ts","../src/view/Reconciler.ts","../src/plugins/table/TableControls.ts","../src/plugins/table/TableNodeViews.ts","../src/plugins/table/TableSelection.ts","../src/plugins/table/TablePlugin.ts","../src/plugins/highlight/HighlightPlugin.ts","../src/plugins/super-sub/SuperSubPlugin.ts","../src/input/InputHandler.ts","../src/input/PasteHandler.ts","../src/view/SelectionSync.ts","../src/view/EditorView.ts","../src/editor/styles.ts","../src/editor/NotectlEditor.ts"],"sourcesContent":["/**\n * Core document model types for the Notectl editor.\n * All types are deeply readonly — mutations create new instances.\n */\n\nimport type { BlockId, InlineTypeName, MarkTypeName, NodeTypeName } from './TypeBrands.js';\n\n// --- Mark Types ---\n\n/** @deprecated Use {@link MarkTypeName} for new code. */\nexport type MarkType = MarkTypeName;\n\nexport interface Mark {\n\treadonly type: MarkTypeName;\n\treadonly attrs?: Readonly<Record<string, string | number | boolean>>;\n}\n\nexport interface BoldMark extends Mark {\n\treadonly type: MarkTypeName & 'bold';\n}\n\nexport interface ItalicMark extends Mark {\n\treadonly type: MarkTypeName & 'italic';\n}\n\nexport interface UnderlineMark extends Mark {\n\treadonly type: MarkTypeName & 'underline';\n}\n\n// --- Node Types ---\n\n/** @deprecated Use {@link NodeTypeName} for new code. */\nexport type NodeType = NodeTypeName;\n\nexport interface BlockAttrs {\n\treadonly [key: string]: string | number | boolean;\n}\n\nexport interface TextNode {\n\treadonly type: 'text';\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n}\n\n/** Atomic inline element (width 1 in offset space). */\nexport interface InlineNode {\n\treadonly type: 'inline';\n\treadonly inlineType: InlineTypeName;\n\treadonly attrs: Readonly<Record<string, string | number | boolean>>;\n}\n\n/** A child of a BlockNode: text, inline element, or nested block. */\nexport type ChildNode = TextNode | InlineNode | BlockNode;\n\nexport interface BlockNode {\n\treadonly id: BlockId;\n\treadonly type: NodeTypeName;\n\treadonly attrs?: BlockAttrs;\n\treadonly children: readonly ChildNode[];\n}\n\nexport interface Document {\n\treadonly children: readonly BlockNode[];\n}\n\n// --- Text Segment (for mark-preserving undo) ---\n\nexport interface TextSegment {\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n}\n\n/** A content segment: either text (with marks) or an inline node. */\nexport type ContentSegment =\n\t| { readonly kind: 'text'; readonly text: string; readonly marks: readonly Mark[] }\n\t| { readonly kind: 'inline'; readonly node: InlineNode };\n\n/** Extracts TextNode segments within a block for the given offset range. */\nexport function getBlockSegmentsInRange(\n\tblock: BlockNode,\n\tfrom: number,\n\tto: number,\n): readonly TextSegment[] {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tconst segments: TextSegment[] = [];\n\tlet pos = 0;\n\n\tfor (const child of inlineChildren) {\n\t\tconst childWidth: number = isInlineNode(child) ? 1 : child.text.length;\n\t\tconst childEnd: number = pos + childWidth;\n\n\t\tif (childEnd <= from || pos >= to) {\n\t\t\tpos = childEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isInlineNode(child)) {\n\t\t\t// InlineNodes are skipped for TextSegment extraction\n\t\t\tpos = childEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst sliceFrom: number = Math.max(0, from - pos);\n\t\tconst sliceTo: number = Math.min(child.text.length, to - pos);\n\t\tconst text: string = child.text.slice(sliceFrom, sliceTo);\n\n\t\tif (text.length > 0) {\n\t\t\tsegments.push({ text, marks: child.marks });\n\t\t}\n\n\t\tpos = childEnd;\n\t}\n\n\treturn segments;\n}\n\n/** Returns content segments (text and inline) for a block range. */\nexport function getBlockContentSegmentsInRange(\n\tblock: BlockNode,\n\tfrom: number,\n\tto: number,\n): readonly ContentSegment[] {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tconst segments: ContentSegment[] = [];\n\tlet pos = 0;\n\n\tfor (const child of inlineChildren) {\n\t\tconst childWidth: number = isInlineNode(child) ? 1 : child.text.length;\n\t\tconst childEnd: number = pos + childWidth;\n\n\t\tif (childEnd <= from || pos >= to) {\n\t\t\tpos = childEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isInlineNode(child)) {\n\t\t\tsegments.push({ kind: 'inline', node: child });\n\t\t} else {\n\t\t\tconst sliceFrom: number = Math.max(0, from - pos);\n\t\t\tconst sliceTo: number = Math.min(child.text.length, to - pos);\n\t\t\tconst text: string = child.text.slice(sliceFrom, sliceTo);\n\t\t\tif (text.length > 0) {\n\t\t\t\tsegments.push({ kind: 'text', text, marks: child.marks });\n\t\t\t}\n\t\t}\n\n\t\tpos = childEnd;\n\t}\n\n\treturn segments;\n}\n\n// --- Type Guards ---\n\n/** Checks whether a value is a {@link TextNode}. */\nexport function isTextNode(node: unknown): node is TextNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\t(node as TextNode).type === 'text' &&\n\t\ttypeof (node as TextNode).text === 'string'\n\t);\n}\n\n/** Checks whether a value is an {@link InlineNode}. */\nexport function isInlineNode(node: unknown): node is InlineNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\t(node as InlineNode).type === 'inline' &&\n\t\ttypeof (node as InlineNode).inlineType === 'string'\n\t);\n}\n\n/** Checks whether a value is a {@link BlockNode}. */\nexport function isBlockNode(node: unknown): node is BlockNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\ttypeof (node as BlockNode).id === 'string' &&\n\t\ttypeof (node as BlockNode).type === 'string' &&\n\t\t(node as BlockNode).type !== ('text' as string) &&\n\t\t(node as BlockNode).type !== ('inline' as string) &&\n\t\tArray.isArray((node as BlockNode).children)\n\t);\n}\n\n// --- Child Node Helpers ---\n\n/** Returns true if a block has only inline content (TextNodes and InlineNodes). */\nexport function isLeafBlock(node: BlockNode): boolean {\n\treturn node.children.every((c) => isTextNode(c) || isInlineNode(c));\n}\n\n/** Returns only the TextNode children of a block. */\nexport function getTextChildren(node: BlockNode): readonly TextNode[] {\n\treturn node.children.filter((c): c is TextNode => isTextNode(c));\n}\n\n/** Returns the inline content children (TextNode | InlineNode) of a block. */\nexport function getInlineChildren(node: BlockNode): readonly (TextNode | InlineNode)[] {\n\treturn node.children.filter((c): c is TextNode | InlineNode => isTextNode(c) || isInlineNode(c));\n}\n\n/** Returns only the BlockNode children of a block. */\nexport function getBlockChildren(node: BlockNode): readonly BlockNode[] {\n\treturn node.children.filter((c): c is BlockNode => isBlockNode(c));\n}\n\n// --- Factory Functions ---\n\n/** Generates a unique block ID using crypto.randomUUID(). */\nexport function generateBlockId(): BlockId {\n\treturn `block-${crypto.randomUUID()}` as BlockId;\n}\n\n/** Creates a new empty {@link Document} with a single empty paragraph. */\nexport function createDocument(children?: readonly BlockNode[]): Document {\n\treturn {\n\t\tchildren: children ?? [createBlockNode('paragraph' as NodeTypeName)],\n\t};\n}\n\n/** Creates a new {@link BlockNode}. */\nexport function createBlockNode(\n\ttype: NodeTypeName,\n\tchildren?: readonly ChildNode[],\n\tid?: BlockId,\n\tattrs?: BlockAttrs,\n): BlockNode {\n\treturn {\n\t\tid: id ?? generateBlockId(),\n\t\ttype,\n\t\t...(attrs ? { attrs } : {}),\n\t\tchildren: children ?? [createTextNode('')],\n\t};\n}\n\n/** Creates a new {@link TextNode}. */\nexport function createTextNode(text: string, marks?: readonly Mark[]): TextNode {\n\treturn {\n\t\ttype: 'text',\n\t\ttext,\n\t\tmarks: marks ?? [],\n\t};\n}\n\n/** Creates a new {@link InlineNode}. */\nexport function createInlineNode(\n\tinlineType: InlineTypeName,\n\tattrs?: Readonly<Record<string, string | number | boolean>>,\n): InlineNode {\n\treturn {\n\t\ttype: 'inline',\n\t\tinlineType,\n\t\tattrs: attrs ?? {},\n\t};\n}\n\n// --- Utility Functions ---\n\n/** Extracts plain text from a block (InlineNodes are skipped). */\nexport function getBlockText(block: BlockNode): string {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet text = '';\n\tfor (const child of inlineChildren) {\n\t\tif (isTextNode(child)) {\n\t\t\ttext += child.text;\n\t\t}\n\t}\n\treturn text;\n}\n\n/** Returns the length of a block's inline content (InlineNodes count as 1). */\nexport function getBlockLength(block: BlockNode): number {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet len = 0;\n\tfor (const child of inlineChildren) {\n\t\tlen += isInlineNode(child) ? 1 : child.text.length;\n\t}\n\treturn len;\n}\n\n/** Returns the marks active at the given offset (empty for InlineNode offsets). */\nexport function getBlockMarksAtOffset(block: BlockNode, offset: number): readonly Mark[] {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet pos = 0;\n\n\tfor (const child of inlineChildren) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (offset === pos) return [];\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst end: number = pos + child.text.length;\n\t\tif (offset >= pos && offset < end) {\n\t\t\treturn child.marks;\n\t\t}\n\t\tif (offset === pos && child.text.length === 0) {\n\t\t\treturn child.marks;\n\t\t}\n\t\tpos = end;\n\t}\n\n\t// Fall back to last text child's marks\n\tfor (let i: number = inlineChildren.length - 1; i >= 0; i--) {\n\t\tconst child: TextNode | InlineNode | undefined = inlineChildren[i];\n\t\tif (child && isTextNode(child)) {\n\t\t\treturn child.marks;\n\t\t}\n\t}\n\treturn [];\n}\n\n/** Checks whether two marks are equal by type and attrs. */\nexport function marksEqual(a: Mark, b: Mark): boolean {\n\tif (a.type !== b.type) return false;\n\tconst aAttrs = a.attrs;\n\tconst bAttrs = b.attrs;\n\tif (!aAttrs && !bAttrs) return true;\n\tif (!aAttrs || !bAttrs) return false;\n\tconst aKeys = Object.keys(aAttrs);\n\tconst bKeys = Object.keys(bAttrs);\n\tif (aKeys.length !== bKeys.length) return false;\n\treturn aKeys.every((key) => aAttrs[key] === bAttrs[key]);\n}\n\n/** Checks whether two mark arrays contain the same marks (order-independent). */\nexport function markSetsEqual(a: readonly Mark[], b: readonly Mark[]): boolean {\n\tif (a.length !== b.length) return false;\n\treturn a.every((markA) => b.some((markB) => marksEqual(markA, markB)));\n}\n\n/** Returns true if the mark set contains a mark of the given type. */\nexport function hasMark(marks: readonly Mark[], markType: MarkTypeName): boolean {\n\treturn marks.some((m) => m.type === markType);\n}\n\n/** Adds a mark to a mark set (no duplicates). */\nexport function addMarkToSet(marks: readonly Mark[], mark: Mark): readonly Mark[] {\n\tif (hasMark(marks, mark.type)) return marks;\n\treturn [...marks, mark];\n}\n\n/** Removes a mark type from a mark set. */\nexport function removeMarkFromSet(marks: readonly Mark[], markType: MarkTypeName): readonly Mark[] {\n\treturn marks.filter((m) => m.type !== markType);\n}\n\n/**\n * Normalizes text nodes within a block: merges adjacent nodes with identical marks,\n * removes empty text nodes (keeping at least one).\n */\nexport function normalizeTextNodes(nodes: readonly TextNode[]): readonly TextNode[] {\n\tif (nodes.length === 0) return [createTextNode('')];\n\n\tconst result: TextNode[] = [];\n\tfor (const node of nodes) {\n\t\tconst prev: TextNode | undefined = result[result.length - 1];\n\t\tif (prev && markSetsEqual(prev.marks, node.marks)) {\n\t\t\tresult[result.length - 1] = createTextNode(prev.text + node.text, prev.marks);\n\t\t} else if (node.text.length > 0 || result.length === 0) {\n\t\t\tresult.push(node);\n\t\t}\n\t}\n\n\treturn result.length === 0 ? [createTextNode('')] : result;\n}\n\n/**\n * Normalizes mixed inline content: merges adjacent TextNodes with same marks,\n * removes empty TextNodes adjacent to InlineNodes, preserves InlineNodes as-is.\n * Guarantees at least one TextNode exists if all text is empty.\n */\nexport function normalizeInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n): readonly (TextNode | InlineNode)[] {\n\tif (nodes.length === 0) return [createTextNode('')];\n\n\t// Fast path: no InlineNodes, delegate to normalizeTextNodes\n\tif (nodes.every((n): n is TextNode => isTextNode(n))) {\n\t\treturn normalizeTextNodes(nodes);\n\t}\n\n\tconst result: (TextNode | InlineNode)[] = [];\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tresult.push(node);\n\t\t\tcontinue;\n\t\t}\n\t\t// TextNode: try to merge with previous TextNode\n\t\tconst prev: TextNode | InlineNode | undefined = result[result.length - 1];\n\t\tif (prev && isTextNode(prev) && markSetsEqual(prev.marks, node.marks)) {\n\t\t\tresult[result.length - 1] = createTextNode(prev.text + node.text, prev.marks);\n\t\t} else if (node.text.length > 0 || result.length === 0) {\n\t\t\tresult.push(node);\n\t\t}\n\t}\n\n\t// Remove empty TextNodes that are adjacent to InlineNodes\n\tconst cleaned: (TextNode | InlineNode)[] = result.filter((node, i) => {\n\t\tif (isInlineNode(node)) return true;\n\t\tif (node.text.length > 0) return true;\n\t\t// Keep if it's the only node\n\t\tif (result.length === 1) return true;\n\t\t// Remove empty TextNode if adjacent to InlineNode\n\t\tconst prev: TextNode | InlineNode | undefined = result[i - 1];\n\t\tconst next: TextNode | InlineNode | undefined = result[i + 1];\n\t\tif ((prev && isInlineNode(prev)) || (next && isInlineNode(next))) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\t// Ensure at least one TextNode exists\n\tif (cleaned.length === 0) return [createTextNode('')];\n\tif (!cleaned.some((n) => isTextNode(n))) {\n\t\treturn [createTextNode(''), ...cleaned];\n\t}\n\n\treturn cleaned;\n}\n\n/** Yields each inline child with its offset range. InlineNodes have width 1. */\nexport function* walkInlineContent(children: readonly (TextNode | InlineNode)[]): Generator<{\n\treadonly child: TextNode | InlineNode;\n\treadonly from: number;\n\treadonly to: number;\n}> {\n\tlet pos = 0;\n\tfor (const child of children) {\n\t\tconst width: number = isInlineNode(child) ? 1 : child.text.length;\n\t\tyield { child, from: pos, to: pos + width };\n\t\tpos += width;\n\t}\n}\n\n/** Returns the content at a specific offset: text char, inline node, or null. */\nexport function getContentAtOffset(\n\tblock: BlockNode,\n\toffset: number,\n):\n\t| { readonly kind: 'text'; readonly char: string; readonly marks: readonly Mark[] }\n\t| { readonly kind: 'inline'; readonly node: InlineNode }\n\t| null {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\n\tfor (const { child, from } of walkInlineContent(inlineChildren)) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (offset === from) return { kind: 'inline', node: child };\n\t\t\tcontinue;\n\t\t}\n\t\tconst localOffset: number = offset - from;\n\t\tif (localOffset >= 0 && localOffset < child.text.length) {\n\t\t\treturn {\n\t\t\t\tkind: 'text',\n\t\t\t\tchar: child.text[localOffset] ?? '',\n\t\t\t\tmarks: child.marks,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n","/**\n * Selection model for the Notectl editor.\n * A selection is defined by an anchor and head position within the document.\n */\n\nimport type { BlockId } from './TypeBrands.js';\n\nexport interface Position {\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\t/** Path from root block to leaf block (optional, for nested structures). */\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface Selection {\n\treadonly anchor: Position;\n\treadonly head: Position;\n}\n\nexport interface SelectionRange {\n\treadonly from: Position;\n\treadonly to: Position;\n}\n\n/** A selection that selects an entire node (e.g. for table selection). */\nexport interface NodeSelection {\n\treadonly type: 'node';\n\treadonly nodeId: BlockId;\n\treadonly path: readonly BlockId[];\n}\n\n/** Creates a Position, optionally with a path. */\nexport function createPosition(\n\tblockId: BlockId,\n\toffset: number,\n\tpath?: readonly BlockId[],\n): Position {\n\treturn path ? { blockId, offset, path } : { blockId, offset };\n}\n\n/** Creates a selection with distinct anchor and head. */\nexport function createSelection(anchor: Position, head: Position): Selection {\n\treturn { anchor, head };\n}\n\n/** Creates a collapsed selection (cursor) at the given position. */\nexport function createCollapsedSelection(blockId: BlockId, offset: number): Selection {\n\tconst pos: Position = { blockId, offset };\n\treturn { anchor: pos, head: pos };\n}\n\n/** Returns true if the selection is collapsed (cursor with no range). */\nexport function isCollapsed(sel: Selection): boolean {\n\treturn sel.anchor.blockId === sel.head.blockId && sel.anchor.offset === sel.head.offset;\n}\n\n/**\n * Returns true if the selection direction is forward (anchor before head).\n * When anchor and head are in the same block, compares offsets.\n * Cross-block ordering uses document order (not determinable here — caller provides block order).\n */\nexport function isForward(sel: Selection, blockOrder?: readonly BlockId[]): boolean {\n\tif (sel.anchor.blockId === sel.head.blockId) {\n\t\treturn sel.anchor.offset <= sel.head.offset;\n\t}\n\tif (blockOrder) {\n\t\tconst anchorIdx = blockOrder.indexOf(sel.anchor.blockId);\n\t\tconst headIdx = blockOrder.indexOf(sel.head.blockId);\n\t\treturn anchorIdx <= headIdx;\n\t}\n\treturn true;\n}\n\n/**\n * Returns a normalized range where `from` is always before `to`.\n */\nexport function selectionRange(sel: Selection, blockOrder?: readonly BlockId[]): SelectionRange {\n\tif (isForward(sel, blockOrder)) {\n\t\treturn { from: sel.anchor, to: sel.head };\n\t}\n\treturn { from: sel.head, to: sel.anchor };\n}\n","/**\n * Schema definition for the Notectl editor.\n * Defines which node types and marks are allowed.\n */\n\nimport type { NodeSpec } from './NodeSpec.js';\nimport type { SchemaRegistry } from './SchemaRegistry.js';\n\nexport interface Schema {\n\treadonly nodeTypes: readonly string[];\n\treadonly markTypes: readonly string[];\n\t/** Looks up the full NodeSpec for a given type. Available when created via schemaFromRegistry. */\n\treadonly getNodeSpec?: (type: string) => NodeSpec | undefined;\n}\n\n/** Creates the default schema with paragraph nodes and bold/italic/underline marks. */\nexport function defaultSchema(): Schema {\n\treturn {\n\t\tnodeTypes: ['paragraph'],\n\t\tmarkTypes: ['bold', 'italic', 'underline'],\n\t\tgetNodeSpec: () => undefined,\n\t};\n}\n\n/** Derives a Schema from a SchemaRegistry's registered specs. */\nexport function schemaFromRegistry(registry: SchemaRegistry): Schema {\n\treturn {\n\t\tnodeTypes: registry.getNodeTypes(),\n\t\tmarkTypes: registry.getMarkTypes(),\n\t\tgetNodeSpec: (type: string) => registry.getNodeSpec(type),\n\t};\n}\n\n/** Checks whether the given mark type is allowed by the schema. */\nexport function isMarkAllowed(schema: Schema, markType: string): boolean {\n\treturn schema.markTypes.includes(markType);\n}\n\n/** Checks whether the given node type is allowed by the schema. */\nexport function isNodeTypeAllowed(schema: Schema, nodeType: string): boolean {\n\treturn schema.nodeTypes.includes(nodeType);\n}\n","/**\n * Branded (nominal) types for semantic string distinctions.\n * Prevents accidental interchange of structurally identical IDs.\n */\n\ndeclare const __brand: unique symbol;\ntype Brand<T, B extends string> = T & { readonly [__brand]: B };\n\n/** Unique identifier for a block node in the document tree. */\nexport type BlockId = Brand<string, 'BlockId'>;\n\n/** Semantic name for a node type (e.g. 'paragraph', 'heading'). */\nexport type NodeTypeName = Brand<string, 'NodeTypeName'>;\n\n/** Semantic name for a mark type (e.g. 'bold', 'link'). */\nexport type MarkTypeName = Brand<string, 'MarkTypeName'>;\n\n/** Unique identifier for a plugin. */\nexport type PluginId = Brand<string, 'PluginId'>;\n\n/** Registered command name. */\nexport type CommandName = Brand<string, 'CommandName'>;\n\n/** Semantic name for an inline node type (e.g. 'image', 'mention'). */\nexport type InlineTypeName = Brand<string, 'InlineTypeName'>;\n\n// --- Constructor Functions ---\n\nexport function blockId(id: string): BlockId {\n\treturn id as BlockId;\n}\n\nexport function nodeType(name: string): NodeTypeName {\n\treturn name as NodeTypeName;\n}\n\nexport function markType(name: string): MarkTypeName {\n\treturn name as MarkTypeName;\n}\n\nexport function pluginId(id: string): PluginId {\n\treturn id as PluginId;\n}\n\nexport function commandName(name: string): CommandName {\n\treturn name as CommandName;\n}\n\nexport function inlineType(name: string): InlineTypeName {\n\treturn name as InlineTypeName;\n}\n","/**\n * Module-augmentable attribute registries for type-safe node/mark attributes.\n *\n * Plugins extend these interfaces via `declare module`:\n * @example\n * declare module '../../model/AttrRegistry.js' {\n * interface NodeAttrRegistry {\n * heading: { level: HeadingLevel; textAlign?: TextAlignment };\n * }\n * }\n */\n\nimport type { TextAlignment } from '../plugins/text-alignment/TextAlignmentPlugin.js';\nimport type { BlockNode, InlineNode, Mark } from './Document.js';\nimport { isInlineNode } from './Document.js';\n\n/** Plugins augment this interface to register typed node attributes. */\nexport interface NodeAttrRegistry {\n\tparagraph: { textAlign?: TextAlignment };\n}\n\n/** Plugins augment this interface to register typed mark attributes. */\nexport interface MarkAttrRegistry {\n\tbold: Record<string, never>;\n\titalic: Record<string, never>;\n\tunderline: Record<string, never>;\n}\n\n/** Resolves typed attributes for known node types, falls back for unknown. */\nexport type NodeAttrsFor<T extends string> = T extends keyof NodeAttrRegistry\n\t? NodeAttrRegistry[T]\n\t: Record<string, string | number | boolean>;\n\n/** Resolves typed attributes for known mark types, falls back for unknown. */\nexport type MarkAttrsFor<T extends string> = T extends keyof MarkAttrRegistry\n\t? MarkAttrRegistry[T]\n\t: Record<string, string | number | boolean>;\n\n/** Narrows a BlockNode to a typed variant with known attributes. */\nexport function isNodeOfType<T extends keyof NodeAttrRegistry>(\n\tnode: BlockNode,\n\ttype: T,\n): node is BlockNode & { readonly type: T; readonly attrs: NodeAttrRegistry[T] } {\n\treturn (node.type as string) === type;\n}\n\n/** Narrows a Mark to a typed variant with known attributes. */\nexport function isMarkOfType<T extends keyof MarkAttrRegistry>(\n\tmark: Mark,\n\ttype: T,\n): mark is Mark & { readonly type: T; readonly attrs: MarkAttrRegistry[T] } {\n\treturn (mark.type as string) === type;\n}\n\n// --- InlineNode Attribute Registry ---\n\n/** Plugins augment this interface to register typed inline node attributes. */\n// biome-ignore lint/suspicious/noEmptyInterface: module augmentation requires interface\nexport interface InlineNodeAttrRegistry {}\n\n/** Resolves typed attributes for known inline node types, falls back for unknown. */\nexport type InlineNodeAttrsFor<T extends string> = T extends keyof InlineNodeAttrRegistry\n\t? InlineNodeAttrRegistry[T]\n\t: Record<string, string | number | boolean>;\n\n/** Narrows an InlineNode to a typed variant with known attributes. */\nexport function isInlineNodeOfType<T extends keyof InlineNodeAttrRegistry>(\n\tnode: InlineNode,\n\tinlineNodeType: T,\n): node is InlineNode & {\n\treadonly inlineType: T;\n\treadonly attrs: InlineNodeAttrRegistry[T];\n} {\n\treturn isInlineNode(node) && (node.inlineType as string) === inlineNodeType;\n}\n","/**\n * NodeSpec: defines how a block-node type behaves and renders to the DOM.\n */\n\nimport type { NodeAttrsFor } from './AttrRegistry.js';\nimport type { BlockNode } from './Document.js';\nimport type { BlockId } from './TypeBrands.js';\n\nexport interface AttrSpec {\n\treadonly default?: string | number | boolean;\n}\n\n/** Describes which children a node type is allowed to contain. */\nexport interface ContentRule {\n\t/** Allowed child types or group names. */\n\treadonly allow: readonly string[];\n\treadonly min?: number;\n\treadonly max?: number;\n}\n\n/** Creates an HTMLElement with the required `data-block-id` attribute. */\nexport function createBlockElement(tag: string, blockId: BlockId): HTMLElement {\n\tconst el = document.createElement(tag);\n\tel.setAttribute('data-block-id', blockId);\n\treturn el;\n}\n\nexport interface NodeSpec<T extends string = string> {\n\treadonly type: T;\n\t/** Renders the block to a DOM element. Must set `data-block-id` on the root. */\n\ttoDOM(node: Omit<BlockNode, 'attrs'> & { readonly attrs: NodeAttrsFor<T> }): HTMLElement;\n\treadonly attrs?: Readonly<Record<string, AttrSpec>>;\n\t/** If true, the node contains no editable text (e.g. Image, HR). */\n\treadonly isVoid?: boolean;\n\t/** Content model: which children this node can contain. */\n\treadonly content?: ContentRule;\n\t/** Group membership: 'block' | 'inline' | custom. */\n\treadonly group?: string;\n\t/** If true, selection cannot cross this node's boundary (e.g. table_cell). */\n\treadonly isolating?: boolean;\n}\n","/**\n * SchemaRegistry: central registry for node specs, mark specs, node views,\n * keymaps, input rules, and toolbar items registered by plugins.\n */\n\nimport type { InputRule } from '../input/InputRule.js';\nimport type { Keymap } from '../input/Keymap.js';\nimport type { ToolbarItem } from '../plugins/toolbar/ToolbarItem.js';\nimport type { NodeViewFactory } from '../view/NodeView.js';\nimport type { InlineNodeSpec } from './InlineNodeSpec.js';\nimport type { MarkSpec } from './MarkSpec.js';\nimport type { NodeSpec } from './NodeSpec.js';\n\nexport class SchemaRegistry {\n\tprivate readonly _nodeSpecs = new Map<string, NodeSpec>();\n\tprivate readonly _markSpecs = new Map<string, MarkSpec>();\n\tprivate readonly _inlineNodeSpecs = new Map<string, InlineNodeSpec>();\n\tprivate readonly _nodeViews = new Map<string, NodeViewFactory>();\n\tprivate readonly _keymaps: Keymap[] = [];\n\tprivate readonly _inputRules: InputRule[] = [];\n\tprivate readonly _toolbarItems = new Map<string, ToolbarItem>();\n\tprivate readonly _toolbarItemPluginMap = new Map<string, string[]>();\n\n\t// --- NodeSpec ---\n\n\tregisterNodeSpec<T extends string>(spec: NodeSpec<T>): void {\n\t\tif (this._nodeSpecs.has(spec.type)) {\n\t\t\tthrow new Error(`NodeSpec for type \"${spec.type}\" is already registered.`);\n\t\t}\n\t\tthis._nodeSpecs.set(spec.type, spec);\n\t}\n\n\tgetNodeSpec(type: string): NodeSpec | undefined {\n\t\treturn this._nodeSpecs.get(type);\n\t}\n\n\tremoveNodeSpec(type: string): void {\n\t\tthis._nodeSpecs.delete(type);\n\t}\n\n\tgetNodeTypes(): string[] {\n\t\treturn [...this._nodeSpecs.keys()];\n\t}\n\n\t// --- MarkSpec ---\n\n\tregisterMarkSpec<T extends string>(spec: MarkSpec<T>): void {\n\t\tif (this._markSpecs.has(spec.type)) {\n\t\t\tthrow new Error(`MarkSpec for type \"${spec.type}\" is already registered.`);\n\t\t}\n\t\tthis._markSpecs.set(spec.type, spec);\n\t}\n\n\tgetMarkSpec(type: string): MarkSpec | undefined {\n\t\treturn this._markSpecs.get(type);\n\t}\n\n\tremoveMarkSpec(type: string): void {\n\t\tthis._markSpecs.delete(type);\n\t}\n\n\tgetMarkTypes(): string[] {\n\t\treturn [...this._markSpecs.keys()];\n\t}\n\n\t// --- InlineNodeSpec ---\n\n\tregisterInlineNodeSpec<T extends string>(spec: InlineNodeSpec<T>): void {\n\t\tif (this._inlineNodeSpecs.has(spec.type)) {\n\t\t\tthrow new Error(`InlineNodeSpec for type \"${spec.type}\" is already registered.`);\n\t\t}\n\t\tthis._inlineNodeSpecs.set(spec.type, spec);\n\t}\n\n\tgetInlineNodeSpec(type: string): InlineNodeSpec | undefined {\n\t\treturn this._inlineNodeSpecs.get(type);\n\t}\n\n\tremoveInlineNodeSpec(type: string): void {\n\t\tthis._inlineNodeSpecs.delete(type);\n\t}\n\n\tgetInlineNodeTypes(): string[] {\n\t\treturn [...this._inlineNodeSpecs.keys()];\n\t}\n\n\t// --- NodeView ---\n\n\tregisterNodeView(type: string, factory: NodeViewFactory): void {\n\t\tif (this._nodeViews.has(type)) {\n\t\t\tthrow new Error(`NodeView for type \"${type}\" is already registered.`);\n\t\t}\n\t\tthis._nodeViews.set(type, factory);\n\t}\n\n\tgetNodeViewFactory(type: string): NodeViewFactory | undefined {\n\t\treturn this._nodeViews.get(type);\n\t}\n\n\tremoveNodeView(type: string): void {\n\t\tthis._nodeViews.delete(type);\n\t}\n\n\t// --- Keymap ---\n\n\tregisterKeymap(keymap: Keymap): void {\n\t\tfor (const key of Object.keys(keymap)) {\n\t\t\tfor (const existing of this._keymaps) {\n\t\t\t\tif (key in existing) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[notectl] Keymap shortcut \"${key}\" is already registered and will be overridden.`,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._keymaps.push(keymap);\n\t}\n\n\tgetKeymaps(): readonly Keymap[] {\n\t\treturn this._keymaps;\n\t}\n\n\tremoveKeymap(keymap: Keymap): void {\n\t\tconst idx = this._keymaps.indexOf(keymap);\n\t\tif (idx !== -1) this._keymaps.splice(idx, 1);\n\t}\n\n\t// --- InputRule ---\n\n\tregisterInputRule(rule: InputRule): void {\n\t\tthis._inputRules.push(rule);\n\t}\n\n\tgetInputRules(): readonly InputRule[] {\n\t\treturn this._inputRules;\n\t}\n\n\tremoveInputRule(rule: InputRule): void {\n\t\tconst idx = this._inputRules.indexOf(rule);\n\t\tif (idx !== -1) this._inputRules.splice(idx, 1);\n\t}\n\n\t// --- ToolbarItem ---\n\n\tregisterToolbarItem(item: ToolbarItem, pluginId?: string): void {\n\t\tif (this._toolbarItems.has(item.id)) {\n\t\t\tthrow new Error(`ToolbarItem with id \"${item.id}\" is already registered.`);\n\t\t}\n\t\tthis._toolbarItems.set(item.id, item);\n\t\tif (pluginId) {\n\t\t\tconst ids = this._toolbarItemPluginMap.get(pluginId) ?? [];\n\t\t\tids.push(item.id);\n\t\t\tthis._toolbarItemPluginMap.set(pluginId, ids);\n\t\t}\n\t}\n\n\tgetToolbarItemsByPlugin(pluginId: string): ToolbarItem[] {\n\t\tconst ids = this._toolbarItemPluginMap.get(pluginId) ?? [];\n\t\tconst items: ToolbarItem[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst item = this._toolbarItems.get(id);\n\t\t\tif (item) items.push(item);\n\t\t}\n\t\treturn items;\n\t}\n\n\tgetToolbarItem(id: string): ToolbarItem | undefined {\n\t\treturn this._toolbarItems.get(id);\n\t}\n\n\tgetToolbarItems(): ToolbarItem[] {\n\t\treturn [...this._toolbarItems.values()];\n\t}\n\n\tremoveToolbarItem(id: string): void {\n\t\tthis._toolbarItems.delete(id);\n\t\tfor (const [pluginId, ids] of this._toolbarItemPluginMap) {\n\t\t\tconst idx = ids.indexOf(id);\n\t\t\tif (idx !== -1) {\n\t\t\t\tids.splice(idx, 1);\n\t\t\t\tif (ids.length === 0) this._toolbarItemPluginMap.delete(pluginId);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Bulk ---\n\n\tclear(): void {\n\t\tthis._nodeSpecs.clear();\n\t\tthis._markSpecs.clear();\n\t\tthis._inlineNodeSpecs.clear();\n\t\tthis._nodeViews.clear();\n\t\tthis._keymaps.length = 0;\n\t\tthis._inputRules.length = 0;\n\t\tthis._toolbarItems.clear();\n\t\tthis._toolbarItemPluginMap.clear();\n\t}\n}\n","/**\n * Utilities for resolving nodes by path within the document tree.\n * Supports both flat and recursive (nested) document structures.\n */\n\nimport type { BlockNode, Document } from './Document.js';\nimport { isBlockNode } from './Document.js';\n\n/**\n * Resolves a node in the document tree by its path (array of block IDs).\n * The path traces the lineage from the root block down to the target.\n */\nexport function resolveNodeByPath(doc: Document, path: readonly string[]): BlockNode | undefined {\n\tif (path.length === 0) return undefined;\n\n\tlet current: BlockNode | undefined = doc.children.find((b) => b.id === path[0]);\n\tif (!current) return undefined;\n\n\tfor (let i = 1; i < path.length; i++) {\n\t\tconst childId = path[i];\n\t\tif (!childId) return undefined;\n\t\tconst next: BlockNode | undefined = current?.children.find(\n\t\t\t(c): c is BlockNode => isBlockNode(c) && c.id === childId,\n\t\t);\n\t\tif (!next) return undefined;\n\t\tcurrent = next;\n\t}\n\n\treturn current;\n}\n\n/**\n * Resolves the parent of a node at the given path.\n * Returns the parent container (Document or BlockNode) and the child's index within it.\n */\nexport function resolveParentByPath(\n\tdoc: Document,\n\tpath: readonly string[],\n): { parent: Document | BlockNode; index: number } | undefined {\n\tif (path.length === 0) return undefined;\n\n\tif (path.length === 1) {\n\t\tconst index = doc.children.findIndex((b) => b.id === path[0]);\n\t\tif (index === -1) return undefined;\n\t\treturn { parent: doc, index };\n\t}\n\n\tconst parentPath = path.slice(0, -1);\n\tconst parent = resolveNodeByPath(doc, parentPath);\n\tif (!parent) return undefined;\n\n\tconst childId = path[path.length - 1];\n\tif (!childId) return undefined;\n\tconst index = parent.children.findIndex(\n\t\t(c): c is BlockNode => isBlockNode(c) && c.id === childId,\n\t);\n\tif (index === -1) return undefined;\n\n\treturn { parent, index };\n}\n\n/**\n * Finds the path (array of block IDs) to a node by its ID.\n * Performs recursive DFS through the document tree.\n */\nexport function findNodePath(doc: Document, nodeId: string): string[] | undefined {\n\tfor (const block of doc.children) {\n\t\tif (block.id === nodeId) return [nodeId];\n\n\t\tconst subPath = findNodePathInBlock(block, nodeId);\n\t\tif (subPath) return [block.id, ...subPath];\n\t}\n\treturn undefined;\n}\n\nfunction findNodePathInBlock(block: BlockNode, nodeId: string): string[] | undefined {\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tif (child.id === nodeId) return [nodeId];\n\n\t\tconst subPath = findNodePathInBlock(child, nodeId);\n\t\tif (subPath) return [child.id, ...subPath];\n\t}\n\treturn undefined;\n}\n\n/**\n * Walks all block nodes in the document tree in depth-first order.\n * Visits every BlockNode, including nested ones, with their full path.\n */\nexport function walkNodes(\n\tdoc: Document,\n\tcallback: (node: BlockNode, path: string[]) => void,\n): void {\n\tfor (const block of doc.children) {\n\t\twalkNodeRecursive(block, [block.id], callback);\n\t}\n}\n\nfunction walkNodeRecursive(\n\tnode: BlockNode,\n\tpath: string[],\n\tcallback: (node: BlockNode, path: string[]) => void,\n): void {\n\tcallback(node, path);\n\tfor (const child of node.children) {\n\t\tif (isBlockNode(child)) {\n\t\t\twalkNodeRecursive(child, [...path, child.id], callback);\n\t\t}\n\t}\n}\n\n/**\n * Finds a block node by ID anywhere in the document tree (recursive DFS).\n */\nexport function findNode(doc: Document, nodeId: string): BlockNode | undefined {\n\tfor (const block of doc.children) {\n\t\tif (block.id === nodeId) return block;\n\t\tconst found = findNodeInBlock(block, nodeId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\nfunction findNodeInBlock(block: BlockNode, nodeId: string): BlockNode | undefined {\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tif (child.id === nodeId) return child;\n\t\tconst found = findNodeInBlock(child, nodeId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\n/**\n * Finds a block node and returns it together with its path.\n */\nexport function findNodeWithPath(\n\tdoc: Document,\n\tnodeId: string,\n): { node: BlockNode; path: string[] } | undefined {\n\tconst path = findNodePath(doc, nodeId);\n\tif (!path) return undefined;\n\tconst node = resolveNodeByPath(doc, path);\n\tif (!node) return undefined;\n\treturn { node, path };\n}\n","/**\n * Content model validation for nested document structures.\n * Validates whether a parent node type can contain given child types.\n */\n\nimport type { SchemaRegistry } from './SchemaRegistry.js';\n\n/**\n * Checks if a parent node type can contain a child node type,\n * using the content rules and group system from NodeSpec.\n */\nexport function canContain(\n\tregistry: SchemaRegistry,\n\tparentType: string,\n\tchildType: string,\n): boolean {\n\tconst parentSpec = registry.getNodeSpec(parentType);\n\tif (!parentSpec?.content) return true; // No content rule = anything allowed\n\n\tconst childSpec = registry.getNodeSpec(childType);\n\tconst childGroup = childSpec?.group;\n\n\tfor (const allowed of parentSpec.content.allow) {\n\t\tif (allowed === childType) return true;\n\t\tif (allowed === 'text') continue; // 'text' refers to TextNodes, not BlockNodes\n\t\tif (childGroup && allowed === childGroup) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Validates whether the given children types are valid for a parent node type.\n * Checks allow list, min/max constraints.\n */\nexport function validateContent(\n\tregistry: SchemaRegistry,\n\tparentType: string,\n\tchildTypes: readonly string[],\n): boolean {\n\tconst parentSpec = registry.getNodeSpec(parentType);\n\tif (!parentSpec?.content) return true;\n\n\tconst { min = 0, max = Number.POSITIVE_INFINITY } = parentSpec.content;\n\n\t// Check count constraints (only for block children, not text)\n\tconst blockChildTypes = childTypes.filter((t) => t !== 'text');\n\tif (blockChildTypes.length < min || blockChildTypes.length > max) return false;\n\n\t// Check each child is allowed\n\tfor (const childType of blockChildTypes) {\n\t\tif (!canContain(registry, parentType, childType)) return false;\n\t}\n\n\treturn true;\n}\n","/**\n * Registers built-in node specs on a SchemaRegistry.\n * Called during editor initialization before plugins.\n *\n * Note: Mark specs (bold, italic, underline) are registered by the\n * TextFormattingPlugin, not here. Only structural node types belong here.\n */\n\nimport { createBlockElement } from './NodeSpec.js';\nimport type { SchemaRegistry } from './SchemaRegistry.js';\n\n/** Registers the built-in paragraph NodeSpec. */\nexport function registerBuiltinSpecs(registry: SchemaRegistry): void {\n\tregistry.registerNodeSpec({\n\t\ttype: 'paragraph',\n\t\tgroup: 'block',\n\t\tcontent: { allow: ['text'] },\n\t\ttoDOM(node) {\n\t\t\treturn createBlockElement('p', node.id);\n\t\t},\n\t});\n}\n","/**\n * Pure step-application functions operating on Document.\n * Extracted from EditorState for reuse in TransactionBuilder.\n */\n\nimport {\n\ttype BlockNode,\n\ttype ChildNode,\n\ttype Document,\n\ttype InlineNode,\n\ttype Mark,\n\ttype TextNode,\n\ttype TextSegment,\n\taddMarkToSet,\n\tcreateBlockNode,\n\tcreateTextNode,\n\tgetBlockLength,\n\tgetInlineChildren,\n\tisBlockNode,\n\tisInlineNode,\n\tisTextNode,\n\tnormalizeInlineContent,\n\tremoveMarkFromSet,\n} from '../model/Document.js';\nimport type {\n\tAddMarkStep,\n\tDeleteTextStep,\n\tInsertInlineNodeStep,\n\tInsertNodeStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveInlineNodeStep,\n\tRemoveMarkStep,\n\tRemoveNodeStep,\n\tSetBlockTypeStep,\n\tSetInlineNodeAttrStep,\n\tSetNodeAttrStep,\n\tSplitBlockStep,\n\tStep,\n} from './Transaction.js';\n\n/** Applies a single step to a document and returns the new document. */\nexport function applyStep(doc: Document, step: Step): Document {\n\tswitch (step.type) {\n\t\tcase 'insertText':\n\t\t\treturn applyInsertText(doc, step);\n\t\tcase 'deleteText':\n\t\t\treturn applyDeleteText(doc, step);\n\t\tcase 'splitBlock':\n\t\t\treturn applySplitBlock(doc, step);\n\t\tcase 'mergeBlocks':\n\t\t\treturn applyMergeBlocks(doc, step);\n\t\tcase 'addMark':\n\t\t\treturn applyAddMark(doc, step);\n\t\tcase 'removeMark':\n\t\t\treturn applyRemoveMark(doc, step);\n\t\tcase 'setStoredMarks':\n\t\t\treturn doc; // Stored marks are handled at the state level, not document\n\t\tcase 'setBlockType':\n\t\t\treturn applySetBlockType(doc, step);\n\t\tcase 'insertNode':\n\t\t\treturn applyInsertNode(doc, step);\n\t\tcase 'removeNode':\n\t\t\treturn applyRemoveNode(doc, step);\n\t\tcase 'setNodeAttr':\n\t\t\treturn applySetNodeAttr(doc, step);\n\t\tcase 'insertInlineNode':\n\t\t\treturn applyInsertInlineNode(doc, step);\n\t\tcase 'removeInlineNode':\n\t\t\treturn applyRemoveInlineNode(doc, step);\n\t\tcase 'setInlineNodeAttr':\n\t\t\treturn applySetInlineNodeAttr(doc, step);\n\t}\n}\n\nfunction applyInsertText(doc: Document, step: InsertTextStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = step.segments\n\t\t\t? insertSegmentsIntoInlineContent(inlineChildren, step.offset, step.segments)\n\t\t\t: insertTextIntoInlineContent(inlineChildren, step.offset, step.text, step.marks);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\nfunction applyDeleteText(doc: Document, step: DeleteTextStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = deleteFromInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.from,\n\t\t\tstep.to,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\nfunction applySplitBlock(doc: Document, step: SplitBlockStep): Document {\n\t// Try at top level first\n\tconst blockIndex: number = doc.children.findIndex((b) => b.id === step.blockId);\n\n\tif (blockIndex !== -1) {\n\t\tconst block: BlockNode | undefined = doc.children[blockIndex];\n\t\tif (!block) return doc;\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst len: number = getBlockLength(block);\n\t\tconst nodesBeforeSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\t0,\n\t\t\tstep.offset,\n\t\t);\n\t\tconst nodesAfterSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t\tlen,\n\t\t);\n\n\t\tconst updatedBlock: BlockNode = {\n\t\t\t...block,\n\t\t\tchildren: normalizeInlineContent(nodesBeforeSplit),\n\t\t};\n\t\tconst newBlock: BlockNode = createBlockNode(\n\t\t\tblock.type,\n\t\t\tnormalizeInlineContent(nodesAfterSplit),\n\t\t\tstep.newBlockId,\n\t\t\tblock.attrs,\n\t\t);\n\n\t\tconst newChildren: BlockNode[] = [...doc.children];\n\t\tnewChildren.splice(blockIndex, 1, updatedBlock, newBlock);\n\t\treturn { children: newChildren };\n\t}\n\n\t// Recurse into block children\n\treturn {\n\t\tchildren: doc.children.map((child) => {\n\t\t\tconst mapped: BlockNode | null = splitBlockRecursive(child, step);\n\t\t\treturn mapped ?? child;\n\t\t}),\n\t};\n}\n\nfunction splitBlockRecursive(node: BlockNode, step: SplitBlockStep): BlockNode | null {\n\tconst idx: number = node.children.findIndex((c) => isBlockNode(c) && c.id === step.blockId);\n\tif (idx !== -1) {\n\t\tconst block: BlockNode = node.children[idx] as BlockNode;\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst len: number = getBlockLength(block);\n\t\tconst nodesBeforeSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\t0,\n\t\t\tstep.offset,\n\t\t);\n\t\tconst nodesAfterSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t\tlen,\n\t\t);\n\n\t\tconst updatedBlock: BlockNode = {\n\t\t\t...block,\n\t\t\tchildren: normalizeInlineContent(nodesBeforeSplit),\n\t\t};\n\t\tconst newBlock: BlockNode = createBlockNode(\n\t\t\tblock.type,\n\t\t\tnormalizeInlineContent(nodesAfterSplit),\n\t\t\tstep.newBlockId,\n\t\t\tblock.attrs,\n\t\t);\n\n\t\tconst newChildren: ChildNode[] = [...node.children] as ChildNode[];\n\t\tnewChildren.splice(idx, 1, updatedBlock, newBlock);\n\t\treturn { ...node, children: newChildren };\n\t}\n\n\t// Recurse deeper\n\tlet changed = false;\n\tconst newChildren: ChildNode[] = node.children.map((child) => {\n\t\tif (!isBlockNode(child)) return child;\n\t\tconst mapped: BlockNode | null = splitBlockRecursive(child, step);\n\t\tif (mapped) {\n\t\t\tchanged = true;\n\t\t\treturn mapped;\n\t\t}\n\t\treturn child;\n\t});\n\n\treturn changed ? { ...node, children: newChildren } : null;\n}\n\nfunction applyMergeBlocks(doc: Document, step: MergeBlocksStep): Document {\n\t// Try at top level first\n\tconst targetIndex: number = doc.children.findIndex((b) => b.id === step.targetBlockId);\n\tconst sourceIndex: number = doc.children.findIndex((b) => b.id === step.sourceBlockId);\n\n\tif (targetIndex !== -1 && sourceIndex !== -1) {\n\t\tconst target: BlockNode | undefined = doc.children[targetIndex];\n\t\tconst source: BlockNode | undefined = doc.children[sourceIndex];\n\t\tif (!target || !source) return doc;\n\t\tconst targetInline: readonly (TextNode | InlineNode)[] = getInlineChildren(target);\n\t\tconst sourceInline: readonly (TextNode | InlineNode)[] = getInlineChildren(source);\n\t\tconst mergedChildren: readonly (TextNode | InlineNode)[] = normalizeInlineContent([\n\t\t\t...targetInline,\n\t\t\t...sourceInline,\n\t\t]);\n\t\tconst mergedBlock: BlockNode = { ...target, children: mergedChildren };\n\n\t\tconst newChildren: readonly BlockNode[] = doc.children.filter(\n\t\t\t(b) => b.id !== step.sourceBlockId,\n\t\t);\n\t\treturn {\n\t\t\tchildren: newChildren.map((b) => (b.id === step.targetBlockId ? mergedBlock : b)),\n\t\t};\n\t}\n\n\t// Recurse into block children\n\treturn {\n\t\tchildren: doc.children.map((child) => {\n\t\t\tconst mapped: BlockNode | null = mergeBlocksRecursive(child, step);\n\t\t\treturn mapped ?? child;\n\t\t}),\n\t};\n}\n\nfunction mergeBlocksRecursive(node: BlockNode, step: MergeBlocksStep): BlockNode | null {\n\tconst targetIdx: number = node.children.findIndex(\n\t\t(c) => isBlockNode(c) && c.id === step.targetBlockId,\n\t);\n\tconst sourceIdx: number = node.children.findIndex(\n\t\t(c) => isBlockNode(c) && c.id === step.sourceBlockId,\n\t);\n\n\tif (targetIdx !== -1 && sourceIdx !== -1) {\n\t\tconst target: BlockNode = node.children[targetIdx] as BlockNode;\n\t\tconst source: BlockNode = node.children[sourceIdx] as BlockNode;\n\t\tconst targetInline: readonly (TextNode | InlineNode)[] = getInlineChildren(target);\n\t\tconst sourceInline: readonly (TextNode | InlineNode)[] = getInlineChildren(source);\n\t\tconst mergedChildren: readonly (TextNode | InlineNode)[] = normalizeInlineContent([\n\t\t\t...targetInline,\n\t\t\t...sourceInline,\n\t\t]);\n\t\tconst mergedBlock: BlockNode = { ...target, children: mergedChildren };\n\n\t\tconst filtered: ChildNode[] = node.children.filter(\n\t\t\t(c) => !isBlockNode(c) || c.id !== step.sourceBlockId,\n\t\t);\n\t\tconst result: ChildNode[] = filtered.map((c) =>\n\t\t\tisBlockNode(c) && c.id === step.targetBlockId ? mergedBlock : c,\n\t\t);\n\t\treturn { ...node, children: result };\n\t}\n\n\t// Recurse deeper\n\tlet changed = false;\n\tconst newChildren: ChildNode[] = node.children.map((child) => {\n\t\tif (!isBlockNode(child)) return child;\n\t\tconst mapped: BlockNode | null = mergeBlocksRecursive(child, step);\n\t\tif (mapped) {\n\t\t\tchanged = true;\n\t\t\treturn mapped;\n\t\t}\n\t\treturn child;\n\t});\n\n\treturn changed ? { ...node, children: newChildren } : null;\n}\n\nfunction applyAddMark(doc: Document, step: AddMarkStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = applyMarkToInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.from,\n\t\t\tstep.to,\n\t\t\tstep.mark,\n\t\t\ttrue,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\nfunction applyRemoveMark(doc: Document, step: RemoveMarkStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = applyMarkToInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.from,\n\t\t\tstep.to,\n\t\t\tstep.mark,\n\t\t\tfalse,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\n// --- InlineNode Step Application ---\n\nfunction applyInsertInlineNode(doc: Document, step: InsertInlineNodeStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = insertInlineNodeAtOffset(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t\tstep.node,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\nfunction applyRemoveInlineNode(doc: Document, step: RemoveInlineNodeStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = removeInlineNodeAtOffset(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, normalizeInlineContent(newChildren)),\n\t\t};\n\t});\n}\n\nfunction applySetInlineNodeAttr(doc: Document, step: SetInlineNodeAttrStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = setInlineNodeAttrsAtOffset(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t\tstep.attrs,\n\t\t);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(block.children, newChildren),\n\t\t};\n\t});\n}\n\n// --- Helpers ---\n\nfunction mapBlock(doc: Document, blockId: string, fn: (block: BlockNode) => BlockNode): Document {\n\treturn {\n\t\tchildren: mapBlockInChildren(doc.children, blockId, fn) as BlockNode[],\n\t};\n}\n\nfunction mapBlockInChildren(\n\tchildren: readonly ChildNode[],\n\tblockId: string,\n\tfn: (block: BlockNode) => BlockNode,\n): ChildNode[] {\n\treturn children.map((child) => {\n\t\tif (!isBlockNode(child)) return child;\n\t\tif (child.id === blockId) return fn(child);\n\t\t// Recurse into block children\n\t\tconst mappedChildren: ChildNode[] = mapBlockInChildren(child.children, blockId, fn);\n\t\tif (mappedChildren === child.children) return child;\n\t\treturn { ...child, children: mappedChildren };\n\t});\n}\n\n/**\n * Replaces the inline content children of a ChildNode array,\n * preserving any BlockNode children in their original positions.\n */\nfunction replaceInlineChildren(\n\toriginal: readonly ChildNode[],\n\tnewInlineChildren: readonly (TextNode | InlineNode)[],\n): readonly ChildNode[] {\n\t// Fast path: if no block children exist, just return new inline nodes\n\tif (original.every((c) => isTextNode(c) || isInlineNode(c))) {\n\t\treturn newInlineChildren;\n\t}\n\t// Mixed: put inline nodes first, then block nodes (preserves structure)\n\tconst blockChildren: ChildNode[] = original.filter((c) => !isTextNode(c) && !isInlineNode(c));\n\treturn [...newInlineChildren, ...blockChildren];\n}\n\n/**\n * Inserts text into mixed inline content at the given offset.\n * Handles both TextNode and InlineNode children.\n */\nfunction insertTextIntoInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\ttext: string,\n\tmarks: readonly Mark[],\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\tlet inserted = false;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (!inserted && offset === pos) {\n\t\t\t\tresult.push(createTextNode(text, marks));\n\t\t\t\tinserted = true;\n\t\t\t}\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (!inserted && offset >= pos && offset <= nodeEnd) {\n\t\t\tconst localOffset: number = offset - pos;\n\t\t\tconst before: string = node.text.slice(0, localOffset);\n\t\t\tconst after: string = node.text.slice(localOffset);\n\n\t\t\tif (before) result.push(createTextNode(before, node.marks));\n\t\t\tresult.push(createTextNode(text, marks));\n\t\t\tif (after) result.push(createTextNode(after, node.marks));\n\t\t\tinserted = true;\n\t\t} else {\n\t\t\tresult.push(node);\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (!inserted) {\n\t\tresult.push(createTextNode(text, marks));\n\t}\n\n\treturn result;\n}\n\n/**\n * Inserts segments into mixed inline content at the given offset.\n */\nfunction insertSegmentsIntoInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tsegments: readonly TextSegment[],\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\tlet inserted = false;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (!inserted && offset === pos) {\n\t\t\t\tfor (const seg of segments) {\n\t\t\t\t\tresult.push(createTextNode(seg.text, seg.marks));\n\t\t\t\t}\n\t\t\t\tinserted = true;\n\t\t\t}\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (!inserted && offset >= pos && offset <= nodeEnd) {\n\t\t\tconst localOffset: number = offset - pos;\n\t\t\tconst before: string = node.text.slice(0, localOffset);\n\t\t\tconst after: string = node.text.slice(localOffset);\n\n\t\t\tif (before) result.push(createTextNode(before, node.marks));\n\t\t\tfor (const seg of segments) {\n\t\t\t\tresult.push(createTextNode(seg.text, seg.marks));\n\t\t\t}\n\t\t\tif (after) result.push(createTextNode(after, node.marks));\n\t\t\tinserted = true;\n\t\t} else {\n\t\t\tresult.push(node);\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (!inserted) {\n\t\tfor (const seg of segments) {\n\t\t\tresult.push(createTextNode(seg.text, seg.marks));\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Deletes content from mixed inline content in the given range.\n * Removes InlineNodes that fall within the range.\n */\nfunction deleteFromInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tconst nodeEnd: number = pos + 1;\n\t\t\t// Keep if outside the delete range\n\t\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tresult.push(node);\n\t\t} else {\n\t\t\tconst deleteFrom: number = Math.max(0, from - pos);\n\t\t\tconst deleteTo: number = Math.min(node.text.length, to - pos);\n\t\t\tconst remaining: string = node.text.slice(0, deleteFrom) + node.text.slice(deleteTo);\n\t\t\tif (remaining.length > 0) {\n\t\t\t\tresult.push(createTextNode(remaining, node.marks));\n\t\t\t}\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\treturn result;\n}\n\n/**\n * Slices mixed inline content to the given range.\n * InlineNodes are preserved as atoms (included if within range).\n */\nfunction sliceInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tconst nodeEnd: number = pos + 1;\n\t\t\tif (nodeEnd > from && pos < to) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\t// Outside the slice range\n\t\t} else {\n\t\t\tconst sliceFrom: number = Math.max(0, from - pos);\n\t\t\tconst sliceTo: number = Math.min(node.text.length, to - pos);\n\t\t\tconst text: string = node.text.slice(sliceFrom, sliceTo);\n\t\t\tif (text.length > 0) {\n\t\t\t\tresult.push(createTextNode(text, node.marks));\n\t\t\t}\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (result.length === 0) {\n\t\tresult.push(createTextNode(''));\n\t}\n\n\treturn result;\n}\n\n/**\n * Applies or removes a mark from mixed inline content in the given range.\n * InlineNodes are passed through unchanged (marks only apply to text).\n */\nfunction applyMarkToInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n\tmark: Mark,\n\tadd: boolean,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tresult.push(node);\n\t\t} else if (pos >= from && nodeEnd <= to) {\n\t\t\tconst newMarks: readonly Mark[] = add\n\t\t\t\t? addMarkToSet(node.marks, mark)\n\t\t\t\t: removeMarkFromSet(node.marks, mark.type);\n\t\t\tresult.push(createTextNode(node.text, newMarks));\n\t\t} else {\n\t\t\tconst overlapStart: number = Math.max(0, from - pos);\n\t\t\tconst overlapEnd: number = Math.min(node.text.length, to - pos);\n\n\t\t\tconst beforeText: string = node.text.slice(0, overlapStart);\n\t\t\tconst insideText: string = node.text.slice(overlapStart, overlapEnd);\n\t\t\tconst afterText: string = node.text.slice(overlapEnd);\n\n\t\t\tif (beforeText) result.push(createTextNode(beforeText, node.marks));\n\t\t\tif (insideText) {\n\t\t\t\tconst newMarks: readonly Mark[] = add\n\t\t\t\t\t? addMarkToSet(node.marks, mark)\n\t\t\t\t\t: removeMarkFromSet(node.marks, mark.type);\n\t\t\t\tresult.push(createTextNode(insideText, newMarks));\n\t\t\t}\n\t\t\tif (afterText) result.push(createTextNode(afterText, node.marks));\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\treturn result;\n}\n\n/** Inserts an InlineNode at the given offset in mixed inline content. */\nfunction insertInlineNodeAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tinlineNode: InlineNode,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\tlet inserted = false;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (!inserted && offset === pos) {\n\t\t\t\tresult.push(inlineNode);\n\t\t\t\tinserted = true;\n\t\t\t}\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (!inserted && offset >= pos && offset <= nodeEnd) {\n\t\t\tconst localOffset: number = offset - pos;\n\t\t\tconst before: string = node.text.slice(0, localOffset);\n\t\t\tconst after: string = node.text.slice(localOffset);\n\n\t\t\tif (before) result.push(createTextNode(before, node.marks));\n\t\t\tresult.push(inlineNode);\n\t\t\tif (after) result.push(createTextNode(after, node.marks));\n\t\t\tinserted = true;\n\t\t} else {\n\t\t\tresult.push(node);\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (!inserted) {\n\t\tresult.push(inlineNode);\n\t}\n\n\treturn result;\n}\n\n/** Removes the InlineNode at the given offset from mixed inline content. */\nfunction removeInlineNodeAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (pos !== offset) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push(node);\n\t\tpos += node.text.length;\n\t}\n\n\treturn result;\n}\n\n/** Replaces the attrs of an InlineNode at the given offset. */\nfunction setInlineNodeAttrsAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tattrs: Readonly<Record<string, string | number | boolean>>,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (pos === offset) {\n\t\t\t\tresult.push({ ...node, attrs });\n\t\t\t} else {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push(node);\n\t\tpos += node.text.length;\n\t}\n\n\treturn result;\n}\n\nfunction applySetBlockType(doc: Document, step: SetBlockTypeStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => ({\n\t\t...block,\n\t\ttype: step.nodeType,\n\t\t...(step.attrs ? { attrs: step.attrs } : { attrs: undefined }),\n\t}));\n}\n\n// --- Structural Step Application ---\n\nfunction applyInsertNode(doc: Document, step: InsertNodeStep): Document {\n\tif (step.parentPath.length === 0) {\n\t\t// Insert at document root\n\t\tconst newChildren: BlockNode[] = [...doc.children];\n\t\tnewChildren.splice(step.index, 0, step.node);\n\t\treturn { children: newChildren };\n\t}\n\n\treturn mapNodeByPath(doc, step.parentPath, (parent) => {\n\t\tconst newChildren: ChildNode[] = [...parent.children];\n\t\tnewChildren.splice(step.index, 0, step.node);\n\t\treturn { ...parent, children: newChildren };\n\t});\n}\n\nfunction applyRemoveNode(doc: Document, step: RemoveNodeStep): Document {\n\tif (step.parentPath.length === 0) {\n\t\t// Remove from document root\n\t\tconst newChildren: BlockNode[] = [...doc.children];\n\t\tnewChildren.splice(step.index, 1);\n\t\treturn { children: newChildren };\n\t}\n\n\treturn mapNodeByPath(doc, step.parentPath, (parent) => {\n\t\tconst newChildren: ChildNode[] = [...parent.children];\n\t\tnewChildren.splice(step.index, 1);\n\t\treturn { ...parent, children: newChildren };\n\t});\n}\n\nfunction applySetNodeAttr(doc: Document, step: SetNodeAttrStep): Document {\n\tconst nodeId: string | undefined = step.path[step.path.length - 1];\n\tif (!nodeId) return doc;\n\n\treturn mapBlock(doc, nodeId, (block) => ({\n\t\t...block,\n\t\tattrs: step.attrs,\n\t}));\n}\n\n/**\n * Maps a node at the given path, replacing it with the result of fn.\n * Navigates down the path immutably, creating new parent nodes as needed.\n */\nfunction mapNodeByPath(\n\tdoc: Document,\n\tpath: readonly string[],\n\tfn: (node: BlockNode) => BlockNode,\n): Document {\n\tif (path.length === 0) return doc;\n\n\tconst rootId: string | undefined = path[0];\n\tif (!rootId) return doc;\n\treturn {\n\t\tchildren: doc.children.map((child) => {\n\t\t\tif (!isBlockNode(child) || child.id !== rootId) return child;\n\t\t\tif (path.length === 1) return fn(child);\n\t\t\treturn mapNodeByPathRecursive(child, path, 1, fn);\n\t\t}),\n\t};\n}\n\nfunction mapNodeByPathRecursive(\n\tnode: BlockNode,\n\tpath: readonly string[],\n\tdepth: number,\n\tfn: (node: BlockNode) => BlockNode,\n): BlockNode {\n\tconst targetId: string | undefined = path[depth];\n\tif (!targetId) return node;\n\tconst newChildren: ChildNode[] = node.children.map((child) => {\n\t\tif (!isBlockNode(child) || child.id !== targetId) return child;\n\t\tif (depth === path.length - 1) return fn(child);\n\t\treturn mapNodeByPathRecursive(child, path, depth + 1, fn);\n\t});\n\treturn { ...node, children: newChildren };\n}\n","/**\n * Transaction system for the Notectl editor.\n * Transactions describe atomic, invertible state changes.\n */\n\nimport type {\n\tBlockAttrs,\n\tBlockNode,\n\tDocument,\n\tInlineNode,\n\tMark,\n\tTextSegment,\n} from '../model/Document.js';\nimport {\n\tgetBlockLength,\n\tgetBlockMarksAtOffset,\n\tgetBlockSegmentsInRange,\n\tgetBlockText,\n\tgetContentAtOffset,\n\tgetInlineChildren,\n\tisBlockNode,\n\tisInlineNode,\n} from '../model/Document.js';\nimport { findNode, resolveNodeByPath } from '../model/NodeResolver.js';\nimport type { Selection } from '../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../model/TypeBrands.js';\nimport { applyStep } from './StepApplication.js';\n\n// --- Step Types ---\n\nexport interface InsertTextStep {\n\treadonly type: 'insertText';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n\treadonly segments?: readonly TextSegment[];\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface DeleteTextStep {\n\treadonly type: 'deleteText';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly deletedText: string;\n\treadonly deletedMarks: readonly Mark[];\n\treadonly deletedSegments: readonly TextSegment[];\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SplitBlockStep {\n\treadonly type: 'splitBlock';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly newBlockId: BlockId;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface MergeBlocksStep {\n\treadonly type: 'mergeBlocks';\n\treadonly targetBlockId: BlockId;\n\treadonly sourceBlockId: BlockId;\n\treadonly targetLengthBefore: number;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface AddMarkStep {\n\treadonly type: 'addMark';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly mark: Mark;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface RemoveMarkStep {\n\treadonly type: 'removeMark';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly mark: Mark;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SetStoredMarksStep {\n\treadonly type: 'setStoredMarks';\n\treadonly marks: readonly Mark[] | null;\n\treadonly previousMarks: readonly Mark[] | null;\n}\n\nexport interface SetBlockTypeStep {\n\treadonly type: 'setBlockType';\n\treadonly blockId: BlockId;\n\treadonly nodeType: NodeTypeName;\n\treadonly attrs?: BlockAttrs;\n\treadonly previousNodeType: NodeTypeName;\n\treadonly previousAttrs?: BlockAttrs;\n\treadonly path?: readonly BlockId[];\n}\n\n// --- Structural Steps (for nested documents) ---\n\nexport interface InsertNodeStep {\n\treadonly type: 'insertNode';\n\treadonly parentPath: readonly BlockId[];\n\treadonly index: number;\n\treadonly node: BlockNode;\n}\n\nexport interface RemoveNodeStep {\n\treadonly type: 'removeNode';\n\treadonly parentPath: readonly BlockId[];\n\treadonly index: number;\n\treadonly removedNode: BlockNode;\n}\n\nexport interface SetNodeAttrStep {\n\treadonly type: 'setNodeAttr';\n\treadonly path: readonly BlockId[];\n\treadonly attrs: BlockAttrs | undefined;\n\treadonly previousAttrs?: BlockAttrs;\n}\n\n// --- InlineNode Steps ---\n\nexport interface InsertInlineNodeStep {\n\treadonly type: 'insertInlineNode';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly node: InlineNode;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface RemoveInlineNodeStep {\n\treadonly type: 'removeInlineNode';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly removedNode: InlineNode;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SetInlineNodeAttrStep {\n\treadonly type: 'setInlineNodeAttr';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly attrs: Readonly<Record<string, string | number | boolean>>;\n\treadonly previousAttrs: Readonly<Record<string, string | number | boolean>>;\n\treadonly path?: readonly BlockId[];\n}\n\nexport type Step =\n\t| InsertTextStep\n\t| DeleteTextStep\n\t| SplitBlockStep\n\t| MergeBlocksStep\n\t| AddMarkStep\n\t| RemoveMarkStep\n\t| SetStoredMarksStep\n\t| SetBlockTypeStep\n\t| InsertNodeStep\n\t| RemoveNodeStep\n\t| SetNodeAttrStep\n\t| InsertInlineNodeStep\n\t| RemoveInlineNodeStep\n\t| SetInlineNodeAttrStep;\n\n// --- Transaction ---\n\nexport type TransactionOrigin = 'input' | 'paste' | 'command' | 'history' | 'api';\n\nexport interface TransactionMetadata {\n\treadonly origin: TransactionOrigin;\n\treadonly timestamp: number;\n}\n\nexport interface Transaction {\n\treadonly steps: readonly Step[];\n\treadonly selectionBefore: Selection;\n\treadonly selectionAfter: Selection;\n\treadonly storedMarksAfter: readonly Mark[] | null;\n\treadonly metadata: TransactionMetadata;\n}\n\n// --- Step Inversion ---\n\n/** Inverts a single step for undo. */\nexport function invertStep(step: Step): Step {\n\tswitch (step.type) {\n\t\tcase 'insertText':\n\t\t\treturn {\n\t\t\t\ttype: 'deleteText',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\tfrom: step.offset,\n\t\t\t\tto: step.offset + step.text.length,\n\t\t\t\tdeletedText: step.text,\n\t\t\t\tdeletedMarks: step.marks,\n\t\t\t\tdeletedSegments: step.segments ?? [{ text: step.text, marks: [...step.marks] }],\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'deleteText':\n\t\t\treturn {\n\t\t\t\ttype: 'insertText',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\toffset: step.from,\n\t\t\t\ttext: step.deletedText,\n\t\t\t\tmarks: step.deletedMarks,\n\t\t\t\tsegments: step.deletedSegments,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'splitBlock':\n\t\t\treturn {\n\t\t\t\ttype: 'mergeBlocks',\n\t\t\t\ttargetBlockId: step.blockId,\n\t\t\t\tsourceBlockId: step.newBlockId,\n\t\t\t\ttargetLengthBefore: step.offset,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'mergeBlocks':\n\t\t\treturn {\n\t\t\t\ttype: 'splitBlock',\n\t\t\t\tblockId: step.targetBlockId,\n\t\t\t\toffset: step.targetLengthBefore,\n\t\t\t\tnewBlockId: step.sourceBlockId,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'addMark':\n\t\t\treturn {\n\t\t\t\ttype: 'removeMark',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\tfrom: step.from,\n\t\t\t\tto: step.to,\n\t\t\t\tmark: step.mark,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'removeMark':\n\t\t\treturn {\n\t\t\t\ttype: 'addMark',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\tfrom: step.from,\n\t\t\t\tto: step.to,\n\t\t\t\tmark: step.mark,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'setStoredMarks':\n\t\t\treturn {\n\t\t\t\ttype: 'setStoredMarks',\n\t\t\t\tmarks: step.previousMarks,\n\t\t\t\tpreviousMarks: step.marks,\n\t\t\t};\n\t\tcase 'setBlockType':\n\t\t\treturn {\n\t\t\t\ttype: 'setBlockType',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\tnodeType: step.previousNodeType,\n\t\t\t\tattrs: step.previousAttrs,\n\t\t\t\tpreviousNodeType: step.nodeType,\n\t\t\t\tpreviousAttrs: step.attrs,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'insertNode':\n\t\t\treturn {\n\t\t\t\ttype: 'removeNode',\n\t\t\t\tparentPath: step.parentPath,\n\t\t\t\tindex: step.index,\n\t\t\t\tremovedNode: step.node,\n\t\t\t};\n\t\tcase 'removeNode':\n\t\t\treturn {\n\t\t\t\ttype: 'insertNode',\n\t\t\t\tparentPath: step.parentPath,\n\t\t\t\tindex: step.index,\n\t\t\t\tnode: step.removedNode,\n\t\t\t};\n\t\tcase 'setNodeAttr':\n\t\t\treturn {\n\t\t\t\ttype: 'setNodeAttr',\n\t\t\t\tpath: step.path,\n\t\t\t\tattrs: step.previousAttrs,\n\t\t\t\tpreviousAttrs: step.attrs,\n\t\t\t};\n\t\tcase 'insertInlineNode':\n\t\t\treturn {\n\t\t\t\ttype: 'removeInlineNode',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\toffset: step.offset,\n\t\t\t\tremovedNode: step.node,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'removeInlineNode':\n\t\t\treturn {\n\t\t\t\ttype: 'insertInlineNode',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\toffset: step.offset,\n\t\t\t\tnode: step.removedNode,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t\tcase 'setInlineNodeAttr':\n\t\t\treturn {\n\t\t\t\ttype: 'setInlineNodeAttr',\n\t\t\t\tblockId: step.blockId,\n\t\t\t\toffset: step.offset,\n\t\t\t\tattrs: step.previousAttrs,\n\t\t\t\tpreviousAttrs: step.attrs,\n\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t};\n\t}\n}\n\n/** Inverts an entire transaction (reverses step order and swaps selections). */\nexport function invertTransaction(tr: Transaction): Transaction {\n\treturn {\n\t\tsteps: tr.steps.map(invertStep).reverse(),\n\t\tselectionBefore: tr.selectionAfter,\n\t\tselectionAfter: tr.selectionBefore,\n\t\tstoredMarksAfter: null,\n\t\tmetadata: {\n\t\t\torigin: 'history',\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t};\n}\n\n// --- TransactionBuilder ---\n\n/** Fluent API for building transactions. */\nexport class TransactionBuilder {\n\tprivate readonly steps: Step[] = [];\n\tprivate selection: Selection;\n\tprivate storedMarks: readonly Mark[] | null;\n\tprivate readonly selectionBefore: Selection;\n\tprivate readonly origin: TransactionOrigin;\n\tprivate workingDoc: Document | null;\n\n\tconstructor(\n\t\tcurrentSelection: Selection,\n\t\tcurrentStoredMarks: readonly Mark[] | null,\n\t\torigin: TransactionOrigin = 'api',\n\t\tdoc?: Document,\n\t) {\n\t\tthis.selection = currentSelection;\n\t\tthis.selectionBefore = currentSelection;\n\t\tthis.storedMarks = currentStoredMarks;\n\t\tthis.origin = origin;\n\t\tthis.workingDoc = doc ?? null;\n\t}\n\n\t/** Adds an insert-text step. Updates workingDoc if available. */\n\tinsertText(\n\t\tblockId: BlockId,\n\t\toffset: number,\n\t\ttext: string,\n\t\tmarks: readonly Mark[],\n\t\tsegments?: readonly TextSegment[],\n\t): this {\n\t\tconst step: InsertTextStep = {\n\t\t\ttype: 'insertText',\n\t\t\tblockId,\n\t\t\toffset,\n\t\t\ttext,\n\t\t\tmarks,\n\t\t\t...(segments ? { segments } : {}),\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Adds a delete-text step with explicit data. Updates workingDoc if available. */\n\tdeleteText(\n\t\tblockId: BlockId,\n\t\tfrom: number,\n\t\tto: number,\n\t\tdeletedText: string,\n\t\tdeletedMarks: readonly Mark[],\n\t\tdeletedSegments?: readonly TextSegment[],\n\t): this {\n\t\tlet segments: readonly TextSegment[];\n\t\tif (deletedSegments) {\n\t\t\tsegments = deletedSegments;\n\t\t} else if (this.workingDoc) {\n\t\t\tconst block = findNode(this.workingDoc, blockId);\n\t\t\tsegments = block\n\t\t\t\t? getBlockSegmentsInRange(block, from, to)\n\t\t\t\t: [{ text: deletedText, marks: [...deletedMarks] }];\n\t\t} else {\n\t\t\tsegments = [{ text: deletedText, marks: [...deletedMarks] }];\n\t\t}\n\t\tconst step: DeleteTextStep = {\n\t\t\ttype: 'deleteText',\n\t\t\tblockId,\n\t\t\tfrom,\n\t\t\tto,\n\t\t\tdeletedText,\n\t\t\tdeletedMarks,\n\t\t\tdeletedSegments: segments,\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Deletes text at the given range, auto-deriving deletedText, deletedMarks, and deletedSegments\n\t * from the working document. Requires a document to be provided at construction.\n\t */\n\tdeleteTextAt(blockId: BlockId, from: number, to: number): this {\n\t\tconst doc = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'deleteTextAt requires a document. Use state.transaction() or provide doc to constructor.',\n\t\t\t);\n\t\t}\n\n\t\tconst block = findNode(doc, blockId);\n\t\tif (!block) {\n\t\t\tthrow new Error(`Block \"${blockId}\" not found in working document.`);\n\t\t}\n\n\t\tconst text = getBlockText(block);\n\t\tconst deletedText = text.slice(from, to);\n\t\tconst deletedMarks = getBlockMarksAtOffset(block, from);\n\t\tconst deletedSegments = getBlockSegmentsInRange(block, from, to);\n\n\t\treturn this.deleteText(blockId, from, to, deletedText, deletedMarks, deletedSegments);\n\t}\n\n\t/** Adds a split-block step. Updates workingDoc if available. */\n\tsplitBlock(blockId: BlockId, offset: number, newBlockId: BlockId): this {\n\t\tconst step: SplitBlockStep = { type: 'splitBlock', blockId, offset, newBlockId };\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Adds a merge-blocks step with explicit targetLengthBefore. Updates workingDoc if available. */\n\tmergeBlocks(targetBlockId: BlockId, sourceBlockId: BlockId, targetLengthBefore: number): this {\n\t\tconst step: MergeBlocksStep = {\n\t\t\ttype: 'mergeBlocks',\n\t\t\ttargetBlockId,\n\t\t\tsourceBlockId,\n\t\t\ttargetLengthBefore,\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Merges two blocks, auto-deriving targetLengthBefore from the working document.\n\t * Requires a document to be provided at construction.\n\t */\n\tmergeBlocksAt(targetBlockId: BlockId, sourceBlockId: BlockId): this {\n\t\tconst doc = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'mergeBlocksAt requires a document. Use state.transaction() or provide doc to constructor.',\n\t\t\t);\n\t\t}\n\n\t\tconst targetBlock = findNode(doc, targetBlockId);\n\t\tif (!targetBlock) {\n\t\t\tthrow new Error(`Target block \"${targetBlockId}\" not found in working document.`);\n\t\t}\n\n\t\tconst targetLengthBefore = getBlockLength(targetBlock);\n\t\treturn this.mergeBlocks(targetBlockId, sourceBlockId, targetLengthBefore);\n\t}\n\n\t/** Adds an add-mark step. Updates workingDoc if available. */\n\taddMark(blockId: BlockId, from: number, to: number, mark: Mark): this {\n\t\tconst step: AddMarkStep = { type: 'addMark', blockId, from, to, mark };\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Adds a remove-mark step. Updates workingDoc if available. */\n\tremoveMark(blockId: BlockId, from: number, to: number, mark: Mark): this {\n\t\tconst step: RemoveMarkStep = { type: 'removeMark', blockId, from, to, mark };\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Adds a set-block-type step, changing a block's node type and optionally its attrs. */\n\tsetBlockType(blockId: BlockId, nodeType: NodeTypeName, attrs?: BlockAttrs): this {\n\t\tconst doc = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'setBlockType requires a document. Use state.transaction() or provide doc to constructor.',\n\t\t\t);\n\t\t}\n\t\tconst block = findNode(doc, blockId);\n\t\tif (!block) {\n\t\t\tthrow new Error(`Block \"${blockId}\" not found in working document.`);\n\t\t}\n\t\tconst step: SetBlockTypeStep = {\n\t\t\ttype: 'setBlockType',\n\t\t\tblockId,\n\t\t\tnodeType,\n\t\t\t...(attrs ? { attrs } : {}),\n\t\t\tpreviousNodeType: block.type,\n\t\t\t...(block.attrs ? { previousAttrs: block.attrs } : {}),\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Inserts a node as a child of the parent at the given path and index. */\n\tinsertNode(parentPath: readonly BlockId[], index: number, node: BlockNode): this {\n\t\tconst step: InsertNodeStep = { type: 'insertNode', parentPath, index, node };\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Removes a node at the given index from the parent at the given path. */\n\tremoveNode(parentPath: readonly BlockId[], index: number): this {\n\t\tconst doc = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'removeNode requires a document. Use state.transaction() or provide doc to constructor.',\n\t\t\t);\n\t\t}\n\n\t\tconst removedNode = resolveRemovedNode(doc, parentPath, index);\n\t\tif (!removedNode) {\n\t\t\tthrow new Error(\n\t\t\t\t`Node at index ${index} not found under parent path [${parentPath.join(', ')}].`,\n\t\t\t);\n\t\t}\n\n\t\tconst step: RemoveNodeStep = { type: 'removeNode', parentPath, index, removedNode };\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Sets attributes on a node at the given path. */\n\tsetNodeAttr(path: readonly BlockId[], attrs: BlockAttrs): this {\n\t\tconst doc = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'setNodeAttr requires a document. Use state.transaction() or provide doc to constructor.',\n\t\t\t);\n\t\t}\n\n\t\tconst node = resolveNodeByPath(doc, path);\n\t\tif (!node) {\n\t\t\tthrow new Error(`Node not found at path [${path.join(', ')}].`);\n\t\t}\n\n\t\tconst step: SetNodeAttrStep = {\n\t\t\ttype: 'setNodeAttr',\n\t\t\tpath,\n\t\t\tattrs,\n\t\t\t...(node.attrs ? { previousAttrs: node.attrs } : {}),\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Inserts an InlineNode at the given offset within a block. */\n\tinsertInlineNode(blockId: BlockId, offset: number, node: InlineNode): this {\n\t\tconst step: InsertInlineNodeStep = {\n\t\t\ttype: 'insertInlineNode',\n\t\t\tblockId,\n\t\t\toffset,\n\t\t\tnode,\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Removes an InlineNode at the given offset, deriving removedNode from workingDoc. */\n\tremoveInlineNode(blockId: BlockId, offset: number): this {\n\t\tconst doc: Document | null = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'removeInlineNode requires a document. Use state.transaction() or provide doc.',\n\t\t\t);\n\t\t}\n\t\tconst block: BlockNode | undefined = findNode(doc, blockId);\n\t\tif (!block) {\n\t\t\tthrow new Error(`Block \"${blockId}\" not found in working document.`);\n\t\t}\n\t\tconst content = getContentAtOffset(block, offset);\n\t\tif (!content || content.kind !== 'inline') {\n\t\t\tthrow new Error(`No InlineNode at offset ${offset} in block \"${blockId}\".`);\n\t\t}\n\t\tconst step: RemoveInlineNodeStep = {\n\t\t\ttype: 'removeInlineNode',\n\t\t\tblockId,\n\t\t\toffset,\n\t\t\tremovedNode: content.node,\n\t\t};\n\t\tthis.steps.push(step);\n\t\tthis.advanceDoc(step);\n\t\treturn this;\n\t}\n\n\t/** Sets attributes on an InlineNode at the given offset. */\n\tsetInlineNodeAttr(\n\t\tblockId: BlockId,\n\t\toffset: number,\n\t\tattrs: Readonly<Record<string, string | number | boolean>>,\n\t): this {\n\t\tconst doc: Document | null = this.workingDoc;\n\t\tif (!doc) {\n\t\t\tthrow new Error(\n\t\t\t\t'setInlineNodeAttr requires a document. Use state.transaction() or provide doc.',\n\t\t\t);\n\t\t}\n\t\tconst block: BlockNode | undefined = findNode(doc, blockId);\n\t\tif (!block) {\n\t\t\tthrow new Error(`Block \"${blockId}\" not found in working document.`);\n\t\t}\n\t\tconst inlineChildren = getInlineChildren(block);\n\t\tlet pos = 0;\n\t\tfor (const child of inlineChildren) {\n\t\t\tif (isInlineNode(child) && pos === offset) {\n\t\t\t\tconst step: SetInlineNodeAttrStep = {\n\t\t\t\t\ttype: 'setInlineNodeAttr',\n\t\t\t\t\tblockId,\n\t\t\t\t\toffset,\n\t\t\t\t\tattrs,\n\t\t\t\t\tpreviousAttrs: child.attrs,\n\t\t\t\t};\n\t\t\t\tthis.steps.push(step);\n\t\t\t\tthis.advanceDoc(step);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tpos += isInlineNode(child) ? 1 : child.text.length;\n\t\t}\n\t\tthrow new Error(`No InlineNode at offset ${offset} in block \"${blockId}\".`);\n\t}\n\n\t/** Sets the selection for the resulting state. */\n\tsetSelection(selection: Selection): this {\n\t\tthis.selection = selection;\n\t\treturn this;\n\t}\n\n\t/** Sets stored marks for the resulting state. */\n\tsetStoredMarks(marks: readonly Mark[] | null, previousMarks: readonly Mark[] | null): this {\n\t\tthis.steps.push({ type: 'setStoredMarks', marks, previousMarks });\n\t\tthis.storedMarks = marks;\n\t\treturn this;\n\t}\n\n\t/** Builds the final transaction. */\n\tbuild(): Transaction {\n\t\treturn {\n\t\t\tsteps: [...this.steps],\n\t\t\tselectionBefore: this.selectionBefore,\n\t\t\tselectionAfter: this.selection,\n\t\t\tstoredMarksAfter: this.storedMarks,\n\t\t\tmetadata: {\n\t\t\t\torigin: this.origin,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t},\n\t\t};\n\t}\n\n\t/** Advances the working document by applying a step. */\n\tprivate advanceDoc(step: Step): void {\n\t\tif (this.workingDoc) {\n\t\t\tthis.workingDoc = applyStep(this.workingDoc, step);\n\t\t}\n\t}\n}\n\n/** Helper to create a TransactionBuilder with input origin. */\nexport function inputTransaction(\n\tselection: Selection,\n\tstoredMarks: readonly Mark[] | null,\n): TransactionBuilder {\n\treturn new TransactionBuilder(selection, storedMarks, 'input');\n}\n\n/** Helper to create a TransactionBuilder with command origin. */\nexport function commandTransaction(\n\tselection: Selection,\n\tstoredMarks: readonly Mark[] | null,\n): TransactionBuilder {\n\treturn new TransactionBuilder(selection, storedMarks, 'command');\n}\n\n/** Resolves the block node to be removed from a parent path and index. */\nfunction resolveRemovedNode(\n\tdoc: Document,\n\tparentPath: readonly BlockId[],\n\tindex: number,\n): BlockNode | undefined {\n\tif (parentPath.length === 0) {\n\t\tconst child = doc.children[index];\n\t\treturn child && isBlockNode(child) ? child : undefined;\n\t}\n\tconst parent = resolveNodeByPath(doc, parentPath);\n\tif (!parent) return undefined;\n\tconst child = parent.children[index];\n\treturn child && isBlockNode(child) ? child : undefined;\n}\n","/**\n * Immutable editor state container.\n * Every mutation produces a new EditorState instance.\n */\n\nimport {\n\ttype BlockNode,\n\ttype Document,\n\ttype Mark,\n\tcreateDocument,\n\tgetBlockLength,\n\tisBlockNode,\n\tisLeafBlock,\n} from '../model/Document.js';\nimport { findNode, findNodePath } from '../model/NodeResolver.js';\nimport type { Schema } from '../model/Schema.js';\nimport { defaultSchema } from '../model/Schema.js';\nimport type { Position, Selection } from '../model/Selection.js';\nimport { createCollapsedSelection, createPosition, createSelection } from '../model/Selection.js';\nimport { type BlockId, blockId } from '../model/TypeBrands.js';\nimport { applyStep } from './StepApplication.js';\nimport type { Transaction } from './Transaction.js';\nimport { TransactionBuilder } from './Transaction.js';\n\nexport class EditorState {\n\treadonly doc: Document;\n\treadonly selection: Selection;\n\treadonly storedMarks: readonly Mark[] | null;\n\treadonly schema: Schema;\n\n\tprivate _blockMap: Map<BlockId, BlockNode> | null = null;\n\tprivate _blockOrder: readonly BlockId[] | null = null;\n\n\tprivate constructor(\n\t\tdoc: Document,\n\t\tselection: Selection,\n\t\tstoredMarks: readonly Mark[] | null,\n\t\tschema: Schema,\n\t) {\n\t\tthis.doc = doc;\n\t\tthis.selection = selection;\n\t\tthis.storedMarks = storedMarks;\n\t\tthis.schema = schema;\n\t}\n\n\t/** Creates a new EditorState with default document. */\n\tstatic create(options?: {\n\t\tdoc?: Document;\n\t\tselection?: Selection;\n\t\tschema?: Schema;\n\t}): EditorState {\n\t\tconst schema = options?.schema ?? defaultSchema();\n\t\tconst doc = options?.doc ?? createDocument();\n\t\tconst firstBlock = doc.children[0];\n\t\tconst selection =\n\t\t\toptions?.selection ?? createCollapsedSelection(firstBlock ? firstBlock.id : blockId(''), 0);\n\n\t\treturn new EditorState(doc, selection, null, schema);\n\t}\n\n\t/** Creates a TransactionBuilder from this state. */\n\ttransaction(\n\t\torigin: 'input' | 'paste' | 'command' | 'history' | 'api' = 'api',\n\t): TransactionBuilder {\n\t\treturn new TransactionBuilder(this.selection, this.storedMarks, origin, this.doc);\n\t}\n\n\t/** Applies a transaction and returns a new EditorState. */\n\tapply(tr: Transaction): EditorState {\n\t\tlet doc = this.doc;\n\n\t\tfor (const step of tr.steps) {\n\t\t\tdoc = applyStep(doc, step);\n\t\t}\n\n\t\tconst selection = validateSelection(doc, tr.selectionAfter);\n\t\treturn new EditorState(doc, selection, tr.storedMarksAfter, this.schema);\n\t}\n\n\t/** Finds a block by its ID anywhere in the tree. Uses a lazy-built Map for O(1) lookup. */\n\tgetBlock(blockId: BlockId): BlockNode | undefined {\n\t\tthis._blockMap ??= buildBlockMap(this.doc);\n\t\treturn this._blockMap.get(blockId);\n\t}\n\n\t/** Returns leaf-block IDs in depth-first order. Cached after first call. */\n\tgetBlockOrder(): readonly BlockId[] {\n\t\tthis._blockOrder ??= buildBlockOrder(this.doc);\n\t\treturn this._blockOrder;\n\t}\n\n\t/** Returns the path (array of block IDs) to a node. */\n\tgetNodePath(nodeId: BlockId): BlockId[] | undefined {\n\t\treturn findNodePath(this.doc, nodeId) as BlockId[] | undefined;\n\t}\n\n\t/** Returns the parent BlockNode of a node, or undefined for top-level blocks. */\n\tgetParent(nodeId: BlockId): BlockNode | undefined {\n\t\tconst path = findNodePath(this.doc, nodeId);\n\t\tif (!path || path.length <= 1) return undefined;\n\t\tconst parentId = path[path.length - 2] as BlockId | undefined;\n\t\tif (!parentId) return undefined;\n\t\treturn findNode(this.doc, parentId);\n\t}\n\n\t/** Serializes the state to JSON. */\n\ttoJSON(): object {\n\t\treturn {\n\t\t\tdoc: this.doc,\n\t\t\tselection: this.selection,\n\t\t};\n\t}\n\n\t/** Deserializes a state from JSON. */\n\tstatic fromJSON(json: { doc: Document; selection: Selection }, schema?: Schema): EditorState {\n\t\treturn new EditorState(json.doc, json.selection, null, schema ?? defaultSchema());\n\t}\n}\n\n/** Validates a position against the document, clamping or falling back as needed. */\nfunction validatePosition(doc: Document, pos: Position): Position {\n\tconst block = findNode(doc, pos.blockId);\n\tif (block) {\n\t\tconst length = getBlockLength(block);\n\t\tif (pos.offset > length) {\n\t\t\treturn createPosition(pos.blockId, length, pos.path);\n\t\t}\n\t\treturn pos;\n\t}\n\n\tconst firstBlock = doc.children[0];\n\tif (!firstBlock) return pos;\n\treturn createPosition(firstBlock.id, 0);\n}\n\n/** Validates a selection against the document, ensuring blockIds exist and offsets are in bounds. */\nfunction validateSelection(doc: Document, sel: Selection): Selection {\n\tconst anchor = validatePosition(doc, sel.anchor);\n\tconst head = validatePosition(doc, sel.head);\n\tif (anchor === sel.anchor && head === sel.head) return sel;\n\treturn createSelection(anchor, head);\n}\n\n/** Recursively builds a Map of blockId → BlockNode for all nodes in the tree. */\nfunction buildBlockMap(doc: Document): Map<BlockId, BlockNode> {\n\tconst map = new Map<BlockId, BlockNode>();\n\tfunction walk(blocks: readonly import('../model/Document.js').ChildNode[]): void {\n\t\tfor (const child of blocks) {\n\t\t\tif (isBlockNode(child)) {\n\t\t\t\tmap.set(child.id, child);\n\t\t\t\twalk(child.children);\n\t\t\t}\n\t\t}\n\t}\n\twalk(doc.children);\n\treturn map;\n}\n\n/** Returns leaf-block IDs in depth-first order. */\nfunction buildBlockOrder(doc: Document): BlockId[] {\n\tconst order: BlockId[] = [];\n\tfunction walk(blocks: readonly import('../model/Document.js').ChildNode[]): void {\n\t\tfor (const child of blocks) {\n\t\t\tif (isBlockNode(child)) {\n\t\t\t\tif (isLeafBlock(child)) {\n\t\t\t\t\torder.push(child.id);\n\t\t\t\t} else {\n\t\t\t\t\twalk(child.children);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\twalk(doc.children);\n\treturn order;\n}\n","/**\n * History manager for undo/redo with transaction grouping.\n */\n\nimport type { EditorState } from './EditorState.js';\nimport type { Step, Transaction } from './Transaction.js';\nimport { invertTransaction } from './Transaction.js';\n\nexport interface HistoryResult {\n\treadonly state: EditorState;\n\treadonly transaction: Transaction;\n}\n\ninterface HistoryGroup {\n\treadonly transactions: readonly Transaction[];\n\treadonly timestamp: number;\n}\n\nconst DEFAULT_GROUP_TIMEOUT_MS = 500;\nconst DEFAULT_MAX_DEPTH = 100;\n\nexport class HistoryManager {\n\tprivate undoStack: HistoryGroup[] = [];\n\tprivate redoStack: HistoryGroup[] = [];\n\tprivate readonly groupTimeoutMs: number;\n\tprivate readonly maxDepth: number;\n\tprivate lastOrigin: string | null = null;\n\n\tconstructor(options?: { groupTimeoutMs?: number; maxDepth?: number }) {\n\t\tthis.groupTimeoutMs = options?.groupTimeoutMs ?? DEFAULT_GROUP_TIMEOUT_MS;\n\t\tthis.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;\n\t}\n\n\t/**\n\t * Pushes a transaction onto the undo stack.\n\t * Groups consecutive input transactions within the timeout window.\n\t */\n\tpush(tr: Transaction): void {\n\t\t// History and redo transactions are not pushed\n\t\tif (tr.metadata.origin === 'history') return;\n\n\t\tconst now = tr.metadata.timestamp;\n\t\tconst lastGroup = this.undoStack[this.undoStack.length - 1];\n\t\tconst shouldGroup =\n\t\t\tlastGroup &&\n\t\t\ttr.metadata.origin === 'input' &&\n\t\t\tthis.lastOrigin === 'input' &&\n\t\t\tnow - lastGroup.timestamp < this.groupTimeoutMs &&\n\t\t\tthis.isSameInputType(lastGroup.transactions, tr);\n\n\t\tif (shouldGroup && lastGroup) {\n\t\t\t// Merge into existing group\n\t\t\tthis.undoStack[this.undoStack.length - 1] = {\n\t\t\t\ttransactions: [...lastGroup.transactions, tr],\n\t\t\t\ttimestamp: now,\n\t\t\t};\n\t\t} else {\n\t\t\t// Start new group\n\t\t\tthis.undoStack.push({\n\t\t\t\ttransactions: [tr],\n\t\t\t\ttimestamp: now,\n\t\t\t});\n\t\t}\n\n\t\tthis.lastOrigin = tr.metadata.origin;\n\n\t\t// Clear redo stack on new input\n\t\tthis.redoStack = [];\n\n\t\t// Enforce max depth\n\t\twhile (this.undoStack.length > this.maxDepth) {\n\t\t\tthis.undoStack.shift();\n\t\t}\n\t}\n\n\t/** Undoes the last group and returns the new state with transaction, or null if nothing to undo. */\n\tundo(state: EditorState): HistoryResult | null {\n\t\tconst group = this.undoStack.pop();\n\t\tif (!group) return null;\n\n\t\tlet currentState = state;\n\t\tconst allSteps: Step[] = [];\n\n\t\t// Apply inverted transactions in reverse order\n\t\tfor (let i = group.transactions.length - 1; i >= 0; i--) {\n\t\t\tconst tr = group.transactions[i];\n\t\t\tif (!tr) continue;\n\t\t\tconst inverted = invertTransaction(tr);\n\t\t\tcurrentState = currentState.apply(inverted);\n\t\t\tallSteps.push(...inverted.steps);\n\t\t}\n\n\t\t// Push to redo stack\n\t\tthis.redoStack.push({\n\t\t\ttransactions: group.transactions,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\n\t\tthis.lastOrigin = null;\n\n\t\tconst transaction: Transaction = {\n\t\t\tsteps: allSteps,\n\t\t\tselectionBefore: state.selection,\n\t\t\tselectionAfter: currentState.selection,\n\t\t\tstoredMarksAfter: currentState.storedMarks,\n\t\t\tmetadata: { origin: 'history', timestamp: Date.now() },\n\t\t};\n\n\t\treturn { state: currentState, transaction };\n\t}\n\n\t/** Redoes the last undone group and returns the new state with transaction, or null if nothing to redo. */\n\tredo(state: EditorState): HistoryResult | null {\n\t\tconst group = this.redoStack.pop();\n\t\tif (!group) return null;\n\n\t\tlet currentState = state;\n\t\tconst allSteps: Step[] = [];\n\n\t\t// Re-apply transactions in original order\n\t\tfor (const tr of group.transactions) {\n\t\t\tcurrentState = currentState.apply(tr);\n\t\t\tallSteps.push(...tr.steps);\n\t\t}\n\n\t\t// Push back to undo stack\n\t\tthis.undoStack.push({\n\t\t\ttransactions: group.transactions,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\n\t\tthis.lastOrigin = null;\n\n\t\tconst transaction: Transaction = {\n\t\t\tsteps: allSteps,\n\t\t\tselectionBefore: state.selection,\n\t\t\tselectionAfter: currentState.selection,\n\t\t\tstoredMarksAfter: currentState.storedMarks,\n\t\t\tmetadata: { origin: 'history', timestamp: Date.now() },\n\t\t};\n\n\t\treturn { state: currentState, transaction };\n\t}\n\n\t/** Returns true if there are entries to undo. */\n\tcanUndo(): boolean {\n\t\treturn this.undoStack.length > 0;\n\t}\n\n\t/** Returns true if there are entries to redo. */\n\tcanRedo(): boolean {\n\t\treturn this.redoStack.length > 0;\n\t}\n\n\t/** Clears all history. */\n\tclear(): void {\n\t\tthis.undoStack = [];\n\t\tthis.redoStack = [];\n\t\tthis.lastOrigin = null;\n\t}\n\n\t/**\n\t * Checks if consecutive transactions are of the same \"type\" for grouping.\n\t * Groups text insertion together, deletion together, but not mixed.\n\t */\n\tprivate isSameInputType(existing: readonly Transaction[], incoming: Transaction): boolean {\n\t\tconst lastTr = existing[existing.length - 1];\n\t\tif (!lastTr) return false;\n\n\t\tconst lastStepType = lastTr.steps[0]?.type;\n\t\tconst incomingStepType = incoming.steps[0]?.type;\n\n\t\t// Group same step types (insertText with insertText, deleteText with deleteText)\n\t\treturn lastStepType === incomingStepType;\n\t}\n}\n","/**\n * Editor commands for formatting, text manipulation, and history.\n */\n\nimport {\n\ttype BlockNode,\n\ttype Mark,\n\ttype MarkType,\n\tgenerateBlockId,\n\tgetBlockLength,\n\tgetBlockMarksAtOffset,\n\tgetContentAtOffset,\n\tgetInlineChildren,\n\thasMark,\n\tisTextNode,\n} from '../model/Document.js';\nimport { isMarkAllowed } from '../model/Schema.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateSelection,\n\tisCollapsed,\n\tselectionRange,\n} from '../model/Selection.js';\nimport { type BlockId, markType as mkType } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport type { TransactionBuilder } from '../state/Transaction.js';\n\n// --- Feature Configuration ---\n\nexport interface FeatureConfig {\n\treadonly bold: boolean;\n\treadonly italic: boolean;\n\treadonly underline: boolean;\n}\n\nconst defaultFeatures: FeatureConfig = { bold: true, italic: true, underline: true };\n\n// --- Mark Commands ---\n\n/**\n * Toggles a mark on the current selection.\n * If collapsed, toggles stored marks. If range, applies/removes from text.\n */\nexport function toggleMark(\n\tstate: EditorState,\n\tmarkType: MarkType,\n\tfeatures: FeatureConfig = defaultFeatures,\n): Transaction | null {\n\tif (isFeatureGated(markType, features)) return null;\n\tif (!isMarkAllowed(state.schema, markType)) return null;\n\n\tconst mark: Mark = { type: markType };\n\tconst sel = state.selection;\n\n\tif (isCollapsed(sel)) {\n\t\t// Toggle stored marks\n\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\tif (!anchorBlock) return null;\n\t\tconst currentMarks = state.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\tconst hasIt = hasMark(currentMarks, markType);\n\t\tconst newMarks = hasIt\n\t\t\t? currentMarks.filter((m) => m.type !== markType)\n\t\t\t: [...currentMarks, mark];\n\n\t\treturn state\n\t\t\t.transaction('command')\n\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t}\n\n\t// Range selection — apply/remove mark to all blocks in range\n\tconst blockOrder = state.getBlockOrder();\n\tconst range = selectionRange(sel, blockOrder);\n\tconst builder = state.transaction('command');\n\n\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t// Determine if we should add or remove\n\tconst shouldRemove = isMarkActiveInRange(state, markType);\n\n\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\tconst blockId = blockOrder[i];\n\t\tif (!blockId) continue;\n\t\tconst block = state.getBlock(blockId);\n\t\tif (!block) continue;\n\t\tconst blockLen = getBlockLength(block);\n\n\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\tif (from === to) continue;\n\n\t\tif (shouldRemove) {\n\t\t\tbuilder.removeMark(blockId, from, to, mark);\n\t\t} else {\n\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t}\n\t}\n\n\tbuilder.setSelection(sel);\n\treturn builder.build();\n}\n\n/** Checks if a mark is active across the entire selection range. */\nfunction isMarkActiveInRange(state: EditorState, markType: MarkType): boolean {\n\tconst sel = state.selection;\n\tconst blockOrder = state.getBlockOrder();\n\tconst range = selectionRange(sel, blockOrder);\n\n\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\tconst blockId = blockOrder[i];\n\t\tif (!blockId) continue;\n\t\tconst block = state.getBlock(blockId);\n\t\tif (!block) continue;\n\t\tconst blockLen = getBlockLength(block);\n\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\tif (!isMarkActiveInBlock(block, from, to, markType)) return false;\n\t}\n\n\treturn true;\n}\n\nfunction isMarkActiveInBlock(\n\tblock: BlockNode,\n\tfrom: number,\n\tto: number,\n\tmarkType: MarkType,\n): boolean {\n\tif (from === to) return false;\n\tlet pos = 0;\n\tfor (const child of getInlineChildren(block)) {\n\t\tif (isTextNode(child)) {\n\t\t\tconst childEnd = pos + child.text.length;\n\t\t\tif (childEnd > from && pos < to) {\n\t\t\t\tif (!hasMark(child.marks, markType)) return false;\n\t\t\t}\n\t\t\tpos = childEnd;\n\t\t} else {\n\t\t\t// InlineNode: skip (width 1, no marks)\n\t\t\tpos += 1;\n\t\t}\n\t}\n\treturn true;\n}\n\nexport function toggleBold(state: EditorState, features?: FeatureConfig): Transaction | null {\n\treturn toggleMark(state, mkType('bold'), features);\n}\n\nexport function toggleItalic(state: EditorState, features?: FeatureConfig): Transaction | null {\n\treturn toggleMark(state, mkType('italic'), features);\n}\n\nexport function toggleUnderline(state: EditorState, features?: FeatureConfig): Transaction | null {\n\treturn toggleMark(state, mkType('underline'), features);\n}\n\n// --- Text Commands ---\n\n/** Inserts text at the current selection, replacing any selected range. */\nexport function insertTextCommand(\n\tstate: EditorState,\n\ttext: string,\n\torigin: 'input' | 'paste' = 'input',\n): Transaction {\n\tconst sel = state.selection;\n\tconst builder = state.transaction(origin);\n\tconst marks = resolveActiveMarks(state);\n\n\tif (!isCollapsed(sel)) {\n\t\taddDeleteSelectionSteps(state, builder);\n\t}\n\n\tconst range = isCollapsed(sel) ? null : selectionRange(sel, state.getBlockOrder());\n\tconst insertBlockId = range ? range.from.blockId : sel.anchor.blockId;\n\tconst insertOffset = range ? range.from.offset : sel.anchor.offset;\n\n\tbuilder.insertText(insertBlockId, insertOffset, text, marks);\n\tbuilder.setSelection(createCollapsedSelection(insertBlockId, insertOffset + text.length));\n\n\treturn builder.build();\n}\n\n/** Deletes the current selection. */\nexport function deleteSelectionCommand(state: EditorState): Transaction | null {\n\tif (isCollapsed(state.selection)) return null;\n\n\tconst builder = state.transaction('input');\n\taddDeleteSelectionSteps(state, builder);\n\n\tconst range = selectionRange(state.selection, state.getBlockOrder());\n\tbuilder.setSelection(createCollapsedSelection(range.from.blockId, range.from.offset));\n\n\treturn builder.build();\n}\n\n/** Handles backspace key. */\nexport function deleteBackward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tif (sel.anchor.offset > 0) {\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.deleteTextAt(block.id, sel.anchor.offset - 1, sel.anchor.offset)\n\t\t\t.setSelection(createCollapsedSelection(block.id, sel.anchor.offset - 1))\n\t\t\t.build();\n\t}\n\n\t// At start of block — merge with previous\n\treturn mergeBlockBackward(state);\n}\n\n/** Handles delete key. */\nexport function deleteForward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tconst blockLen = getBlockLength(block);\n\n\tif (sel.anchor.offset < blockLen) {\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.deleteTextAt(block.id, sel.anchor.offset, sel.anchor.offset + 1)\n\t\t\t.setSelection(createCollapsedSelection(block.id, sel.anchor.offset))\n\t\t\t.build();\n\t}\n\n\t// At end of block — merge with next\n\treturn mergeBlockForward(state);\n}\n\n/** Handles Ctrl+Backspace: delete word backward. */\nexport function deleteWordBackward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tif (sel.anchor.offset === 0) {\n\t\treturn mergeBlockBackward(state);\n\t}\n\n\tconst wordStart = findWordBoundaryBackward(block, sel.anchor.offset);\n\n\treturn state\n\t\t.transaction('input')\n\t\t.deleteTextAt(block.id, wordStart, sel.anchor.offset)\n\t\t.setSelection(createCollapsedSelection(block.id, wordStart))\n\t\t.build();\n}\n\n/** Handles Ctrl+Delete: delete word forward. */\nexport function deleteWordForward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tconst blockLen = getBlockLength(block);\n\tif (sel.anchor.offset === blockLen) {\n\t\treturn mergeBlockForward(state);\n\t}\n\n\tconst wordEnd = findWordBoundaryForward(block, sel.anchor.offset);\n\n\treturn state\n\t\t.transaction('input')\n\t\t.deleteTextAt(block.id, sel.anchor.offset, wordEnd)\n\t\t.setSelection(createCollapsedSelection(block.id, sel.anchor.offset))\n\t\t.build();\n}\n\n/** Handles Cmd+Backspace: delete to start of line/block. */\nexport function deleteSoftLineBackward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tif (sel.anchor.offset === 0) {\n\t\treturn mergeBlockBackward(state);\n\t}\n\n\treturn state\n\t\t.transaction('input')\n\t\t.deleteTextAt(block.id, 0, sel.anchor.offset)\n\t\t.setSelection(createCollapsedSelection(block.id, 0))\n\t\t.build();\n}\n\n/** Handles Cmd+Delete: delete to end of line/block. */\nexport function deleteSoftLineForward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isCollapsed(sel)) {\n\t\treturn deleteSelectionCommand(state);\n\t}\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\n\tconst blockLen = getBlockLength(block);\n\tif (sel.anchor.offset === blockLen) {\n\t\treturn mergeBlockForward(state);\n\t}\n\n\treturn state\n\t\t.transaction('input')\n\t\t.deleteTextAt(block.id, sel.anchor.offset, blockLen)\n\t\t.setSelection(createCollapsedSelection(block.id, sel.anchor.offset))\n\t\t.build();\n}\n\n/** Splits the current block at the cursor position (Enter key). */\nexport function splitBlockCommand(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\tconst builder = state.transaction('input');\n\n\tif (!isCollapsed(sel)) {\n\t\taddDeleteSelectionSteps(state, builder);\n\t}\n\n\tconst blockId = isCollapsed(sel)\n\t\t? sel.anchor.blockId\n\t\t: selectionRange(sel, state.getBlockOrder()).from.blockId;\n\tconst offset = isCollapsed(sel)\n\t\t? sel.anchor.offset\n\t\t: selectionRange(sel, state.getBlockOrder()).from.offset;\n\n\tconst newBlockId = generateBlockId();\n\n\t// splitBlock operates at the same level in the tree — the StepApplication\n\t// handles this correctly because it looks up the block by ID recursively.\n\tbuilder.splitBlock(blockId, offset, newBlockId);\n\tbuilder.setSelection(createCollapsedSelection(newBlockId, 0));\n\n\treturn builder.build();\n}\n\n/** Checks whether two blocks share the same parent in the document tree. */\nexport function sharesParent(state: EditorState, blockIdA: BlockId, blockIdB: BlockId): boolean {\n\tconst pathA = state.getNodePath(blockIdA);\n\tconst pathB = state.getNodePath(blockIdB);\n\tif (!pathA || !pathB) return false;\n\tif (pathA.length !== pathB.length) return false;\n\t// Compare parent paths (all but last element)\n\tfor (let i = 0; i < pathA.length - 1; i++) {\n\t\tif (pathA[i] !== pathB[i]) return false;\n\t}\n\treturn true;\n}\n\n/** Checks whether a block is inside an isolating node (e.g. table_cell). */\nexport function isInsideIsolating(state: EditorState, blockId: BlockId): boolean {\n\tconst getNodeSpec = state.schema.getNodeSpec;\n\tif (!getNodeSpec) return false;\n\tconst path = state.getNodePath(blockId);\n\tif (!path || path.length <= 1) return false;\n\n\t// Check ancestors (not the block itself)\n\tfor (let i = 0; i < path.length - 1; i++) {\n\t\tconst ancestorId = path[i];\n\t\tif (!ancestorId) continue;\n\t\tconst ancestor = state.getBlock(ancestorId);\n\t\tif (!ancestor) continue;\n\t\tconst spec = getNodeSpec(ancestor.type);\n\t\tif (spec?.isolating) return true;\n\t}\n\treturn false;\n}\n\n/** Merges the current block with the previous block, respecting isolating boundaries. */\nexport function mergeBlockBackward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\tconst blockOrder = state.getBlockOrder();\n\tconst blockIdx = blockOrder.indexOf(sel.anchor.blockId);\n\n\tif (blockIdx <= 0) return null;\n\n\tconst prevBlockId = blockOrder[blockIdx - 1];\n\tif (!prevBlockId) return null;\n\n\t// Prevent merge across isolating boundaries\n\tif (!sharesParent(state, sel.anchor.blockId, prevBlockId)) {\n\t\tif (isInsideIsolating(state, sel.anchor.blockId)) return null;\n\t}\n\n\tconst prevBlock = state.getBlock(prevBlockId);\n\tif (!prevBlock) return null;\n\tconst prevLen = getBlockLength(prevBlock);\n\n\treturn state\n\t\t.transaction('input')\n\t\t.mergeBlocksAt(prevBlockId, sel.anchor.blockId)\n\t\t.setSelection(createCollapsedSelection(prevBlockId, prevLen))\n\t\t.build();\n}\n\n/** Merges the next block into the current block, respecting isolating boundaries. */\nfunction mergeBlockForward(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\tconst blockOrder = state.getBlockOrder();\n\tconst blockIdx = blockOrder.indexOf(sel.anchor.blockId);\n\n\tif (blockIdx >= blockOrder.length - 1) return null;\n\n\tconst nextBlockId = blockOrder[blockIdx + 1];\n\tif (!nextBlockId) return null;\n\n\t// Prevent merge across isolating boundaries\n\tif (!sharesParent(state, sel.anchor.blockId, nextBlockId)) {\n\t\tif (isInsideIsolating(state, sel.anchor.blockId)) return null;\n\t}\n\n\treturn state\n\t\t.transaction('input')\n\t\t.mergeBlocksAt(sel.anchor.blockId, nextBlockId)\n\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, sel.anchor.offset))\n\t\t.build();\n}\n\n/** Selects all content in the editor. */\nexport function selectAll(state: EditorState): Transaction {\n\tconst blocks = state.doc.children;\n\tconst firstBlock = blocks[0];\n\tconst lastBlock = blocks[blocks.length - 1];\n\tif (!firstBlock || !lastBlock)\n\t\treturn state.transaction('command').setSelection(state.selection).build();\n\tconst lastBlockLen = getBlockLength(lastBlock);\n\n\treturn state\n\t\t.transaction('command')\n\t\t.setSelection(\n\t\t\tcreateSelection(\n\t\t\t\t{ blockId: firstBlock.id, offset: 0 },\n\t\t\t\t{ blockId: lastBlock.id, offset: lastBlockLen },\n\t\t\t),\n\t\t)\n\t\t.build();\n}\n\n// --- Check Commands ---\n\n/** Checks if a mark is active at the current selection. */\nexport function isMarkActive(state: EditorState, markType: MarkType): boolean {\n\tconst sel = state.selection;\n\n\tif (isCollapsed(sel)) {\n\t\tif (state.storedMarks) {\n\t\t\treturn hasMark(state.storedMarks, markType);\n\t\t}\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\treturn hasMark(marks, markType);\n\t}\n\n\treturn isMarkActiveInRange(state, markType);\n}\n\n// --- Internal Helpers ---\n\nfunction resolveActiveMarks(state: EditorState): readonly Mark[] {\n\tif (state.storedMarks) return state.storedMarks;\n\n\tconst block = state.getBlock(state.selection.anchor.blockId);\n\tif (!block) return [];\n\n\treturn getBlockMarksAtOffset(block, state.selection.anchor.offset);\n}\n\nexport function addDeleteSelectionSteps(state: EditorState, builder: TransactionBuilder): void {\n\tconst blockOrder = state.getBlockOrder();\n\tconst range = selectionRange(state.selection, blockOrder);\n\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\tif (fromIdx === toIdx) {\n\t\tbuilder.deleteTextAt(range.from.blockId, range.from.offset, range.to.offset);\n\t} else {\n\t\tconst firstBlock = state.getBlock(range.from.blockId);\n\t\tif (!firstBlock) return;\n\t\tconst firstLen = getBlockLength(firstBlock);\n\n\t\t// Delete from the end of first block\n\t\tif (range.from.offset < firstLen) {\n\t\t\tbuilder.deleteTextAt(range.from.blockId, range.from.offset, firstLen);\n\t\t}\n\n\t\t// Delete from start of last block\n\t\tif (range.to.offset > 0) {\n\t\t\tbuilder.deleteTextAt(range.to.blockId, 0, range.to.offset);\n\t\t}\n\n\t\t// Delete middle blocks entirely and merge last into first\n\t\tfor (let i = fromIdx + 1; i < toIdx; i++) {\n\t\t\tconst midBlockId = blockOrder[i];\n\t\t\tif (!midBlockId) continue;\n\t\t\tconst midBlock = state.getBlock(midBlockId);\n\t\t\tif (!midBlock) continue;\n\t\t\tconst midLen = getBlockLength(midBlock);\n\t\t\tif (midLen > 0) {\n\t\t\t\tbuilder.deleteTextAt(midBlockId, 0, midLen);\n\t\t\t}\n\t\t\tbuilder.mergeBlocksAt(range.from.blockId, midBlockId);\n\t\t}\n\n\t\t// Merge last block into first\n\t\tbuilder.mergeBlocksAt(range.from.blockId, range.to.blockId);\n\t}\n}\n\n/**\n * Finds the word boundary backward from the given offset.\n * InlineNodes act as word boundaries.\n */\nfunction findWordBoundaryBackward(block: BlockNode, offset: number): number {\n\tlet pos = offset - 1;\n\t// Skip trailing whitespace\n\twhile (pos >= 0) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (!content || content.kind === 'inline') break;\n\t\tif (!/\\s/.test(content.char)) break;\n\t\tpos--;\n\t}\n\t// If at InlineNode, delete just it (treat as word boundary)\n\tif (pos >= 0) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (content?.kind === 'inline') return pos;\n\t}\n\t// Skip word characters until whitespace or InlineNode\n\twhile (pos >= 0) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (!content || content.kind === 'inline') break;\n\t\tif (/\\s/.test(content.char)) break;\n\t\tpos--;\n\t}\n\treturn pos + 1;\n}\n\n/**\n * Finds the word boundary forward from the given offset.\n * InlineNodes act as word boundaries.\n */\nfunction findWordBoundaryForward(block: BlockNode, offset: number): number {\n\tconst len = getBlockLength(block);\n\tlet pos = offset;\n\t// Skip word characters first\n\twhile (pos < len) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (!content || content.kind === 'inline') break;\n\t\tif (/\\s/.test(content.char)) break;\n\t\tpos++;\n\t}\n\t// If at InlineNode and haven't moved, delete just the InlineNode\n\tif (pos === offset && pos < len) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (content?.kind === 'inline') return pos + 1;\n\t}\n\t// Skip trailing whitespace\n\twhile (pos < len) {\n\t\tconst content = getContentAtOffset(block, pos);\n\t\tif (!content || content.kind === 'inline') break;\n\t\tif (!/\\s/.test(content.char)) break;\n\t\tpos++;\n\t}\n\treturn pos;\n}\n\nfunction isFeatureGated(type: MarkType, features: FeatureConfig): boolean {\n\tconst key = type as string;\n\tif (key === 'bold') return !features.bold;\n\tif (key === 'italic') return !features.italic;\n\tif (key === 'underline') return !features.underline;\n\treturn false;\n}\n","/**\n * Keyboard handler: intercepts keydown events for shortcuts.\n * Checks plugin-registered keymaps first, then falls back to built-in\n * structural shortcuts (undo, redo, select all).\n *\n * Mark-specific shortcuts (Mod-B, Mod-I, Mod-U) are registered by\n * their respective plugins via keymaps, not hardcoded here.\n */\n\nimport { selectAll } from '../commands/Commands.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport type { DispatchFn, GetStateFn, RedoFn, UndoFn } from './InputHandler.js';\n\nexport interface KeyboardHandlerOptions {\n\tgetState: GetStateFn;\n\tdispatch: DispatchFn;\n\tundo: UndoFn;\n\tredo: RedoFn;\n\tschemaRegistry?: SchemaRegistry;\n}\n\nexport class KeyboardHandler {\n\tprivate readonly getState: GetStateFn;\n\tprivate readonly dispatch: DispatchFn;\n\tprivate readonly undo: UndoFn;\n\tprivate readonly redo: RedoFn;\n\tprivate readonly schemaRegistry?: SchemaRegistry;\n\tprivate readonly handleKeydown: (e: KeyboardEvent) => void;\n\n\tconstructor(\n\t\tprivate readonly element: HTMLElement,\n\t\toptions: KeyboardHandlerOptions,\n\t) {\n\t\tthis.getState = options.getState;\n\t\tthis.dispatch = options.dispatch;\n\t\tthis.undo = options.undo;\n\t\tthis.redo = options.redo;\n\t\tthis.schemaRegistry = options.schemaRegistry;\n\n\t\tthis.handleKeydown = this.onKeydown.bind(this);\n\t\telement.addEventListener('keydown', this.handleKeydown);\n\t}\n\n\tprivate onKeydown(e: KeyboardEvent): void {\n\t\t// Try plugin keymaps first (last registered has highest precedence)\n\t\tif (this.schemaRegistry) {\n\t\t\tconst descriptor = normalizeKeyDescriptor(e);\n\t\t\tconst keymaps = this.schemaRegistry.getKeymaps();\n\t\t\t// Iterate in reverse so later-registered keymaps take precedence\n\t\t\tfor (let i = keymaps.length - 1; i >= 0; i--) {\n\t\t\t\tconst handler = keymaps[i]?.[descriptor];\n\t\t\t\tif (handler?.()) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to built-in structural shortcuts\n\t\tconst mod = e.metaKey || e.ctrlKey;\n\t\tif (!mod) return;\n\n\t\tconst key = e.key.toLowerCase();\n\t\tconst state = this.getState();\n\t\tlet tr: Transaction | null = null;\n\n\t\tif (key === 'z' && !e.shiftKey) {\n\t\t\te.preventDefault();\n\t\t\tthis.undo();\n\t\t\treturn;\n\t\t}\n\n\t\tif ((key === 'z' && e.shiftKey) || (key === 'y' && !e.shiftKey)) {\n\t\t\te.preventDefault();\n\t\t\tthis.redo();\n\t\t\treturn;\n\t\t}\n\n\t\tif (key === 'a' && !e.shiftKey) {\n\t\t\te.preventDefault();\n\t\t\ttr = selectAll(state);\n\t\t}\n\n\t\tif (tr) {\n\t\t\tthis.dispatch(tr);\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.element.removeEventListener('keydown', this.handleKeydown);\n\t}\n}\n\n/**\n * Normalizes a KeyboardEvent into a consistent key descriptor string.\n * Format: `\"Mod-Shift-Alt-Key\"` where Mod = Ctrl/Cmd.\n */\nexport function normalizeKeyDescriptor(e: KeyboardEvent): string {\n\tconst parts: string[] = [];\n\tif (e.metaKey || e.ctrlKey) parts.push('Mod');\n\tif (e.shiftKey) parts.push('Shift');\n\tif (e.altKey) parts.push('Alt');\n\n\tlet key = e.key;\n\t// Normalize common keys\n\tif (key === ' ') key = 'Space';\n\telse if (key.length === 1) key = key.toUpperCase();\n\t// For special keys like Enter, Tab, Backspace, keep as-is\n\n\tparts.push(key);\n\treturn parts.join('-');\n}\n","/**\n * Plugin system types for the Notectl editor.\n */\n\nimport type { DecorationSet } from '../decorations/Decoration.js';\nimport type { InputRule } from '../input/InputRule.js';\nimport type { Keymap } from '../input/Keymap.js';\nimport type { InlineNodeSpec } from '../model/InlineNodeSpec.js';\nimport type { MarkSpec } from '../model/MarkSpec.js';\nimport type { NodeSpec } from '../model/NodeSpec.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport type { NodeViewFactory } from '../view/NodeView.js';\nimport type { ToolbarItem } from './toolbar/ToolbarItem.js';\n\n// --- Type-Safe Keys ---\n\n/** Type-safe event key for compile-time payload checking. */\nexport class EventKey<T> {\n\tdeclare readonly _type: T;\n\tconstructor(public readonly id: string) {}\n}\n\n/** Type-safe service key for compile-time type checking. */\nexport class ServiceKey<T> {\n\tdeclare readonly _type: T;\n\tconstructor(public readonly id: string) {}\n}\n\n// --- Command System ---\n\nexport type CommandHandler = () => boolean;\n\nexport interface CommandEntry {\n\treadonly name: string;\n\treadonly handler: CommandHandler;\n\treadonly pluginId: string;\n}\n\n// --- Event System ---\n\nexport type PluginEventCallback<T = unknown> = (payload: T) => void;\n\nexport interface PluginEventBus {\n\temit<T>(key: EventKey<T>, payload: T): void;\n\ton<T>(key: EventKey<T>, callback: PluginEventCallback<T>): () => void;\n\toff<T>(key: EventKey<T>, callback: PluginEventCallback<T>): void;\n}\n\n// --- Configuration ---\n\nexport type PluginConfig = Record<string, unknown>;\n\n// --- Middleware ---\n\nexport type MiddlewareNext = (tr: Transaction) => void;\nexport type TransactionMiddleware = (\n\ttr: Transaction,\n\tstate: EditorState,\n\tnext: MiddlewareNext,\n) => void;\n\n// --- Plugin Context ---\n\nexport interface PluginContext {\n\tgetState(): EditorState;\n\tdispatch(transaction: Transaction): void;\n\tgetContainer(): HTMLElement;\n\tgetPluginContainer(position: 'top' | 'bottom'): HTMLElement;\n\tregisterCommand(name: string, handler: CommandHandler): void;\n\texecuteCommand(name: string): boolean;\n\tgetEventBus(): PluginEventBus;\n\tregisterMiddleware(middleware: TransactionMiddleware, priority?: number): void;\n\tregisterService<T>(key: ServiceKey<T>, service: T): void;\n\tgetService<T>(key: ServiceKey<T>): T | undefined;\n\tupdateConfig(config: PluginConfig): void;\n\n\t// --- Schema Extension ---\n\tregisterNodeSpec<T extends string>(spec: NodeSpec<T>): void;\n\tregisterMarkSpec<T extends string>(spec: MarkSpec<T>): void;\n\tregisterNodeView(type: string, factory: NodeViewFactory): void;\n\tregisterKeymap(keymap: Keymap): void;\n\tregisterInputRule(rule: InputRule): void;\n\tregisterToolbarItem(item: ToolbarItem): void;\n\tregisterInlineNodeSpec<T extends string>(spec: InlineNodeSpec<T>): void;\n\tgetSchemaRegistry(): SchemaRegistry;\n}\n\n// --- Plugin Interface ---\n\nexport interface Plugin<TConfig extends Record<string, unknown> = Record<string, unknown>> {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly priority?: number;\n\treadonly dependencies?: readonly string[];\n\n\tinit(context: PluginContext): void | Promise<void>;\n\tdestroy?(): void | Promise<void>;\n\tonStateChange?(oldState: EditorState, newState: EditorState, tr: Transaction): void;\n\tonConfigure?(config: TConfig): void;\n\t/** Called after ALL plugins have been initialized. */\n\tonReady?(): void | Promise<void>;\n\t/**\n\t * Returns decorations for the given state.\n\t * Called after state.apply() but BEFORE reconciliation.\n\t * Plugins should cache and only recompute when needed.\n\t */\n\tdecorations?(state: EditorState, tr?: Transaction): DecorationSet;\n}\n","/**\n * Standalone event bus with error isolation and type-safe event keys.\n * Each listener is wrapped in try/catch — a failing listener never affects others.\n */\n\nimport type { EventKey, PluginEventCallback } from './Plugin.js';\n\nexport class EventBus {\n\tprivate readonly listeners = new Map<string, Set<PluginEventCallback>>();\n\n\t/** Emits an event to all registered listeners. Errors are caught per listener. */\n\temit<T>(key: EventKey<T>, payload: T): void {\n\t\tconst set = this.listeners.get(key.id);\n\t\tif (!set) return;\n\n\t\tfor (const listener of set) {\n\t\t\ttry {\n\t\t\t\tlistener(payload);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[EventBus] Listener error on \"${key.id}\":`, err);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Subscribes to an event. Returns an unsubscribe function. */\n\ton<T>(key: EventKey<T>, callback: PluginEventCallback<T>): () => void {\n\t\tconst id = key.id;\n\t\tif (!this.listeners.has(id)) {\n\t\t\tthis.listeners.set(id, new Set());\n\t\t}\n\t\tconst set = this.listeners.get(id) ?? new Set();\n\t\tset.add(callback as PluginEventCallback);\n\n\t\treturn () => {\n\t\t\tset.delete(callback as PluginEventCallback);\n\t\t\tif (set.size === 0) this.listeners.delete(id);\n\t\t};\n\t}\n\n\t/** Removes a specific listener from an event. */\n\toff<T>(key: EventKey<T>, callback: PluginEventCallback<T>): void {\n\t\tconst set = this.listeners.get(key.id);\n\t\tif (!set) return;\n\t\tset.delete(callback as PluginEventCallback);\n\t\tif (set.size === 0) this.listeners.delete(key.id);\n\t}\n\n\t/** Removes all listeners for all events. */\n\tclear(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n","/**\n * Pure functions for mapping decorations through transaction steps.\n * Handles position adjustments when the document changes — insertions,\n * deletions, splits, merges, and structural node removal.\n */\n\nimport type {\n\tDeleteTextStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveNodeStep,\n\tSplitBlockStep,\n\tStep,\n} from '../state/Transaction.js';\nimport type {\n\tDecoration,\n\tInlineDecoration,\n\tNodeDecoration,\n\tWidgetDecoration,\n} from './Decoration.js';\n\n/**\n * Maps a single decoration through a step.\n * Returns the mapped decoration, an array (when a split produces two),\n * or null if the decoration was deleted by the step.\n */\nexport function mapDecorationThroughStep(\n\tdeco: Decoration,\n\tstep: Step,\n): Decoration | readonly Decoration[] | null {\n\tswitch (deco.type) {\n\t\tcase 'inline':\n\t\t\treturn mapInline(deco, step);\n\t\tcase 'widget':\n\t\t\treturn mapWidget(deco, step);\n\t\tcase 'node':\n\t\t\treturn mapNode(deco, step);\n\t}\n}\n\nfunction mapInline(\n\tdeco: InlineDecoration,\n\tstep: Step,\n): InlineDecoration | readonly InlineDecoration[] | null {\n\tswitch (step.type) {\n\t\tcase 'insertText':\n\t\t\treturn mapInlineInsert(deco, step);\n\t\tcase 'deleteText':\n\t\t\treturn mapInlineDelete(deco, step);\n\t\tcase 'splitBlock':\n\t\t\treturn mapInlineSplit(deco, step);\n\t\tcase 'mergeBlocks':\n\t\t\treturn mapInlineMerge(deco, step);\n\t\tcase 'removeNode':\n\t\t\treturn removeIfBlockDeleted(deco, step);\n\t\tdefault:\n\t\t\treturn deco;\n\t}\n}\n\nfunction mapWidget(deco: WidgetDecoration, step: Step): WidgetDecoration | null {\n\tswitch (step.type) {\n\t\tcase 'insertText':\n\t\t\treturn mapWidgetInsert(deco, step);\n\t\tcase 'deleteText':\n\t\t\treturn mapWidgetDelete(deco, step);\n\t\tcase 'splitBlock':\n\t\t\treturn mapWidgetSplit(deco, step);\n\t\tcase 'mergeBlocks':\n\t\t\treturn mapWidgetMerge(deco, step);\n\t\tcase 'removeNode':\n\t\t\treturn removeIfBlockDeleted(deco, step);\n\t\tdefault:\n\t\t\treturn deco;\n\t}\n}\n\nfunction mapNode(deco: NodeDecoration, step: Step): NodeDecoration | null {\n\tswitch (step.type) {\n\t\tcase 'mergeBlocks':\n\t\t\treturn mapNodeMerge(deco, step);\n\t\tcase 'removeNode':\n\t\t\treturn removeIfBlockDeleted(deco, step);\n\t\tdefault:\n\t\t\treturn deco;\n\t}\n}\n\n// --- InsertText ---\n\nfunction mapInlineInsert(deco: InlineDecoration, step: InsertTextStep): InlineDecoration {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\tconst len: number = step.text.length;\n\t// from: assoc=-1 (stays at boundary — only shifts if insertion is strictly before)\n\tconst newFrom: number = deco.from > step.offset ? deco.from + len : deco.from;\n\t// to: assoc=1 (moves past insertion — shifts if insertion is at or before)\n\tconst newTo: number = deco.to >= step.offset ? deco.to + len : deco.to;\n\n\tif (newFrom === deco.from && newTo === deco.to) return deco;\n\treturn { ...deco, from: newFrom, to: newTo };\n}\n\nfunction mapWidgetInsert(deco: WidgetDecoration, step: InsertTextStep): WidgetDecoration {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\tconst len: number = step.text.length;\n\t// At boundary: side=-1 means \"before insertion\" (assoc=-1, stays), side=1 means \"after\" (moves)\n\tif (deco.offset > step.offset) {\n\t\treturn { ...deco, offset: deco.offset + len };\n\t}\n\tif (deco.offset === step.offset && deco.side >= 1) {\n\t\treturn { ...deco, offset: deco.offset + len };\n\t}\n\treturn deco;\n}\n\n// --- DeleteText ---\n\nfunction mapInlineDelete(deco: InlineDecoration, step: DeleteTextStep): InlineDecoration | null {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\tconst delLen: number = step.to - step.from;\n\tconst newFrom: number = clampAndShift(deco.from, step.from, step.to, delLen);\n\tconst newTo: number = clampAndShift(deco.to, step.from, step.to, delLen);\n\n\tif (newFrom >= newTo) return null;\n\tif (newFrom === deco.from && newTo === deco.to) return deco;\n\treturn { ...deco, from: newFrom, to: newTo };\n}\n\nfunction mapWidgetDelete(deco: WidgetDecoration, step: DeleteTextStep): WidgetDecoration | null {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\t// Widget strictly inside deleted range → deleted\n\tif (deco.offset > step.from && deco.offset < step.to) return null;\n\n\tconst delLen: number = step.to - step.from;\n\tif (deco.offset >= step.to) {\n\t\treturn { ...deco, offset: deco.offset - delLen };\n\t}\n\treturn deco;\n}\n\n// --- SplitBlock ---\n\nfunction mapInlineSplit(\n\tdeco: InlineDecoration,\n\tstep: SplitBlockStep,\n): InlineDecoration | readonly InlineDecoration[] {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\t// Entirely before split point → unchanged\n\tif (deco.to <= step.offset) return deco;\n\n\t// Entirely after split point → move to new block, adjust offsets\n\tif (deco.from >= step.offset) {\n\t\treturn {\n\t\t\t...deco,\n\t\t\tblockId: step.newBlockId,\n\t\t\tfrom: deco.from - step.offset,\n\t\t\tto: deco.to - step.offset,\n\t\t};\n\t}\n\n\t// Spanning the split point → split into two decorations\n\tconst left: InlineDecoration = { ...deco, to: step.offset };\n\tconst right: InlineDecoration = {\n\t\t...deco,\n\t\tblockId: step.newBlockId,\n\t\tfrom: 0,\n\t\tto: deco.to - step.offset,\n\t};\n\treturn [left, right];\n}\n\nfunction mapWidgetSplit(deco: WidgetDecoration, step: SplitBlockStep): WidgetDecoration {\n\tif (deco.blockId !== step.blockId) return deco;\n\n\t// Before split → stays\n\tif (deco.offset < step.offset) return deco;\n\n\t// After split → new block\n\tif (deco.offset > step.offset) {\n\t\treturn {\n\t\t\t...deco,\n\t\t\tblockId: step.newBlockId,\n\t\t\toffset: deco.offset - step.offset,\n\t\t};\n\t}\n\n\t// At boundary: side determines which block\n\tif (deco.side >= 1) {\n\t\treturn {\n\t\t\t...deco,\n\t\t\tblockId: step.newBlockId,\n\t\t\toffset: 0,\n\t\t};\n\t}\n\treturn deco;\n}\n\n// --- MergeBlocks ---\n\nfunction mapInlineMerge(deco: InlineDecoration, step: MergeBlocksStep): InlineDecoration {\n\tif (deco.blockId !== step.sourceBlockId) return deco;\n\n\treturn {\n\t\t...deco,\n\t\tblockId: step.targetBlockId,\n\t\tfrom: deco.from + step.targetLengthBefore,\n\t\tto: deco.to + step.targetLengthBefore,\n\t};\n}\n\nfunction mapWidgetMerge(deco: WidgetDecoration, step: MergeBlocksStep): WidgetDecoration {\n\tif (deco.blockId !== step.sourceBlockId) return deco;\n\n\treturn {\n\t\t...deco,\n\t\tblockId: step.targetBlockId,\n\t\toffset: deco.offset + step.targetLengthBefore,\n\t};\n}\n\nfunction mapNodeMerge(deco: NodeDecoration, step: MergeBlocksStep): NodeDecoration | null {\n\t// Source block disappears → delete its node decoration\n\tif (deco.blockId === step.sourceBlockId) return null;\n\treturn deco;\n}\n\n// --- RemoveNode ---\n\nfunction removeIfBlockDeleted<T extends Decoration>(deco: T, step: RemoveNodeStep): T | null {\n\tif (deco.blockId === step.removedNode.id) return null;\n\treturn deco;\n}\n\n// --- Helpers ---\n\nfunction clampAndShift(pos: number, delFrom: number, delTo: number, delLen: number): number {\n\tif (pos <= delFrom) return pos;\n\tif (pos >= delTo) return pos - delLen;\n\treturn delFrom;\n}\n","/**\n * Decoration types and DecorationSet for transient, view-only annotations.\n * Decorations are NOT part of the document model and do NOT affect undo/redo.\n */\n\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { mapDecorationThroughStep } from './PositionMapping.js';\n\n// --- Decoration Attrs ---\n\nexport interface DecorationAttrs {\n\treadonly class?: string;\n\treadonly style?: string;\n\treadonly nodeName?: string;\n\treadonly [key: string]: string | undefined;\n}\n\n// --- Decoration Types ---\n\nexport interface InlineDecoration {\n\treadonly type: 'inline';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly attrs: DecorationAttrs;\n}\n\nexport interface NodeDecoration {\n\treadonly type: 'node';\n\treadonly blockId: BlockId;\n\treadonly attrs: DecorationAttrs;\n}\n\nexport interface WidgetDecoration {\n\treadonly type: 'widget';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly toDOM: () => HTMLElement;\n\treadonly side: -1 | 1;\n\treadonly key?: string;\n}\n\nexport type Decoration = InlineDecoration | NodeDecoration | WidgetDecoration;\n\n// --- Factory Functions ---\n\n/** Creates an inline decoration for a text range within a block. */\nexport function inline(\n\tblockId: BlockId,\n\tfrom: number,\n\tto: number,\n\tattrs: DecorationAttrs,\n): InlineDecoration {\n\treturn { type: 'inline', blockId, from, to, attrs };\n}\n\n/** Creates a node decoration that applies to a whole block element. */\nexport function node(blockId: BlockId, attrs: DecorationAttrs): NodeDecoration {\n\treturn { type: 'node', blockId, attrs };\n}\n\n/** Creates a widget decoration that inserts a DOM element at a position. */\nexport function widget(\n\tblockId: BlockId,\n\toffset: number,\n\ttoDOM: () => HTMLElement,\n\toptions?: { readonly side?: -1 | 1; readonly key?: string },\n): WidgetDecoration {\n\treturn {\n\t\ttype: 'widget',\n\t\tblockId,\n\t\toffset,\n\t\ttoDOM,\n\t\tside: options?.side ?? -1,\n\t\tkey: options?.key,\n\t};\n}\n\n// --- DecorationSet ---\n\n/**\n * Immutable set of decorations indexed by block ID.\n * Provides efficient lookup and merging of decoration collections.\n */\nexport class DecorationSet {\n\tstatic readonly empty: DecorationSet = new DecorationSet(new Map());\n\n\tprivate constructor(private readonly byBlock: ReadonlyMap<BlockId, readonly Decoration[]>) {}\n\n\t/** Creates a DecorationSet from a flat array of decorations. */\n\tstatic create(decorations: readonly Decoration[]): DecorationSet {\n\t\tif (decorations.length === 0) return DecorationSet.empty;\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const deco of decorations) {\n\t\t\tconst existing = map.get(deco.blockId);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(deco);\n\t\t\t} else {\n\t\t\t\tmap.set(deco.blockId, [deco]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns all decorations for a given block. */\n\tfind(blockId: BlockId): readonly Decoration[] {\n\t\treturn this.byBlock.get(blockId) ?? [];\n\t}\n\n\t/** Returns only inline decorations for a given block. */\n\tfindInline(blockId: BlockId): readonly InlineDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is InlineDecoration => d.type === 'inline');\n\t}\n\n\t/** Returns only node decorations for a given block. */\n\tfindNode(blockId: BlockId): readonly NodeDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is NodeDecoration => d.type === 'node');\n\t}\n\n\t/** Returns only widget decorations for a given block. */\n\tfindWidget(blockId: BlockId): readonly WidgetDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is WidgetDecoration => d.type === 'widget');\n\t}\n\n\t/** Returns a new DecorationSet with the given decorations added. */\n\tadd(decorations: readonly Decoration[]): DecorationSet {\n\t\tif (decorations.length === 0) return this;\n\t\tif (this.isEmpty) return DecorationSet.create(decorations);\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tmap.set(bid, [...decos]);\n\t\t}\n\t\tfor (const deco of decorations) {\n\t\t\tconst existing = map.get(deco.blockId);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(deco);\n\t\t\t} else {\n\t\t\t\tmap.set(deco.blockId, [deco]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns a new DecorationSet with decorations matching the predicate removed. */\n\tremove(predicate: (d: Decoration) => boolean): DecorationSet {\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tlet changed = false;\n\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tconst filtered = decos.filter((d) => !predicate(d));\n\t\t\tif (filtered.length !== decos.length) changed = true;\n\t\t\tif (filtered.length > 0) {\n\t\t\t\tmap.set(bid, filtered);\n\t\t\t}\n\t\t}\n\n\t\tif (!changed) return this;\n\t\tif (map.size === 0) return DecorationSet.empty;\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns a new DecorationSet merging this set with another. */\n\tmerge(other: DecorationSet): DecorationSet {\n\t\tif (other.isEmpty) return this;\n\t\tif (this.isEmpty) return other;\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tmap.set(bid, [...decos]);\n\t\t}\n\t\tfor (const [bid, decos] of other.byBlock) {\n\t\t\tconst existing = map.get(bid);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(...decos);\n\t\t\t} else {\n\t\t\t\tmap.set(bid, [...decos]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Checks equality — reference first, then structural comparison. */\n\tequals(other: DecorationSet): boolean {\n\t\tif (this === other) return true;\n\t\tif (this.byBlock.size !== other.byBlock.size) return false;\n\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tconst otherDecos = other.byBlock.get(bid);\n\t\t\tif (!otherDecos) return false;\n\t\t\tif (!decorationArraysEqual(decos, otherDecos)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** True if the set contains no decorations. */\n\tget isEmpty(): boolean {\n\t\treturn this.byBlock.size === 0;\n\t}\n\n\t/**\n\t * Maps decorations through document changes described by a transaction.\n\t * Decorations that become invalid (e.g. fully deleted range) are removed.\n\t * Decorations that span a split point are split into two.\n\t */\n\tmap(tr: Transaction): DecorationSet {\n\t\tif (this.isEmpty || tr.steps.length === 0) return this;\n\n\t\tlet mapped: Decoration[] = [];\n\t\tfor (const decos of this.byBlock.values()) {\n\t\t\tfor (const d of decos) {\n\t\t\t\tmapped.push(d);\n\t\t\t}\n\t\t}\n\n\t\tfor (const step of tr.steps) {\n\t\t\tconst next: Decoration[] = [];\n\t\t\tfor (const deco of mapped) {\n\t\t\t\tconst result = mapDecorationThroughStep(deco, step);\n\t\t\t\tif (result === null) continue;\n\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\tfor (const r of result) {\n\t\t\t\t\t\tnext.push(r);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnext.push(result as Decoration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmapped = next;\n\t\t}\n\n\t\tif (mapped.length === 0) return DecorationSet.empty;\n\t\treturn DecorationSet.create(mapped);\n\t}\n}\n\n// --- Helpers ---\n\n/** Compares two decoration arrays for structural equality. */\nexport function decorationArraysEqual(a: readonly Decoration[], b: readonly Decoration[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst ai = a[i];\n\t\tconst bi = b[i];\n\t\tif (!ai || !bi || !decorationsEqual(ai, bi)) return false;\n\t}\n\treturn true;\n}\n\n/** Compares two individual decorations for structural equality. */\nfunction decorationsEqual(a: Decoration, b: Decoration): boolean {\n\tif (a.type !== b.type) return false;\n\tif (a.blockId !== b.blockId) return false;\n\n\tswitch (a.type) {\n\t\tcase 'inline': {\n\t\t\tconst bi = b as InlineDecoration;\n\t\t\treturn a.from === bi.from && a.to === bi.to && attrsEqual(a.attrs, bi.attrs);\n\t\t}\n\t\tcase 'node': {\n\t\t\tconst bn = b as NodeDecoration;\n\t\t\treturn attrsEqual(a.attrs, bn.attrs);\n\t\t}\n\t\tcase 'widget': {\n\t\t\tconst bw = b as WidgetDecoration;\n\t\t\treturn (\n\t\t\t\ta.offset === bw.offset && a.side === bw.side && a.key === bw.key && a.toDOM === bw.toDOM\n\t\t\t);\n\t\t}\n\t}\n}\n\n/** Compares two DecorationAttrs objects. */\nfunction attrsEqual(a: DecorationAttrs, b: DecorationAttrs): boolean {\n\tif (a === b) return true;\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\tif (aKeys.length !== bKeys.length) return false;\n\tfor (const key of aKeys) {\n\t\tif (a[key] !== b[key]) return false;\n\t}\n\treturn true;\n}\n","/**\n * Plugin manager: handles plugin lifecycle, dependency resolution,\n * middleware chain, command/service registries, and error isolation.\n *\n * Per-plugin registration tracking ensures clean teardown —\n * commands, services, middleware, event subscriptions, and schema\n * registrations are automatically cleaned up when a plugin is destroyed.\n */\n\nimport { DecorationSet } from '../decorations/Decoration.js';\nimport type { InputRule } from '../input/InputRule.js';\nimport type { Keymap } from '../input/Keymap.js';\nimport { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { EventBus } from './EventBus.js';\nimport type {\n\tCommandEntry,\n\tCommandHandler,\n\tMiddlewareNext,\n\tPlugin,\n\tPluginConfig,\n\tPluginContext,\n\tPluginEventBus,\n\tServiceKey,\n\tTransactionMiddleware,\n} from './Plugin.js';\n\nconst DEFAULT_PRIORITY = 100;\n\ninterface MiddlewareEntry {\n\tmiddleware: TransactionMiddleware;\n\tpriority: number;\n}\n\ninterface PluginRegistrations {\n\tcommands: string[];\n\tservices: string[];\n\tmiddlewares: MiddlewareEntry[];\n\tunsubscribers: (() => void)[];\n\tnodeSpecs: string[];\n\tmarkSpecs: string[];\n\tinlineNodeSpecs: string[];\n\tnodeViews: string[];\n\tkeymaps: Keymap[];\n\tinputRules: InputRule[];\n\ttoolbarItems: string[];\n}\n\nexport interface PluginManagerInitOptions {\n\tgetState(): EditorState;\n\tdispatch(transaction: Transaction): void;\n\tgetContainer(): HTMLElement;\n\tgetPluginContainer(position: 'top' | 'bottom'): HTMLElement;\n\t/** Called after all plugin init() calls complete, before onReady(). */\n\tonBeforeReady?(): void | Promise<void>;\n}\n\nexport class PluginManager {\n\tprivate readonly plugins = new Map<string, Plugin>();\n\tprivate readonly commands = new Map<string, CommandEntry>();\n\tprivate readonly services = new Map<string, unknown>();\n\tprivate readonly middlewares: MiddlewareEntry[] = [];\n\tprivate readonly registrations = new Map<string, PluginRegistrations>();\n\tprivate readonly eventBus = new EventBus();\n\treadonly schemaRegistry = new SchemaRegistry();\n\tprivate middlewareSorted: MiddlewareEntry[] | null = null;\n\tprivate initOrder: string[] = [];\n\tprivate initialized = false;\n\tprivate initializing = false;\n\n\t/** Registers a plugin. Must be called before init(). */\n\tregister(plugin: Plugin): void {\n\t\tif (this.initialized || this.initializing) {\n\t\t\tthrow new Error(`Cannot register plugin \"${plugin.id}\" after initialization.`);\n\t\t}\n\t\tif (this.plugins.has(plugin.id)) {\n\t\t\tthrow new Error(`Plugin \"${plugin.id}\" is already registered.`);\n\t\t}\n\t\tthis.plugins.set(plugin.id, plugin);\n\t}\n\n\t/** Initializes all registered plugins in dependency/priority order. */\n\tasync init(options: PluginManagerInitOptions): Promise<void> {\n\t\tif (this.initialized || this.initializing) return;\n\t\tthis.initializing = true;\n\n\t\tthis.initOrder = this.resolveOrder();\n\n\t\tfor (const id of this.initOrder) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tif (!plugin) continue;\n\t\t\tconst context = this.createContext(id, options);\n\t\t\ttry {\n\t\t\t\tawait plugin.init(context);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[PluginManager] Plugin \"${id}\" failed to initialize:`, err);\n\t\t\t}\n\t\t}\n\n\t\t// Hook between init and onReady — lets the host rebuild schema/state\n\t\t// after all plugins have registered their specs but before plugins render.\n\t\tif (options.onBeforeReady) {\n\t\t\tawait options.onBeforeReady();\n\t\t}\n\n\t\t// Call onReady on all plugins after all init() calls have completed\n\t\tfor (const id of this.initOrder) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tif (!plugin?.onReady) continue;\n\t\t\ttry {\n\t\t\t\tawait plugin.onReady();\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[PluginManager] Plugin \"${id}\" error in onReady:`, err);\n\t\t\t}\n\t\t}\n\n\t\tthis.initialized = true;\n\t\tthis.initializing = false;\n\t}\n\n\t/** Notifies all plugins of a state change, in init order. */\n\tnotifyStateChange(oldState: EditorState, newState: EditorState, tr: Transaction): void {\n\t\tfor (const id of this.initOrder) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tif (!plugin?.onStateChange) continue;\n\t\t\ttry {\n\t\t\t\tplugin.onStateChange(oldState, newState, tr);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[PluginManager] Plugin \"${id}\" error in onStateChange:`, err);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Collects and merges decorations from all plugins. */\n\tcollectDecorations(state: EditorState, tr?: Transaction): DecorationSet {\n\t\tlet result: DecorationSet = DecorationSet.empty;\n\t\tfor (const id of this.initOrder) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tif (!plugin?.decorations) continue;\n\t\t\ttry {\n\t\t\t\tconst decos = plugin.decorations(state, tr);\n\t\t\t\tif (!decos.isEmpty) {\n\t\t\t\t\tresult = result.merge(decos);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[PluginManager] Plugin \"${id}\" error in decorations():`, err);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Dispatches a transaction through the middleware chain, then calls the final dispatch.\n\t * If no middleware is registered, calls finalDispatch directly.\n\t */\n\tdispatchWithMiddleware(\n\t\ttr: Transaction,\n\t\tstate: EditorState,\n\t\tfinalDispatch: (tr: Transaction) => void,\n\t): void {\n\t\tif (this.middlewares.length === 0) {\n\t\t\tfinalDispatch(tr);\n\t\t\treturn;\n\t\t}\n\n\t\tconst sorted = this.getSortedMiddleware();\n\t\tlet index = 0;\n\t\tlet dispatched = false;\n\n\t\tconst next: MiddlewareNext = (currentTr) => {\n\t\t\tif (index < sorted.length) {\n\t\t\t\tconst entry = sorted[index++];\n\t\t\t\tif (!entry) return;\n\t\t\t\tlet called = false;\n\t\t\t\tconst guardedNext: MiddlewareNext = (tr) => {\n\t\t\t\t\tif (called) return;\n\t\t\t\t\tcalled = true;\n\t\t\t\t\tnext(tr);\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\tentry.middleware(currentTr, state, guardedNext);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error('[PluginManager] Middleware error:', err);\n\t\t\t\t\tguardedNext(currentTr);\n\t\t\t\t}\n\t\t\t} else if (!dispatched) {\n\t\t\t\tdispatched = true;\n\t\t\t\tfinalDispatch(currentTr);\n\t\t\t}\n\t\t};\n\n\t\tnext(tr);\n\t}\n\n\t/** Executes a named command. Returns false if command not found. */\n\texecuteCommand(name: string): boolean {\n\t\tconst entry = this.commands.get(name);\n\t\tif (!entry) return false;\n\t\ttry {\n\t\t\treturn entry.handler();\n\t\t} catch (err) {\n\t\t\tconsole.error(`[PluginManager] Command \"${name}\" error:`, err);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/** Configures a plugin at runtime via onConfigure(). */\n\tconfigurePlugin(pluginId: string, config: PluginConfig): void {\n\t\tconst plugin = this.plugins.get(pluginId);\n\t\tif (!plugin) {\n\t\t\tthrow new Error(`Plugin \"${pluginId}\" not found.`);\n\t\t}\n\t\tif (!plugin.onConfigure) return;\n\t\ttry {\n\t\t\tplugin.onConfigure(config);\n\t\t} catch (err) {\n\t\t\tconsole.error(`[PluginManager] Plugin \"${pluginId}\" error in onConfigure:`, err);\n\t\t}\n\t}\n\n\t/** Returns all registered plugin IDs. */\n\tgetPluginIds(): string[] {\n\t\treturn [...this.plugins.keys()];\n\t}\n\n\t/** Gets a plugin by ID. */\n\tget(id: string): Plugin | undefined {\n\t\treturn this.plugins.get(id);\n\t}\n\n\t/** Gets a registered service by typed key. */\n\tgetService<T>(key: ServiceKey<T>): T | undefined {\n\t\treturn this.services.get(key.id) as T | undefined;\n\t}\n\n\t/** Destroys all plugins in reverse init order. */\n\tasync destroy(): Promise<void> {\n\t\tconst reversed = [...this.initOrder].reverse();\n\t\tfor (const id of reversed) {\n\t\t\tawait this.destroyPlugin(id);\n\t\t}\n\t\tthis.plugins.clear();\n\t\tthis.commands.clear();\n\t\tthis.services.clear();\n\t\tthis.middlewares.length = 0;\n\t\tthis.middlewareSorted = null;\n\t\tthis.eventBus.clear();\n\t\tthis.registrations.clear();\n\t\tthis.schemaRegistry.clear();\n\t\tthis.initOrder = [];\n\t\tthis.initialized = false;\n\t}\n\n\t// --- Private ---\n\n\tprivate async destroyPlugin(id: string): Promise<void> {\n\t\tconst plugin = this.plugins.get(id);\n\t\tif (plugin?.destroy) {\n\t\t\ttry {\n\t\t\t\tawait plugin.destroy();\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[PluginManager] Plugin \"${id}\" error in destroy:`, err);\n\t\t\t}\n\t\t}\n\t\tthis.cleanupRegistrations(id);\n\t}\n\n\tprivate cleanupRegistrations(id: string): void {\n\t\tconst reg = this.registrations.get(id);\n\t\tif (!reg) return;\n\n\t\tfor (const name of reg.commands) this.commands.delete(name);\n\t\tfor (const serviceId of reg.services) this.services.delete(serviceId);\n\t\tfor (const entry of reg.middlewares) {\n\t\t\tconst idx = this.middlewares.indexOf(entry);\n\t\t\tif (idx !== -1) this.middlewares.splice(idx, 1);\n\t\t}\n\t\tfor (const unsub of reg.unsubscribers) unsub();\n\n\t\t// Clean up schema registrations\n\t\tfor (const type of reg.nodeSpecs) this.schemaRegistry.removeNodeSpec(type);\n\t\tfor (const type of reg.markSpecs) this.schemaRegistry.removeMarkSpec(type);\n\t\tfor (const type of reg.inlineNodeSpecs) {\n\t\t\tthis.schemaRegistry.removeInlineNodeSpec(type);\n\t\t}\n\t\tfor (const type of reg.nodeViews) this.schemaRegistry.removeNodeView(type);\n\t\tfor (const keymap of reg.keymaps) this.schemaRegistry.removeKeymap(keymap);\n\t\tfor (const rule of reg.inputRules) this.schemaRegistry.removeInputRule(rule);\n\t\tfor (const itemId of reg.toolbarItems) this.schemaRegistry.removeToolbarItem(itemId);\n\n\t\tthis.middlewareSorted = null;\n\t\tthis.registrations.delete(id);\n\t}\n\n\tprivate getSortedMiddleware(): MiddlewareEntry[] {\n\t\tif (!this.middlewareSorted) {\n\t\t\tthis.middlewareSorted = [...this.middlewares].sort((a, b) => a.priority - b.priority);\n\t\t}\n\t\treturn this.middlewareSorted;\n\t}\n\n\tprivate createContext(pluginId: string, options: PluginManagerInitOptions): PluginContext {\n\t\tconst reg: PluginRegistrations = {\n\t\t\tcommands: [],\n\t\t\tservices: [],\n\t\t\tmiddlewares: [],\n\t\t\tunsubscribers: [],\n\t\t\tnodeSpecs: [],\n\t\t\tmarkSpecs: [],\n\t\t\tinlineNodeSpecs: [],\n\t\t\tnodeViews: [],\n\t\t\tkeymaps: [],\n\t\t\tinputRules: [],\n\t\t\ttoolbarItems: [],\n\t\t};\n\t\tthis.registrations.set(pluginId, reg);\n\n\t\tconst pluginEventBus: PluginEventBus = {\n\t\t\temit: (key, payload) => this.eventBus.emit(key, payload),\n\t\t\ton: (key, callback) => {\n\t\t\t\tconst unsub = this.eventBus.on(key, callback);\n\t\t\t\treg.unsubscribers.push(unsub);\n\t\t\t\treturn unsub;\n\t\t\t},\n\t\t\toff: (key, callback) => this.eventBus.off(key, callback),\n\t\t};\n\n\t\treturn {\n\t\t\tgetState: options.getState,\n\t\t\tdispatch: options.dispatch,\n\t\t\tgetContainer: options.getContainer,\n\t\t\tgetPluginContainer: options.getPluginContainer,\n\n\t\t\tregisterCommand: (name: string, handler: CommandHandler) => {\n\t\t\t\tif (this.commands.has(name)) {\n\t\t\t\t\tconst existing = this.commands.get(name);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Command \"${name}\" is already registered by plugin \"${existing?.pluginId}\".`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.commands.set(name, { name, handler, pluginId });\n\t\t\t\treg.commands.push(name);\n\t\t\t},\n\n\t\t\texecuteCommand: (name: string) => this.executeCommand(name),\n\n\t\t\tgetEventBus: () => pluginEventBus,\n\n\t\t\tregisterMiddleware: (middleware: TransactionMiddleware, priority = DEFAULT_PRIORITY) => {\n\t\t\t\tconst entry: MiddlewareEntry = { middleware, priority };\n\t\t\t\tthis.middlewares.push(entry);\n\t\t\t\treg.middlewares.push(entry);\n\t\t\t\tthis.middlewareSorted = null;\n\t\t\t},\n\n\t\t\tregisterService: <T>(key: ServiceKey<T>, service: T) => {\n\t\t\t\tif (this.services.has(key.id)) {\n\t\t\t\t\tthrow new Error(`Service \"${key.id}\" is already registered by another plugin.`);\n\t\t\t\t}\n\t\t\t\tthis.services.set(key.id, service);\n\t\t\t\treg.services.push(key.id);\n\t\t\t},\n\n\t\t\tgetService: <T>(key: ServiceKey<T>) => this.services.get(key.id) as T | undefined,\n\n\t\t\tupdateConfig: (config: PluginConfig) => {\n\t\t\t\tconst plugin = this.plugins.get(pluginId);\n\t\t\t\tif (plugin?.onConfigure) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tplugin.onConfigure(config);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[PluginManager] Plugin \"${pluginId}\" error in onConfigure:`, err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// --- Schema Extension Methods ---\n\n\t\t\tregisterNodeSpec: (spec) => {\n\t\t\t\tthis.schemaRegistry.registerNodeSpec(spec);\n\t\t\t\treg.nodeSpecs.push(spec.type);\n\t\t\t},\n\n\t\t\tregisterMarkSpec: (spec) => {\n\t\t\t\tthis.schemaRegistry.registerMarkSpec(spec);\n\t\t\t\treg.markSpecs.push(spec.type);\n\t\t\t},\n\n\t\t\tregisterNodeView: (type, factory) => {\n\t\t\t\tthis.schemaRegistry.registerNodeView(type, factory);\n\t\t\t\treg.nodeViews.push(type);\n\t\t\t},\n\n\t\t\tregisterKeymap: (keymap) => {\n\t\t\t\tthis.schemaRegistry.registerKeymap(keymap);\n\t\t\t\treg.keymaps.push(keymap);\n\t\t\t},\n\n\t\t\tregisterInputRule: (rule) => {\n\t\t\t\tthis.schemaRegistry.registerInputRule(rule);\n\t\t\t\treg.inputRules.push(rule);\n\t\t\t},\n\n\t\t\tregisterToolbarItem: (item) => {\n\t\t\t\tthis.schemaRegistry.registerToolbarItem(item, pluginId);\n\t\t\t\treg.toolbarItems.push(item.id);\n\t\t\t},\n\n\t\t\tregisterInlineNodeSpec: (spec) => {\n\t\t\t\tthis.schemaRegistry.registerInlineNodeSpec(spec);\n\t\t\t\treg.inlineNodeSpecs.push(spec.type);\n\t\t\t},\n\n\t\t\tgetSchemaRegistry: () => this.schemaRegistry,\n\t\t};\n\t}\n\n\t/**\n\t * Resolves plugin initialization order via topological sort + priority.\n\t * Throws on dependency cycles or missing dependencies.\n\t */\n\tprivate resolveOrder(): string[] {\n\t\tconst ids = [...this.plugins.keys()];\n\n\t\t// Validate dependencies exist\n\t\tfor (const id of ids) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tif (!plugin) continue;\n\t\t\tfor (const dep of plugin.dependencies ?? []) {\n\t\t\t\tif (!this.plugins.has(dep)) {\n\t\t\t\t\tthrow new Error(`Plugin \"${id}\" depends on \"${dep}\", which is not registered.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Topological sort (Kahn's algorithm)\n\t\tconst inDegree = new Map<string, number>();\n\t\tconst dependents = new Map<string, string[]>();\n\n\t\tfor (const id of ids) {\n\t\t\tinDegree.set(id, 0);\n\t\t\tdependents.set(id, []);\n\t\t}\n\n\t\tfor (const id of ids) {\n\t\t\tconst plugin = this.plugins.get(id);\n\t\t\tconst deps = plugin?.dependencies ?? [];\n\t\t\tinDegree.set(id, deps.length);\n\t\t\tfor (const dep of deps) {\n\t\t\t\tconst depList = dependents.get(dep);\n\t\t\t\tif (depList) depList.push(id);\n\t\t\t}\n\t\t}\n\n\t\tconst queue: string[] = [];\n\t\tfor (const [id, deg] of inDegree) {\n\t\t\tif (deg === 0) queue.push(id);\n\t\t}\n\n\t\tconst sorted: string[] = [];\n\t\twhile (queue.length > 0) {\n\t\t\tqueue.sort((a, b) => {\n\t\t\t\tconst pa = this.plugins.get(a)?.priority ?? DEFAULT_PRIORITY;\n\t\t\t\tconst pb = this.plugins.get(b)?.priority ?? DEFAULT_PRIORITY;\n\t\t\t\treturn pa - pb;\n\t\t\t});\n\n\t\t\tconst id = queue.shift();\n\t\t\tif (!id) break;\n\t\t\tsorted.push(id);\n\n\t\t\tfor (const dep of dependents.get(id) ?? []) {\n\t\t\t\tconst newDeg = (inDegree.get(dep) ?? 0) - 1;\n\t\t\t\tinDegree.set(dep, newDeg);\n\t\t\t\tif (newDeg === 0) queue.push(dep);\n\t\t\t}\n\t\t}\n\n\t\tif (sorted.length !== ids.length) {\n\t\t\tconst missing = ids.filter((id) => !sorted.includes(id));\n\t\t\tthrow new Error(`Circular dependency detected among plugins: ${missing.join(', ')}`);\n\t\t}\n\n\t\treturn sorted;\n\t}\n}\n","/**\n * Toolbar plugin: renders toolbar items registered by other plugins.\n * Acts as a pure rendering engine — has no knowledge of specific features.\n * Supports buttons, dropdowns, grid pickers, and custom popups.\n */\n\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport { ServiceKey } from '../Plugin.js';\nimport type { Plugin, PluginConfig, PluginContext } from '../Plugin.js';\nimport type { DropdownConfig, GridPickerConfig, ToolbarItem } from './ToolbarItem.js';\n\n// --- Layout Config ---\n\nexport interface ToolbarLayoutConfig {\n\treadonly groups: ReadonlyArray<ReadonlyArray<string>>;\n}\n\n// --- Typed Service API ---\n\nexport interface ToolbarServiceAPI {\n\t/** Re-reads isActive/isEnabled from state and updates all buttons. */\n\trefresh(): void;\n}\n\nexport const ToolbarServiceKey = new ServiceKey<ToolbarServiceAPI>('toolbar');\n\n// --- Plugin ---\n\ninterface ToolbarButton {\n\telement: HTMLButtonElement;\n\titem: ToolbarItem;\n}\n\nexport class ToolbarPlugin implements Plugin {\n\treadonly id = 'toolbar';\n\treadonly name = 'Toolbar';\n\treadonly priority = 10;\n\n\tprivate context: PluginContext | null = null;\n\tprivate toolbarElement: HTMLElement | null = null;\n\tprivate buttons: ToolbarButton[] = [];\n\tprivate activePopup: HTMLElement | null = null;\n\tprivate closePopupHandler: ((e: MouseEvent) => void) | null = null;\n\tprivate readonly hiddenItems = new Set<string>();\n\tprivate tooltipElement: HTMLElement | null = null;\n\tprivate tooltipTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate readonly layoutConfig: ToolbarLayoutConfig | null;\n\n\tconstructor(layoutConfig?: ToolbarLayoutConfig) {\n\t\tthis.layoutConfig = layoutConfig ?? null;\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\n\n\t\tcontext.registerService(ToolbarServiceKey, {\n\t\t\trefresh: () => this.updateButtonStates(context.getState()),\n\t\t});\n\n\t\tthis.createToolbarElement();\n\t\tthis.createTooltipElement();\n\t}\n\n\tonReady(): void {\n\t\tthis.renderItems();\n\t}\n\n\tdestroy(): void {\n\t\tthis.closePopup();\n\t\tthis.hideTooltip();\n\t\tif (this.tooltipElement) {\n\t\t\tthis.tooltipElement.remove();\n\t\t\tthis.tooltipElement = null;\n\t\t}\n\t\tif (this.toolbarElement) {\n\t\t\tthis.toolbarElement.remove();\n\t\t\tthis.toolbarElement = null;\n\t\t}\n\t\tthis.buttons = [];\n\t\tthis.context = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\tthis.updateButtonStates(newState);\n\t}\n\n\tonConfigure(config: PluginConfig): void {\n\t\tfor (const [key, value] of Object.entries(config)) {\n\t\t\tif (value === false) {\n\t\t\t\tthis.hiddenItems.add(key);\n\t\t\t} else {\n\t\t\t\tthis.hiddenItems.delete(key);\n\t\t\t}\n\t\t}\n\t\tthis.renderItems();\n\t}\n\n\t// --- Tooltip ---\n\n\tprivate createTooltipElement(): void {\n\t\tthis.tooltipElement = document.createElement('div');\n\t\tthis.tooltipElement.className = 'notectl-toolbar-tooltip';\n\t\tthis.tooltipElement.setAttribute('role', 'tooltip');\n\t\tthis.tooltipElement.style.display = 'none';\n\t}\n\n\tprivate showTooltip(button: HTMLButtonElement): void {\n\t\tthis.hideTooltip();\n\n\t\tif (this.activePopup || button.disabled) return;\n\n\t\tconst text = button.getAttribute('data-tooltip');\n\t\tif (!text || !this.tooltipElement) return;\n\n\t\tthis.tooltipTimer = setTimeout(() => {\n\t\t\tif (!this.tooltipElement || this.activePopup) return;\n\n\t\t\tthis.tooltipElement.textContent = text;\n\t\t\tthis.tooltipElement.style.display = '';\n\n\t\t\t// Append to shadow root to escape overflow:hidden on .notectl-editor\n\t\t\tconst root = button.getRootNode();\n\t\t\tif (root instanceof ShadowRoot && !this.tooltipElement.parentNode) {\n\t\t\t\troot.appendChild(this.tooltipElement);\n\t\t\t} else if (!(root instanceof ShadowRoot) && !this.tooltipElement.parentNode) {\n\t\t\t\tdocument.body.appendChild(this.tooltipElement);\n\t\t\t}\n\n\t\t\t// Position with fixed coordinates so clipping is impossible\n\t\t\tconst rect = button.getBoundingClientRect();\n\t\t\tthis.tooltipElement.style.position = 'fixed';\n\t\t\tthis.tooltipElement.style.top = `${rect.bottom + 6}px`;\n\t\t\tthis.tooltipElement.style.left = `${rect.left + rect.width / 2}px`;\n\t\t\tthis.tooltipElement.style.transform = 'translateX(-50%)';\n\t\t}, 500);\n\t}\n\n\tprivate hideTooltip(): void {\n\t\tif (this.tooltipTimer) {\n\t\t\tclearTimeout(this.tooltipTimer);\n\t\t\tthis.tooltipTimer = null;\n\t\t}\n\t\tif (this.tooltipElement) {\n\t\t\tthis.tooltipElement.style.display = 'none';\n\t\t}\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate createToolbarElement(): void {\n\t\tif (!this.context) return;\n\n\t\tif (this.toolbarElement) {\n\t\t\tthis.toolbarElement.remove();\n\t\t}\n\t\tthis.buttons = [];\n\n\t\tconst container = this.context.getPluginContainer('top');\n\t\tthis.toolbarElement = document.createElement('div');\n\t\tthis.toolbarElement.setAttribute('role', 'toolbar');\n\t\tthis.toolbarElement.setAttribute('aria-label', 'Formatting options');\n\t\tthis.toolbarElement.className = 'notectl-toolbar';\n\n\t\tcontainer.appendChild(this.toolbarElement);\n\t}\n\n\tprivate renderItems(): void {\n\t\tif (!this.context || !this.toolbarElement) return;\n\n\t\t// Remove existing buttons\n\t\tfor (const btn of this.buttons) {\n\t\t\tbtn.element.remove();\n\t\t}\n\t\tthis.buttons = [];\n\n\t\t// Remove existing separators\n\t\tfor (const sep of this.toolbarElement.querySelectorAll('.notectl-toolbar-separator')) {\n\t\t\tsep.remove();\n\t\t}\n\n\t\tif (this.layoutConfig) {\n\t\t\tthis.renderItemsByLayout();\n\t\t} else {\n\t\t\tthis.renderItemsByPriority();\n\t\t}\n\n\t\t// Re-attach toolbar if it was removed but has visible buttons\n\t\tif (this.buttons.length > 0 && !this.toolbarElement.parentElement) {\n\t\t\tconst container = this.context.getPluginContainer('top');\n\t\t\tcontainer.appendChild(this.toolbarElement);\n\t\t}\n\n\t\tthis.updateButtonStates(this.context.getState());\n\t}\n\n\tprivate renderItemsByLayout(): void {\n\t\tif (!this.context || !this.toolbarElement || !this.layoutConfig) return;\n\n\t\tconst registry = this.context.getSchemaRegistry();\n\t\tlet firstGroup = true;\n\n\t\tfor (const groupPluginIds of this.layoutConfig.groups) {\n\t\t\tconst groupItems: ToolbarItem[] = [];\n\t\t\tfor (const pId of groupPluginIds) {\n\t\t\t\tconst items = registry\n\t\t\t\t\t.getToolbarItemsByPlugin(pId)\n\t\t\t\t\t.filter((item) => !this.hiddenItems.has(item.id));\n\t\t\t\t// Sort within plugin by priority (bold before italic etc.)\n\t\t\t\titems.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\n\t\t\t\tgroupItems.push(...items);\n\t\t\t}\n\n\t\t\tif (groupItems.length === 0) continue;\n\n\t\t\tif (!firstGroup) {\n\t\t\t\tconst sep = document.createElement('span');\n\t\t\t\tsep.className = 'notectl-toolbar-separator';\n\t\t\t\tsep.setAttribute('role', 'separator');\n\t\t\t\tthis.toolbarElement.appendChild(sep);\n\t\t\t}\n\t\t\tfirstGroup = false;\n\n\t\t\tfor (const item of groupItems) {\n\t\t\t\tconst btn = this.createButton(item);\n\t\t\t\tthis.toolbarElement.appendChild(btn.element);\n\t\t\t\tthis.buttons.push(btn);\n\t\t\t}\n\t\t}\n\n\t\tif (this.buttons.length === 0) {\n\t\t\tthis.toolbarElement.remove();\n\t\t}\n\t}\n\n\tprivate renderItemsByPriority(): void {\n\t\tif (!this.context || !this.toolbarElement) return;\n\n\t\tconst registry = this.context.getSchemaRegistry();\n\t\tconst items = registry.getToolbarItems().filter((item) => !this.hiddenItems.has(item.id));\n\t\tif (items.length === 0) {\n\t\t\tthis.toolbarElement.remove();\n\t\t\treturn;\n\t\t}\n\n\t\t// Sort by priority (lower = further left)\n\t\tconst sorted = [...items].sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\n\n\t\tconst hasSeparatorAfter = sorted.some((item) => item.separatorAfter);\n\n\t\tif (hasSeparatorAfter) {\n\t\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\t\tconst item = sorted[i];\n\t\t\t\tif (!item) continue;\n\t\t\t\tconst btn = this.createButton(item);\n\t\t\t\tthis.toolbarElement.appendChild(btn.element);\n\t\t\t\tthis.buttons.push(btn);\n\n\t\t\t\tif (item.separatorAfter && i < sorted.length - 1) {\n\t\t\t\t\tconst sep = document.createElement('span');\n\t\t\t\t\tsep.className = 'notectl-toolbar-separator';\n\t\t\t\t\tsep.setAttribute('role', 'separator');\n\t\t\t\t\tthis.toolbarElement.appendChild(sep);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst groups = new Map<string, ToolbarItem[]>();\n\t\t\tfor (const item of sorted) {\n\t\t\t\tconst list = groups.get(item.group) ?? [];\n\t\t\t\tlist.push(item);\n\t\t\t\tgroups.set(item.group, list);\n\t\t\t}\n\n\t\t\tlet firstGroup = true;\n\t\t\tfor (const [, groupItems] of groups) {\n\t\t\t\tif (!firstGroup) {\n\t\t\t\t\tconst sep = document.createElement('span');\n\t\t\t\t\tsep.className = 'notectl-toolbar-separator';\n\t\t\t\t\tsep.setAttribute('role', 'separator');\n\t\t\t\t\tthis.toolbarElement.appendChild(sep);\n\t\t\t\t}\n\t\t\t\tfirstGroup = false;\n\n\t\t\t\tfor (const item of groupItems) {\n\t\t\t\t\tconst btn = this.createButton(item);\n\t\t\t\t\tthis.toolbarElement.appendChild(btn.element);\n\t\t\t\t\tthis.buttons.push(btn);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate createButton(item: ToolbarItem): ToolbarButton {\n\t\tconst btn = document.createElement('button');\n\t\tbtn.type = 'button';\n\t\tbtn.className = `notectl-toolbar-btn notectl-toolbar-btn--${item.id}`;\n\t\tbtn.setAttribute('aria-pressed', 'false');\n\t\tbtn.setAttribute('aria-label', item.label);\n\t\tbtn.setAttribute('data-toolbar-item', item.id);\n\t\tbtn.setAttribute('data-tooltip', item.tooltip ?? item.label);\n\n\t\tconst span = document.createElement('span');\n\t\tspan.className = 'notectl-toolbar-btn__icon';\n\t\tspan.innerHTML = item.icon;\n\t\tbtn.appendChild(span);\n\n\t\tbtn.addEventListener('mousedown', (e) => {\n\t\t\te.preventDefault();\n\t\t\tthis.hideTooltip();\n\t\t\tif (item.popupType) {\n\t\t\t\tthis.togglePopup(btn, item);\n\t\t\t} else {\n\t\t\t\tthis.context?.executeCommand(item.command);\n\t\t\t}\n\t\t});\n\n\t\tbtn.addEventListener('mouseenter', () => this.showTooltip(btn));\n\t\tbtn.addEventListener('mouseleave', () => this.hideTooltip());\n\n\t\treturn { element: btn, item };\n\t}\n\n\tprivate activePopupButton: HTMLButtonElement | null = null;\n\n\tprivate togglePopup(button: HTMLButtonElement, item: ToolbarItem): void {\n\t\tif (this.activePopup) {\n\t\t\tthis.closePopup();\n\t\t\treturn;\n\t\t}\n\n\t\tconst popup = document.createElement('div');\n\t\tpopup.className = 'notectl-toolbar-popup';\n\n\t\tswitch (item.popupType) {\n\t\t\tcase 'gridPicker':\n\t\t\t\tthis.renderGridPicker(popup, item.popupConfig);\n\t\t\t\tbreak;\n\t\t\tcase 'dropdown':\n\t\t\t\tthis.renderDropdown(popup, item.popupConfig);\n\t\t\t\tbreak;\n\t\t\tcase 'custom':\n\t\t\t\tif (this.context) item.renderPopup(popup, this.context);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Position below the button using fixed coordinates to escape overflow:hidden\n\t\tconst rect = button.getBoundingClientRect();\n\t\tpopup.style.position = 'fixed';\n\t\tpopup.style.top = `${rect.bottom + 2}px`;\n\t\tpopup.style.left = `${rect.left}px`;\n\t\tpopup.style.zIndex = '10000';\n\n\t\t// Append to shadow root directly to avoid clipping by .notectl-editor\n\t\tconst root = button.getRootNode();\n\t\tif (root instanceof ShadowRoot) {\n\t\t\troot.appendChild(popup);\n\t\t} else {\n\t\t\tdocument.body.appendChild(popup);\n\t\t}\n\n\t\tthis.activePopup = popup;\n\t\tthis.activePopupButton = button;\n\t\tbutton.classList.add('notectl-toolbar-btn--popup-open');\n\n\t\tthis.closePopupHandler = (e: MouseEvent) => {\n\t\t\tif (!popup.contains(e.target as Node) && e.target !== button) {\n\t\t\t\tthis.closePopup();\n\t\t\t}\n\t\t};\n\t\tsetTimeout(() => {\n\t\t\tif (this.closePopupHandler) {\n\t\t\t\tdocument.addEventListener('mousedown', this.closePopupHandler);\n\t\t\t}\n\t\t}, 0);\n\t}\n\n\tprivate closePopup(): void {\n\t\tif (this.activePopupButton) {\n\t\t\tthis.activePopupButton.classList.remove('notectl-toolbar-btn--popup-open');\n\t\t\tthis.activePopupButton = null;\n\t\t}\n\t\tif (this.activePopup) {\n\t\t\tthis.activePopup.remove();\n\t\t\tthis.activePopup = null;\n\t\t}\n\t\tif (this.closePopupHandler) {\n\t\t\tdocument.removeEventListener('mousedown', this.closePopupHandler);\n\t\t\tthis.closePopupHandler = null;\n\t\t}\n\t}\n\n\tprivate renderGridPicker(container: HTMLElement, config: GridPickerConfig): void {\n\t\tcontainer.className += ' notectl-grid-picker';\n\t\tconst grid = document.createElement('div');\n\t\tgrid.className = 'notectl-grid-picker__grid';\n\t\tgrid.style.display = 'grid';\n\t\tgrid.style.gridTemplateColumns = `repeat(${config.maxCols}, 1fr)`;\n\t\tgrid.style.gap = '2px';\n\t\tgrid.style.padding = '8px';\n\n\t\tconst label = document.createElement('div');\n\t\tlabel.className = 'notectl-grid-picker__label';\n\t\tlabel.textContent = '1 x 1';\n\t\tlabel.style.textAlign = 'center';\n\t\tlabel.style.padding = '4px';\n\t\tlabel.style.fontSize = '12px';\n\n\t\tfor (let r = 1; r <= config.maxRows; r++) {\n\t\t\tfor (let c = 1; c <= config.maxCols; c++) {\n\t\t\t\tconst cell = document.createElement('div');\n\t\t\t\tcell.className = 'notectl-grid-picker__cell';\n\t\t\t\tcell.style.width = '20px';\n\t\t\t\tcell.style.height = '20px';\n\t\t\t\tcell.style.border = '1px solid #ccc';\n\t\t\t\tcell.style.cursor = 'pointer';\n\t\t\t\tcell.setAttribute('data-row', String(r));\n\t\t\t\tcell.setAttribute('data-col', String(c));\n\n\t\t\t\tcell.addEventListener('mouseenter', () => {\n\t\t\t\t\tconst cells = grid.querySelectorAll('.notectl-grid-picker__cell');\n\t\t\t\t\tfor (const other of cells) {\n\t\t\t\t\t\tconst otherR = Number(other.getAttribute('data-row'));\n\t\t\t\t\t\tconst otherC = Number(other.getAttribute('data-col'));\n\t\t\t\t\t\t(other as HTMLElement).style.background = otherR <= r && otherC <= c ? '#4a9eff' : '';\n\t\t\t\t\t}\n\t\t\t\t\tlabel.textContent = `${r} x ${c}`;\n\t\t\t\t});\n\n\t\t\t\tcell.addEventListener('mousedown', (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tconfig.onSelect(r, c);\n\t\t\t\t\tthis.closePopup();\n\t\t\t\t});\n\n\t\t\t\tgrid.appendChild(cell);\n\t\t\t}\n\t\t}\n\n\t\tcontainer.appendChild(grid);\n\t\tcontainer.appendChild(label);\n\t}\n\n\tprivate renderDropdown(container: HTMLElement, config: DropdownConfig): void {\n\t\tcontainer.classList.add('notectl-dropdown');\n\t\tfor (const item of config.items) {\n\t\t\tconst btn = document.createElement('button');\n\t\t\tbtn.type = 'button';\n\t\t\tbtn.className = 'notectl-dropdown__item';\n\n\t\t\tif (item.icon) {\n\t\t\t\tconst iconSpan = document.createElement('span');\n\t\t\t\ticonSpan.className = 'notectl-dropdown__item-icon';\n\t\t\t\ticonSpan.innerHTML = item.icon;\n\t\t\t\tbtn.appendChild(iconSpan);\n\t\t\t}\n\n\t\t\tconst labelSpan = document.createElement('span');\n\t\t\tlabelSpan.className = 'notectl-dropdown__item-label';\n\t\t\tlabelSpan.textContent = item.label;\n\t\t\tbtn.appendChild(labelSpan);\n\n\t\t\tbtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tthis.context?.executeCommand(item.command);\n\t\t\t\tthis.closePopup();\n\t\t\t});\n\n\t\t\tcontainer.appendChild(btn);\n\t\t}\n\t}\n\n\tprivate updateButtonStates(state: EditorState): void {\n\t\tfor (const btn of this.buttons) {\n\t\t\tconst active = btn.item.isActive?.(state) ?? false;\n\t\t\tconst enabled = btn.item.isEnabled?.(state) ?? true;\n\t\t\tbtn.element.setAttribute('aria-pressed', String(active));\n\t\t\tbtn.element.classList.toggle('notectl-toolbar-btn--active', active);\n\t\t\tbtn.element.disabled = !enabled;\n\t\t\tif (!enabled) {\n\t\t\t\tbtn.element.setAttribute('aria-disabled', 'true');\n\t\t\t} else {\n\t\t\t\tbtn.element.removeAttribute('aria-disabled');\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * ToolbarItem: describes a toolbar button registered by a plugin.\n */\n\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\n\nexport interface GridPickerConfig {\n\treadonly maxRows: number;\n\treadonly maxCols: number;\n\tonSelect(rows: number, cols: number): void;\n}\n\nexport interface DropdownConfig {\n\treadonly items: readonly { label: string; command: string; icon?: string }[];\n}\n\nexport type ToolbarGroup = 'format' | 'block' | 'insert' | (string & {});\nexport type PopupType = 'gridPicker' | 'dropdown' | 'custom';\n\ninterface ToolbarItemBase {\n\treadonly id: string;\n\t/** Grouping key: 'format' | 'insert' | 'block' or custom. */\n\treadonly group: ToolbarGroup;\n\t/** Icon content: inline SVG markup or plain text. Rendered via innerHTML. */\n\treadonly icon: string;\n\treadonly label: string;\n\t/** Tooltip shown on hover, e.g. \"Bold (Ctrl+B)\". Falls back to label. */\n\treadonly tooltip?: string;\n\t/** Command name to execute on click. */\n\treadonly command: string;\n\t/**\n\t * Lower priority renders further left.\n\t * @deprecated Use the declarative `toolbar` config on `createEditor()` instead.\n\t */\n\treadonly priority?: number;\n\t/**\n\t * When true, a visual separator is rendered after this item.\n\t * @deprecated Use the declarative `toolbar` config on `createEditor()` instead.\n\t */\n\treadonly separatorAfter?: boolean;\n\tisActive?(state: EditorState): boolean;\n\tisEnabled?(state: EditorState): boolean;\n}\n\ninterface ToolbarItemNoPopup extends ToolbarItemBase {\n\treadonly popupType?: undefined;\n}\n\ninterface ToolbarItemGridPicker extends ToolbarItemBase {\n\treadonly popupType: 'gridPicker';\n\treadonly popupConfig: GridPickerConfig;\n}\n\ninterface ToolbarItemDropdown extends ToolbarItemBase {\n\treadonly popupType: 'dropdown';\n\treadonly popupConfig: DropdownConfig;\n}\n\ninterface ToolbarItemCustomPopup extends ToolbarItemBase {\n\treadonly popupType: 'custom';\n\trenderPopup(container: HTMLElement, context: PluginContext): void;\n}\n\nexport type ToolbarItem =\n\t| ToolbarItemNoPopup\n\t| ToolbarItemGridPicker\n\t| ToolbarItemDropdown\n\t| ToolbarItemCustomPopup;\n\n/**\n * Formats a keymap binding string into a human-readable shortcut,\n * using platform-appropriate modifier symbols (⌘ on Mac, Ctrl on others).\n *\n * @example formatShortcut('Mod-B') → \"Ctrl+B\" or \"⌘B\"\n * @example formatShortcut('Mod-Shift-X') → \"Ctrl+Shift+X\" or \"⌘⇧X\"\n */\nexport function formatShortcut(binding: string): string {\n\tconst isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.platform);\n\tif (isMac) {\n\t\treturn binding\n\t\t\t.replace(/Mod/g, '⌘')\n\t\t\t.replace(/Shift/g, '⇧')\n\t\t\t.replace(/Alt/g, '⌥')\n\t\t\t.replace(/-/g, '');\n\t}\n\treturn binding.replace(/Mod/g, 'Ctrl').replace(/-/g, '+');\n}\n","/**\n * TextFormattingPlugin: registers inline marks (bold, italic, underline)\n * with their MarkSpecs, toggle commands, keyboard shortcuts, and toolbar items.\n *\n * This plugin is data-driven — each mark type is defined declaratively and\n * all registrations (MarkSpec, command, keymap, toolbar item) are derived\n * from the same definition.\n *\n * Supports two separate config dimensions:\n * - Feature config (bold/italic/underline): controls whether the mark is\n * registered in the schema. When disabled, the keyboard shortcut does nothing.\n * - Toolbar config: controls whether the toolbar button is visible.\n * When a feature is disabled but toolbar is enabled, the button renders as disabled.\n */\n\nimport { isMarkActive, toggleMark } from '../../commands/Commands.js';\nimport { markType as mkType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\n\n// --- Configuration ---\n\n/** Controls toolbar button visibility per mark. */\nexport interface TextFormattingToolbarConfig {\n\treadonly bold?: boolean;\n\treadonly italic?: boolean;\n\treadonly underline?: boolean;\n}\n\n/** Controls which inline marks are enabled and which toolbar buttons are shown. */\nexport interface TextFormattingConfig {\n\treadonly bold: boolean;\n\treadonly italic: boolean;\n\treadonly underline: boolean;\n\treadonly toolbar?: TextFormattingToolbarConfig;\n\t/** When true, a separator is rendered after the last text-formatting toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: TextFormattingConfig = {\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n};\n\n// --- Mark Definitions ---\n\ninterface MarkDefinition {\n\treadonly type: string;\n\treadonly configKey: keyof Omit<TextFormattingConfig, 'toolbar' | 'separatorAfter'>;\n\treadonly rank: number;\n\treadonly tag: string;\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly keyBinding: string;\n}\n\nconst BOLD_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z\"/></svg>';\nconst ITALIC_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z\"/></svg>';\nconst UNDERLINE_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z\"/></svg>';\n\nconst MARK_DEFINITIONS: readonly MarkDefinition[] = [\n\t{\n\t\ttype: 'bold',\n\t\tconfigKey: 'bold',\n\t\trank: 0,\n\t\ttag: 'strong',\n\t\tlabel: 'Bold',\n\t\ticon: BOLD_ICON,\n\t\tkeyBinding: 'Mod-B',\n\t},\n\t{\n\t\ttype: 'italic',\n\t\tconfigKey: 'italic',\n\t\trank: 1,\n\t\ttag: 'em',\n\t\tlabel: 'Italic',\n\t\ticon: ITALIC_ICON,\n\t\tkeyBinding: 'Mod-I',\n\t},\n\t{\n\t\ttype: 'underline',\n\t\tconfigKey: 'underline',\n\t\trank: 2,\n\t\ttag: 'u',\n\t\tlabel: 'Underline',\n\t\ticon: UNDERLINE_ICON,\n\t\tkeyBinding: 'Mod-U',\n\t},\n];\n\n// --- Plugin ---\n\nexport class TextFormattingPlugin implements Plugin {\n\treadonly id = 'text-formatting';\n\treadonly name = 'Text Formatting';\n\treadonly priority = 20;\n\n\tprivate readonly config: TextFormattingConfig;\n\n\tconstructor(config?: Partial<TextFormattingConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tconst enabledMarks = MARK_DEFINITIONS.filter((def) => this.config[def.configKey]);\n\n\t\t// Determine which marks will have visible toolbar items\n\t\tconst visibleToolbarMarks = enabledMarks.filter((def) => this.isToolbarVisible(def.configKey));\n\t\tconst lastVisibleMark = visibleToolbarMarks.at(-1);\n\n\t\tfor (const def of enabledMarks) {\n\t\t\tconst isSeparatorTarget = this.config.separatorAfter && def === lastVisibleMark;\n\t\t\tthis.registerMark(context, def, isSeparatorTarget);\n\t\t}\n\n\t\tthis.registerKeymaps(context, enabledMarks);\n\n\t\t// Register disabled placeholder buttons for marks that are disabled\n\t\t// as features but explicitly requested in the toolbar config\n\t\tthis.registerDisabledToolbarItems(context);\n\t}\n\n\tprivate registerMark(\n\t\tcontext: PluginContext,\n\t\tdef: MarkDefinition,\n\t\tseparatorAfter?: boolean,\n\t): void {\n\t\tconst commandName = toCommandName(def.type);\n\t\tconst toolbarVisible = this.isToolbarVisible(def.configKey);\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: def.type,\n\t\t\trank: def.rank,\n\t\t\ttoDOM() {\n\t\t\t\treturn document.createElement(def.tag);\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerCommand(commandName, () => {\n\t\t\tconst tr = toggleMark(context.getState(), mkType(def.type));\n\t\t\tif (tr) {\n\t\t\t\tcontext.dispatch(tr);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\n\t\tif (toolbarVisible) {\n\t\t\tcontext.registerToolbarItem({\n\t\t\t\tid: def.type,\n\t\t\t\tgroup: 'format',\n\t\t\t\ticon: def.icon,\n\t\t\t\tlabel: def.label,\n\t\t\t\ttooltip: `${def.label} (${formatShortcut(def.keyBinding)})`,\n\t\t\t\tcommand: commandName,\n\t\t\t\tpriority: def.rank * 10 + 10,\n\t\t\t\tseparatorAfter,\n\t\t\t\tisActive: (state) => isMarkActive(state, mkType(def.type)),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerKeymaps(context: PluginContext, marks: readonly MarkDefinition[]): void {\n\t\tconst keymap: Record<string, () => boolean> = {};\n\t\tfor (const def of marks) {\n\t\t\tconst commandName = toCommandName(def.type);\n\t\t\tkeymap[def.keyBinding] = () => context.executeCommand(commandName);\n\t\t}\n\t\tif (Object.keys(keymap).length > 0) {\n\t\t\tcontext.registerKeymap(keymap);\n\t\t}\n\t}\n\n\t/**\n\t * Registers disabled toolbar buttons for marks whose feature is disabled\n\t * but whose toolbar button is explicitly requested.\n\t */\n\tprivate registerDisabledToolbarItems(context: PluginContext): void {\n\t\tif (!this.config.toolbar) return;\n\n\t\tfor (const def of MARK_DEFINITIONS) {\n\t\t\tconst featureEnabled = this.config[def.configKey];\n\t\t\tconst toolbarVisible = this.config.toolbar[def.configKey] ?? true;\n\n\t\t\tif (!featureEnabled && toolbarVisible) {\n\t\t\t\tcontext.registerToolbarItem({\n\t\t\t\t\tid: def.type,\n\t\t\t\t\tgroup: 'format',\n\t\t\t\t\ticon: def.icon,\n\t\t\t\t\tlabel: def.label,\n\t\t\t\t\tcommand: toCommandName(def.type),\n\t\t\t\t\tpriority: def.rank * 10 + 10,\n\t\t\t\t\tisEnabled: () => false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Checks if a toolbar button should be visible for a given mark. */\n\tprivate isToolbarVisible(\n\t\tconfigKey: keyof Omit<TextFormattingConfig, 'toolbar' | 'separatorAfter'>,\n\t): boolean {\n\t\tif (!this.config.toolbar) return true;\n\t\treturn this.config.toolbar[configKey] ?? true;\n\t}\n}\n\n/** Converts a mark type to its toggle command name (e.g. 'bold' → 'toggleBold'). */\nfunction toCommandName(markType: string): string {\n\treturn `toggle${markType.charAt(0).toUpperCase()}${markType.slice(1)}`;\n}\n","/**\n * HeadingPlugin: registers Title, Subtitle, and H1–H6 heading block types\n * with NodeSpec, toggle commands, keyboard shortcuts, input rules, and a\n * combobox-style toolbar dropdown that reflects the current block type.\n */\n\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { createCollapsedSelection, isCollapsed } from '../../model/Selection.js';\nimport { type NodeTypeName, nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport type { TextAlignment } from '../text-alignment/TextAlignmentPlugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\theading: { level: HeadingLevel; textAlign?: TextAlignment };\n\t\ttitle: { textAlign?: TextAlignment };\n\t\tsubtitle: { textAlign?: TextAlignment };\n\t}\n}\n\n// --- Configuration ---\n\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport interface HeadingConfig {\n\t/** Which heading levels to enable. Defaults to [1, 2, 3, 4, 5, 6]. */\n\treadonly levels: readonly HeadingLevel[];\n\t/** When true, a separator is rendered after the heading toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: HeadingConfig = {\n\tlevels: [1, 2, 3, 4, 5, 6],\n};\n\n// --- Heading Tag Mapping ---\n\nconst HEADING_TAGS: Record<HeadingLevel, string> = {\n\t1: 'h1',\n\t2: 'h2',\n\t3: 'h3',\n\t4: 'h4',\n\t5: 'h5',\n\t6: 'h6',\n};\n\n// --- Display Labels ---\n\nconst HEADING_LABELS: Record<HeadingLevel, string> = {\n\t1: 'Heading 1',\n\t2: 'Heading 2',\n\t3: 'Heading 3',\n\t4: 'Heading 4',\n\t5: 'Heading 5',\n\t6: 'Heading 6',\n};\n\nconst TITLE_LABEL = 'Title';\nconst SUBTITLE_LABEL = 'Subtitle';\nconst PARAGRAPH_LABEL = 'Paragraph';\n\n// --- Picker Item Styling ---\n\ninterface PickerItemStyle {\n\treadonly fontSize: string;\n\treadonly fontWeight: string;\n\treadonly color?: string;\n}\n\n// --- Plugin ---\n\nexport class HeadingPlugin implements Plugin {\n\treadonly id = 'heading';\n\treadonly name = 'Heading';\n\treadonly priority = 30;\n\n\tprivate readonly config: HeadingConfig;\n\tprivate context: PluginContext | null = null;\n\tprivate comboLabel: HTMLSpanElement | null = null;\n\n\tconstructor(config?: Partial<HeadingConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\n\t\tthis.registerNodeSpecs(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInputRules(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tdestroy(): void {\n\t\tthis.context = null;\n\t\tthis.comboLabel = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\tthis.updateComboLabel(newState);\n\t}\n\n\tprivate registerNodeSpecs(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'title',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\ttoDOM(node) {\n\t\t\t\tconst el = createBlockElement('h1', node.id);\n\t\t\t\tel.classList.add('notectl-title');\n\t\t\t\treturn el;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'subtitle',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\ttoDOM(node) {\n\t\t\t\tconst el = createBlockElement('h2', node.id);\n\t\t\t\tel.classList.add('notectl-subtitle');\n\t\t\t\treturn el;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'heading',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\tattrs: {\n\t\t\t\tlevel: { default: 1 },\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\tconst level = node.attrs?.level ?? 1;\n\t\t\t\tconst tag = HEADING_TAGS[level] ?? 'h1';\n\t\t\t\treturn createBlockElement(tag, node.id);\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\t// Title / Subtitle\n\t\tcontext.registerCommand('setTitle', () => {\n\t\t\treturn this.toggleSpecialBlock(context, 'title');\n\t\t});\n\n\t\tcontext.registerCommand('setSubtitle', () => {\n\t\t\treturn this.toggleSpecialBlock(context, 'subtitle');\n\t\t});\n\n\t\t// Heading levels\n\t\tfor (const level of this.config.levels) {\n\t\t\tcontext.registerCommand(`setHeading${level}`, () => {\n\t\t\t\treturn this.toggleHeading(context, level);\n\t\t\t});\n\t\t}\n\n\t\t// Generic command that toggles back to paragraph\n\t\tcontext.registerCommand('toggleHeading', () => {\n\t\t\treturn this.toggleHeading(context, 1);\n\t\t});\n\n\t\t// Set paragraph (reset heading)\n\t\tcontext.registerCommand('setParagraph', () => {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t});\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tconst keymap: Record<string, () => boolean> = {};\n\n\t\tfor (const level of this.config.levels) {\n\t\t\tif (level <= 6) {\n\t\t\t\tkeymap[`Mod-Shift-${level}`] = () => context.executeCommand(`setHeading${level}`);\n\t\t\t}\n\t\t}\n\n\t\tif (Object.keys(keymap).length > 0) {\n\t\t\tcontext.registerKeymap(keymap);\n\t\t}\n\t}\n\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tfor (const level of this.config.levels) {\n\t\t\tconst hashes = '#'.repeat(level);\n\t\t\tconst pattern = new RegExp(`^${hashes} $`);\n\n\t\t\tcontext.registerInputRule({\n\t\t\t\tpattern,\n\t\t\t\thandler(state, _match, start, _end) {\n\t\t\t\t\tconst sel = state.selection;\n\t\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\t\treturn state\n\t\t\t\t\t\t.transaction('input')\n\t\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, start, start + level + 1)\n\t\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('heading'), { level })\n\t\t\t\t\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, 0))\n\t\t\t\t\t\t.build();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon: string = `<span class=\"notectl-heading-select__label\" data-heading-label>${PARAGRAPH_LABEL}</span><span class=\"notectl-heading-select__arrow\">\\u25BE</span>`;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'heading',\n\t\t\tgroup: 'block',\n\t\t\ticon,\n\t\t\tlabel: 'Block Type',\n\t\t\ttooltip: 'Block Type',\n\t\t\tcommand: 'setParagraph',\n\t\t\tpriority: 50,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderHeadingPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => {\n\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\treturn block?.type === 'heading' || block?.type === 'title' || block?.type === 'subtitle';\n\t\t\t},\n\t\t});\n\t}\n\n\t// --- Combo Label ---\n\n\tprivate updateComboLabel(state: EditorState): void {\n\t\tif (!this.comboLabel) {\n\t\t\tconst container: HTMLElement | undefined = this.context?.getPluginContainer('top');\n\t\t\tif (!container) return;\n\t\t\tthis.comboLabel = container.querySelector<HTMLSpanElement>('[data-heading-label]') ?? null;\n\t\t\tif (!this.comboLabel) return;\n\t\t}\n\n\t\tthis.comboLabel.textContent = this.getActiveLabel(state);\n\t}\n\n\tprivate getActiveLabel(state: EditorState): string {\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block) return PARAGRAPH_LABEL;\n\n\t\tif (block.type === 'title') return TITLE_LABEL;\n\t\tif (block.type === 'subtitle') return SUBTITLE_LABEL;\n\n\t\tif (block.type === 'heading') {\n\t\t\tconst level = block.attrs?.level as HeadingLevel | undefined;\n\t\t\tif (!level) return HEADING_LABELS[1];\n\t\t\treturn HEADING_LABELS[level] ?? HEADING_LABELS[1];\n\t\t}\n\n\t\treturn PARAGRAPH_LABEL;\n\t}\n\n\t// --- Custom Popup ---\n\n\tprivate dismissPopup(): void {\n\t\tsetTimeout(() => {\n\t\t\tdocument.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));\n\t\t}, 0);\n\t}\n\n\tprivate renderHeadingPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-heading-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tconst currentType: string = block?.type ?? 'paragraph';\n\t\tconst activeLevel: HeadingLevel | null =\n\t\t\tcurrentType === 'heading' ? ((block?.attrs?.level as HeadingLevel) ?? 1) : null;\n\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-heading-picker__list';\n\n\t\tconst addItem = (\n\t\t\tlabel: string,\n\t\t\tactive: boolean,\n\t\t\tcommand: string,\n\t\t\tstyle?: PickerItemStyle,\n\t\t): void => {\n\t\t\tlist.appendChild(\n\t\t\t\tthis.createPickerItem(\n\t\t\t\t\tlabel,\n\t\t\t\t\tactive,\n\t\t\t\t\t(e: MouseEvent) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\tcontext.executeCommand(command);\n\t\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t\t},\n\t\t\t\t\tstyle,\n\t\t\t\t),\n\t\t\t);\n\t\t};\n\n\t\t// Paragraph\n\t\taddItem(PARAGRAPH_LABEL, currentType === 'paragraph', 'setParagraph');\n\n\t\t// Title\n\t\taddItem(TITLE_LABEL, currentType === 'title', 'setTitle', {\n\t\t\tfontSize: '1.6em',\n\t\t\tfontWeight: '700',\n\t\t});\n\n\t\t// Subtitle\n\t\taddItem(SUBTITLE_LABEL, currentType === 'subtitle', 'setSubtitle', {\n\t\t\tfontSize: '1.3em',\n\t\t\tfontWeight: '500',\n\t\t});\n\n\t\t// Heading levels\n\t\tfor (const level of this.config.levels) {\n\t\t\taddItem(HEADING_LABELS[level], activeLevel === level, `setHeading${level}`, {\n\t\t\t\tfontSize: `${1.4 - level * 0.1}em`,\n\t\t\t\tfontWeight: '600',\n\t\t\t});\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\t}\n\n\tprivate createPickerItem(\n\t\tlabel: string,\n\t\tisActive: boolean,\n\t\thandler: (e: MouseEvent) => void,\n\t\tstyle?: PickerItemStyle,\n\t): HTMLButtonElement {\n\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\titem.type = 'button';\n\t\titem.className = 'notectl-heading-picker__item';\n\n\t\tif (isActive) {\n\t\t\titem.classList.add('notectl-heading-picker__item--active');\n\t\t}\n\n\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\tcheck.className = 'notectl-heading-picker__check';\n\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\titem.appendChild(check);\n\n\t\tconst labelSpan: HTMLSpanElement = document.createElement('span');\n\t\tlabelSpan.className = 'notectl-heading-picker__label';\n\t\tlabelSpan.textContent = label;\n\t\tif (style) {\n\t\t\tlabelSpan.style.fontSize = style.fontSize;\n\t\t\tlabelSpan.style.fontWeight = style.fontWeight;\n\t\t\tif (style.color) {\n\t\t\t\tlabelSpan.style.color = style.color;\n\t\t\t}\n\t\t}\n\t\titem.appendChild(labelSpan);\n\n\t\titem.addEventListener('mousedown', handler);\n\t\treturn item;\n\t}\n\n\t/**\n\t * Toggles between a special block type (title/subtitle) and paragraph.\n\t * If the block is already that type, resets to paragraph.\n\t */\n\tprivate toggleSpecialBlock(context: PluginContext, type: string): boolean {\n\t\tconst state = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tif (block.type === type) {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t}\n\n\t\treturn this.setBlockType(context, nodeType(type) as NodeTypeName);\n\t}\n\n\t/**\n\t * Toggles between heading (at given level) and paragraph.\n\t * If the block is already a heading at the same level, resets to paragraph.\n\t */\n\tprivate toggleHeading(context: PluginContext, level: HeadingLevel): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tif (block.type === 'heading' && block.attrs?.level === level) {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t}\n\n\t\treturn this.setBlockType(context, nodeType('heading'), { level });\n\t}\n\n\tprivate setBlockType(\n\t\tcontext: PluginContext,\n\t\ttype: NodeTypeName,\n\t\tattrs?: Record<string, string | number | boolean>,\n\t): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, type, attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n}\n","/**\n * LinkPlugin: registers a link mark type with href attribute,\n * toggle command, keyboard shortcut (Mod-K), and toolbar button\n * with a URL input popup.\n */\n\nimport { getBlockMarksAtOffset, hasMark } from '../../model/Document.js';\nimport { isCollapsed, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tlink: { href: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface LinkConfig {\n\t/** Whether to add rel=\"noopener noreferrer\" and target=\"_blank\" by default. */\n\treadonly openInNewTab: boolean;\n\t/** When true, a separator is rendered after the link toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: LinkConfig = {\n\topenInNewTab: true,\n};\n\n// --- Plugin ---\n\nexport class LinkPlugin implements Plugin {\n\treadonly id = 'link';\n\treadonly name = 'Link';\n\treadonly priority = 25;\n\n\tprivate readonly config: LinkConfig;\n\n\tconstructor(config?: Partial<LinkConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymap(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tconst openInNewTab = this.config.openInNewTab;\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'link',\n\t\t\trank: 10,\n\t\t\tattrs: {\n\t\t\t\thref: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst a = document.createElement('a');\n\t\t\t\tconst href = mark.attrs?.href ?? '';\n\t\t\t\ta.setAttribute('href', href);\n\t\t\t\tif (openInNewTab) {\n\t\t\t\t\ta.setAttribute('target', '_blank');\n\t\t\t\t\ta.setAttribute('rel', 'noopener noreferrer');\n\t\t\t\t}\n\t\t\t\treturn a;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.toggleLink(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setLink', () => {\n\t\t\t// setLink is called by the popup after URL input\n\t\t\t// The actual URL is set via the popup's custom render\n\t\t\treturn false;\n\t\t});\n\n\t\tcontext.registerCommand('removeLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeLink(context, state);\n\t\t});\n\t}\n\n\tprivate registerKeymap(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-K': () => context.executeCommand('toggleLink'),\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'link',\n\t\t\tgroup: 'insert',\n\t\t\ticon,\n\t\t\tlabel: 'Link',\n\t\t\ttooltip: `Insert Link (${formatShortcut('Mod-K')})`,\n\t\t\tcommand: 'toggleLink',\n\t\t\tpriority: 60,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderLinkPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isLinkActive(state),\n\t\t\tisEnabled: (state) => !isCollapsed(state.selection),\n\t\t});\n\t}\n\n\tprivate isLinkActive(state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return false;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\treturn hasMark(marks, markType('link'));\n\t\t}\n\n\t\t// Check if link is active anywhere in selection\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\treturn hasMark(marks, markType('link'));\n\t}\n\n\tprivate toggleLink(context: PluginContext, state: EditorState): boolean {\n\t\tif (this.isLinkActive(state)) {\n\t\t\treturn this.removeLink(context, state);\n\t\t}\n\t\t// Adding links requires the toolbar popup for URL input\n\t\treturn false;\n\t}\n\n\tprivate addLink(context: PluginContext, state: EditorState, href: string): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isCollapsed(sel)) return false;\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\tconst mark = { type: markType('link'), attrs: { href } };\n\n\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeLink(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = isCollapsed(sel)\n\t\t\t? { from: sel.anchor, to: sel.anchor }\n\t\t\t: selectionRange(sel, blockOrder);\n\n\t\tconst builder = state.transaction('command');\n\n\t\tif (isCollapsed(sel)) {\n\t\t\t// Remove link from entire link span around cursor\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return false;\n\n\t\t\t// Find the extent of the link mark around the cursor.\n\t\t\t// Build a list of text children with their positions first,\n\t\t\t// then scan backward and forward from the cursor node.\n\t\t\tconst textChildren: { pos: number; end: number; hasLink: boolean }[] = [];\n\t\t\tlet pos = 0;\n\t\t\tfor (const child of block.children) {\n\t\t\t\tif (!('text' in child)) continue;\n\t\t\t\tconst end = pos + child.text.length;\n\t\t\t\ttextChildren.push({ pos, end, hasLink: hasMark(child.marks, markType('link')) });\n\t\t\t\tpos = end;\n\t\t\t}\n\n\t\t\t// Find the text child containing the cursor\n\t\t\tconst cursorIdx = textChildren.findIndex(\n\t\t\t\t(c) => sel.anchor.offset >= c.pos && sel.anchor.offset <= c.end,\n\t\t\t);\n\t\t\tconst cursorEntry = cursorIdx >= 0 ? textChildren[cursorIdx] : undefined;\n\t\t\tif (cursorIdx === -1 || !cursorEntry?.hasLink) return false;\n\n\t\t\t// Scan backward from cursor node to find link start\n\t\t\tlet startIdx = cursorIdx;\n\t\t\twhile (startIdx > 0 && textChildren[startIdx - 1]?.hasLink) {\n\t\t\t\tstartIdx--;\n\t\t\t}\n\n\t\t\t// Scan forward from cursor node to find link end\n\t\t\tlet endIdx = cursorIdx;\n\t\t\twhile (endIdx < textChildren.length - 1 && textChildren[endIdx + 1]?.hasLink) {\n\t\t\t\tendIdx++;\n\t\t\t}\n\n\t\t\tconst startEntry = textChildren[startIdx];\n\t\t\tconst endEntry = textChildren[endIdx];\n\t\t\tif (!startEntry || !endEntry) return false;\n\n\t\t\tconst linkStart = startEntry.pos;\n\t\t\tconst linkEnd = endEntry.end;\n\n\t\t\tbuilder.removeMark(sel.anchor.blockId, linkStart, linkEnd, { type: markType('link') });\n\t\t} else {\n\t\t\t// Remove link from selection range\n\t\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\t\tconst blockId = blockOrder[i];\n\t\t\t\tif (!blockId) continue;\n\t\t\t\tconst block = state.getBlock(blockId);\n\t\t\t\tif (!block) continue;\n\t\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t\t0,\n\t\t\t\t);\n\n\t\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\t\tif (from !== to) {\n\t\t\t\t\tbuilder.removeMark(blockId, from, to, { type: markType('link') });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate renderLinkPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.style.padding = '8px';\n\t\tcontainer.style.minWidth = '200px';\n\n\t\tconst state = context.getState();\n\t\tconst isActive = this.isLinkActive(state);\n\n\t\tif (isActive) {\n\t\t\t// Show remove link button\n\t\t\tconst removeBtn = document.createElement('button');\n\t\t\tremoveBtn.type = 'button';\n\t\t\tremoveBtn.textContent = 'Remove Link';\n\t\t\tremoveBtn.style.cssText = 'width:100%;padding:6px 12px;cursor:pointer;';\n\t\t\tremoveBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tcontext.executeCommand('removeLink');\n\t\t\t});\n\t\t\tcontainer.appendChild(removeBtn);\n\t\t} else {\n\t\t\t// Show URL input\n\t\t\tconst input = document.createElement('input');\n\t\t\tinput.type = 'url';\n\t\t\tinput.placeholder = 'https://...';\n\t\t\tinput.style.cssText = 'width:100%;padding:4px;box-sizing:border-box;';\n\n\t\t\tconst applyBtn = document.createElement('button');\n\t\t\tapplyBtn.type = 'button';\n\t\t\tapplyBtn.textContent = 'Apply';\n\t\t\tapplyBtn.style.cssText = 'width:100%;padding:6px 12px;margin-top:4px;cursor:pointer;';\n\n\t\t\tapplyBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tconst href = input.value.trim();\n\t\t\t\tif (href) {\n\t\t\t\t\tthis.addLink(context, context.getState(), href);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tinput.addEventListener('keydown', (e) => {\n\t\t\t\tif (e.key === 'Enter') {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tconst href = input.value.trim();\n\t\t\t\t\tif (href) {\n\t\t\t\t\t\tthis.addLink(context, context.getState(), href);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tcontainer.appendChild(input);\n\t\t\tcontainer.appendChild(applyBtn);\n\n\t\t\t// Auto-focus input\n\t\t\trequestAnimationFrame(() => input.focus());\n\t\t}\n\t}\n}\n","/**\n * ListPlugin: registers ordered, unordered, and checklist block types\n * with NodeSpecs, toggle commands, indent/outdent (Tab/Shift-Tab),\n * input rules, and toolbar buttons.\n *\n * List items are modeled as flat blocks with a `listType` and `indent` attribute,\n * allowing simple nesting representation without deep tree structures.\n */\n\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport { generateBlockId, getBlockText } from '../../model/Document.js';\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { createCollapsedSelection, isCollapsed } from '../../model/Selection.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\nexport type ListType = 'bullet' | 'ordered' | 'checklist';\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\tlist_item: { listType: ListType; indent: number; checked: boolean };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface ListConfig {\n\t/** Which list types to enable. Defaults to all. */\n\treadonly types: readonly ListType[];\n\t/** Maximum indent depth. Defaults to 4. */\n\treadonly maxIndent: number;\n\t/** When true, a separator is rendered after the last list toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: ListConfig = {\n\ttypes: ['bullet', 'ordered', 'checklist'],\n\tmaxIndent: 4,\n};\n\n// --- List Type Metadata ---\n\ninterface ListTypeDefinition {\n\treadonly type: ListType;\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly inputPattern: RegExp;\n\treadonly inputPrefix: string;\n}\n\nconst BULLET_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z\"/></svg>';\nconst NUMBERED_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z\"/></svg>';\nconst CHECKLIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M22 7h-9v2h9V7zm0 8h-9v2h9v-2zM5.54 11L2 7.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 11zm0 8L2 15.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 19z\"/></svg>';\n\nconst LIST_TYPE_DEFINITIONS: readonly ListTypeDefinition[] = [\n\t{\n\t\ttype: 'bullet',\n\t\tlabel: 'Bullet List',\n\t\ticon: BULLET_LIST_ICON,\n\t\tinputPattern: /^[-*] $/,\n\t\tinputPrefix: '- ',\n\t},\n\t{\n\t\ttype: 'ordered',\n\t\tlabel: 'Numbered List',\n\t\ticon: NUMBERED_LIST_ICON,\n\t\tinputPattern: /^\\d+\\. $/,\n\t\tinputPrefix: '1. ',\n\t},\n\t{\n\t\ttype: 'checklist',\n\t\tlabel: 'Checklist',\n\t\ticon: CHECKLIST_ICON,\n\t\tinputPattern: /^\\[[ x]] $/,\n\t\tinputPrefix: '[ ] ',\n\t},\n];\n\n// --- Plugin ---\n\nexport class ListPlugin implements Plugin {\n\treadonly id = 'list';\n\treadonly name = 'List';\n\treadonly priority = 35;\n\n\tprivate readonly config: ListConfig;\n\n\tconstructor(config?: Partial<ListConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerNodeSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInputRules(context);\n\t\tthis.registerToolbarItems(context);\n\t}\n\n\tprivate registerNodeSpec(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'list_item',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\tattrs: {\n\t\t\t\tlistType: { default: 'bullet' },\n\t\t\t\tindent: { default: 0 },\n\t\t\t\tchecked: { default: false },\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\tconst listType = node.attrs?.listType ?? 'bullet';\n\t\t\t\tconst indent = node.attrs?.indent ?? 0;\n\t\t\t\tconst checked = node.attrs?.checked ?? false;\n\n\t\t\t\tconst li = createBlockElement('div', node.id);\n\t\t\t\tli.setAttribute('data-list-type', listType);\n\t\t\t\tli.setAttribute('data-indent', String(indent));\n\t\t\t\tli.className = `notectl-list-item notectl-list-item--${listType}`;\n\n\t\t\t\tif (indent > 0) {\n\t\t\t\t\tli.style.marginLeft = `${indent * 24}px`;\n\t\t\t\t}\n\n\t\t\t\tif (listType === 'checklist') {\n\t\t\t\t\tli.setAttribute('data-checked', String(checked));\n\t\t\t\t}\n\n\t\t\t\treturn li;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerCommand(`toggleList:${def.type}`, () => {\n\t\t\t\treturn this.toggleList(context, def.type);\n\t\t\t});\n\t\t}\n\n\t\tcontext.registerCommand('indentListItem', () => {\n\t\t\treturn this.indent(context);\n\t\t});\n\n\t\tcontext.registerCommand('outdentListItem', () => {\n\t\t\treturn this.outdent(context);\n\t\t});\n\n\t\tif (this.config.types.includes('checklist')) {\n\t\t\tcontext.registerCommand('toggleChecklistItem', () => {\n\t\t\t\treturn this.toggleChecked(context);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\tEnter: () => this.handleEnter(context),\n\t\t\tBackspace: () => this.handleBackspace(context),\n\t\t\tTab: () => this.indent(context),\n\t\t\t'Shift-Tab': () => this.outdent(context),\n\t\t});\n\t}\n\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerInputRule({\n\t\t\t\tpattern: def.inputPattern,\n\t\t\t\thandler: (state, match, start, _end) => {\n\t\t\t\t\tconst sel = state.selection;\n\t\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\t\tconst matchStr = match[0] ?? '';\n\t\t\t\t\tconst matchLen = matchStr.length;\n\t\t\t\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\t\t\t\tlistType: def.type,\n\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (def.type === 'checklist') {\n\t\t\t\t\t\tattrs.checked = matchStr.includes('[x]');\n\t\t\t\t\t}\n\n\t\t\t\t\treturn state\n\t\t\t\t\t\t.transaction('input')\n\t\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, start, start + matchLen)\n\t\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t\t\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, 0))\n\t\t\t\t\t\t.build();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerToolbarItems(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\t\tconst lastType = enabledTypes.at(-1);\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerToolbarItem({\n\t\t\t\tid: `list-${def.type}`,\n\t\t\t\tgroup: 'block',\n\t\t\t\ticon: def.icon,\n\t\t\t\tlabel: def.label,\n\t\t\t\tcommand: `toggleList:${def.type}`,\n\t\t\t\tpriority: def.type === 'bullet' ? 70 : def.type === 'ordered' ? 71 : 72,\n\t\t\t\tseparatorAfter: this.config.separatorAfter && def === lastType,\n\t\t\t\tisActive: (state) => this.isListActive(state, def.type),\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Command Implementations ---\n\n\tprivate toggleList(context: PluginContext, listType: ListType): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\t// If already this list type, convert back to paragraph\n\t\tif (block.type === 'list_item' && block.attrs?.listType === listType) {\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Convert to list item\n\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\tlistType,\n\t\t\tindent: isNodeOfType(block, 'list_item') ? block.attrs.indent : 0,\n\t\t};\n\t\tif (listType === 'checklist') {\n\t\t\tattrs.checked = false;\n\t\t}\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate indent(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block || !isNodeOfType(block, 'list_item')) return false;\n\n\t\tif (block.attrs.indent >= this.config.maxIndent) return false;\n\n\t\treturn this.setIndent(context, state, block.attrs.indent + 1);\n\t}\n\n\tprivate outdent(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block || !isNodeOfType(block, 'list_item')) return false;\n\n\t\tif (block.attrs.indent <= 0) return false;\n\n\t\treturn this.setIndent(context, state, block.attrs.indent - 1);\n\t}\n\n\tprivate setIndent(context: PluginContext, state: EditorState, indent: number): boolean {\n\t\tconst sel = state.selection;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst attrs = { ...block.attrs, indent } as Record<string, string | number | boolean>;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate toggleChecked(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block || block.type !== 'list_item' || block.attrs?.listType !== 'checklist') {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst checked = !block.attrs?.checked;\n\t\tconst attrs = { ...block.attrs, checked } as Record<string, string | number | boolean>;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(state.selection.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(state.selection)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Handles Backspace at the start of a list item.\n\t * Converts the list item back to a paragraph, preserving text.\n\t */\n\tprivate handleBackspace(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block || block.type !== 'list_item') return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst tr = state\n\t\t\t.transaction('input')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Handles Enter inside a list item.\n\t * Empty item → exit list (convert to paragraph).\n\t * Non-empty item → split and create a new list item with the same type.\n\t */\n\tprivate handleEnter(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block || block.type !== 'list_item') return false;\n\n\t\tconst text = getBlockText(block);\n\n\t\tif (text === '') {\n\t\t\t// Empty list item → convert to paragraph (exit list)\n\t\t\tconst tr = state\n\t\t\t\t.transaction('input')\n\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Non-empty → split block and set new block to same list type\n\t\tconst newBlockId = generateBlockId();\n\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\tlistType: isNodeOfType(block, 'list_item') ? block.attrs.listType : 'bullet',\n\t\t\tindent: isNodeOfType(block, 'list_item') ? block.attrs.indent : 0,\n\t\t};\n\t\tif (attrs.listType === 'checklist') {\n\t\t\tattrs.checked = false;\n\t\t}\n\n\t\tconst tr = state\n\t\t\t.transaction('input')\n\t\t\t.splitBlock(sel.anchor.blockId, sel.anchor.offset, newBlockId)\n\t\t\t.setBlockType(newBlockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(createCollapsedSelection(newBlockId, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t// --- Helpers ---\n\n\tprivate isListActive(state: EditorState, listType: ListType): boolean {\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\treturn block?.type === 'list_item' && block.attrs?.listType === listType;\n\t}\n\n\tprivate getEnabledTypes(): readonly ListTypeDefinition[] {\n\t\treturn LIST_TYPE_DEFINITIONS.filter((def) => this.config.types.includes(def.type));\n\t}\n}\n","/**\n * BlockquotePlugin: registers a blockquote block type with NodeSpec,\n * toggle command, keyboard shortcut, input rule, and a toolbar button.\n */\n\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { isCollapsed } from '../../model/Selection.js';\nimport { type NodeTypeName, nodeType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\tblockquote: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\nexport interface BlockquoteConfig {\n\t/** When true, a separator is rendered after the blockquote toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: BlockquoteConfig = {};\n\n// --- Plugin ---\n\nexport class BlockquotePlugin implements Plugin {\n\treadonly id = 'blockquote';\n\treadonly name = 'Blockquote';\n\treadonly priority = 35;\n\n\tprivate readonly config: BlockquoteConfig;\n\n\tconstructor(config?: Partial<BlockquoteConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerNodeSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymap(context);\n\t\tthis.registerInputRule(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerNodeSpec(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'blockquote',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\ttoDOM(node) {\n\t\t\t\treturn createBlockElement('blockquote', node.id);\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleBlockquote', () => {\n\t\t\treturn this.toggleBlockquote(context);\n\t\t});\n\n\t\tcontext.registerCommand('setBlockquote', () => {\n\t\t\treturn this.setBlockType(context, nodeType('blockquote'));\n\t\t});\n\t}\n\n\tprivate registerKeymap(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-Shift->': () => context.executeCommand('toggleBlockquote'),\n\t\t});\n\t}\n\n\tprivate registerInputRule(context: PluginContext): void {\n\t\tcontext.registerInputRule({\n\t\t\tpattern: /^> $/,\n\t\t\thandler(state, _match, start, _end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, start, start + 2)\n\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('blockquote'))\n\t\t\t\t\t.setSelection(sel)\n\t\t\t\t\t.build();\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'blockquote',\n\t\t\tgroup: 'block',\n\t\t\ticon,\n\t\t\tlabel: 'Blockquote',\n\t\t\ttooltip: `Blockquote (${formatShortcut('Mod-Shift->')})`,\n\t\t\tcommand: 'toggleBlockquote',\n\t\t\tpriority: 55,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tisActive: (state) => {\n\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\treturn block?.type === 'blockquote';\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Toggles between blockquote and paragraph.\n\t * If the block is already a blockquote, resets to paragraph.\n\t */\n\tprivate toggleBlockquote(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tif (block.type === 'blockquote') {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t}\n\n\t\treturn this.setBlockType(context, nodeType('blockquote'));\n\t}\n\n\tprivate setBlockType(\n\t\tcontext: PluginContext,\n\t\ttype: NodeTypeName,\n\t\tattrs?: Record<string, string | number | boolean>,\n\t): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, type, attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n}\n","/**\n * StrikethroughPlugin: registers a strikethrough inline mark with MarkSpec,\n * toggle command, keyboard shortcut (Mod-Shift-X), and a toolbar button.\n */\n\nimport { isMarkActive, toggleMark } from '../../commands/Commands.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tstrikethrough: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\nexport interface StrikethroughConfig {\n\t/** When true, a separator is rendered after the strikethrough toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: StrikethroughConfig = {};\n\n// --- Plugin ---\n\nexport class StrikethroughPlugin implements Plugin {\n\treadonly id = 'strikethrough';\n\treadonly name = 'Strikethrough';\n\treadonly priority = 22;\n\n\tprivate readonly config: StrikethroughConfig;\n\n\tconstructor(config?: Partial<StrikethroughConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommand(context);\n\t\tthis.registerKeymap(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'strikethrough',\n\t\t\trank: 3,\n\t\t\ttoDOM() {\n\t\t\t\treturn document.createElement('s');\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommand(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleStrikethrough', () => {\n\t\t\tconst tr = toggleMark(context.getState(), markType('strikethrough'));\n\t\t\tif (tr) {\n\t\t\t\tcontext.dispatch(tr);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t}\n\n\tprivate registerKeymap(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-Shift-X': () => context.executeCommand('toggleStrikethrough'),\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'strikethrough',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Strikethrough',\n\t\t\ttooltip: `Strikethrough (${formatShortcut('Mod-Shift-X')})`,\n\t\t\tcommand: 'toggleStrikethrough',\n\t\t\tpriority: 40,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tisActive: (state) => isMarkActive(state, markType('strikethrough')),\n\t\t});\n\t}\n}\n","/**\n * TextColorPlugin: registers a text color mark with attrs,\n * toolbar button with a color picker popup, and removeTextColor command.\n */\n\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, hasMark } from '../../model/Document.js';\nimport { isCollapsed, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\ttextColor: { color: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface TextColorConfig {\n\t/**\n\t * Restricts the color picker to a specific set of hex colors.\n\t * Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).\n\t * Duplicates are removed automatically (case-insensitive).\n\t * When omitted, the full default palette is shown.\n\t */\n\treadonly colors?: readonly string[];\n\t/** When true, a separator is rendered after the textColor toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: TextColorConfig = {};\n\n// --- Color Validation ---\n\nconst HEX_COLOR_PATTERN: RegExp = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\nfunction isValidHexColor(value: string): boolean {\n\treturn HEX_COLOR_PATTERN.test(value);\n}\n\n/**\n * Validates, deduplicates, and normalizes the user-supplied color list.\n * Returns the default palette when no custom colors are provided.\n *\n * @throws {Error} if any value is not a valid hex color code.\n */\nfunction resolveColors(colors: readonly string[] | undefined): readonly string[] {\n\tif (!colors || colors.length === 0) return COLOR_PALETTE;\n\n\tconst invalid: string[] = colors.filter((c) => !isValidHexColor(c));\n\tif (invalid.length > 0) {\n\t\tthrow new Error(\n\t\t\t`TextColorPlugin: invalid hex color(s): ${invalid.join(', ')}. Expected format: #RGB or #RRGGBB.`,\n\t\t);\n\t}\n\n\tconst seen: Set<string> = new Set();\n\tconst unique: string[] = [];\n\tfor (const color of colors) {\n\t\tconst normalized: string = color.toLowerCase();\n\t\tif (!seen.has(normalized)) {\n\t\t\tseen.add(normalized);\n\t\t\tunique.push(normalized);\n\t\t}\n\t}\n\treturn unique;\n}\n\n// --- Color Palette (Google Docs style: 10 columns x 7 rows) ---\n\nconst COLOR_PALETTE: readonly string[] = [\n\t// Row 1 — dark\n\t'#000000',\n\t'#434343',\n\t'#666666',\n\t'#999999',\n\t'#b7b7b7',\n\t'#cccccc',\n\t'#d9d9d9',\n\t'#efefef',\n\t'#f3f3f3',\n\t'#ffffff',\n\t// Row 2 — vivid\n\t'#980000',\n\t'#ff0000',\n\t'#ff9900',\n\t'#ffff00',\n\t'#00ff00',\n\t'#00ffff',\n\t'#4a86e8',\n\t'#0000ff',\n\t'#9900ff',\n\t'#ff00ff',\n\t// Row 3 — light 3\n\t'#e6b8af',\n\t'#f4cccc',\n\t'#fce5cd',\n\t'#fff2cc',\n\t'#d9ead3',\n\t'#d0e0e3',\n\t'#c9daf8',\n\t'#cfe2f3',\n\t'#d9d2e9',\n\t'#ead1dc',\n\t// Row 4 — light 2\n\t'#dd7e6b',\n\t'#ea9999',\n\t'#f9cb9c',\n\t'#ffe599',\n\t'#b6d7a8',\n\t'#a2c4c9',\n\t'#a4c2f4',\n\t'#9fc5e8',\n\t'#b4a7d6',\n\t'#d5a6bd',\n\t// Row 5 — light 1\n\t'#cc4125',\n\t'#e06666',\n\t'#f6b26b',\n\t'#ffd966',\n\t'#93c47d',\n\t'#76a5af',\n\t'#6d9eeb',\n\t'#6fa8dc',\n\t'#8e7cc3',\n\t'#c27ba0',\n\t// Row 6 — dark 1\n\t'#a61c00',\n\t'#cc0000',\n\t'#e69138',\n\t'#f1c232',\n\t'#6aa84f',\n\t'#45818e',\n\t'#3c78d8',\n\t'#3d85c6',\n\t'#674ea7',\n\t'#a64d79',\n\t// Row 7 — dark 2\n\t'#85200c',\n\t'#990000',\n\t'#b45f06',\n\t'#bf9000',\n\t'#38761d',\n\t'#134f5c',\n\t'#1155cc',\n\t'#0b5394',\n\t'#351c75',\n\t'#741b47',\n];\n\n// --- Plugin ---\n\nexport class TextColorPlugin implements Plugin {\n\treadonly id = 'textColor';\n\treadonly name = 'Text Color';\n\treadonly priority = 23;\n\n\tprivate readonly config: TextColorConfig;\n\tprivate readonly colors: readonly string[];\n\n\tconstructor(config?: Partial<TextColorConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t\tthis.colors = resolveColors(config?.colors);\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'textColor',\n\t\t\trank: 5,\n\t\t\tattrs: {\n\t\t\t\tcolor: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span = document.createElement('span');\n\t\t\t\tconst color = mark.attrs?.color ?? '';\n\t\t\t\tspan.style.color = color;\n\t\t\t\treturn span;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeTextColor', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeColor(context, state);\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst pathD =\n\t\t\t'M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2z' + 'm-1.38 9L12 5.67 14.38 12H9.62z';\n\t\tconst icon: string = [\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t' viewBox=\"0 0 24 24\">',\n\t\t\t`<path d=\"${pathD}\"/>`,\n\t\t\t'<rect x=\"3\" y=\"19.5\" width=\"18\" height=\"3\"',\n\t\t\t' rx=\"0.5\" fill=\"#e53935\"/>',\n\t\t\t'</svg>',\n\t\t].join('');\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'textColor',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Text Color',\n\t\t\ttooltip: 'Text Color',\n\t\t\tcommand: 'removeTextColor',\n\t\t\tpriority: 45,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderColorPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isTextColorActive(state),\n\t\t});\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isTextColorActive(state: EditorState): boolean {\n\t\treturn this.getActiveColor(state) !== null;\n\t}\n\n\tprivate getActiveColor(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tif (state.storedMarks) {\n\t\t\t\tconst mark = state.storedMarks.find((m) => m.type === 'textColor');\n\t\t\t\treturn mark && isMarkOfType(mark, 'textColor') ? (mark.attrs.color ?? null) : null;\n\t\t\t}\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return null;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\tconst mark = marks.find((m) => m.type === 'textColor');\n\t\t\treturn mark && isMarkOfType(mark, 'textColor') ? (mark.attrs.color ?? null) : null;\n\t\t}\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\tconst mark = marks.find((m) => m.type === 'textColor');\n\t\treturn mark && isMarkOfType(mark, 'textColor') ? (mark.attrs.color ?? null) : null;\n\t}\n\n\t// --- Color Application ---\n\n\tprivate applyColor(context: PluginContext, state: EditorState, color: string): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\t// Set stored marks with the new color\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tconst withoutColor = currentMarks.filter((m) => m.type !== 'textColor');\n\t\t\tconst newMarks = [...withoutColor, { type: markType('textColor'), attrs: { color } }];\n\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Range selection: remove existing textColor, then add new one\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\tconst mark = { type: markType('textColor'), attrs: { color } };\n\n\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\t// Remove existing textColor first, then add new one\n\t\t\t\tbuilder.removeMark(blockId, from, to, { type: markType('textColor') });\n\t\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeColor(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\t// Remove textColor from stored marks\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tif (!hasMark(currentMarks, markType('textColor'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'textColor');\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Range selection: remove textColor from range\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, { type: markType('textColor') });\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate renderColorPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-color-picker');\n\n\t\tconst state = context.getState();\n\t\tconst activeColor = this.getActiveColor(state);\n\n\t\t// \"Default\" button to remove color\n\t\tconst defaultBtn = document.createElement('button');\n\t\tdefaultBtn.type = 'button';\n\t\tdefaultBtn.className = 'notectl-color-picker__default';\n\t\tdefaultBtn.textContent = 'Default';\n\t\tdefaultBtn.addEventListener('mousedown', (e) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tcontext.executeCommand('removeTextColor');\n\t\t});\n\t\tcontainer.appendChild(defaultBtn);\n\n\t\t// Color grid\n\t\tconst grid = document.createElement('div');\n\t\tgrid.className = 'notectl-color-picker__grid';\n\n\t\tfor (const color of this.colors) {\n\t\t\tconst swatch = document.createElement('button');\n\t\t\tswatch.type = 'button';\n\t\t\tswatch.className = 'notectl-color-picker__swatch';\n\t\t\tif (activeColor && activeColor.toLowerCase() === color.toLowerCase()) {\n\t\t\t\tswatch.classList.add('notectl-color-picker__swatch--active');\n\t\t\t}\n\t\t\tswatch.style.backgroundColor = color;\n\t\t\tif (color === '#ffffff') {\n\t\t\t\tswatch.style.border = '1px solid #d0d0d0';\n\t\t\t}\n\t\t\tswatch.title = color;\n\n\t\t\tswatch.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tthis.applyColor(context, context.getState(), color);\n\t\t\t});\n\n\t\t\tgrid.appendChild(swatch);\n\t\t}\n\n\t\tcontainer.appendChild(grid);\n\t}\n}\n","/**\n * HorizontalRulePlugin: registers a horizontal rule (divider) void block type\n * with NodeSpec, insert command, input rule, and toolbar button.\n */\n\nimport { createBlockNode } from '../../model/Document.js';\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { createCollapsedSelection, isCollapsed } from '../../model/Selection.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\thorizontal_rule: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\nexport interface HorizontalRuleConfig {\n\t/** When true, a separator is rendered after the toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: HorizontalRuleConfig = {};\n\n// --- Plugin ---\n\nexport class HorizontalRulePlugin implements Plugin {\n\treadonly id = 'horizontal-rule';\n\treadonly name = 'Horizontal Rule';\n\treadonly priority = 40;\n\n\tprivate readonly config: HorizontalRuleConfig;\n\n\tconstructor(config?: Partial<HorizontalRuleConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerNodeSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerInputRule(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerNodeSpec(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'horizontal_rule',\n\t\t\tgroup: 'block',\n\t\t\tisVoid: true,\n\t\t\ttoDOM(node) {\n\t\t\t\treturn createBlockElement('hr', node.id);\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('insertHorizontalRule', () => {\n\t\t\treturn this.insertHorizontalRule(context);\n\t\t});\n\t}\n\n\tprivate registerInputRule(context: PluginContext): void {\n\t\tcontext.registerInputRule({\n\t\t\tpattern: /^-{3,} $/,\n\t\t\thandler(state, _match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\tconst blockIndex = state.doc.children.findIndex((b) => b.id === sel.anchor.blockId);\n\t\t\t\tif (blockIndex === -1) return null;\n\n\t\t\t\tconst newParagraph = createBlockNode(nodeType('paragraph'));\n\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, 0, end)\n\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('horizontal_rule'))\n\t\t\t\t\t.insertNode([], blockIndex + 1, newParagraph)\n\t\t\t\t\t.setSelection(createCollapsedSelection(newParagraph.id, 0))\n\t\t\t\t\t.build();\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M4 11h16v2H4z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'horizontal-rule',\n\t\t\tgroup: 'block',\n\t\t\ticon,\n\t\t\tlabel: 'Horizontal Rule',\n\t\t\ttooltip: 'Horizontal Rule',\n\t\t\tcommand: 'insertHorizontalRule',\n\t\t\tpriority: 60,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t});\n\t}\n\n\t/**\n\t * Inserts a horizontal rule after the current block,\n\t * followed by a new paragraph for continued editing.\n\t */\n\tprivate insertHorizontalRule(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst blockIndex = state.doc.children.findIndex((b) => b.id === sel.anchor.blockId);\n\t\tif (blockIndex === -1) return false;\n\n\t\tconst hrBlock = createBlockNode(nodeType('horizontal_rule'));\n\t\tconst newParagraph = createBlockNode(nodeType('paragraph'));\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.insertNode([], blockIndex + 1, hrBlock)\n\t\t\t.insertNode([], blockIndex + 2, newParagraph)\n\t\t\t.setSelection(createCollapsedSelection(newParagraph.id, 0))\n\t\t\t.build();\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n}\n","/**\n * TextAlignmentPlugin: adds left/center/right/justify alignment as a block\n * attribute on paragraphs and headings. Patches their NodeSpecs to render\n * the `textAlign` attribute via inline `text-align` style and provides\n * toggle commands, keyboard shortcuts, and a toolbar dropdown.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Public Types ---\n\nexport type TextAlignment = 'left' | 'center' | 'right' | 'justify';\n\nexport interface TextAlignmentConfig {\n\t/** Which alignments to expose. Defaults to all four. */\n\treadonly alignments: readonly TextAlignment[];\n\t/** Block types that support alignment. Defaults to paragraph + heading. */\n\treadonly alignableTypes: readonly string[];\n\t/** When true, a separator is rendered after the toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\n// --- Constants ---\n\nconst DEFAULT_CONFIG: TextAlignmentConfig = {\n\talignments: ['left', 'center', 'right', 'justify'],\n\talignableTypes: ['paragraph', 'heading', 'title', 'subtitle'],\n};\n\nconst ALIGNMENT_LABELS: Readonly<Record<TextAlignment, string>> = {\n\tleft: 'Align Left',\n\tcenter: 'Align Center',\n\tright: 'Align Right',\n\tjustify: 'Justify',\n};\n\nconst ALIGNMENT_ICONS: Readonly<Record<TextAlignment, string>> = {\n\tleft: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z\"/></svg>',\n\tcenter:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z\"/></svg>',\n\tright:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z\"/></svg>',\n\tjustify:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z\"/></svg>',\n};\n\n// --- Plugin ---\n\nexport class TextAlignmentPlugin implements Plugin {\n\treadonly id = 'text-alignment';\n\treadonly name = 'Text Alignment';\n\treadonly priority = 90;\n\n\tprivate readonly config: TextAlignmentConfig;\n\tprivate alignableTypes!: ReadonlySet<string>;\n\n\tconstructor(config?: Partial<TextAlignmentConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.alignableTypes = new Set(this.config.alignableTypes);\n\t\tthis.patchNodeSpecs(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.registerMiddleware(context);\n\t}\n\n\t// --- NodeSpec Patching ---\n\n\t/**\n\t * Patches existing NodeSpecs for alignable block types to support the\n\t * `textAlign` attribute and render it as an inline style.\n\t */\n\tprivate patchNodeSpecs(context: PluginContext): void {\n\t\tconst registry = context.getSchemaRegistry();\n\n\t\tfor (const type of this.config.alignableTypes) {\n\t\t\tconst spec = registry.getNodeSpec(type);\n\t\t\tif (!spec) continue;\n\n\t\t\tconst originalToDOM = spec.toDOM;\n\n\t\t\tregistry.removeNodeSpec(type);\n\t\t\tregistry.registerNodeSpec({\n\t\t\t\t...spec,\n\t\t\t\tattrs: {\n\t\t\t\t\t...spec.attrs,\n\t\t\t\t\ttextAlign: { default: 'left' },\n\t\t\t\t},\n\t\t\t\ttoDOM(node) {\n\t\t\t\t\tconst el = originalToDOM.call(spec, node);\n\t\t\t\t\tapplyAlignment(el, node);\n\t\t\t\t\treturn el;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tfor (const alignment of this.config.alignments) {\n\t\t\tcontext.registerCommand(`align${capitalize(alignment)}`, () => {\n\t\t\t\treturn this.setAlignment(context, alignment);\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Keymaps ---\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tconst bindings: Record<string, () => boolean> = {};\n\n\t\tif (this.config.alignments.includes('left')) {\n\t\t\tbindings['Mod-Shift-L'] = () => context.executeCommand('alignLeft');\n\t\t}\n\t\tif (this.config.alignments.includes('center')) {\n\t\t\tbindings['Mod-Shift-E'] = () => context.executeCommand('alignCenter');\n\t\t}\n\t\tif (this.config.alignments.includes('right')) {\n\t\t\tbindings['Mod-Shift-R'] = () => context.executeCommand('alignRight');\n\t\t}\n\t\tif (this.config.alignments.includes('justify')) {\n\t\t\tbindings['Mod-Shift-J'] = () => context.executeCommand('alignJustify');\n\t\t}\n\n\t\tif (Object.keys(bindings).length > 0) {\n\t\t\tcontext.registerKeymap(bindings);\n\t\t}\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst dropdownItems = this.config.alignments.map((alignment) => ({\n\t\t\tlabel: ALIGNMENT_LABELS[alignment],\n\t\t\tcommand: `align${capitalize(alignment)}`,\n\t\t\ticon: ALIGNMENT_ICONS[alignment],\n\t\t}));\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'text-alignment',\n\t\t\tgroup: 'block',\n\t\t\ticon: ALIGNMENT_ICONS.left,\n\t\t\tlabel: 'Text Alignment',\n\t\t\ttooltip: 'Text Alignment',\n\t\t\tcommand: 'alignLeft',\n\t\t\tpriority: 60,\n\t\t\tpopupType: 'dropdown',\n\t\t\tpopupConfig: { items: dropdownItems },\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tisActive: (state) => this.isNonDefaultAlignment(state),\n\t\t\tisEnabled: (state) => this.isAlignable(state),\n\t\t});\n\t}\n\n\t// --- Middleware ---\n\n\t/**\n\t * Preserves the `textAlign` attribute when other plugins change the block\n\t * type (e.g. paragraph → heading) via `setBlockType`, which replaces attrs.\n\t */\n\tprivate registerMiddleware(context: PluginContext): void {\n\t\tcontext.registerMiddleware((tr, _state, next) => {\n\t\t\tlet patched = false;\n\n\t\t\tconst patchedSteps = tr.steps.map((step) => {\n\t\t\t\tif (step.type !== 'setBlockType') return step;\n\t\t\t\tif (!this.alignableTypes.has(step.nodeType)) return step;\n\n\t\t\t\tconst prevAlign = step.previousAttrs?.textAlign;\n\t\t\t\tif (!prevAlign || prevAlign === 'left') return step;\n\n\t\t\t\t// Carry forward textAlign into new attrs\n\t\t\t\tpatched = true;\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\tattrs: { ...step.attrs, textAlign: prevAlign },\n\t\t\t\t};\n\t\t\t});\n\n\t\t\tnext(patched ? { ...tr, steps: patchedSteps } : tr);\n\t\t});\n\t}\n\n\t// --- Alignment Logic ---\n\n\tprivate setAlignment(context: PluginContext, alignment: TextAlignment): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block || !this.alignableTypes.has(block.type)) return false;\n\n\t\tconst newAttrs = { ...block.attrs, textAlign: alignment };\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setNodeAttr([sel.anchor.blockId], newAttrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate isNonDefaultAlignment(state: EditorState): boolean {\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block || !this.alignableTypes.has(block.type)) return false;\n\t\tconst align = block.attrs?.textAlign;\n\t\treturn align != null && align !== 'left';\n\t}\n\n\tprivate isAlignable(state: EditorState): boolean {\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\treturn block != null && this.alignableTypes.has(block.type);\n\t}\n}\n\n// --- Helpers ---\n\nfunction applyAlignment(el: HTMLElement, node: BlockNode): void {\n\tconst align = node.attrs?.textAlign;\n\tif (typeof align === 'string' && align !== 'left') {\n\t\tel.style.textAlign = align;\n\t}\n}\n\nfunction capitalize(s: string): string {\n\treturn s.charAt(0).toUpperCase() + s.slice(1);\n}\n","/**\n * FontPlugin: registers a font-family mark, a combobox-style toolbar selector\n * for font selection, and a developer-friendly API for registering custom fonts\n * (WOFF2, TTF, OTF).\n */\n\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, getTextChildren, hasMark } from '../../model/Document.js';\nimport type { BlockNode, Mark } from '../../model/Document.js';\nimport { isCollapsed, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tfont: { family: string };\n\t}\n}\n\n// --- Public Types ---\n\n/** Describes a single @font-face source. */\nexport interface FontFaceDescriptor {\n\t/** CSS `src` value, e.g. `\"url('/fonts/My.woff2') format('woff2')\"`. */\n\treadonly src: string;\n\t/** Font weight, e.g. `'400'` or `'300 700'` for variable fonts. */\n\treadonly weight?: string;\n\t/** Font style, e.g. `'normal'` or `'italic'`. */\n\treadonly style?: string;\n\t/** Font display strategy. Defaults to `'swap'`. */\n\treadonly display?: string;\n}\n\n/** Defines a font available in the editor. */\nexport interface FontDefinition {\n\t/** Display name shown in the toolbar dropdown. */\n\treadonly name: string;\n\t/** CSS `font-family` value, e.g. `\"'Fira Code', monospace\"`. */\n\treadonly family: string;\n\t/** Font category for grouping in the UI. */\n\treadonly category?: 'serif' | 'sans-serif' | 'monospace' | 'display' | 'handwriting';\n\t/**\n\t * Optional `@font-face` descriptors. When provided, the plugin\n\t * auto-injects the corresponding CSS rules into the document.\n\t */\n\treadonly fontFaces?: readonly FontFaceDescriptor[];\n}\n\n// --- Configuration ---\n\nexport interface FontConfig {\n\t/**\n\t * Fonts available in the editor. System fonts require no `fontFaces`.\n\t * Custom fonts with `fontFaces` get their `@font-face` rules auto-injected.\n\t *\n\t * Use `STARTER_FONTS` for a pre-configured set of fonts:\n\t * ```ts\n\t * new FontPlugin({ fonts: [...STARTER_FONTS] })\n\t * ```\n\t */\n\treadonly fonts: readonly FontDefinition[];\n\t/**\n\t * Name of the font that acts as the editor's default.\n\t * Selecting this font removes the mark (since the editor already uses it).\n\t * Defaults to the first font in the list.\n\t */\n\treadonly defaultFont?: string;\n\t/** When true, a separator is rendered after the font toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\n// --- Plugin ---\n\nexport class FontPlugin implements Plugin {\n\treadonly id = 'font';\n\treadonly name = 'Font';\n\treadonly priority = 22;\n\n\tprivate readonly config: FontConfig;\n\tprivate injectedStyleElement: HTMLStyleElement | null = null;\n\tprivate context: PluginContext | null = null;\n\tprivate comboLabel: HTMLSpanElement | null = null;\n\n\tconstructor(config: FontConfig) {\n\t\tthis.config = config;\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.injectFontFaces();\n\t}\n\n\tdestroy(): void {\n\t\tthis.injectedStyleElement?.remove();\n\t\tthis.injectedStyleElement = null;\n\t\tthis.context = null;\n\t\tthis.comboLabel = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\tthis.updateComboLabel(newState);\n\t}\n\n\t// --- Schema ---\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'font',\n\t\t\trank: 6,\n\t\t\tattrs: {\n\t\t\t\tfamily: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span: HTMLElement = document.createElement('span');\n\t\t\t\tconst family: string = mark.attrs?.family ?? '';\n\t\t\t\tif (family) {\n\t\t\t\t\tspan.style.fontFamily = family;\n\t\t\t\t}\n\t\t\t\treturn span;\n\t\t\t},\n\t\t});\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeFont', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.removeFont(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setFont', () => {\n\t\t\treturn false;\n\t\t});\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate get defaultFont(): FontDefinition {\n\t\tif (this.config.defaultFont) {\n\t\t\tconst found: FontDefinition | undefined = this.config.fonts.find(\n\t\t\t\t(f) => f.name === this.config.defaultFont,\n\t\t\t);\n\t\t\tif (found) return found;\n\t\t}\n\t\tconst first: FontDefinition | undefined = this.config.fonts[0];\n\t\tif (!first) throw new Error('FontPlugin: fonts list is empty');\n\t\treturn first;\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\t// The icon content renders as a combobox label + dropdown arrow.\n\t\t// The actual label text is updated via onStateChange → updateComboLabel.\n\t\tconst defaultName: string = this.defaultFont.name;\n\t\tconst label: string = `<span class=\"notectl-font-select__label\" data-font-label>${defaultName}</span>`;\n\t\tconst arrow = '<span class=\"notectl-font-select__arrow\">\\u25BE</span>';\n\t\tconst icon = `${label}${arrow}`;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'font',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Font',\n\t\t\ttooltip: 'Font Family',\n\t\t\tcommand: 'removeFont',\n\t\t\tpriority: 5,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderFontPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isFontActive(state),\n\t\t});\n\t}\n\n\tprivate updateComboLabel(state: EditorState): void {\n\t\t// Lazily find the label element in the DOM\n\t\tif (!this.comboLabel) {\n\t\t\tconst container: HTMLElement | undefined = this.context?.getPluginContainer('top');\n\t\t\tif (!container) return;\n\t\t\tthis.comboLabel = container.querySelector<HTMLSpanElement>('[data-font-label]') ?? null;\n\t\t\tif (!this.comboLabel) return;\n\t\t}\n\n\t\tconst activeFamily: string | null = this.getActiveFont(state);\n\t\tconst displayName: string = this.resolveFontName(activeFamily);\n\t\tthis.comboLabel.textContent = displayName;\n\t}\n\n\tprivate resolveFontName(family: string | null): string {\n\t\tif (!family) return this.defaultFont.name;\n\t\tconst match: FontDefinition | undefined = this.config.fonts.find((f) => f.family === family);\n\t\treturn match?.name ?? (family.split(',')[0] ?? '').trim().replace(/'/g, '');\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isFontActive(state: EditorState): boolean {\n\t\treturn this.getActiveFont(state) !== null;\n\t}\n\n\tgetActiveFont(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tif (state.storedMarks) {\n\t\t\t\tconst mark = state.storedMarks.find((m) => m.type === 'font');\n\t\t\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? null) : null;\n\t\t\t}\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return null;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\tconst mark = marks.find((m) => m.type === 'font');\n\t\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? null) : null;\n\t\t}\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\tconst mark = marks.find((m) => m.type === 'font');\n\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? null) : null;\n\t}\n\n\t// --- Font Application ---\n\n\tapplyFont(context: PluginContext, state: EditorState, family: string): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tconst withoutFont = currentMarks.filter((m) => m.type !== 'font');\n\t\t\tconst newMarks = [...withoutFont, { type: markType('font'), attrs: { family } }];\n\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx: number = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx: number = blockOrder.indexOf(range.to.blockId);\n\n\t\tconst mark = { type: markType('font'), attrs: { family } };\n\n\t\tfor (let i: number = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen: number = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from: number = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to: number = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tconst existing: Mark | undefined = this.findFontMarkInRange(block, from, to);\n\t\t\t\tif (existing) {\n\t\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t\t}\n\t\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeFont(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tif (!hasMark(currentMarks, markType('font'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'font');\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx: number = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx: number = blockOrder.indexOf(range.to.blockId);\n\n\t\tfor (let i: number = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen: number = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from: number = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to: number = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tconst existing: Mark | undefined = this.findFontMarkInRange(block, from, to);\n\t\t\t\tif (existing) {\n\t\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t/** Finds the first font mark in a block's text range (for proper step inversion). */\n\tprivate findFontMarkInRange(block: BlockNode, from: number, to: number): Mark | undefined {\n\t\tconst textChildren = getTextChildren(block);\n\t\tlet pos = 0;\n\t\tfor (const node of textChildren) {\n\t\t\tconst nodeEnd: number = pos + node.text.length;\n\t\t\tif (nodeEnd > from && pos < to) {\n\t\t\t\tconst fontMark: Mark | undefined = node.marks.find((m) => m.type === 'font');\n\t\t\t\tif (fontMark) return fontMark;\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// --- @font-face Injection ---\n\n\tprivate injectFontFaces(): void {\n\t\tconst rules: string[] = [];\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tif (!font.fontFaces?.length) continue;\n\n\t\t\tfor (const face of font.fontFaces) {\n\t\t\t\tconst familyName: string = (font.family.split(',')[0] ?? '').trim().replace(/'/g, '');\n\t\t\t\tconst declarations: string[] = [`font-family: '${familyName}'`, `src: ${face.src}`];\n\t\t\t\tif (face.weight) {\n\t\t\t\t\tdeclarations.push(`font-weight: ${face.weight}`);\n\t\t\t\t}\n\t\t\t\tif (face.style) {\n\t\t\t\t\tdeclarations.push(`font-style: ${face.style}`);\n\t\t\t\t}\n\t\t\t\tdeclarations.push(`font-display: ${face.display ?? 'swap'}`);\n\n\t\t\t\trules.push(`@font-face {\\n\\t${declarations.join(';\\n\\t')};\\n}`);\n\t\t\t}\n\t\t}\n\n\t\tif (rules.length === 0) return;\n\n\t\tconst style: HTMLStyleElement = document.createElement('style');\n\t\tstyle.setAttribute('data-notectl-fonts', '');\n\t\tstyle.textContent = rules.join('\\n\\n');\n\t\tdocument.head.appendChild(style);\n\t\tthis.injectedStyleElement = style;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate dismissPopup(): void {\n\t\t// Trigger the ToolbarPlugin's outside-click handler to close the popup.\n\t\tsetTimeout(() => {\n\t\t\tdocument.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));\n\t\t}, 0);\n\t}\n\n\tprivate renderFontPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-font-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst activeFont: string | null = this.getActiveFont(state);\n\t\tconst defaultFamily: string = this.defaultFont.family;\n\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-font-picker__list';\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tconst isDefault: boolean = font.family === defaultFamily;\n\t\t\tconst isActive: boolean = isDefault\n\t\t\t\t? !activeFont || activeFont === font.family\n\t\t\t\t: activeFont === font.family;\n\n\t\t\tconst item: HTMLButtonElement = this.createFontItem(\n\t\t\t\tfont.name,\n\t\t\t\tfont.family,\n\t\t\t\tisActive,\n\t\t\t\t(e: MouseEvent) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tif (isDefault) {\n\t\t\t\t\t\tcontext.executeCommand('removeFont');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.applyFont(context, context.getState(), font.family);\n\t\t\t\t\t}\n\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (font.category) {\n\t\t\t\titem.setAttribute('data-category', font.category);\n\t\t\t}\n\n\t\t\tlist.appendChild(item);\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\t}\n\n\tprivate createFontItem(\n\t\tname: string,\n\t\tfamily: string,\n\t\tisActive: boolean,\n\t\thandler: (e: MouseEvent) => void,\n\t): HTMLButtonElement {\n\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\titem.type = 'button';\n\t\titem.className = 'notectl-font-picker__item';\n\n\t\tif (isActive) {\n\t\t\titem.classList.add('notectl-font-picker__item--active');\n\t\t}\n\n\t\t// Checkmark indicator\n\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\tcheck.className = 'notectl-font-picker__check';\n\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\titem.appendChild(check);\n\n\t\t// Font name label (rendered in the font itself for preview)\n\t\tconst label: HTMLSpanElement = document.createElement('span');\n\t\tlabel.className = 'notectl-font-picker__label';\n\t\tlabel.textContent = name;\n\t\tif (family) {\n\t\t\tlabel.style.fontFamily = family;\n\t\t}\n\t\titem.appendChild(label);\n\n\t\titem.addEventListener('mousedown', handler);\n\t\treturn item;\n\t}\n}\n","/**\n * FontSizePlugin: registers a fontSize mark with attrs, a combobox-style\n * toolbar selector with WCAG-accessible popup, and commands for\n * increasing / decreasing font size.\n */\n\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, hasMark } from '../../model/Document.js';\nimport { isCollapsed, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tfontSize: { size: string };\n\t}\n}\n\n// --- Constants ---\n\n/** Default preset sizes shown in the font size dropdown. */\nexport const DEFAULT_FONT_SIZES: readonly number[] = [\n\t8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 64, 72, 96,\n];\n\nconst DEFAULT_FONT_SIZE = 16;\nconst MIN_CUSTOM_SIZE = 1;\nconst MAX_CUSTOM_SIZE = 400;\n\n// --- Configuration ---\n\nexport interface FontSizeConfig {\n\t/**\n\t * Preset sizes shown in the font size dropdown.\n\t * Must contain positive integers. Values are sorted and deduplicated automatically.\n\t * Defaults to {@link DEFAULT_FONT_SIZES} when omitted or empty.\n\t */\n\treadonly sizes?: readonly number[];\n\t/**\n\t * The base font size that text has when no fontSize mark is applied.\n\t * Shown as the initial value in the toolbar combo and used as the\n\t * \"neutral\" size — selecting it removes the mark instead of applying one.\n\t * Defaults to 16.\n\t */\n\treadonly defaultSize?: number;\n\t/** When true, a separator is rendered after the fontSize toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: FontSizeConfig = {};\n\n// --- Plugin ---\n\nexport class FontSizePlugin implements Plugin {\n\treadonly id = 'fontSize';\n\treadonly name = 'Font Size';\n\treadonly priority = 21;\n\n\tprivate readonly config: FontSizeConfig;\n\tprivate readonly sizes: readonly number[];\n\tprivate readonly defaultSize: number;\n\tprivate context: PluginContext | null = null;\n\tprivate comboLabel: HTMLSpanElement | null = null;\n\n\tconstructor(config?: Partial<FontSizeConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t\tthis.sizes = resolveSizes(config?.sizes);\n\t\tthis.defaultSize = resolveDefaultSize(config?.defaultSize);\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tdestroy(): void {\n\t\tthis.context = null;\n\t\tthis.comboLabel = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\tthis.updateComboLabel(newState);\n\t}\n\n\t// --- Schema ---\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'fontSize',\n\t\t\trank: 4,\n\t\t\tattrs: {\n\t\t\t\tsize: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span: HTMLElement = document.createElement('span');\n\t\t\t\tconst size: string = mark.attrs?.size ?? '';\n\t\t\t\tif (size) {\n\t\t\t\t\tspan.style.fontSize = size;\n\t\t\t\t}\n\t\t\t\treturn span;\n\t\t\t},\n\t\t});\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeFontSize', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.removeFontSize(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setFontSize', () => {\n\t\t\treturn false;\n\t\t});\n\n\t\tcontext.registerCommand('increaseFontSize', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.stepFontSize(context, state, 'up');\n\t\t});\n\n\t\tcontext.registerCommand('decreaseFontSize', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.stepFontSize(context, state, 'down');\n\t\t});\n\t}\n\n\t// --- Keymaps ---\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-Shift-+': () => {\n\t\t\t\tconst state: EditorState = context.getState();\n\t\t\t\treturn this.stepFontSize(context, state, 'up');\n\t\t\t},\n\t\t\t'Mod-Shift-_': () => {\n\t\t\t\tconst state: EditorState = context.getState();\n\t\t\t\treturn this.stepFontSize(context, state, 'down');\n\t\t\t},\n\t\t});\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon: string = `<span class=\"notectl-font-size-select__label\" data-font-size-label>${this.defaultSize}</span><span class=\"notectl-font-size-select__arrow\">\\u25BE</span>`;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'fontSize',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Font Size',\n\t\t\ttooltip: 'Font Size',\n\t\t\tcommand: 'removeFontSize',\n\t\t\tpriority: 6,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderFontSizePopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isFontSizeActive(state),\n\t\t});\n\t}\n\n\tprivate updateComboLabel(state: EditorState): void {\n\t\tif (!this.comboLabel) {\n\t\t\tconst container: HTMLElement | undefined = this.context?.getPluginContainer('top');\n\t\t\tif (!container) return;\n\t\t\tthis.comboLabel = container.querySelector<HTMLSpanElement>('[data-font-size-label]') ?? null;\n\t\t\tif (!this.comboLabel) return;\n\t\t}\n\n\t\tconst activeSize: number = this.getActiveSizeNumeric(state);\n\t\tthis.comboLabel.textContent = String(activeSize);\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isFontSizeActive(state: EditorState): boolean {\n\t\treturn this.getActiveSize(state) !== null;\n\t}\n\n\tprivate getActiveSize(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tif (state.storedMarks) {\n\t\t\t\tconst mark = state.storedMarks.find((m) => m.type === 'fontSize');\n\t\t\t\treturn mark && isMarkOfType(mark, 'fontSize') ? (mark.attrs.size ?? null) : null;\n\t\t\t}\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return null;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\tconst mark = marks.find((m) => m.type === 'fontSize');\n\t\t\treturn mark && isMarkOfType(mark, 'fontSize') ? (mark.attrs.size ?? null) : null;\n\t\t}\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\tconst mark = marks.find((m) => m.type === 'fontSize');\n\t\treturn mark && isMarkOfType(mark, 'fontSize') ? (mark.attrs.size ?? null) : null;\n\t}\n\n\tprivate getActiveSizeNumeric(state: EditorState): number {\n\t\tconst raw: string | null = this.getActiveSize(state);\n\t\tif (!raw) return this.defaultSize;\n\t\tconst parsed: number = Number.parseInt(raw, 10);\n\t\treturn Number.isNaN(parsed) ? this.defaultSize : parsed;\n\t}\n\n\t// --- Font Size Application ---\n\n\tprivate applyFontSize(context: PluginContext, state: EditorState, size: string): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tconst withoutSize = currentMarks.filter((m) => m.type !== 'fontSize');\n\t\t\tconst newMarks = [...withoutSize, { type: markType('fontSize'), attrs: { size } }];\n\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx: number = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx: number = blockOrder.indexOf(range.to.blockId);\n\n\t\tconst mark = { type: markType('fontSize'), attrs: { size } };\n\n\t\tfor (let i: number = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen: number = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from: number = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to: number = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, {\n\t\t\t\t\ttype: markType('fontSize'),\n\t\t\t\t});\n\t\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeFontSize(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tif (!hasMark(currentMarks, markType('fontSize'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'fontSize');\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx: number = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx: number = blockOrder.indexOf(range.to.blockId);\n\n\t\tfor (let i: number = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen: number = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from: number = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to: number = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, {\n\t\t\t\t\ttype: markType('fontSize'),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t// --- Increase / Decrease ---\n\n\tprivate stepFontSize(\n\t\tcontext: PluginContext,\n\t\tstate: EditorState,\n\t\tdirection: 'up' | 'down',\n\t): boolean {\n\t\tconst current: number = this.getActiveSizeNumeric(state);\n\t\tconst next: number | null = this.getNextPresetSize(current, direction);\n\t\tif (next === null) return false;\n\n\t\tif (next === this.defaultSize) {\n\t\t\treturn this.removeFontSize(context, state);\n\t\t}\n\t\treturn this.applyFontSize(context, state, `${next}px`);\n\t}\n\n\tprivate getNextPresetSize(current: number, direction: 'up' | 'down'): number | null {\n\t\tif (direction === 'up') {\n\t\t\tfor (const size of this.sizes) {\n\t\t\t\tif (size > current) return size;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tfor (let i: number = this.sizes.length - 1; i >= 0; i--) {\n\t\t\tconst size: number | undefined = this.sizes[i];\n\t\t\tif (size !== undefined && size < current) return size;\n\t\t}\n\t\treturn null;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate dismissPopup(): void {\n\t\tsetTimeout(() => {\n\t\t\tdocument.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));\n\t\t}, 0);\n\t}\n\n\tprivate renderFontSizePopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-font-size-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst currentSize: number = this.getActiveSizeNumeric(state);\n\t\tlet focusedIndex = -1;\n\n\t\t// --- Custom Input ---\n\t\tconst inputWrapper: HTMLDivElement = document.createElement('div');\n\t\tinputWrapper.className = 'notectl-font-size-picker__input-wrapper';\n\n\t\tconst input: HTMLInputElement = document.createElement('input');\n\t\tinput.type = 'number';\n\t\tinput.className = 'notectl-font-size-picker__input';\n\t\tinput.min = String(MIN_CUSTOM_SIZE);\n\t\tinput.max = String(MAX_CUSTOM_SIZE);\n\t\tinput.value = String(currentSize);\n\t\tinput.setAttribute('aria-label', 'Custom font size');\n\n\t\tinputWrapper.appendChild(input);\n\t\tcontainer.appendChild(inputWrapper);\n\n\t\t// --- List ---\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-font-size-picker__list';\n\t\tlist.setAttribute('role', 'listbox');\n\t\tlist.setAttribute('aria-label', 'Font sizes');\n\n\t\tconst items: HTMLButtonElement[] = [];\n\n\t\tfor (let idx = 0; idx < this.sizes.length; idx++) {\n\t\t\tconst size: number | undefined = this.sizes[idx];\n\t\t\tif (size === undefined) continue;\n\t\t\tconst isActive: boolean = size === currentSize;\n\t\t\tconst itemId: string = `notectl-font-size-option-${size}`;\n\n\t\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\t\titem.type = 'button';\n\t\t\titem.id = itemId;\n\t\t\titem.className = 'notectl-font-size-picker__item';\n\t\t\titem.setAttribute('role', 'option');\n\t\t\titem.setAttribute('aria-selected', String(isActive));\n\n\t\t\tif (isActive) {\n\t\t\t\titem.classList.add('notectl-font-size-picker__item--active');\n\t\t\t}\n\n\t\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\t\tcheck.className = 'notectl-font-size-picker__check';\n\t\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\t\titem.appendChild(check);\n\n\t\t\tconst label: HTMLSpanElement = document.createElement('span');\n\t\t\tlabel.className = 'notectl-font-size-picker__label';\n\t\t\tlabel.textContent = String(size);\n\t\t\titem.appendChild(label);\n\n\t\t\titem.addEventListener('mousedown', (e: MouseEvent) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tthis.selectSize(context, size);\n\t\t\t\tthis.dismissPopup();\n\t\t\t});\n\n\t\t\titems.push(item);\n\t\t\tlist.appendChild(item);\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\n\t\t// --- Scroll active item into view ---\n\t\tconst activeIdx: number = this.sizes.indexOf(currentSize);\n\t\tif (activeIdx >= 0) {\n\t\t\tconst activeItem: HTMLButtonElement | undefined = items[activeIdx];\n\t\t\tif (activeItem) {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tactiveItem.scrollIntoView({ block: 'nearest' });\n\t\t\t\t});\n\t\t\t\tlist.setAttribute('aria-activedescendant', activeItem.id);\n\t\t\t}\n\t\t}\n\n\t\t// --- Keyboard helpers ---\n\t\tconst setFocusedIndex = (idx: number): void => {\n\t\t\tif (focusedIndex >= 0 && focusedIndex < items.length) {\n\t\t\t\titems[focusedIndex]?.classList.remove('notectl-font-size-picker__item--focused');\n\t\t\t}\n\t\t\tfocusedIndex = idx;\n\t\t\tconst focused: HTMLButtonElement | undefined = items[focusedIndex];\n\t\t\tif (focusedIndex >= 0 && focusedIndex < items.length && focused) {\n\t\t\t\tfocused.classList.add('notectl-font-size-picker__item--focused');\n\t\t\t\tfocused.scrollIntoView({ block: 'nearest' });\n\t\t\t\tlist.setAttribute('aria-activedescendant', focused.id);\n\t\t\t}\n\t\t};\n\n\t\t// --- Input Events ---\n\t\tinput.addEventListener('keydown', (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Enter') {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst val: number = Number.parseInt(input.value, 10);\n\t\t\t\tif (!Number.isNaN(val) && val >= MIN_CUSTOM_SIZE && val <= MAX_CUSTOM_SIZE) {\n\t\t\t\t\tthis.selectSize(context, val);\n\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t}\n\t\t\t} else if (e.key === 'ArrowDown') {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetFocusedIndex(0);\n\t\t\t\titems[0]?.focus();\n\t\t\t} else if (e.key === 'Escape') {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis.dismissPopup();\n\t\t\t}\n\t\t});\n\n\t\t// --- List Keyboard Navigation ---\n\t\tlist.addEventListener('keydown', (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'ArrowDown') {\n\t\t\t\te.preventDefault();\n\t\t\t\tif (focusedIndex < items.length - 1) {\n\t\t\t\t\tsetFocusedIndex(focusedIndex + 1);\n\t\t\t\t\titems[focusedIndex]?.focus();\n\t\t\t\t}\n\t\t\t} else if (e.key === 'ArrowUp') {\n\t\t\t\te.preventDefault();\n\t\t\t\tif (focusedIndex > 0) {\n\t\t\t\t\tsetFocusedIndex(focusedIndex - 1);\n\t\t\t\t\titems[focusedIndex]?.focus();\n\t\t\t\t} else {\n\t\t\t\t\tsetFocusedIndex(-1);\n\t\t\t\t\tinput.focus();\n\t\t\t\t}\n\t\t\t} else if (e.key === 'Enter') {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst selectedSize: number | undefined = this.sizes[focusedIndex];\n\t\t\t\tif (focusedIndex >= 0 && focusedIndex < this.sizes.length && selectedSize !== undefined) {\n\t\t\t\t\tthis.selectSize(context, selectedSize);\n\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t}\n\t\t\t} else if (e.key === 'Escape') {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis.dismissPopup();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate selectSize(context: PluginContext, size: number): void {\n\t\tif (size === this.defaultSize) {\n\t\t\tcontext.executeCommand('removeFontSize');\n\t\t} else {\n\t\t\tthis.applyFontSize(context, context.getState(), `${size}px`);\n\t\t}\n\t}\n}\n\n// --- Helpers ---\n\nfunction resolveSizes(sizes: readonly number[] | undefined): readonly number[] {\n\tif (!sizes || sizes.length === 0) return DEFAULT_FONT_SIZES;\n\tconst unique: number[] = [...new Set(sizes)].filter((n) => Number.isInteger(n) && n > 0);\n\tunique.sort((a, b) => a - b);\n\treturn unique.length > 0 ? unique : DEFAULT_FONT_SIZES;\n}\n\nfunction resolveDefaultSize(size: number | undefined): number {\n\tif (size === undefined) return DEFAULT_FONT_SIZE;\n\treturn Number.isInteger(size) && size > 0 ? size : DEFAULT_FONT_SIZE;\n}\n","/**\n * Embedded starter font data for the FontPlugin.\n * Contains FiraCode (monospace) and FiraSans (sans-serif) as WOFF2 data URIs.\n * Tree-shakeable: only imported when used.\n */\n\nimport type { FontDefinition } from './FontPlugin.js';\n\nexport const FIRA_CODE_WOFF2_DATA: string =\n\t'data:font/woff2;base64,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';\n\nexport const FIRA_SANS_WOFF2_DATA: string =\n\t'data:font/woff2;base64,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';\n\n/** Fira Code — a monospace font with programming ligatures. */\nexport const FIRA_CODE: FontDefinition = {\n\tname: 'Fira Code',\n\tfamily: \"'Fira Code', monospace\",\n\tcategory: 'monospace',\n\tfontFaces: [\n\t\t{\n\t\t\tsrc: `url(${FIRA_CODE_WOFF2_DATA}) format('woff2')`,\n\t\t\tweight: '400',\n\t\t\tstyle: 'normal',\n\t\t},\n\t],\n};\n\n/** Fira Sans — a humanist sans-serif typeface. */\nexport const FIRA_SANS: FontDefinition = {\n\tname: 'Fira Sans',\n\tfamily: \"'Fira Sans', sans-serif\",\n\tcategory: 'sans-serif',\n\tfontFaces: [\n\t\t{\n\t\t\tsrc: `url(${FIRA_SANS_WOFF2_DATA}) format('woff2')`,\n\t\t\tweight: '400',\n\t\t\tstyle: 'normal',\n\t\t},\n\t],\n};\n\n/** All starter fonts bundled with notectl. */\nexport const STARTER_FONTS: readonly FontDefinition[] = [FIRA_SANS, FIRA_CODE];\n","/**\n * Utility functions for table operations: creating table structures,\n * finding table context, and navigating cells.\n */\n\nimport {\n\ttype BlockNode,\n\ttype ChildNode,\n\tcreateBlockNode,\n\tcreateTextNode,\n\tgenerateBlockId,\n\tgetBlockChildren,\n} from '../../model/Document.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\n\n/** Context information about a cell within a table. */\nexport interface TableContext {\n\treadonly tableId: BlockId;\n\treadonly tableIndex: number;\n\treadonly rowId: BlockId;\n\treadonly rowIndex: number;\n\treadonly cellId: BlockId;\n\treadonly colIndex: number;\n\treadonly totalRows: number;\n\treadonly totalCols: number;\n}\n\n/** Creates a table BlockNode structure with the given dimensions. */\nexport function createTable(rows: number, cols: number): BlockNode {\n\tconst tableId: BlockId = generateBlockId();\n\tconst rowNodes: ChildNode[] = [];\n\n\tfor (let r = 0; r < rows; r++) {\n\t\tconst cellNodes: ChildNode[] = [];\n\t\tfor (let c = 0; c < cols; c++) {\n\t\t\tcellNodes.push(\n\t\t\t\tcreateBlockNode(\n\t\t\t\t\tnodeType('table_cell') as NodeTypeName,\n\t\t\t\t\t[createTextNode('')],\n\t\t\t\t\tgenerateBlockId(),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\trowNodes.push(\n\t\t\tcreateBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId()),\n\t\t);\n\t}\n\n\treturn createBlockNode(nodeType('table') as NodeTypeName, rowNodes, tableId);\n}\n\n/** Creates a single table row with the given number of cells. */\nexport function createTableRow(cols: number): BlockNode {\n\tconst cellNodes: ChildNode[] = [];\n\tfor (let c = 0; c < cols; c++) {\n\t\tcellNodes.push(\n\t\t\tcreateBlockNode(\n\t\t\t\tnodeType('table_cell') as NodeTypeName,\n\t\t\t\t[createTextNode('')],\n\t\t\t\tgenerateBlockId(),\n\t\t\t),\n\t\t);\n\t}\n\treturn createBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId());\n}\n\n/** Creates a single empty table cell. */\nexport function createTableCell(): BlockNode {\n\treturn createBlockNode(\n\t\tnodeType('table_cell') as NodeTypeName,\n\t\t[createTextNode('')],\n\t\tgenerateBlockId(),\n\t);\n}\n\n/**\n * Finds table context for a given block ID.\n * Returns null if the block is not inside a table.\n */\nexport function findTableContext(state: EditorState, blockId: BlockId): TableContext | null {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return null;\n\n\t// Find table node in the path\n\tlet tableId: BlockId | null = null;\n\tlet tableNode: BlockNode | null = null;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table') {\n\t\t\ttableId = id as BlockId;\n\t\t\ttableNode = node;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!tableId || !tableNode) return null;\n\n\t// Find table index in document\n\tconst tableIndex: number = state.doc.children.findIndex((b) => b.id === tableId);\n\n\t// Find the cell — could be the block itself or an ancestor\n\tlet cellId: BlockId | null = null;\n\tlet rowId: BlockId | null = null;\n\n\t// Walk path to identify row and cell\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table_row') {\n\t\t\trowId = id as BlockId;\n\t\t}\n\t\tif (node?.type === 'table_cell') {\n\t\t\tcellId = id as BlockId;\n\t\t}\n\t}\n\n\t// If the block itself is a cell\n\tconst block = state.getBlock(blockId);\n\tif (block?.type === 'table_cell') {\n\t\tcellId = blockId;\n\t}\n\n\tif (!cellId || !rowId) return null;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(tableNode);\n\tconst rowIndex: number = rows.findIndex((r) => r.id === rowId);\n\tif (rowIndex === -1) return null;\n\n\tconst rowNode: BlockNode | undefined = rows[rowIndex];\n\tif (!rowNode) return null;\n\tconst cells: readonly BlockNode[] = getBlockChildren(rowNode);\n\tconst colIndex: number = cells.findIndex((c) => c.id === cellId);\n\tif (colIndex === -1) return null;\n\n\tconst totalCols: number = cells.length;\n\tconst totalRows: number = rows.length;\n\n\treturn {\n\t\ttableId,\n\t\ttableIndex,\n\t\trowId,\n\t\trowIndex,\n\t\tcellId,\n\t\tcolIndex,\n\t\ttotalRows,\n\t\ttotalCols,\n\t};\n}\n\n/**\n * Gets the cell BlockId at the given row and column indices.\n * Returns null if out of bounds.\n */\nexport function getCellAt(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): BlockId | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst row: BlockNode | undefined = rows[rowIndex];\n\tif (!row) return null;\n\n\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\tconst cell: BlockNode | undefined = cells[colIndex];\n\treturn cell?.id ?? null;\n}\n\n/** Returns all cell IDs in a table in row-major order. */\nexport function getAllCellIds(state: EditorState, tableId: BlockId): readonly BlockId[] {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return [];\n\n\tconst result: BlockId[] = [];\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tfor (const row of rows) {\n\t\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\t\tfor (const cell of cells) {\n\t\t\tresult.push(cell.id);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Checks whether a block is inside a table. */\nexport function isInsideTable(state: EditorState, blockId: BlockId): boolean {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return false;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table') return true;\n\t}\n\treturn false;\n}\n","/**\n * Table commands: insert table, add/remove rows and columns, delete table.\n * All commands are registered via PluginContext and operate through transactions.\n */\n\nimport { createBlockNode, getBlockChildren } from '../../model/Document.js';\nimport { createCollapsedSelection } from '../../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { PluginContext } from '../Plugin.js';\nimport {\n\ttype TableContext,\n\tcreateTable,\n\tcreateTableCell,\n\tcreateTableRow,\n\tfindTableContext,\n\tgetCellAt,\n} from './TableHelpers.js';\n\n/**\n * Inserts a table with the given dimensions at the current cursor position.\n * Adds a paragraph after the table for cursor escape.\n * Moves cursor into the first cell.\n */\nexport function insertTable(context: PluginContext, rows: number, cols: number): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\n\tconst currentBlockId: BlockId = sel.anchor.blockId;\n\n\t// Find which root-level block contains the current selection\n\tlet rootIndex = -1;\n\tfor (let i = 0; i < state.doc.children.length; i++) {\n\t\tconst rootBlock = state.doc.children[i];\n\t\tif (!rootBlock) continue;\n\t\tif (rootBlock.id === currentBlockId) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t\t// Check if current block is nested inside this root block\n\t\tconst path = state.getNodePath(currentBlockId);\n\t\tif (path && path[0] === rootBlock.id) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (rootIndex === -1) rootIndex = state.doc.children.length - 1;\n\n\tconst tableNode = createTable(rows, cols);\n\tconst paragraphAfter = createBlockNode(nodeType('paragraph') as NodeTypeName);\n\n\t// Insert table after current block, then paragraph after table\n\tconst insertIndex: number = rootIndex + 1;\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.insertNode([], insertIndex, tableNode)\n\t\t.insertNode([], insertIndex + 1, paragraphAfter);\n\n\t// Set cursor in first cell\n\tconst firstRow = getBlockChildren(tableNode)[0];\n\tconst firstCell = firstRow ? getBlockChildren(firstRow)[0] : undefined;\n\n\tif (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Adds a row above the current row. */\nexport function addRowAbove(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst table = state.getBlock(tableCtx.tableId);\n\tif (!table) return false;\n\n\tconst newRow = createTableRow(tableCtx.totalCols);\n\tconst tr = state.transaction('command').insertNode([tableCtx.tableId], tableCtx.rowIndex, newRow);\n\n\t// Move cursor to first cell of new row\n\tconst firstCell = getBlockChildren(newRow)[0];\n\tif (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Adds a row below the current row. */\nexport function addRowBelow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst newRow = createTableRow(tableCtx.totalCols);\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.insertNode([tableCtx.tableId], tableCtx.rowIndex + 1, newRow);\n\n\t// Move cursor to first cell of new row\n\tconst firstCell = getBlockChildren(newRow)[0];\n\tif (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Adds a column to the left of the current column. */\nexport function addColumnLeft(context: PluginContext): boolean {\n\treturn addColumn(context, 'left');\n}\n\n/** Adds a column to the right of the current column. */\nexport function addColumnRight(context: PluginContext): boolean {\n\treturn addColumn(context, 'right');\n}\n\nfunction addColumn(context: PluginContext, side: 'left' | 'right'): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst table = state.getBlock(tableCtx.tableId);\n\tif (!table) return false;\n\n\tconst rows = getBlockChildren(table);\n\tconst insertColIndex: number = side === 'left' ? tableCtx.colIndex : tableCtx.colIndex + 1;\n\n\tconst tr = state.transaction('command');\n\n\t// Insert a new cell in each row at the column index\n\tfor (const row of rows) {\n\t\tconst newCell = createTableCell();\n\t\ttr.insertNode([tableCtx.tableId, row.id], insertColIndex, newCell);\n\t}\n\n\ttr.setSelection(state.selection);\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/**\n * Deletes the current row. If it's the last row, deletes the entire table.\n */\nexport function deleteRow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.totalRows <= 1) {\n\t\treturn deleteTable(context);\n\t}\n\n\tconst tr = state.transaction('command').removeNode([tableCtx.tableId], tableCtx.rowIndex);\n\n\t// Move cursor to cell in adjacent row\n\tconst targetRowIndex: number = tableCtx.rowIndex > 0 ? tableCtx.rowIndex - 1 : 0;\n\tconst targetCellId: BlockId | null = getCellAt(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttargetRowIndex === tableCtx.rowIndex ? targetRowIndex + 1 : targetRowIndex,\n\t\tMath.min(tableCtx.colIndex, tableCtx.totalCols - 1),\n\t);\n\n\tif (targetCellId) {\n\t\ttr.setSelection(createCollapsedSelection(targetCellId, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/**\n * Deletes the current column. If it's the last column, deletes the entire table.\n */\nexport function deleteColumn(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.totalCols <= 1) {\n\t\treturn deleteTable(context);\n\t}\n\n\tconst table = state.getBlock(tableCtx.tableId);\n\tif (!table) return false;\n\n\tconst rows = getBlockChildren(table);\n\tconst tr = state.transaction('command');\n\n\t// Remove the cell at colIndex from each row (reverse order for index stability)\n\tfor (let r = rows.length - 1; r >= 0; r--) {\n\t\tconst row = rows[r];\n\t\tif (!row) continue;\n\t\ttr.removeNode([tableCtx.tableId, row.id], tableCtx.colIndex);\n\t}\n\n\t// Move cursor to adjacent cell\n\tconst targetColIndex: number = tableCtx.colIndex > 0 ? tableCtx.colIndex - 1 : 0;\n\tconst targetCellId: BlockId | null = getCellAt(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttableCtx.rowIndex,\n\t\ttargetColIndex === tableCtx.colIndex ? targetColIndex + 1 : targetColIndex,\n\t);\n\n\tif (targetCellId) {\n\t\ttr.setSelection(createCollapsedSelection(targetCellId, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Deletes the entire table and moves cursor to surrounding block. */\nexport function deleteTable(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = state.transaction('command').removeNode([], tableCtx.tableIndex);\n\n\t// Move cursor to block after the table, or before if none after\n\tconst blockAfterIndex: number = tableCtx.tableIndex;\n\tconst blockBeforeIndex: number = tableCtx.tableIndex - 1;\n\n\tif (blockAfterIndex < state.doc.children.length - 1) {\n\t\tconst afterBlock = state.doc.children[blockAfterIndex + 1];\n\t\tif (afterBlock) {\n\t\t\ttr.setSelection(createCollapsedSelection(afterBlock.id, 0));\n\t\t}\n\t} else if (blockBeforeIndex >= 0) {\n\t\tconst beforeBlock = state.doc.children[blockBeforeIndex];\n\t\tif (beforeBlock) {\n\t\t\ttr.setSelection(createCollapsedSelection(beforeBlock.id, 0));\n\t\t}\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Registers all table commands on the given plugin context. */\nexport function registerTableCommands(context: PluginContext): void {\n\tcontext.registerCommand('insertTable', () => insertTable(context, 3, 3));\n\tcontext.registerCommand('addRowAbove', () => addRowAbove(context));\n\tcontext.registerCommand('addRowBelow', () => addRowBelow(context));\n\tcontext.registerCommand('addColumnLeft', () => addColumnLeft(context));\n\tcontext.registerCommand('addColumnRight', () => addColumnRight(context));\n\tcontext.registerCommand('deleteRow', () => deleteRow(context));\n\tcontext.registerCommand('deleteColumn', () => deleteColumn(context));\n\tcontext.registerCommand('deleteTable', () => deleteTable(context));\n}\n","/**\n * Keyboard navigation handlers for table cells.\n * Handles Tab, Shift-Tab, arrow keys, Enter, Backspace, Delete, and Escape.\n */\n\nimport type { Keymap } from '../../input/Keymap.js';\nimport { getBlockLength } from '../../model/Document.js';\nimport { createCollapsedSelection, isCollapsed } from '../../model/Selection.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { addRowBelow } from './TableCommands.js';\nimport { type TableContext, findTableContext, getCellAt, isInsideTable } from './TableHelpers.js';\n\n/** Registers all table navigation keymaps. */\nexport function registerTableKeymaps(context: PluginContext): void {\n\tconst keymap: Keymap = {\n\t\tTab: () => handleTab(context),\n\t\t'Shift-Tab': () => handleShiftTab(context),\n\t\tEnter: () => handleEnter(context),\n\t\tBackspace: () => handleBackspace(context),\n\t\tDelete: () => handleDelete(context),\n\t\tArrowDown: () => handleArrowDown(context),\n\t\tArrowUp: () => handleArrowUp(context),\n\t\tArrowRight: () => handleArrowRight(context),\n\t\tArrowLeft: () => handleArrowLeft(context),\n\t\tEscape: () => handleEscape(context),\n\t};\n\n\tcontext.registerKeymap(keymap);\n}\n\n/** Tab: move to next cell. At end of table, add a new row. */\nfunction handleTab(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Try next cell in same row\n\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex + 1);\n\t}\n\n\t// Try first cell in next row\n\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t}\n\n\t// At end of table — add a new row and move there\n\taddRowBelow(context);\n\treturn true;\n}\n\n/** Shift-Tab: move to previous cell. At start of table, return false. */\nfunction handleShiftTab(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Try previous cell in same row\n\tif (tableCtx.colIndex > 0) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex - 1);\n\t}\n\n\t// Try last cell in previous row\n\tif (tableCtx.rowIndex > 0) {\n\t\treturn moveToCellAndSelect(\n\t\t\tcontext,\n\t\t\ttableCtx.tableId,\n\t\t\ttableCtx.rowIndex - 1,\n\t\t\ttableCtx.totalCols - 1,\n\t\t);\n\t}\n\n\t// At start of table — stay put\n\treturn true;\n}\n\n/** Enter: move to same column in next row (spreadsheet behavior). */\nfunction handleEnter(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Move to same column in next row\n\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n\t}\n\n\t// On last row — block to prevent splitBlock\n\treturn true;\n}\n\n/** Backspace at cell start: block to prevent mergeBlockBackward. */\nfunction handleBackspace(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (!isCollapsed(sel)) return false;\n\tif (sel.anchor.offset !== 0) return false;\n\n\treturn isInsideTable(state, sel.anchor.blockId);\n}\n\n/** Delete at cell end: block to prevent mergeBlockForward. */\nfunction handleDelete(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (!isCollapsed(sel)) return false;\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return false;\n\n\tconst blockLen: number = getBlockLength(block);\n\tif (sel.anchor.offset !== blockLen) return false;\n\n\treturn isInsideTable(state, sel.anchor.blockId);\n}\n\n/** ArrowDown: move to same column in next row. */\nfunction handleArrowDown(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.rowIndex >= tableCtx.totalRows - 1) {\n\t\t// At last row — move cursor to paragraph after table\n\t\treturn handleEscape(context);\n\t}\n\n\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n}\n\n/** ArrowUp: move to same column in previous row. */\nfunction handleArrowUp(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.rowIndex <= 0) {\n\t\t// At first row — let default behavior handle it\n\t\treturn false;\n\t}\n\n\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex - 1, tableCtx.colIndex);\n}\n\n/** ArrowRight at cell end: move to next cell. */\nfunction handleArrowRight(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (!isCollapsed(sel)) return false;\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return false;\n\n\tconst blockLen: number = getBlockLength(block);\n\tif (sel.anchor.offset !== blockLen) return false;\n\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Try next cell in same row\n\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex + 1);\n\t}\n\n\t// Try first cell in next row\n\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t}\n\n\treturn true;\n}\n\n/** ArrowLeft at cell start: move to previous cell. */\nfunction handleArrowLeft(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (!isCollapsed(sel)) return false;\n\tif (sel.anchor.offset !== 0) return false;\n\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Try previous cell in same row\n\tif (tableCtx.colIndex > 0) {\n\t\treturn moveToCellAtEnd(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex - 1);\n\t}\n\n\t// Try last cell in previous row\n\tif (tableCtx.rowIndex > 0) {\n\t\treturn moveToCellAtEnd(\n\t\t\tcontext,\n\t\t\ttableCtx.tableId,\n\t\t\ttableCtx.rowIndex - 1,\n\t\t\ttableCtx.totalCols - 1,\n\t\t);\n\t}\n\n\treturn true;\n}\n\n/** Escape: move cursor to the paragraph after the table. */\nfunction handleEscape(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\t// Find the block after the table\n\tconst nextIndex: number = tableCtx.tableIndex + 1;\n\tif (nextIndex < state.doc.children.length) {\n\t\tconst nextBlock = state.doc.children[nextIndex];\n\t\tif (!nextBlock) return false;\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setSelection(createCollapsedSelection(nextBlock.id, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/** Moves cursor to the start of a cell. */\nfunction moveToCellAndSelect(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst tr = state.transaction('command').setSelection(createCollapsedSelection(cellId, 0)).build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Moves cursor to the end of a cell (for ArrowLeft navigation). */\nfunction moveToCellAtEnd(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst cell = state.getBlock(cellId);\n\tif (!cell) return false;\n\n\tconst cellLen: number = getBlockLength(cell);\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setSelection(createCollapsedSelection(cellId, cellLen))\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n","/**\n * Reconciler: diffs old and new state and applies minimal DOM patches.\n * Uses block-level granularity — changed blocks are re-rendered entirely.\n * Supports plugin-registered NodeSpecs, MarkSpecs, and NodeViews via SchemaRegistry.\n */\n\nimport type { Decoration, DecorationAttrs, InlineDecoration } from '../decorations/Decoration.js';\nimport { type DecorationSet, decorationArraysEqual } from '../decorations/Decoration.js';\nimport type { MarkAttrsFor, NodeAttrsFor } from '../model/AttrRegistry.js';\nimport type { BlockNode, InlineNode, Mark, TextNode } from '../model/Document.js';\nimport {\n\tgetBlockChildren,\n\tgetInlineChildren,\n\tisInlineNode,\n\tisLeafBlock,\n\tisTextNode,\n\tmarkSetsEqual,\n} from '../model/Document.js';\nimport { createBlockElement } from '../model/NodeSpec.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport { blockId as toBlockId } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { NodeView } from './NodeView.js';\n\nexport interface ReconcileOptions {\n\tregistry?: SchemaRegistry;\n\tnodeViews?: Map<string, NodeView>;\n\tgetState?: () => EditorState;\n\tdispatch?: (tr: import('../state/Transaction.js').Transaction) => void;\n\tdecorations?: DecorationSet;\n\toldDecorations?: DecorationSet;\n}\n\n/** Reconciles the DOM container to match the new state. */\nexport function reconcile(\n\tcontainer: HTMLElement,\n\toldState: EditorState | null,\n\tnewState: EditorState,\n\toptions?: ReconcileOptions,\n): void {\n\tconst oldBlocks = oldState?.doc.children ?? [];\n\tconst newBlocks = newState.doc.children;\n\tconst registry = options?.registry;\n\tconst nodeViews = options?.nodeViews;\n\n\tconst oldBlockMap = new Map<BlockId, HTMLElement>();\n\tfor (const child of Array.from(container.children)) {\n\t\tconst el = child as HTMLElement;\n\t\tconst bid = el.getAttribute('data-block-id');\n\t\tif (bid) {\n\t\t\toldBlockMap.set(toBlockId(bid), el);\n\t\t}\n\t}\n\n\t// Build set of new block IDs for removal detection\n\tconst newBlockIds = new Set(newBlocks.map((b) => b.id));\n\n\t// Remove blocks that no longer exist\n\tfor (const [blockId, el] of oldBlockMap) {\n\t\tif (!newBlockIds.has(blockId)) {\n\t\t\tcontainer.removeChild(el);\n\t\t\toldBlockMap.delete(blockId);\n\t\t\t// Destroy NodeView if exists\n\t\t\tconst nv = nodeViews?.get(blockId);\n\t\t\tif (nv) {\n\t\t\t\tnv.destroy?.();\n\t\t\t\tnodeViews?.delete(blockId);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Mapping from old state for change detection\n\tconst oldBlockById = new Map<string, BlockNode>();\n\tfor (const block of oldBlocks) {\n\t\toldBlockById.set(block.id, block);\n\t}\n\n\t// Insert/update blocks in order\n\tlet previousSibling: Element | null = null;\n\n\tfor (const block of newBlocks) {\n\t\tconst existingEl = oldBlockMap.get(block.id);\n\t\tconst oldBlock = oldBlockById.get(block.id);\n\n\t\tconst oldDecos = options?.oldDecorations?.find(block.id);\n\t\tconst newDecos = options?.decorations?.find(block.id);\n\n\t\tif (existingEl && oldBlock && !blockChanged(oldBlock, block, oldDecos, newDecos)) {\n\t\t\t// Block unchanged — keep existing DOM\n\t\t\tpreviousSibling = existingEl;\n\t\t} else if (existingEl) {\n\t\t\t// Block changed — try NodeView update first\n\t\t\tconst existingNv = nodeViews?.get(block.id);\n\t\t\tif (existingNv) {\n\t\t\t\tconst handled = existingNv.update?.(block) ?? false;\n\t\t\t\tif (handled) {\n\t\t\t\t\tpreviousSibling = existingNv.dom;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Update not handled — destroy and re-create\n\t\t\t\texistingNv.destroy?.();\n\t\t\t\tnodeViews?.delete(block.id);\n\t\t\t}\n\n\t\t\tconst newEl = renderBlock(block, registry, nodeViews, options);\n\t\t\tcontainer.replaceChild(newEl, existingEl);\n\t\t\tpreviousSibling = newEl;\n\t\t} else {\n\t\t\t// New block — insert after previousSibling\n\t\t\tconst newEl = renderBlock(block, registry, nodeViews, options);\n\t\t\tif (previousSibling?.nextSibling) {\n\t\t\t\tcontainer.insertBefore(newEl, previousSibling.nextSibling);\n\t\t\t} else if (!previousSibling && container.firstChild) {\n\t\t\t\tcontainer.insertBefore(newEl, container.firstChild);\n\t\t\t} else {\n\t\t\t\tcontainer.appendChild(newEl);\n\t\t\t}\n\t\t\tpreviousSibling = newEl;\n\t\t}\n\t}\n}\n\n/** Checks whether a block has changed by comparing its children, attrs, and decorations. */\nfunction blockChanged(\n\toldBlock: BlockNode,\n\tnewBlock: BlockNode,\n\toldDecos?: readonly Decoration[],\n\tnewDecos?: readonly Decoration[],\n): boolean {\n\tif (oldBlock.type !== newBlock.type) return true;\n\tif (oldBlock.children.length !== newBlock.children.length) return true;\n\n\t// Compare attrs\n\tconst oldAttrs = oldBlock.attrs;\n\tconst newAttrs = newBlock.attrs;\n\tif (oldAttrs !== newAttrs) {\n\t\tif (!oldAttrs || !newAttrs) return true;\n\t\tconst oldKeys = Object.keys(oldAttrs);\n\t\tconst newKeys = Object.keys(newAttrs);\n\t\tif (oldKeys.length !== newKeys.length) return true;\n\t\tfor (const key of oldKeys) {\n\t\t\tif (oldAttrs[key] !== newAttrs[key]) return true;\n\t\t}\n\t}\n\n\tfor (let i = 0; i < oldBlock.children.length; i++) {\n\t\tconst oldChild = oldBlock.children[i];\n\t\tconst newChild = newBlock.children[i];\n\t\tif (!oldChild || !newChild) return true;\n\n\t\tif (isTextNode(oldChild) && isTextNode(newChild)) {\n\t\t\tif (oldChild.text !== newChild.text) return true;\n\t\t\tif (!markSetsEqual(oldChild.marks, newChild.marks)) return true;\n\t\t} else if (isInlineNode(oldChild) && isInlineNode(newChild)) {\n\t\t\tif (oldChild.inlineType !== newChild.inlineType) return true;\n\t\t\tif (!inlineAttrsEqual(oldChild.attrs, newChild.attrs)) return true;\n\t\t} else if (\n\t\t\t!isTextNode(oldChild) &&\n\t\t\t!isTextNode(newChild) &&\n\t\t\t!isInlineNode(oldChild) &&\n\t\t\t!isInlineNode(newChild)\n\t\t) {\n\t\t\t// Both are BlockNodes — compare recursively\n\t\t\tif (blockChanged(oldChild as BlockNode, newChild as BlockNode)) return true;\n\t\t} else {\n\t\t\t// Different child types\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Compare decorations\n\tconst oldArr = oldDecos ?? [];\n\tconst newArr = newDecos ?? [];\n\tif (oldArr !== newArr && !decorationArraysEqual(oldArr, newArr)) return true;\n\n\treturn false;\n}\n\n/** Renders a block node to a DOM element, using registry specs or NodeViews. */\nexport function renderBlock(\n\tblock: BlockNode,\n\tregistry?: SchemaRegistry,\n\tnodeViews?: Map<string, NodeView>,\n\toptions?: ReconcileOptions,\n): HTMLElement {\n\tconst inlineDecos = options?.decorations?.findInline(block.id);\n\n\t// 1. Try NodeViewFactory\n\tif (registry && nodeViews && options?.getState && options?.dispatch) {\n\t\tconst factory = registry.getNodeViewFactory(block.type);\n\t\tif (factory) {\n\t\t\tconst nv = factory(block, options.getState, options.dispatch);\n\t\t\tnodeViews.set(block.id, nv);\n\n\t\t\t// Recursively render block children into NodeView content areas\n\t\t\tconst blockChildren = getBlockChildren(block);\n\t\t\tfor (const child of blockChildren) {\n\t\t\t\tconst contentDOM = nv.getContentDOM?.(child.id) ?? nv.contentDOM;\n\t\t\t\tif (contentDOM) {\n\t\t\t\t\tconst childEl = renderBlock(child, registry, nodeViews, options);\n\t\t\t\t\tcontentDOM.appendChild(childEl);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tapplyNodeDecorations(nv.dom, block.id, options);\n\t\t\treturn nv.dom;\n\t\t}\n\t}\n\n\t// 2. Try NodeSpec\n\tif (registry) {\n\t\tconst spec = registry.getNodeSpec(block.type);\n\t\tif (spec) {\n\t\t\tconst el = spec.toDOM(\n\t\t\t\tblock as Omit<BlockNode, 'attrs'> & { readonly attrs: NodeAttrsFor<string> },\n\t\t\t);\n\t\t\tif (!spec.isVoid) {\n\t\t\t\tif (isLeafBlock(block)) {\n\t\t\t\t\trenderBlockContent(el, block, registry, inlineDecos);\n\t\t\t\t} else {\n\t\t\t\t\t// Render block children recursively\n\t\t\t\t\tconst blockChildren = getBlockChildren(block);\n\t\t\t\t\tfor (const child of blockChildren) {\n\t\t\t\t\t\tconst childEl = renderBlock(child, registry, nodeViews, options);\n\t\t\t\t\t\tel.appendChild(childEl);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tapplyNodeDecorations(el, block.id, options);\n\t\t\treturn el;\n\t\t}\n\t}\n\n\t// 3. Fallback — render as paragraph\n\treturn renderParagraphFallback(block, registry, inlineDecos);\n}\n\n/** Renders block content (inline children) into a container element. */\nexport function renderBlockContent(\n\tcontainer: HTMLElement,\n\tblock: BlockNode,\n\tregistry?: SchemaRegistry,\n\tinlineDecos?: readonly InlineDecoration[],\n): void {\n\tconst inlineChildren = getInlineChildren(block);\n\n\t// Empty block: single empty text node → render <br> placeholder\n\tif (\n\t\tinlineChildren.length === 1 &&\n\t\tisTextNode(inlineChildren[0]) &&\n\t\tinlineChildren[0].text === ''\n\t) {\n\t\tcontainer.appendChild(document.createElement('br'));\n\t\treturn;\n\t}\n\n\t// Fast path: no inline decorations\n\tif (!inlineDecos || inlineDecos.length === 0) {\n\t\tfor (const child of inlineChildren) {\n\t\t\tif (isTextNode(child)) {\n\t\t\t\tcontainer.appendChild(renderTextNode(child, registry));\n\t\t\t} else {\n\t\t\t\tcontainer.appendChild(renderInlineNode(child, registry));\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\t// Decorated path: split content into micro-segments\n\trenderDecoratedContent(container, inlineChildren, inlineDecos, registry);\n}\n\n/** Fallback paragraph rendering when no NodeSpec is found. */\nfunction renderParagraphFallback(\n\tblock: BlockNode,\n\tregistry?: SchemaRegistry,\n\tinlineDecos?: readonly InlineDecoration[],\n): HTMLElement {\n\tconst p = createBlockElement('p', block.id);\n\trenderBlockContent(p, block, registry, inlineDecos);\n\treturn p;\n}\n\n/**\n * Converts spaces for contenteditable rendering.\n * Trailing spaces and double spaces are replaced with \\u00a0 (non-breaking space)\n * to prevent the browser from collapsing them.\n */\nfunction preserveSpaces(text: string): string {\n\t// Replace consecutive spaces: alternate regular and non-breaking\n\tlet result = text.replace(/ {2}/g, ' \\u00a0');\n\t// If the text ends with a space, replace it with nbsp\n\tif (result.endsWith(' ')) {\n\t\tresult = `${result.slice(0, -1)}\\u00a0`;\n\t}\n\t// If the text starts with a space, replace it with nbsp\n\tif (result.startsWith(' ')) {\n\t\tresult = `\\u00a0${result.slice(1)}`;\n\t}\n\treturn result;\n}\n\n/** Renders a text node with marks as nested inline elements. */\nfunction renderTextNode(node: TextNode, registry?: SchemaRegistry): Node {\n\tif (node.text === '') {\n\t\treturn document.createTextNode('');\n\t}\n\n\tconst textNode = document.createTextNode(preserveSpaces(node.text));\n\n\tif (node.marks.length === 0) {\n\t\treturn textNode;\n\t}\n\n\t// Sort marks: use MarkSpec.rank if available, otherwise fallback order\n\tconst sortedMarks = [...node.marks].sort(\n\t\t(a, b) => markOrder(a, registry) - markOrder(b, registry),\n\t);\n\n\tlet current: Node = textNode;\n\n\t// Wrap from inside out (last mark is outermost)\n\tfor (let i = sortedMarks.length - 1; i >= 0; i--) {\n\t\tconst mark = sortedMarks[i];\n\t\tif (!mark) continue;\n\t\tconst el = createMarkElement(mark, registry);\n\t\tel.appendChild(current);\n\t\tcurrent = el;\n\t}\n\n\treturn current;\n}\n\n/** Renders an InlineNode, using InlineNodeSpec.toDOM() or a fallback element. */\nfunction renderInlineNode(node: InlineNode, registry?: SchemaRegistry): HTMLElement {\n\tif (registry) {\n\t\tconst spec = registry.getInlineNodeSpec(node.inlineType);\n\t\tif (spec) {\n\t\t\tconst el = spec.toDOM(node);\n\t\t\tel.setAttribute('contenteditable', 'false');\n\t\t\treturn el;\n\t\t}\n\t}\n\t// Fallback: generic non-editable span\n\tconst el = document.createElement('span');\n\tel.setAttribute('data-inline-type', node.inlineType);\n\tel.setAttribute('contenteditable', 'false');\n\treturn el;\n}\n\n/** Compares two InlineNode attr records for equality. */\nfunction inlineAttrsEqual(\n\ta: Readonly<Record<string, string | number | boolean>>,\n\tb: Readonly<Record<string, string | number | boolean>>,\n): boolean {\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\tif (aKeys.length !== bKeys.length) return false;\n\tfor (const key of aKeys) {\n\t\tif (a[key] !== b[key]) return false;\n\t}\n\treturn true;\n}\n\nfunction markOrder(mark: Mark, registry?: SchemaRegistry): number {\n\tif (registry) {\n\t\tconst spec = registry.getMarkSpec(mark.type);\n\t\tif (spec) return spec.rank ?? 100;\n\t}\n\t// Fallback order for built-in marks\n\tswitch (mark.type) {\n\t\tcase 'bold':\n\t\t\treturn 0;\n\t\tcase 'italic':\n\t\t\treturn 1;\n\t\tcase 'underline':\n\t\t\treturn 2;\n\t\tdefault:\n\t\t\treturn 100;\n\t}\n}\n\nfunction createMarkElement(mark: Mark, registry?: SchemaRegistry): HTMLElement {\n\tif (registry) {\n\t\tconst spec = registry.getMarkSpec(mark.type);\n\t\tif (spec)\n\t\t\treturn spec.toDOM(mark as Omit<Mark, 'attrs'> & { readonly attrs: MarkAttrsFor<string> });\n\t}\n\t// Fallback for built-in marks\n\tswitch (mark.type) {\n\t\tcase 'bold':\n\t\t\treturn document.createElement('strong');\n\t\tcase 'italic':\n\t\t\treturn document.createElement('em');\n\t\tcase 'underline':\n\t\t\treturn document.createElement('u');\n\t\tdefault:\n\t\t\treturn document.createElement('span');\n\t}\n}\n\n// --- Decoration Rendering ---\n\n/**\n * Renders inline content with decorations. InlineNodes are width-1 split points\n * rendered as their own elements (not wrapped by decorations).\n *\n * For each child:\n * - TextNode: split by decoration boundaries, render text → marks → decorations\n * - InlineNode: render directly without decoration wrapping\n */\nfunction renderDecoratedContent(\n\tcontainer: HTMLElement,\n\tinlineChildren: readonly (TextNode | InlineNode)[],\n\tinlineDecos: readonly InlineDecoration[],\n\tregistry?: SchemaRegistry,\n): void {\n\tlet globalOffset = 0;\n\n\tfor (const child of inlineChildren) {\n\t\tif (isInlineNode(child)) {\n\t\t\t// InlineNodes are rendered directly, not wrapped by decorations\n\t\t\tcontainer.appendChild(renderInlineNode(child, registry));\n\t\t\tglobalOffset += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// TextNode: split by decoration boundaries within this node's range\n\t\tconst textFrom = globalOffset;\n\t\tconst textTo = globalOffset + child.text.length;\n\n\t\tif (child.text.length === 0) {\n\t\t\tglobalOffset = textTo;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find split points within this text range\n\t\tconst splitSet = new Set<number>();\n\t\tsplitSet.add(textFrom);\n\t\tsplitSet.add(textTo);\n\t\tfor (const deco of inlineDecos) {\n\t\t\tconst dFrom = Math.max(textFrom, deco.from);\n\t\t\tconst dTo = Math.min(textTo, deco.to);\n\t\t\tif (dFrom > textFrom && dFrom < textTo) splitSet.add(dFrom);\n\t\t\tif (dTo > textFrom && dTo < textTo) splitSet.add(dTo);\n\t\t}\n\t\tconst splits = [...splitSet].sort((a, b) => a - b);\n\n\t\t// Render micro-segments\n\t\tfor (let i = 0; i < splits.length - 1; i++) {\n\t\t\tconst from = splits[i];\n\t\t\tconst to = splits[i + 1];\n\t\t\tif (from === undefined || to === undefined || from >= to) continue;\n\n\t\t\tconst localFrom = from - textFrom;\n\t\t\tconst localTo = to - textFrom;\n\t\t\tconst text = child.text.slice(localFrom, localTo);\n\n\t\t\t// Find decorations that fully cover this micro-segment\n\t\t\tconst activeDecos: InlineDecoration[] = [];\n\t\t\tfor (const deco of inlineDecos) {\n\t\t\t\tif (deco.from <= from && deco.to >= to) {\n\t\t\t\t\tactiveDecos.push(deco);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Render: text → marks (inner) → decorations (outer)\n\t\t\tconst textNode = document.createTextNode(preserveSpaces(text));\n\t\t\tlet current: Node = textNode;\n\n\t\t\t// Wrap with marks (innermost to outermost)\n\t\t\tif (child.marks.length > 0) {\n\t\t\t\tconst sortedMarks = [...child.marks].sort(\n\t\t\t\t\t(a, b) => markOrder(a, registry) - markOrder(b, registry),\n\t\t\t\t);\n\t\t\t\tfor (let j = sortedMarks.length - 1; j >= 0; j--) {\n\t\t\t\t\tconst mark = sortedMarks[j];\n\t\t\t\t\tif (!mark) continue;\n\t\t\t\t\tconst el = createMarkElement(mark, registry);\n\t\t\t\t\tel.appendChild(current);\n\t\t\t\t\tcurrent = el;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Wrap with decorations (outermost)\n\t\t\tfor (const deco of activeDecos) {\n\t\t\t\tconst el = createDecorationElement(deco.attrs);\n\t\t\t\tel.appendChild(current);\n\t\t\t\tcurrent = el;\n\t\t\t}\n\n\t\t\tcontainer.appendChild(current);\n\t\t}\n\n\t\tglobalOffset = textTo;\n\t}\n}\n\n/** Creates a DOM element for an inline decoration. */\nfunction createDecorationElement(attrs: DecorationAttrs): HTMLElement {\n\tconst tagName = attrs.nodeName ?? 'span';\n\tconst el = document.createElement(tagName);\n\tel.setAttribute('data-decoration', 'true');\n\n\tif (attrs.class) {\n\t\tfor (const cls of attrs.class.split(' ')) {\n\t\t\tif (cls) el.classList.add(cls);\n\t\t}\n\t}\n\tif (attrs.style) {\n\t\tel.style.cssText = attrs.style;\n\t}\n\n\t// Apply any other custom attributes\n\tfor (const [key, value] of Object.entries(attrs)) {\n\t\tif (key === 'class' || key === 'style' || key === 'nodeName') continue;\n\t\tif (value !== undefined) {\n\t\t\tel.setAttribute(key, value);\n\t\t}\n\t}\n\n\treturn el;\n}\n\n/** Applies node decorations (CSS classes/styles) to a block element. */\nfunction applyNodeDecorations(el: HTMLElement, bid: BlockId, options?: ReconcileOptions): void {\n\tconst nodeDecos = options?.decorations?.findNode(bid);\n\tif (!nodeDecos || nodeDecos.length === 0) return;\n\n\tfor (const deco of nodeDecos) {\n\t\tif (deco.attrs.class) {\n\t\t\tfor (const cls of deco.attrs.class.split(' ')) {\n\t\t\t\tif (cls) el.classList.add(cls);\n\t\t\t}\n\t\t}\n\t\tif (deco.attrs.style) {\n\t\t\tconst current: string = el.style.cssText;\n\t\t\tel.style.cssText = current ? `${current}; ${deco.attrs.style}` : deco.attrs.style;\n\t\t}\n\t}\n}\n","/**\n * Interactive table controls: floating insert lines between borders,\n * add row/column buttons at edges, and column/row handles with delete.\n * All controls appear on hover with smooth CSS animations.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport { createCollapsedSelection } from '../../model/Selection.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport { createTableCell, createTableRow, getCellAt } from './TableHelpers.js';\n\n// --- SVG Icons ---\n\nconst PLUS_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" ' +\n\t'viewBox=\"0 0 12 12\" fill=\"none\">' +\n\t'<path d=\"M6 1v10M1 6h10\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.8\" stroke-linecap=\"round\"/></svg>';\n\nconst DELETE_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" ' +\n\t'viewBox=\"0 0 10 10\" fill=\"none\">' +\n\t'<path d=\"M2 2l6 6M8 2l-6 6\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>';\n\n// --- Constants ---\n\nconst BORDER_THRESHOLD: number = 10;\n\n// --- Types ---\n\nexport interface TableControlsHandle {\n\tupdate(node: BlockNode): void;\n\tdestroy(): void;\n}\n\ninterface BorderInfo {\n\treadonly position: number;\n\treadonly index: number;\n}\n\n// --- Transaction Helpers ---\n\nfunction insertRowAtIndex(\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n\ttableId: BlockId,\n\trowIndex: number,\n): void {\n\tconst state: EditorState = getState();\n\tconst table: BlockNode | undefined = state.getBlock(tableId);\n\tif (!table) return;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\tif (numCols === 0) return;\n\n\tconst newRow: BlockNode = createTableRow(numCols);\n\tconst firstCell: BlockNode | undefined = getBlockChildren(newRow)[0];\n\n\tconst tr = state.transaction('command').insertNode([tableId], rowIndex, newRow);\n\n\tif (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tdispatch(tr.build());\n}\n\nfunction insertColumnAtIndex(\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n\ttableId: BlockId,\n\tcolIndex: number,\n): void {\n\tconst state: EditorState = getState();\n\tconst table: BlockNode | undefined = state.getBlock(tableId);\n\tif (!table) return;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst tr = state.transaction('command');\n\n\tfor (const row of rows) {\n\t\tconst newCell: BlockNode = createTableCell();\n\t\ttr.insertNode([tableId, row.id], colIndex, newCell);\n\t}\n\n\ttr.setSelection(state.selection);\n\tdispatch(tr.build());\n}\n\nfunction deleteRowAtIndex(\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n\ttableId: BlockId,\n\trowIndex: number,\n): void {\n\tconst state: EditorState = getState();\n\tconst table: BlockNode | undefined = state.getBlock(tableId);\n\tif (!table) return;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tif (rows.length <= 1) {\n\t\tdeleteEntireTable(getState, dispatch, tableId);\n\t\treturn;\n\t}\n\n\tconst tr = state.transaction('command').removeNode([tableId], rowIndex);\n\n\tconst targetRow: number = rowIndex > 0 ? rowIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, targetRow, 0);\n\tif (cellId) {\n\t\ttr.setSelection(createCollapsedSelection(cellId, 0));\n\t}\n\n\tdispatch(tr.build());\n}\n\nfunction deleteColumnAtIndex(\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n\ttableId: BlockId,\n\tcolIndex: number,\n): void {\n\tconst state: EditorState = getState();\n\tconst table: BlockNode | undefined = state.getBlock(tableId);\n\tif (!table) return;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\n\tif (numCols <= 1) {\n\t\tdeleteEntireTable(getState, dispatch, tableId);\n\t\treturn;\n\t}\n\n\tconst tr = state.transaction('command');\n\n\tfor (let r: number = rows.length - 1; r >= 0; r--) {\n\t\tconst row: BlockNode | undefined = rows[r];\n\t\tif (!row) continue;\n\t\ttr.removeNode([tableId, row.id], colIndex);\n\t}\n\n\tconst targetCol: number = colIndex > 0 ? colIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, 0, targetCol);\n\tif (cellId) {\n\t\ttr.setSelection(createCollapsedSelection(cellId, 0));\n\t}\n\n\tdispatch(tr.build());\n}\n\nfunction deleteEntireTable(\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n\ttableId: BlockId,\n): void {\n\tconst state: EditorState = getState();\n\tconst tableIndex: number = state.doc.children.findIndex((b) => b.id === tableId);\n\tif (tableIndex === -1) return;\n\n\tconst tr = state.transaction('command').removeNode([], tableIndex);\n\n\tif (tableIndex < state.doc.children.length - 1) {\n\t\tconst after: BlockNode | undefined = state.doc.children[tableIndex + 1];\n\t\tif (after) {\n\t\t\ttr.setSelection(createCollapsedSelection(after.id, 0));\n\t\t}\n\t} else if (tableIndex > 0) {\n\t\tconst before: BlockNode | undefined = state.doc.children[tableIndex - 1];\n\t\tif (before) {\n\t\t\ttr.setSelection(createCollapsedSelection(before.id, 0));\n\t\t}\n\t}\n\n\tdispatch(tr.build());\n}\n\n// --- DOM Builders ---\n\nfunction createButton(className: string, innerHTML: string, title: string): HTMLButtonElement {\n\tconst btn: HTMLButtonElement = document.createElement('button');\n\tbtn.className = className;\n\tbtn.innerHTML = innerHTML;\n\tbtn.title = title;\n\tbtn.type = 'button';\n\tbtn.setAttribute('contenteditable', 'false');\n\tbtn.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\treturn btn;\n}\n\nfunction buildInsertLine(orientation: 'horizontal' | 'vertical'): HTMLDivElement {\n\tconst line: HTMLDivElement = document.createElement('div');\n\tline.className = `ntbl-insert-line ntbl-insert-line--${orientation}`;\n\tline.setAttribute('contenteditable', 'false');\n\n\tconst title: string = orientation === 'horizontal' ? 'Insert row' : 'Insert column';\n\tconst btn: HTMLButtonElement = createButton('ntbl-insert-btn', PLUS_SVG, title);\n\tline.appendChild(btn);\n\n\treturn line;\n}\n\nfunction buildAddButton(className: string, title: string): HTMLDivElement {\n\tconst container: HTMLDivElement = document.createElement('div');\n\tcontainer.className = `ntbl-add-zone ${className}`;\n\tcontainer.setAttribute('contenteditable', 'false');\n\tcontainer.title = title;\n\n\tconst icon: HTMLSpanElement = document.createElement('span');\n\ticon.className = 'ntbl-add-icon';\n\ticon.innerHTML = PLUS_SVG;\n\tcontainer.appendChild(icon);\n\n\tcontainer.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\n\treturn container;\n}\n\nfunction buildHandleBar(className: string): HTMLDivElement {\n\tconst bar: HTMLDivElement = document.createElement('div');\n\tbar.className = className;\n\tbar.setAttribute('contenteditable', 'false');\n\treturn bar;\n}\n\nfunction buildHandle(\n\tclassName: string,\n\tindex: number,\n\tonDelete: (idx: number) => void,\n): HTMLDivElement {\n\tconst handle: HTMLDivElement = document.createElement('div');\n\thandle.className = `ntbl-handle ${className}`;\n\thandle.dataset.index = String(index);\n\n\tconst deleteBtn: HTMLButtonElement = createButton(\n\t\t'ntbl-handle-delete',\n\t\tDELETE_SVG,\n\t\tclassName.includes('col') ? 'Delete column' : 'Delete row',\n\t);\n\tdeleteBtn.addEventListener('click', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tonDelete(index);\n\t});\n\thandle.appendChild(deleteBtn);\n\n\treturn handle;\n}\n\n// --- Main Factory ---\n\nexport function createTableControls(\n\tcontainer: HTMLElement,\n\ttableEl: HTMLTableElement,\n\tinitialNode: BlockNode,\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n): TableControlsHandle {\n\tlet tableId: BlockId = initialNode.id;\n\tlet numRows: number = countRows(initialNode);\n\tlet numCols: number = countCols(initialNode);\n\n\t// --- Create DOM elements ---\n\n\tconst colBar: HTMLDivElement = buildHandleBar('ntbl-col-bar');\n\tconst rowBar: HTMLDivElement = buildHandleBar('ntbl-row-bar');\n\tconst insertLineH: HTMLDivElement = buildInsertLine('horizontal');\n\tconst insertLineV: HTMLDivElement = buildInsertLine('vertical');\n\tconst addRowZone: HTMLDivElement = buildAddButton('ntbl-add-row', 'Add row');\n\tconst addColZone: HTMLDivElement = buildAddButton('ntbl-add-col', 'Add column');\n\n\t// --- Insert line state ---\n\n\tlet activeRowIndex = -1;\n\tlet activeColIndex = -1;\n\n\t// --- Append to container ---\n\n\tcontainer.append(colBar, rowBar, insertLineH, insertLineV, addRowZone, addColZone);\n\n\t// --- Build handles ---\n\n\trebuildColHandles();\n\trebuildRowHandles();\n\n\t// --- Event handlers ---\n\n\tconst insertBtnH: HTMLButtonElement = insertLineH.querySelector(\n\t\t'.ntbl-insert-btn',\n\t) as HTMLButtonElement;\n\tconst insertBtnV: HTMLButtonElement = insertLineV.querySelector(\n\t\t'.ntbl-insert-btn',\n\t) as HTMLButtonElement;\n\n\tinsertBtnH.addEventListener('click', () => {\n\t\tif (activeRowIndex >= 0) {\n\t\t\tinsertRowAtIndex(getState, dispatch, tableId, activeRowIndex);\n\t\t}\n\t});\n\n\tinsertBtnV.addEventListener('click', () => {\n\t\tif (activeColIndex >= 0) {\n\t\t\tinsertColumnAtIndex(getState, dispatch, tableId, activeColIndex);\n\t\t}\n\t});\n\n\taddRowZone.addEventListener('click', () => {\n\t\tinsertRowAtIndex(getState, dispatch, tableId, numRows);\n\t});\n\n\taddColZone.addEventListener('click', () => {\n\t\tinsertColumnAtIndex(getState, dispatch, tableId, numCols);\n\t});\n\n\tcontainer.addEventListener('mousemove', onMouseMove);\n\tcontainer.addEventListener('mouseleave', onMouseLeave);\n\n\t// --- Positioning ---\n\n\tconst observer: ResizeObserver = new ResizeObserver(() => {\n\t\tpositionControls();\n\t});\n\tobserver.observe(tableEl);\n\trequestAnimationFrame(() => positionControls());\n\n\t// --- Functions ---\n\n\tfunction countRows(node: BlockNode): number {\n\t\treturn getBlockChildren(node).length;\n\t}\n\n\tfunction countCols(node: BlockNode): number {\n\t\tconst rows: readonly BlockNode[] = getBlockChildren(node);\n\t\treturn rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t}\n\n\t/** Returns the table's offset relative to the container (walks offsetParent chain). */\n\tfunction getTableOffset(): { top: number; left: number } {\n\t\tlet top = 0;\n\t\tlet left = 0;\n\t\tlet el: HTMLElement | null = tableEl;\n\t\twhile (el && el !== container) {\n\t\t\ttop += el.offsetTop;\n\t\t\tleft += el.offsetLeft;\n\t\t\tel = el.offsetParent as HTMLElement | null;\n\t\t}\n\t\treturn { top, left };\n\t}\n\n\tfunction measureRowBorders(): BorderInfo[] {\n\t\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\t\tconst tableTop: number = tableEl.offsetTop;\n\t\tconst borders: BorderInfo[] = [];\n\n\t\tfor (let i = 1; i < trs.length; i++) {\n\t\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\t\tif (!tr) continue;\n\t\t\tborders.push({\n\t\t\t\tposition: tr.offsetTop - tableTop,\n\t\t\t\tindex: i,\n\t\t\t});\n\t\t}\n\n\t\treturn borders;\n\t}\n\n\tfunction measureColBorders(): BorderInfo[] {\n\t\tif (numCols <= 1) return [];\n\t\tconst tableWidth: number = tableEl.offsetWidth;\n\t\tconst colWidth: number = tableWidth / numCols;\n\t\tconst borders: BorderInfo[] = [];\n\n\t\tfor (let i = 1; i < numCols; i++) {\n\t\t\tborders.push({\n\t\t\t\tposition: Math.round(colWidth * i),\n\t\t\t\tindex: i,\n\t\t\t});\n\t\t}\n\n\t\treturn borders;\n\t}\n\n\tfunction positionControls(): void {\n\t\tpositionColHandles();\n\t\tpositionRowHandles();\n\t\tpositionAddButtons();\n\t}\n\n\tfunction positionColHandles(): void {\n\t\tconst handles: HTMLCollection = colBar.children;\n\t\tif (handles.length === 0) return;\n\n\t\tconst tableWidth: number = tableEl.offsetWidth;\n\t\tconst colWidth: number = tableWidth / numCols;\n\n\t\tfor (let i = 0; i < handles.length; i++) {\n\t\t\tconst h = handles[i] as HTMLElement;\n\t\t\th.style.left = `${Math.round(colWidth * i)}px`;\n\t\t\th.style.width = `${Math.round(colWidth)}px`;\n\t\t}\n\n\t\tcolBar.style.width = `${tableWidth}px`;\n\t}\n\n\tfunction positionRowHandles(): void {\n\t\tconst handles: HTMLCollection = rowBar.children;\n\t\tif (handles.length === 0) return;\n\n\t\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\n\t\tconst tableTop: number = tableEl.offsetTop;\n\t\tlet totalHeight = 0;\n\n\t\tfor (let i = 0; i < handles.length; i++) {\n\t\t\tconst h = handles[i] as HTMLElement;\n\t\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\t\tif (tr) {\n\t\t\t\tconst top: number = tr.offsetTop - tableTop;\n\t\t\t\tconst height: number = tr.offsetHeight;\n\t\t\t\th.style.top = `${top}px`;\n\t\t\t\th.style.height = `${height}px`;\n\t\t\t\ttotalHeight = top + height;\n\t\t\t}\n\t\t}\n\n\t\trowBar.style.height = `${totalHeight}px`;\n\t}\n\n\tfunction positionAddButtons(): void {\n\t\tconst offset = getTableOffset();\n\t\tconst tableHeight: number = tableEl.offsetHeight;\n\t\tconst tableWidth: number = tableEl.offsetWidth;\n\n\t\taddRowZone.style.width = `${tableWidth}px`;\n\t\taddRowZone.style.left = `${offset.left}px`;\n\n\t\taddColZone.style.height = `${tableHeight}px`;\n\t\taddColZone.style.top = `${offset.top}px`;\n\t}\n\n\tfunction onMouseMove(e: MouseEvent): void {\n\t\tconst tableRect: DOMRect = tableEl.getBoundingClientRect();\n\t\tconst x: number = e.clientX - tableRect.left;\n\t\tconst y: number = e.clientY - tableRect.top;\n\n\t\t// Check if mouse is inside table bounds (with margin)\n\t\tconst inTable: boolean =\n\t\t\tx >= -BORDER_THRESHOLD &&\n\t\t\tx <= tableRect.width + BORDER_THRESHOLD &&\n\t\t\ty >= -BORDER_THRESHOLD &&\n\t\t\ty <= tableRect.height + BORDER_THRESHOLD;\n\n\t\tif (!inTable) {\n\t\t\thideInsertLines();\n\t\t\treturn;\n\t\t}\n\n\t\t// Find nearest row border\n\t\tconst rowBorders: BorderInfo[] = measureRowBorders();\n\t\tlet nearestRowDist: number = Number.POSITIVE_INFINITY;\n\t\tlet nearestRowBorder: BorderInfo | null = null;\n\n\t\tfor (const border of rowBorders) {\n\t\t\tconst dist: number = Math.abs(y - border.position);\n\t\t\tif (dist < nearestRowDist && dist < BORDER_THRESHOLD) {\n\t\t\t\tnearestRowDist = dist;\n\t\t\t\tnearestRowBorder = border;\n\t\t\t}\n\t\t}\n\n\t\t// Find nearest column border\n\t\tconst colBorders: BorderInfo[] = measureColBorders();\n\t\tlet nearestColDist: number = Number.POSITIVE_INFINITY;\n\t\tlet nearestColBorder: BorderInfo | null = null;\n\n\t\tfor (const border of colBorders) {\n\t\t\tconst dist: number = Math.abs(x - border.position);\n\t\t\tif (dist < nearestColDist && dist < BORDER_THRESHOLD) {\n\t\t\t\tnearestColDist = dist;\n\t\t\t\tnearestColBorder = border;\n\t\t\t}\n\t\t}\n\n\t\t// Show the nearest line (prefer the closer one)\n\t\tif (nearestRowBorder && (!nearestColBorder || nearestRowDist <= nearestColDist)) {\n\t\t\tshowHorizontalLine(nearestRowBorder);\n\t\t\thideVerticalLine();\n\t\t} else if (nearestColBorder) {\n\t\t\tshowVerticalLine(nearestColBorder);\n\t\t\thideHorizontalLine();\n\t\t} else {\n\t\t\thideInsertLines();\n\t\t}\n\t}\n\n\tfunction onMouseLeave(): void {\n\t\thideInsertLines();\n\t}\n\n\tfunction showHorizontalLine(border: BorderInfo): void {\n\t\tactiveRowIndex = border.index;\n\t\tconst offset = getTableOffset();\n\t\tinsertLineH.style.top = `${offset.top + border.position - 1}px`;\n\t\tinsertLineH.style.left = `${offset.left}px`;\n\t\tinsertLineH.style.width = `${tableEl.offsetWidth}px`;\n\t\tinsertLineH.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tfunction showVerticalLine(border: BorderInfo): void {\n\t\tactiveColIndex = border.index;\n\t\tconst offset = getTableOffset();\n\t\tinsertLineV.style.left = `${offset.left + border.position - 1}px`;\n\t\tinsertLineV.style.top = `${offset.top}px`;\n\t\tinsertLineV.style.height = `${tableEl.offsetHeight}px`;\n\t\tinsertLineV.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tfunction hideInsertLines(): void {\n\t\thideHorizontalLine();\n\t\thideVerticalLine();\n\t}\n\n\tfunction hideHorizontalLine(): void {\n\t\tinsertLineH.classList.remove('ntbl-insert-line--visible');\n\t\tactiveRowIndex = -1;\n\t}\n\n\tfunction hideVerticalLine(): void {\n\t\tinsertLineV.classList.remove('ntbl-insert-line--visible');\n\t\tactiveColIndex = -1;\n\t}\n\n\tfunction rebuildColHandles(): void {\n\t\tcolBar.innerHTML = '';\n\t\tfor (let i = 0; i < numCols; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle('ntbl-col-handle', i, (idx: number) => {\n\t\t\t\tdeleteColumnAtIndex(getState, dispatch, tableId, idx);\n\t\t\t});\n\t\t\tcolBar.appendChild(handle);\n\t\t}\n\t}\n\n\tfunction rebuildRowHandles(): void {\n\t\trowBar.innerHTML = '';\n\t\tfor (let i = 0; i < numRows; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle('ntbl-row-handle', i, (idx: number) => {\n\t\t\t\tdeleteRowAtIndex(getState, dispatch, tableId, idx);\n\t\t\t});\n\t\t\trowBar.appendChild(handle);\n\t\t}\n\t}\n\n\t// --- Public API ---\n\n\treturn {\n\t\tupdate(node: BlockNode): void {\n\t\t\ttableId = node.id;\n\t\t\tconst newRows: number = countRows(node);\n\t\t\tconst newCols: number = countCols(node);\n\n\t\t\tif (newRows !== numRows || newCols !== numCols) {\n\t\t\t\tnumRows = newRows;\n\t\t\t\tnumCols = newCols;\n\t\t\t\trebuildColHandles();\n\t\t\t\trebuildRowHandles();\n\t\t\t}\n\n\t\t\trequestAnimationFrame(() => positionControls());\n\t\t},\n\n\t\tdestroy(): void {\n\t\t\tobserver.disconnect();\n\t\t\tcontainer.removeEventListener('mousemove', onMouseMove);\n\t\t\tcontainer.removeEventListener('mouseleave', onMouseLeave);\n\t\t\tcolBar.remove();\n\t\t\trowBar.remove();\n\t\t\tinsertLineH.remove();\n\t\t\tinsertLineV.remove();\n\t\t\taddRowZone.remove();\n\t\t\taddColZone.remove();\n\t\t},\n\t};\n}\n","/**\n * NodeViewFactories for table, table_row, and table_cell.\n * Provides custom DOM rendering with proper HTML table elements and ARIA.\n * The table NodeView includes interactive controls for row/column management.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport type { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { NodeView, NodeViewFactory } from '../../view/NodeView.js';\nimport { renderBlockContent } from '../../view/Reconciler.js';\nimport { type TableControlsHandle, createTableControls } from './TableControls.js';\n\n/**\n * Creates a NodeViewFactory for the table node type.\n * Renders as outer container with controls + table + tbody.\n */\nexport function createTableNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\tgetState: () => EditorState,\n\t\tdispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\t// Outer container: holds controls + wrapper\n\t\tconst container: HTMLDivElement = document.createElement('div');\n\t\tcontainer.className = 'ntbl-container';\n\t\tcontainer.setAttribute('data-block-id', node.id);\n\n\t\t// Table wrapper: provides overflow scrolling\n\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\twrapper.className = 'notectl-table-wrapper';\n\n\t\tconst table: HTMLTableElement = document.createElement('table');\n\t\ttable.className = 'notectl-table';\n\t\ttable.setAttribute('role', 'table');\n\n\t\tconst rows: readonly BlockNode[] = getBlockChildren(node);\n\t\tconst totalRows: number = rows.length;\n\t\tconst totalCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t\ttable.setAttribute('aria-label', `Table with ${totalRows} rows and ${totalCols} columns`);\n\n\t\tconst tbody: HTMLTableSectionElement = document.createElement('tbody');\n\t\ttable.appendChild(tbody);\n\t\twrapper.appendChild(table);\n\t\tcontainer.appendChild(wrapper);\n\n\t\t// Live region for screen reader announcements\n\t\tconst liveRegion: HTMLDivElement = document.createElement('div');\n\t\tliveRegion.className = 'notectl-sr-only';\n\t\tliveRegion.setAttribute('aria-live', 'polite');\n\t\tliveRegion.setAttribute('aria-atomic', 'true');\n\t\tcontainer.appendChild(liveRegion);\n\n\t\t// Initialize interactive controls\n\t\tconst controls: TableControlsHandle = createTableControls(\n\t\t\tcontainer,\n\t\t\ttable,\n\t\t\tnode,\n\t\t\tgetState,\n\t\t\tdispatch,\n\t\t);\n\n\t\treturn {\n\t\t\tdom: container,\n\t\t\tcontentDOM: tbody,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table') return false;\n\t\t\t\tcontainer.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\tconst updatedRows: readonly BlockNode[] = getBlockChildren(updatedNode);\n\t\t\t\tconst newTotalRows: number = updatedRows.length;\n\t\t\t\tconst newTotalCols: number = updatedRows[0] ? getBlockChildren(updatedRows[0]).length : 0;\n\t\t\t\ttable.setAttribute(\n\t\t\t\t\t'aria-label',\n\t\t\t\t\t`Table with ${newTotalRows} rows and ${newTotalCols} columns`,\n\t\t\t\t);\n\n\t\t\t\t// Update controls to reflect new structure\n\t\t\t\tcontrols.update(updatedNode);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\tcontrols.destroy();\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_row node type.\n * Renders as `<tr role=\"row\">`.\n */\nexport function createTableRowNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\ttr.setAttribute('data-block-id', node.id);\n\t\ttr.setAttribute('role', 'row');\n\n\t\treturn {\n\t\t\tdom: tr,\n\t\t\tcontentDOM: tr,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_row') return false;\n\t\t\t\ttr.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_cell node type.\n * Renders as `<td role=\"cell\">` with text content rendered inside.\n */\nexport function createTableCellNodeViewFactory(registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\ttd.setAttribute('data-block-id', node.id);\n\t\ttd.setAttribute('role', 'cell');\n\n\t\tconst colspan: number = (node.attrs?.colspan as number | undefined) ?? 1;\n\t\tconst rowspan: number = (node.attrs?.rowspan as number | undefined) ?? 1;\n\t\tif (colspan > 1) td.colSpan = colspan;\n\t\tif (rowspan > 1) td.rowSpan = rowspan;\n\n\t\t// Render text content\n\t\trenderBlockContent(td, node, registry);\n\n\t\treturn {\n\t\t\tdom: td,\n\t\t\tcontentDOM: td,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_cell') return false;\n\t\t\t\ttd.setAttribute('data-block-id', updatedNode.id);\n\n\t\t\t\tconst newColspan: number = (updatedNode.attrs?.colspan as number | undefined) ?? 1;\n\t\t\t\tconst newRowspan: number = (updatedNode.attrs?.rowspan as number | undefined) ?? 1;\n\t\t\t\tif (newColspan > 1) {\n\t\t\t\t\ttd.colSpan = newColspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('colspan');\n\t\t\t\t}\n\t\t\t\tif (newRowspan > 1) {\n\t\t\t\t\ttd.rowSpan = newRowspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('rowspan');\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n","/**\n * Multi-cell selection service for tables.\n * Tracks selected cell range and provides IDs for bulk formatting.\n */\n\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { ServiceKey } from '../Plugin.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { findTableContext, getCellAt } from './TableHelpers.js';\n\n/** Rectangular range of cells within a table. */\nexport interface CellRange {\n\treadonly tableId: BlockId;\n\treadonly fromRow: number;\n\treadonly fromCol: number;\n\treadonly toRow: number;\n\treadonly toCol: number;\n}\n\n/** Service for managing multi-cell selection. */\nexport interface TableSelectionService {\n\tgetSelectedRange(): CellRange | null;\n\tsetSelectedRange(range: CellRange | null): void;\n\tgetSelectedCellIds(): readonly BlockId[];\n\tisSelected(cellId: BlockId): boolean;\n}\n\nexport const TableSelectionServiceKey = new ServiceKey<TableSelectionService>('tableSelection');\n\n/** Creates and registers the TableSelectionService. */\nexport function createTableSelectionService(context: PluginContext): TableSelectionService {\n\tlet selectedRange: CellRange | null = null;\n\tlet cachedCellIds: readonly BlockId[] = [];\n\tlet cachedCellIdSet: Set<BlockId> = new Set();\n\n\tfunction updateCache(): void {\n\t\tif (!selectedRange) {\n\t\t\tcachedCellIds = [];\n\t\t\tcachedCellIdSet = new Set();\n\t\t\treturn;\n\t\t}\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst ids: BlockId[] = [];\n\n\t\tconst minRow: number = Math.min(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst maxRow: number = Math.max(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst minCol: number = Math.min(selectedRange.fromCol, selectedRange.toCol);\n\t\tconst maxCol: number = Math.max(selectedRange.fromCol, selectedRange.toCol);\n\n\t\tfor (let r = minRow; r <= maxRow; r++) {\n\t\t\tfor (let c = minCol; c <= maxCol; c++) {\n\t\t\t\tconst cellId: BlockId | null = getCellAt(state, selectedRange.tableId, r, c);\n\t\t\t\tif (cellId) ids.push(cellId);\n\t\t\t}\n\t\t}\n\n\t\tcachedCellIds = ids;\n\t\tcachedCellIdSet = new Set(ids);\n\t}\n\n\tconst service: TableSelectionService = {\n\t\tgetSelectedRange(): CellRange | null {\n\t\t\treturn selectedRange;\n\t\t},\n\n\t\tsetSelectedRange(range: CellRange | null): void {\n\t\t\tselectedRange = range;\n\t\t\tupdateCache();\n\t\t\tupdateCellHighlights(context, cachedCellIdSet);\n\t\t},\n\n\t\tgetSelectedCellIds(): readonly BlockId[] {\n\t\t\treturn cachedCellIds;\n\t\t},\n\n\t\tisSelected(cellId: BlockId): boolean {\n\t\t\treturn cachedCellIdSet.has(cellId);\n\t\t},\n\t};\n\n\tcontext.registerService(TableSelectionServiceKey, service);\n\treturn service;\n}\n\n/** Updates CSS class on selected cells for visual highlighting. */\nfunction updateCellHighlights(context: PluginContext, selectedIds: Set<BlockId>): void {\n\tconst container: HTMLElement = context.getContainer();\n\tconst cells: NodeListOf<Element> = container.querySelectorAll('td[data-block-id]');\n\n\tfor (const cell of cells) {\n\t\tconst cellId = cell.getAttribute('data-block-id') as BlockId;\n\t\tif (selectedIds.has(cellId)) {\n\t\t\tcell.classList.add('notectl-table-cell--selected');\n\t\t} else {\n\t\t\tcell.classList.remove('notectl-table-cell--selected');\n\t\t}\n\t}\n}\n\n/**\n * Installs mouse handlers for multi-cell selection on the editor container.\n * Returns a cleanup function.\n */\nexport function installMouseSelection(\n\tcontext: PluginContext,\n\tservice: TableSelectionService,\n): () => void {\n\tconst container: HTMLElement = context.getContainer();\n\tlet anchorCell: { tableId: BlockId; row: number; col: number } | null = null;\n\tlet isDragging = false;\n\n\tfunction handleMouseDown(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) {\n\t\t\tservice.setSelectedRange(null);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!e.shiftKey) {\n\t\t\t// Clear any existing multi-cell selection before starting a new anchor\n\t\t\tservice.setSelectedRange(null);\n\t\t\t// Start new selection anchor\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx) return;\n\n\t\t\tanchorCell = {\n\t\t\t\ttableId: tableCtx.tableId,\n\t\t\t\trow: tableCtx.rowIndex,\n\t\t\t\tcol: tableCtx.colIndex,\n\t\t\t};\n\t\t\tisDragging = true;\n\t\t\t// Don't set range yet — wait for mousemove to avoid interfering with clicks\n\t\t} else if (anchorCell) {\n\t\t\t// Shift-click: extend selection\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseMove(e: MouseEvent): void {\n\t\tif (!isDragging || !anchorCell) return;\n\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) return;\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\tconst tableCtx = findTableContext(state, cellId);\n\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t// Only set range if we've moved to a different cell\n\t\tif (tableCtx.rowIndex !== anchorCell.row || tableCtx.colIndex !== anchorCell.col) {\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseUp(): void {\n\t\tisDragging = false;\n\t}\n\n\tcontainer.addEventListener('mousedown', handleMouseDown);\n\tcontainer.addEventListener('mousemove', handleMouseMove);\n\tdocument.addEventListener('mouseup', handleMouseUp);\n\n\treturn () => {\n\t\tcontainer.removeEventListener('mousedown', handleMouseDown);\n\t\tcontainer.removeEventListener('mousemove', handleMouseMove);\n\t\tdocument.removeEventListener('mouseup', handleMouseUp);\n\t};\n}\n","/**\n * TablePlugin: registers table, table_row, and table_cell node types\n * with NodeSpecs, NodeViews, commands, keyboard navigation, toolbar\n * grid picker, multi-cell selection, and context menu.\n */\n\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { insertTable, registerTableCommands } from './TableCommands.js';\nimport { isInsideTable } from './TableHelpers.js';\nimport { registerTableKeymaps } from './TableNavigation.js';\nimport {\n\tcreateTableCellNodeViewFactory,\n\tcreateTableNodeViewFactory,\n\tcreateTableRowNodeViewFactory,\n} from './TableNodeViews.js';\nimport {\n\ttype TableSelectionService,\n\tcreateTableSelectionService,\n\tinstallMouseSelection,\n} from './TableSelection.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\ttable: Record<string, never>;\n\t\ttable_row: Record<string, never>;\n\t\ttable_cell: { colspan?: number; rowspan?: number };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface TableConfig {\n\t/** Maximum rows in grid picker. Defaults to 8. */\n\treadonly maxPickerRows?: number;\n\t/** Maximum columns in grid picker. Defaults to 8. */\n\treadonly maxPickerCols?: number;\n\t/** When true, a separator is rendered after the table toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: TableConfig = {\n\tmaxPickerRows: 8,\n\tmaxPickerCols: 8,\n};\n\n// --- SVG Icon ---\n\nconst TABLE_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">' +\n\t'<path d=\"M3 3h18v18H3V3zm2 2v4h6V5H5zm8 0v4h6V5h-6zm-8 6v4h6v-4H5z' +\n\t'm8 0v4h6v-4h-6zm-8 6v4h6v-4H5zm8 0v4h6v-4h-6z\"/></svg>';\n\n// --- Plugin ---\n\nexport class TablePlugin implements Plugin {\n\treadonly id = 'table';\n\treadonly name = 'Table';\n\treadonly priority = 40;\n\n\tprivate readonly config: TableConfig;\n\tprivate selectionService: TableSelectionService | null = null;\n\tprivate cleanupMouseSelection: (() => void) | null = null;\n\tprivate context: PluginContext | null = null;\n\n\tconstructor(config?: Partial<TableConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\n\n\t\tthis.registerNodeSpecs(context);\n\t\tthis.registerNodeViews(context);\n\t\tregisterTableCommands(context);\n\t\tregisterTableKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.selectionService = createTableSelectionService(context);\n\t}\n\n\tonReady(): void {\n\t\tif (this.context && this.selectionService) {\n\t\t\tthis.cleanupMouseSelection = installMouseSelection(this.context, this.selectionService);\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.cleanupMouseSelection?.();\n\t\tthis.cleanupMouseSelection = null;\n\t\tthis.selectionService = null;\n\t\tthis.context = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\t// Clear multi-cell selection when cursor moves outside table\n\t\tif (this.selectionService?.getSelectedRange()) {\n\t\t\tconst sel = newState.selection;\n\t\t\tif (!isInsideTable(newState, sel.anchor.blockId)) {\n\t\t\t\tthis.selectionService.setSelectedRange(null);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate registerNodeSpecs(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['table_row'], min: 1 },\n\t\t\tisolating: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\t\t\twrapper.className = 'notectl-table-wrapper';\n\t\t\t\twrapper.setAttribute('data-block-id', node.id);\n\t\t\t\treturn wrapper;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_row',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: { allow: ['table_cell'], min: 1 },\n\t\t\ttoDOM(node) {\n\t\t\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\t\t\ttr.setAttribute('data-block-id', node.id);\n\t\t\t\ttr.setAttribute('role', 'row');\n\t\t\t\treturn tr;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_cell',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\tisolating: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\t\t\ttd.setAttribute('data-block-id', node.id);\n\t\t\t\ttd.setAttribute('role', 'cell');\n\t\t\t\treturn td;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerNodeViews(context: PluginContext): void {\n\t\tconst registry = context.getSchemaRegistry();\n\n\t\tcontext.registerNodeView('table', createTableNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_row', createTableRowNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_cell', createTableCellNodeViewFactory(registry));\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst maxRows: number = this.config.maxPickerRows ?? 8;\n\t\tconst maxCols: number = this.config.maxPickerCols ?? 8;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'table',\n\t\t\tgroup: 'insert',\n\t\t\ticon: TABLE_ICON,\n\t\t\tlabel: 'Insert Table',\n\t\t\ttooltip: 'Insert Table',\n\t\t\tcommand: 'insertTable',\n\t\t\tpriority: 80,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tpopupType: 'gridPicker',\n\t\t\tpopupConfig: {\n\t\t\t\tmaxRows,\n\t\t\t\tmaxCols,\n\t\t\t\tonSelect: (rows: number, cols: number) => {\n\t\t\t\t\tinsertTable(context, rows, cols);\n\t\t\t\t},\n\t\t\t},\n\t\t\tisActive: (state: EditorState) => {\n\t\t\t\treturn isInsideTable(state, state.selection.anchor.blockId);\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * HighlightPlugin: registers a highlight (background-color) mark with attrs,\n * toolbar button with a color picker popup, and removeHighlight command.\n */\n\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, hasMark } from '../../model/Document.js';\nimport { isCollapsed, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\thighlight: { color: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface HighlightConfig {\n\t/**\n\t * Restricts the color picker to a specific set of hex colors.\n\t * Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).\n\t * Duplicates are removed automatically (case-insensitive).\n\t * When omitted, the full default palette is shown.\n\t */\n\treadonly colors?: readonly string[];\n\t/** When true, a separator is rendered after the highlight toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: HighlightConfig = {};\n\n// --- Color Validation ---\n\nconst HEX_COLOR_PATTERN: RegExp = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\nfunction isValidHexColor(value: string): boolean {\n\treturn HEX_COLOR_PATTERN.test(value);\n}\n\n/**\n * Validates, deduplicates, and normalizes the user-supplied color list.\n * Returns the default palette when no custom colors are provided.\n *\n * @throws {Error} if any value is not a valid hex color code.\n */\nfunction resolveColors(colors: readonly string[] | undefined): readonly string[] {\n\tif (!colors || colors.length === 0) return HIGHLIGHT_PALETTE;\n\n\tconst invalid: string[] = colors.filter((c) => !isValidHexColor(c));\n\tif (invalid.length > 0) {\n\t\tthrow new Error(\n\t\t\t`HighlightPlugin: invalid hex color(s): ${invalid.join(', ')}. Expected format: #RGB or #RRGGBB.`,\n\t\t);\n\t}\n\n\tconst seen: Set<string> = new Set();\n\tconst unique: string[] = [];\n\tfor (const color of colors) {\n\t\tconst normalized: string = color.toLowerCase();\n\t\tif (!seen.has(normalized)) {\n\t\t\tseen.add(normalized);\n\t\t\tunique.push(normalized);\n\t\t}\n\t}\n\treturn unique;\n}\n\n// --- Color Palette (Highlight-optimized: 10 columns x 5 rows) ---\n\nconst HIGHLIGHT_PALETTE: readonly string[] = [\n\t// Row 1 — Classic highlighter colors (bright, vivid)\n\t'#fff176',\n\t'#aed581',\n\t'#4dd0e1',\n\t'#64b5f6',\n\t'#ce93d8',\n\t'#f48fb1',\n\t'#ffab91',\n\t'#ff8a65',\n\t'#e6ee9c',\n\t'#80cbc4',\n\n\t// Row 2 — Light pastels\n\t'#fff9c4',\n\t'#dcedc8',\n\t'#e0f7fa',\n\t'#e3f2fd',\n\t'#f3e5f5',\n\t'#fce4ec',\n\t'#fff3e0',\n\t'#fbe9e7',\n\t'#f9fbe7',\n\t'#e0f2f1',\n\n\t// Row 3 — Medium pastels\n\t'#fff59d',\n\t'#c5e1a5',\n\t'#80deea',\n\t'#90caf9',\n\t'#e1bee7',\n\t'#f8bbd0',\n\t'#ffcc80',\n\t'#ffab91',\n\t'#e6ee9c',\n\t'#a5d6a7',\n\n\t// Row 4 — Bold pastels\n\t'#ffee58',\n\t'#9ccc65',\n\t'#26c6da',\n\t'#42a5f5',\n\t'#ab47bc',\n\t'#ec407a',\n\t'#ffa726',\n\t'#ff7043',\n\t'#d4e157',\n\t'#66bb6a',\n\n\t// Row 5 — Grays and neutral highlights\n\t'#ffffff',\n\t'#fafafa',\n\t'#f5f5f5',\n\t'#eeeeee',\n\t'#e0e0e0',\n\t'#bdbdbd',\n\t'#e8eaf6',\n\t'#efebe9',\n\t'#eceff1',\n\t'#fafafa',\n];\n\n// --- Plugin ---\n\nexport class HighlightPlugin implements Plugin {\n\treadonly id = 'highlight';\n\treadonly name = 'Highlight';\n\treadonly priority = 24;\n\n\tprivate readonly config: HighlightConfig;\n\tprivate readonly colors: readonly string[];\n\n\tconstructor(config?: Partial<HighlightConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t\tthis.colors = resolveColors(config?.colors);\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'highlight',\n\t\t\trank: 4,\n\t\t\tattrs: {\n\t\t\t\tcolor: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span = document.createElement('span');\n\t\t\t\tconst color = mark.attrs?.color ?? '';\n\t\t\t\tspan.style.backgroundColor = color;\n\t\t\t\treturn span;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeHighlight', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeHighlight(context, state);\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst pathD =\n\t\t\t'M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2z' + 'm-1.38 9L12 5.67 14.38 12H9.62z';\n\t\tconst icon: string = [\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t' viewBox=\"0 0 24 24\">',\n\t\t\t`<path d=\"${pathD}\"/>`,\n\t\t\t'<rect x=\"3\" y=\"17\" width=\"18\" height=\"6\"',\n\t\t\t' rx=\"0.5\" fill=\"#fff176\"/>',\n\t\t\t'</svg>',\n\t\t].join('');\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'highlight',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Highlight',\n\t\t\ttooltip: 'Highlight Color',\n\t\t\tcommand: 'removeHighlight',\n\t\t\tpriority: 46,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderHighlightPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isHighlightActive(state),\n\t\t});\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isHighlightActive(state: EditorState): boolean {\n\t\treturn this.getActiveColor(state) !== null;\n\t}\n\n\tprivate getActiveColor(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tif (state.storedMarks) {\n\t\t\t\tconst mark = state.storedMarks.find((m) => m.type === 'highlight');\n\t\t\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t\t\t}\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return null;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\tconst mark = marks.find((m) => m.type === 'highlight');\n\t\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t\t}\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\tconst mark = marks.find((m) => m.type === 'highlight');\n\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t}\n\n\t// --- Highlight Application ---\n\n\tprivate applyHighlight(context: PluginContext, state: EditorState, color: string): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tconst withoutHighlight = currentMarks.filter((m) => m.type !== 'highlight');\n\t\t\tconst newMarks = [...withoutHighlight, { type: markType('highlight'), attrs: { color } }];\n\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\tconst mark = { type: markType('highlight'), attrs: { color } };\n\n\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, {\n\t\t\t\t\ttype: markType('highlight'),\n\t\t\t\t});\n\t\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeHighlight(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tif (!hasMark(currentMarks, markType('highlight'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'highlight');\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockOrder = state.getBlockOrder();\n\t\tconst range = selectionRange(sel, blockOrder);\n\t\tconst builder = state.transaction('command');\n\n\t\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\t\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\t\tfor (let i = fromIdx; i <= toIdx; i++) {\n\t\t\tconst blockId = blockOrder[i];\n\t\t\tif (!blockId) continue;\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (!block) continue;\n\t\t\tconst blockLen = block.children.reduce(\n\t\t\t\t(sum, c) => sum + ('text' in c ? c.text.length : 0),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tconst from = i === fromIdx ? range.from.offset : 0;\n\t\t\tconst to = i === toIdx ? range.to.offset : blockLen;\n\n\t\t\tif (from !== to) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, {\n\t\t\t\t\ttype: markType('highlight'),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate renderHighlightPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-color-picker');\n\n\t\tconst state = context.getState();\n\t\tconst activeColor = this.getActiveColor(state);\n\n\t\tconst defaultBtn = document.createElement('button');\n\t\tdefaultBtn.type = 'button';\n\t\tdefaultBtn.className = 'notectl-color-picker__default';\n\t\tdefaultBtn.textContent = 'None';\n\t\tdefaultBtn.addEventListener('mousedown', (e) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tcontext.executeCommand('removeHighlight');\n\t\t});\n\t\tcontainer.appendChild(defaultBtn);\n\n\t\tconst grid = document.createElement('div');\n\t\tgrid.className = 'notectl-color-picker__grid';\n\n\t\tfor (const color of this.colors) {\n\t\t\tconst swatch = document.createElement('button');\n\t\t\tswatch.type = 'button';\n\t\t\tswatch.className = 'notectl-color-picker__swatch';\n\t\t\tif (activeColor && activeColor.toLowerCase() === color.toLowerCase()) {\n\t\t\t\tswatch.classList.add('notectl-color-picker__swatch--active');\n\t\t\t}\n\t\t\tswatch.style.backgroundColor = color;\n\t\t\tif (color === '#ffffff') {\n\t\t\t\tswatch.style.border = '1px solid #d0d0d0';\n\t\t\t}\n\t\t\tswatch.title = color;\n\n\t\t\tswatch.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tthis.applyHighlight(context, context.getState(), color);\n\t\t\t});\n\n\t\t\tgrid.appendChild(swatch);\n\t\t}\n\n\t\tcontainer.appendChild(grid);\n\t}\n}\n","/**\n * SuperSubPlugin: registers superscript and subscript inline marks with\n * MarkSpecs, toggle commands, keyboard shortcuts, toolbar buttons, and\n * a middleware that enforces mutual exclusivity between the two marks.\n *\n * Data-driven — each mark type is defined declaratively and all\n * registrations are derived from the same definition table.\n */\n\nimport { isMarkActive, toggleMark } from '../../commands/Commands.js';\nimport type { Mark } from '../../model/Document.js';\nimport { markType as mkType } from '../../model/TypeBrands.js';\nimport type { RemoveMarkStep, Step } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tsuperscript: Record<string, never>;\n\t\tsubscript: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\n/** Controls toolbar button visibility per mark. */\nexport interface SuperSubToolbarConfig {\n\treadonly superscript?: boolean;\n\treadonly subscript?: boolean;\n}\n\n/** Controls which marks are enabled and which toolbar buttons are shown. */\nexport interface SuperSubConfig {\n\treadonly superscript: boolean;\n\treadonly subscript: boolean;\n\treadonly toolbar?: SuperSubToolbarConfig;\n\t/** When true, a separator is rendered after the last toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: SuperSubConfig = {\n\tsuperscript: true,\n\tsubscript: true,\n};\n\n// --- Mark Definitions ---\n\ninterface MarkDefinition {\n\treadonly type: 'superscript' | 'subscript';\n\treadonly opposite: 'superscript' | 'subscript';\n\treadonly configKey: keyof Omit<SuperSubConfig, 'toolbar' | 'separatorAfter'>;\n\treadonly rank: number;\n\treadonly tag: string;\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly keyBinding: string;\n\treadonly toolbarPriority: number;\n}\n\nconst SUPERSCRIPT_ICON: string = [\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">',\n\t'<path d=\"M16 7.41L11.41 12 16 16.59 14.59 18l-6-6 6-6z\"',\n\t' fill=\"none\"/>',\n\t'<path d=\"M9.64 7.64c.23-.5.36-1.05.36-1.64',\n\t' 0-2.21-1.79-4-4-4H2v14h4.36c2.34 0 4.24-1.9',\n\t' 4.24-4.24 0-1.6-.89-2.99-2.2-3.71zM4.5 4.5H6c.83',\n\t' 0 1.5.67 1.5 1.5S6.83 7.5 6 7.5H4.5v-3zm2 9H4.5v-3H6.5c.83',\n\t' 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z\" fill=\"none\"/>',\n\t'<path d=\"M15.97 3.84c0-.47.19-.91.53-1.21.34-.31.8-.49',\n\t' 1.3-.49.5 0 .95.18 1.28.48.32.3.5.7.51 1.15h1.59c-.02',\n\t'-.96-.43-1.83-1.13-2.42C19.36.77 18.45.44 17.5.44c-.88',\n\t' 0-1.74.28-2.39.8-.67.53-1.06 1.28-1.06 2.1 0 .76.34',\n\t' 1.47.93 1.97.59.49 1.41.84 2.32 1.15.7.24 1.26.5 1.62.8.35.3.53.64.53',\n\t' 1.02 0 .48-.2.93-.55 1.24-.36.3-.84.48-1.37.48-.55 0-1.04-.2-1.39-.54',\n\t'-.34-.33-.53-.8-.53-1.32h-1.58c.01 1.02.43 1.95 1.16 2.57.72.62 1.67.96',\n\t' 2.67.96.92 0 1.81-.3 2.46-.84.67-.56 1.04-1.33 1.04-2.18 0-.81-.36-1.56',\n\t'-.99-2.08-.62-.51-1.48-.88-2.43-1.2-.67-.23-1.2-.47-1.52-.75-.32-.27-.46',\n\t'-.59-.46-.94z\"/>',\n\t'<path d=\"M5.88 20h2.66l3.4-5.42L15.3 20h2.67l-4.73-7.38',\n\t' 4.37-6.62h-2.6l-3.07 4.98L8.92 6h-2.6l4.26 6.58z\"/>',\n\t'</svg>',\n].join('');\n\nconst SUBSCRIPT_ICON: string = [\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">',\n\t'<path d=\"M15.97 16.84c0-.47.19-.91.53-1.21.34-.31.8-.49',\n\t' 1.3-.49.5 0 .95.18 1.28.48.32.3.5.7.51 1.15h1.59c-.02',\n\t'-.96-.43-1.83-1.13-2.42-.7-.58-1.61-.91-2.56-.91-.88',\n\t' 0-1.74.28-2.39.8-.67.53-1.06 1.28-1.06 2.1 0 .76.34',\n\t' 1.47.93 1.97.59.49 1.41.84 2.32 1.15.7.24 1.26.5 1.62.8.35.3.53.64.53',\n\t' 1.02 0 .48-.2.93-.55 1.24-.36.3-.84.48-1.37.48-.55 0-1.04-.2-1.39-.54',\n\t'-.34-.33-.53-.8-.53-1.32h-1.58c.01 1.02.43 1.95 1.16 2.57.72.62 1.67.96',\n\t' 2.67.96.92 0 1.81-.3 2.46-.84.67-.56 1.04-1.33 1.04-2.18 0-.81-.36-1.56',\n\t'-.99-2.08-.62-.51-1.48-.88-2.43-1.2-.67-.23-1.2-.47-1.52-.75-.32-.27-.46',\n\t'-.59-.46-.94z\"/>',\n\t'<path d=\"M5.88 18h2.66l3.4-5.42L15.3 18h2.67l-4.73-7.38',\n\t' 4.37-6.62h-2.6l-3.07 4.98L8.92 4h-2.6l4.26 6.58z\"/>',\n\t'</svg>',\n].join('');\n\nconst MARK_DEFINITIONS: readonly MarkDefinition[] = [\n\t{\n\t\ttype: 'superscript',\n\t\topposite: 'subscript',\n\t\tconfigKey: 'superscript',\n\t\trank: 4,\n\t\ttag: 'sup',\n\t\tlabel: 'Superscript',\n\t\ticon: SUPERSCRIPT_ICON,\n\t\tkeyBinding: 'Mod-.',\n\t\ttoolbarPriority: 50,\n\t},\n\t{\n\t\ttype: 'subscript',\n\t\topposite: 'superscript',\n\t\tconfigKey: 'subscript',\n\t\trank: 4,\n\t\ttag: 'sub',\n\t\tlabel: 'Subscript',\n\t\ticon: SUBSCRIPT_ICON,\n\t\tkeyBinding: 'Mod-,',\n\t\ttoolbarPriority: 51,\n\t},\n];\n\n// --- Plugin ---\n\nexport class SuperSubPlugin implements Plugin {\n\treadonly id = 'super-sub';\n\treadonly name = 'Superscript & Subscript';\n\treadonly priority = 23;\n\n\tprivate readonly config: SuperSubConfig;\n\n\tconstructor(config?: Partial<SuperSubConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tconst enabledMarks: MarkDefinition[] = MARK_DEFINITIONS.filter(\n\t\t\t(def) => this.config[def.configKey],\n\t\t);\n\n\t\tconst visibleToolbarMarks: MarkDefinition[] = enabledMarks.filter((def) =>\n\t\t\tthis.isToolbarVisible(def.configKey),\n\t\t);\n\t\tconst lastVisibleMark: MarkDefinition | undefined = visibleToolbarMarks.at(-1);\n\n\t\tfor (const def of enabledMarks) {\n\t\t\tconst isSeparatorTarget: boolean = !!this.config.separatorAfter && def === lastVisibleMark;\n\t\t\tthis.registerMark(context, def, isSeparatorTarget);\n\t\t}\n\n\t\tthis.registerKeymaps(context, enabledMarks);\n\t\tthis.registerExclusivityMiddleware(context, enabledMarks);\n\t\tthis.registerDisabledToolbarItems(context);\n\t}\n\n\tprivate registerMark(context: PluginContext, def: MarkDefinition, separatorAfter: boolean): void {\n\t\tconst commandName: string = toCommandName(def.type);\n\t\tconst toolbarVisible: boolean = this.isToolbarVisible(def.configKey);\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: def.type,\n\t\t\trank: def.rank,\n\t\t\ttoDOM() {\n\t\t\t\treturn document.createElement(def.tag);\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerCommand(commandName, () => {\n\t\t\tconst tr = toggleMark(context.getState(), mkType(def.type));\n\t\t\tif (tr) {\n\t\t\t\tcontext.dispatch(tr);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\n\t\tif (toolbarVisible) {\n\t\t\tcontext.registerToolbarItem({\n\t\t\t\tid: def.type,\n\t\t\t\tgroup: 'format',\n\t\t\t\ticon: def.icon,\n\t\t\t\tlabel: def.label,\n\t\t\t\ttooltip: `${def.label} (${formatShortcut(def.keyBinding)})`,\n\t\t\t\tcommand: commandName,\n\t\t\t\tpriority: def.toolbarPriority,\n\t\t\t\tseparatorAfter,\n\t\t\t\tisActive: (state) => isMarkActive(state, mkType(def.type)),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerKeymaps(context: PluginContext, marks: readonly MarkDefinition[]): void {\n\t\tconst keymap: Record<string, () => boolean> = {};\n\t\tfor (const def of marks) {\n\t\t\tconst commandName: string = toCommandName(def.type);\n\t\t\tkeymap[def.keyBinding] = () => context.executeCommand(commandName);\n\t\t}\n\t\tif (Object.keys(keymap).length > 0) {\n\t\t\tcontext.registerKeymap(keymap);\n\t\t}\n\t}\n\n\t/**\n\t * Ensures superscript and subscript are mutually exclusive.\n\t * When an addMark step for one type is found, a removeMark step\n\t * for the opposite type is injected. For stored marks, the opposite\n\t * mark is filtered out.\n\t */\n\tprivate registerExclusivityMiddleware(\n\t\tcontext: PluginContext,\n\t\tenabledMarks: readonly MarkDefinition[],\n\t): void {\n\t\tconst bothEnabled: boolean =\n\t\t\tenabledMarks.some((d) => d.type === 'superscript') &&\n\t\t\tenabledMarks.some((d) => d.type === 'subscript');\n\n\t\tif (!bothEnabled) return;\n\n\t\tcontext.registerMiddleware((tr, _state, next) => {\n\t\t\tlet patched = false;\n\n\t\t\t// Handle addMark steps: inject removeMark for the opposite type\n\t\t\tconst patchedSteps: Step[] = [];\n\t\t\tfor (const step of tr.steps) {\n\t\t\t\tif (step.type !== 'addMark') {\n\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst markName: string = step.mark.type;\n\t\t\t\tconst def: MarkDefinition | undefined = MARK_DEFINITIONS.find((d) => d.type === markName);\n\t\t\t\tif (!def) {\n\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tpatched = true;\n\t\t\t\tconst removeStep: RemoveMarkStep = {\n\t\t\t\t\ttype: 'removeMark',\n\t\t\t\t\tblockId: step.blockId,\n\t\t\t\t\tfrom: step.from,\n\t\t\t\t\tto: step.to,\n\t\t\t\t\tmark: { type: mkType(def.opposite) },\n\t\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t\t};\n\t\t\t\tpatchedSteps.push(removeStep, step);\n\t\t\t}\n\n\t\t\t// Handle stored marks: remove the opposite mark\n\t\t\tlet storedMarksAfter: readonly Mark[] | null = tr.storedMarksAfter;\n\t\t\tif (storedMarksAfter) {\n\t\t\t\tconst hasSup: boolean = storedMarksAfter.some((m) => m.type === 'superscript');\n\t\t\t\tconst hasSub: boolean = storedMarksAfter.some((m) => m.type === 'subscript');\n\n\t\t\t\tif (hasSup && hasSub) {\n\t\t\t\t\t// Keep the one that was most recently added (last in array)\n\t\t\t\t\tconst lastSupIdx: number = storedMarksAfter.findLastIndex(\n\t\t\t\t\t\t(m) => m.type === 'superscript',\n\t\t\t\t\t);\n\t\t\t\t\tconst lastSubIdx: number = storedMarksAfter.findLastIndex((m) => m.type === 'subscript');\n\t\t\t\t\tconst removeType: string = lastSupIdx > lastSubIdx ? 'subscript' : 'superscript';\n\n\t\t\t\t\tstoredMarksAfter = storedMarksAfter.filter((m) => m.type !== removeType);\n\t\t\t\t\tpatched = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnext(patched ? { ...tr, steps: patchedSteps, storedMarksAfter } : tr);\n\t\t});\n\t}\n\n\t/**\n\t * Registers disabled toolbar buttons for marks whose feature is disabled\n\t * but whose toolbar button is explicitly requested.\n\t */\n\tprivate registerDisabledToolbarItems(context: PluginContext): void {\n\t\tif (!this.config.toolbar) return;\n\n\t\tfor (const def of MARK_DEFINITIONS) {\n\t\t\tconst featureEnabled: boolean = this.config[def.configKey];\n\t\t\tconst toolbarVisible: boolean = this.config.toolbar[def.configKey] ?? true;\n\n\t\t\tif (!featureEnabled && toolbarVisible) {\n\t\t\t\tcontext.registerToolbarItem({\n\t\t\t\t\tid: def.type,\n\t\t\t\t\tgroup: 'format',\n\t\t\t\t\ticon: def.icon,\n\t\t\t\t\tlabel: def.label,\n\t\t\t\t\tcommand: toCommandName(def.type),\n\t\t\t\t\tpriority: def.toolbarPriority,\n\t\t\t\t\tisEnabled: () => false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isToolbarVisible(\n\t\tconfigKey: keyof Omit<SuperSubConfig, 'toolbar' | 'separatorAfter'>,\n\t): boolean {\n\t\tif (!this.config.toolbar) return true;\n\t\treturn this.config.toolbar[configKey] ?? true;\n\t}\n}\n\n/** Converts a mark type to its toggle command name (e.g. 'superscript' → 'toggleSuperscript'). */\nfunction toCommandName(markType: string): string {\n\treturn `toggle${markType.charAt(0).toUpperCase()}${markType.slice(1)}`;\n}\n","/**\n * Input handler: intercepts all beforeinput events, maps them to transactions.\n * After text insertion, checks registered InputRules for pattern matches.\n */\n\nimport {\n\tdeleteBackward,\n\tdeleteForward,\n\tdeleteSoftLineBackward,\n\tdeleteSoftLineForward,\n\tdeleteWordBackward,\n\tdeleteWordForward,\n\tinsertTextCommand,\n\tsplitBlockCommand,\n} from '../commands/Commands.js';\nimport { getBlockText } from '../model/Document.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { Transaction } from '../state/Transaction.js';\n\nimport type { EditorState } from '../state/EditorState.js';\n\nexport type DispatchFn = (tr: Transaction) => void;\nexport type GetStateFn = () => EditorState;\nexport type UndoFn = () => void;\nexport type RedoFn = () => void;\n\nexport type SyncSelectionFn = () => void;\n\nexport interface InputHandlerOptions {\n\tgetState: GetStateFn;\n\tdispatch: DispatchFn;\n\tsyncSelection: SyncSelectionFn;\n\tschemaRegistry?: SchemaRegistry;\n}\n\nexport class InputHandler {\n\tprivate readonly getState: GetStateFn;\n\tprivate readonly dispatch: DispatchFn;\n\tprivate readonly syncSelection: SyncSelectionFn;\n\tprivate readonly schemaRegistry?: SchemaRegistry;\n\tprivate composing = false;\n\n\tprivate readonly handleBeforeInput: (e: InputEvent) => void;\n\tprivate readonly handleCompositionStart: (e: CompositionEvent) => void;\n\tprivate readonly handleCompositionEnd: (e: CompositionEvent) => void;\n\n\tconstructor(\n\t\tprivate readonly element: HTMLElement,\n\t\toptions: InputHandlerOptions,\n\t) {\n\t\tthis.getState = options.getState;\n\t\tthis.dispatch = options.dispatch;\n\t\tthis.syncSelection = options.syncSelection;\n\t\tthis.schemaRegistry = options.schemaRegistry;\n\n\t\tthis.handleBeforeInput = this.onBeforeInput.bind(this);\n\t\tthis.handleCompositionStart = this.onCompositionStart.bind(this);\n\t\tthis.handleCompositionEnd = this.onCompositionEnd.bind(this);\n\n\t\telement.addEventListener('beforeinput', this.handleBeforeInput);\n\t\telement.addEventListener('compositionstart', this.handleCompositionStart);\n\t\telement.addEventListener('compositionend', this.handleCompositionEnd);\n\t}\n\n\tprivate onBeforeInput(e: InputEvent): void {\n\t\t// During composition, let the browser handle it\n\t\tif (this.composing && e.inputType === 'insertCompositionText') {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\n\t\t// Sync selection from DOM before processing non-insert operations\n\t\t// (handles arrow key / mouse navigation that doesn't go through our state)\n\t\tconst needsSelectionSync =\n\t\t\te.inputType !== 'insertText' && e.inputType !== 'insertCompositionText';\n\t\tif (needsSelectionSync) {\n\t\t\tthis.syncSelection();\n\t\t}\n\n\t\tconst state = this.getState();\n\t\tlet tr: Transaction | null = null;\n\n\t\tswitch (e.inputType) {\n\t\t\tcase 'insertText':\n\t\t\t\tif (e.data) {\n\t\t\t\t\ttr = insertTextCommand(state, e.data, 'input');\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'insertParagraph':\n\t\t\tcase 'insertLineBreak':\n\t\t\t\ttr = splitBlockCommand(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteContentBackward':\n\t\t\t\ttr = deleteBackward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteContentForward':\n\t\t\t\ttr = deleteForward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteWordBackward':\n\t\t\t\ttr = deleteWordBackward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteWordForward':\n\t\t\t\ttr = deleteWordForward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteSoftLineBackward':\n\t\t\t\ttr = deleteSoftLineBackward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteSoftLineForward':\n\t\t\t\ttr = deleteSoftLineForward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'deleteByCut':\n\t\t\t\ttr = deleteBackward(state);\n\t\t\t\tbreak;\n\n\t\t\tcase 'insertFromPaste':\n\t\t\t\t// Handled by PasteHandler\n\t\t\t\tbreak;\n\n\t\t\tcase 'insertFromDrop':\n\t\t\t\t// Handled by PasteHandler\n\t\t\t\tbreak;\n\n\t\t\tcase 'formatBold':\n\t\t\tcase 'formatItalic':\n\t\t\tcase 'formatUnderline':\n\t\t\tcase 'historyUndo':\n\t\t\tcase 'historyRedo':\n\t\t\t\t// Handled by KeyboardHandler — just prevent default\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (tr) {\n\t\t\tthis.dispatch(tr);\n\n\t\t\t// Check input rules after text insertion\n\t\t\tif (e.inputType === 'insertText') {\n\t\t\t\tthis.checkInputRules();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onCompositionStart(_e: CompositionEvent): void {\n\t\tthis.composing = true;\n\t}\n\n\tprivate onCompositionEnd(e: CompositionEvent): void {\n\t\tthis.composing = false;\n\t\tconst composedText = e.data;\n\t\tif (!composedText) return;\n\n\t\tconst state = this.getState();\n\t\tconst tr = insertTextCommand(state, composedText, 'input');\n\t\tthis.dispatch(tr);\n\t}\n\n\tprivate checkInputRules(): void {\n\t\tif (!this.schemaRegistry) return;\n\t\tconst rules = this.schemaRegistry.getInputRules();\n\t\tif (rules.length === 0) return;\n\n\t\tconst state = this.getState();\n\t\tconst { anchor } = state.selection;\n\t\tconst block = state.getBlock(anchor.blockId);\n\t\tif (!block) return;\n\n\t\tconst text = getBlockText(block);\n\t\tconst textBefore = text.slice(0, anchor.offset);\n\n\t\tfor (const rule of rules) {\n\t\t\tconst match = rule.pattern.exec(textBefore);\n\t\t\tif (match) {\n\t\t\t\tconst start = match.index;\n\t\t\t\tconst end = start + match[0].length;\n\t\t\t\tconst tr = rule.handler(state, match, start, end);\n\t\t\t\tif (tr) {\n\t\t\t\t\tthis.dispatch(tr);\n\t\t\t\t\treturn; // Only first matching rule fires\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.element.removeEventListener('beforeinput', this.handleBeforeInput);\n\t\tthis.element.removeEventListener('compositionstart', this.handleCompositionStart);\n\t\tthis.element.removeEventListener('compositionend', this.handleCompositionEnd);\n\t}\n}\n","/**\n * Paste handler: intercepts paste events and converts clipboard content to transactions.\n */\n\nimport DOMPurify from 'dompurify';\nimport { insertTextCommand } from '../commands/Commands.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { DispatchFn, GetStateFn } from './InputHandler.js';\n\nexport interface PasteHandlerOptions {\n\tgetState: GetStateFn;\n\tdispatch: DispatchFn;\n\tschemaRegistry?: SchemaRegistry;\n}\n\nexport class PasteHandler {\n\tprivate readonly getState: GetStateFn;\n\tprivate readonly dispatch: DispatchFn;\n\tprivate readonly handlePaste: (e: ClipboardEvent) => void;\n\n\tconstructor(\n\t\tprivate readonly element: HTMLElement,\n\t\toptions: PasteHandlerOptions,\n\t) {\n\t\tthis.getState = options.getState;\n\t\tthis.dispatch = options.dispatch;\n\n\t\tthis.handlePaste = this.onPaste.bind(this);\n\t\telement.addEventListener('paste', this.handlePaste);\n\t}\n\n\tprivate onPaste(e: ClipboardEvent): void {\n\t\te.preventDefault();\n\n\t\tconst clipboardData = e.clipboardData;\n\t\tif (!clipboardData) return;\n\n\t\tconst state = this.getState();\n\n\t\t// Try HTML first, fall back to plain text\n\t\tconst html = clipboardData.getData('text/html');\n\t\tif (html) {\n\t\t\tconst sanitized = DOMPurify.sanitize(html, {\n\t\t\t\tALLOWED_TAGS: ['strong', 'em', 'u', 'b', 'i', 'p', 'br', 'div', 'span'],\n\t\t\t\tALLOWED_ATTR: [],\n\t\t\t});\n\n\t\t\t// TODO: Rich-text paste not yet supported — extract plain text for now\n\t\t\tconst text = this.extractTextFromHTML(sanitized);\n\t\t\tif (text) {\n\t\t\t\tconst tr = insertTextCommand(state, text, 'paste');\n\t\t\t\tthis.dispatch(tr);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst text = clipboardData.getData('text/plain');\n\t\tif (text) {\n\t\t\tconst tr = insertTextCommand(state, text, 'paste');\n\t\t\tthis.dispatch(tr);\n\t\t}\n\t}\n\n\tprivate extractTextFromHTML(html: string): string {\n\t\tconst template = document.createElement('template');\n\t\ttemplate.innerHTML = html;\n\t\treturn template.content.textContent ?? '';\n\t}\n\n\tdestroy(): void {\n\t\tthis.element.removeEventListener('paste', this.handlePaste);\n\t}\n}\n","/**\n * Selection synchronization between editor state and DOM.\n */\n\nimport type { Position, Selection } from '../model/Selection.js';\nimport { createPosition, createSelection } from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport { blockId as toBlockId } from '../model/TypeBrands.js';\n\ninterface DOMPosition {\n\tnode: Node;\n\toffset: number;\n}\n\n/** Gets the selection object, preferring shadow root's selection for Shadow DOM. */\nfunction getSelection(container: HTMLElement): globalThis.Selection | null {\n\tconst root = container.getRootNode();\n\tif (root instanceof ShadowRoot && 'getSelection' in root) {\n\t\treturn (root as ShadowRoot & { getSelection(): globalThis.Selection | null }).getSelection();\n\t}\n\treturn window.getSelection();\n}\n\n/** Syncs the editor state selection to the DOM. */\nexport function syncSelectionToDOM(container: HTMLElement, selection: Selection): void {\n\tconst domSel = getSelection(container);\n\tif (!domSel) return;\n\n\tconst anchorPos = statePositionToDOM(container, selection.anchor);\n\tconst headPos = statePositionToDOM(container, selection.head);\n\n\tif (!anchorPos || !headPos) return;\n\n\ttry {\n\t\tdomSel.setBaseAndExtent(anchorPos.node, anchorPos.offset, headPos.node, headPos.offset);\n\t} catch {\n\t\t// Selection may fail if DOM is not yet rendered\n\t}\n}\n\n/** Reads the current DOM selection and converts it to a state selection. */\nexport function readSelectionFromDOM(container: HTMLElement): Selection | null {\n\tconst domSel = getSelection(container);\n\tif (!domSel || domSel.rangeCount === 0) return null;\n\n\tconst anchorNode = domSel.anchorNode;\n\tconst focusNode = domSel.focusNode;\n\n\tif (!anchorNode || !focusNode) return null;\n\tif (!container.contains(anchorNode) || !container.contains(focusNode)) return null;\n\n\tconst anchor = domPositionToState(container, anchorNode, domSel.anchorOffset);\n\tconst head = domPositionToState(container, focusNode, domSel.focusOffset);\n\n\tif (!anchor || !head) return null;\n\n\treturn createSelection(anchor, head);\n}\n\n/** Converts a state position (blockId + offset) to a DOM position (node + offset). */\nfunction statePositionToDOM(container: HTMLElement, pos: Position): DOMPosition | null {\n\t// If path is available, navigate directly to the leaf block\n\tlet blockEl: Element | null = null;\n\tif (pos.path && pos.path.length > 0) {\n\t\tlet current: Element = container;\n\t\tfor (const id of pos.path) {\n\t\t\tconst found = current.querySelector(`:scope [data-block-id=\"${id}\"]`);\n\t\t\tif (!found) break;\n\t\t\tcurrent = found;\n\t\t}\n\t\tif (current !== container && current.getAttribute('data-block-id') === pos.blockId) {\n\t\t\tblockEl = current;\n\t\t}\n\t}\n\tblockEl ??= container.querySelector(`[data-block-id=\"${pos.blockId}\"]`);\n\tif (!blockEl) return null;\n\n\t// Handle empty paragraphs with <br>\n\tif (blockEl.childNodes.length === 1 && blockEl.firstChild?.nodeName === 'BR') {\n\t\treturn { node: blockEl, offset: 0 };\n\t}\n\n\t// Walk through text nodes and inline elements to find the correct position\n\tlet remaining = pos.offset;\n\tconst walker = createInlineContentWalker(blockEl);\n\n\tlet current = walker.nextNode();\n\twhile (current) {\n\t\tif (current.nodeType === Node.TEXT_NODE) {\n\t\t\tconst len = current.textContent?.length ?? 0;\n\t\t\tif (remaining <= len) {\n\t\t\t\treturn { node: current, offset: remaining };\n\t\t\t}\n\t\t\tremaining -= len;\n\t\t} else if (\n\t\t\tcurrent instanceof HTMLElement &&\n\t\t\tcurrent.getAttribute('contenteditable') === 'false'\n\t\t) {\n\t\t\t// InlineNode element — width 1 in state offset space\n\t\t\tif (remaining === 0) {\n\t\t\t\t// Position before this inline element\n\t\t\t\tconst parent = current.parentNode;\n\t\t\t\tif (parent) {\n\t\t\t\t\tconst childIndex = childIndexOf(parent, current);\n\t\t\t\t\treturn { node: parent, offset: childIndex };\n\t\t\t\t}\n\t\t\t}\n\t\t\tremaining -= 1;\n\t\t}\n\t\tcurrent = walker.nextNode();\n\t}\n\n\t// Fallback: position at end of block\n\tconst lastChild = blockEl.lastChild;\n\tif (lastChild) {\n\t\tif (lastChild.nodeType === Node.TEXT_NODE) {\n\t\t\treturn { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n\t\t}\n\t\treturn { node: blockEl, offset: blockEl.childNodes.length };\n\t}\n\n\treturn { node: blockEl, offset: 0 };\n}\n\n/** Converts a DOM position to a state position, including nested path. */\nfunction domPositionToState(\n\tcontainer: HTMLElement,\n\tnode: Node,\n\tdomOffset: number,\n): Position | null {\n\t// Find the innermost block element\n\tconst blockEl = findBlockElement(container, node);\n\tif (!blockEl) return null;\n\n\tconst rawBlockId = blockEl.getAttribute('data-block-id');\n\tif (!rawBlockId) return null;\n\tconst bid = toBlockId(rawBlockId);\n\n\t// Build path by collecting all data-block-id ancestors from leaf to root\n\tconst path = buildBlockPath(container, blockEl);\n\n\t// Handle clicks on the block element itself (e.g. empty paragraph with <br>)\n\tif (node === blockEl) {\n\t\tlet childOffset = 0;\n\t\tlet childIdx = 0;\n\t\tfor (const child of Array.from(blockEl.childNodes)) {\n\t\t\tif (childIdx >= domOffset) break;\n\t\t\tchildOffset += inlineContentWidth(child);\n\t\t\tchildIdx++;\n\t\t}\n\t\treturn createPosition(bid, childOffset, path.length > 1 ? path : undefined);\n\t}\n\n\t// Calculate offset by walking text nodes and inline elements\n\tlet offset = 0;\n\tconst walker = createInlineContentWalker(blockEl);\n\n\tlet walkerNode = walker.nextNode();\n\twhile (walkerNode) {\n\t\tif (walkerNode === node) {\n\t\t\tif (walkerNode.nodeType === Node.TEXT_NODE) {\n\t\t\t\treturn createPosition(bid, offset + domOffset, path.length > 1 ? path : undefined);\n\t\t\t}\n\t\t\t// Node is an inline element — return offset at its start\n\t\t\treturn createPosition(bid, offset, path.length > 1 ? path : undefined);\n\t\t}\n\t\tif (walkerNode.nodeType === Node.TEXT_NODE) {\n\t\t\toffset += walkerNode.textContent?.length ?? 0;\n\t\t} else if (\n\t\t\twalkerNode instanceof HTMLElement &&\n\t\t\twalkerNode.getAttribute('contenteditable') === 'false'\n\t\t) {\n\t\t\toffset += 1;\n\t\t}\n\t\twalkerNode = walker.nextNode();\n\t}\n\n\t// If the node is not a text node, try to find the offset from element context\n\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\tlet childOffset = 0;\n\t\tlet childIdx = 0;\n\n\t\tfor (const child of Array.from(node.childNodes)) {\n\t\t\tif (childIdx >= domOffset) break;\n\t\t\tchildOffset += inlineContentWidth(child);\n\t\t\tchildIdx++;\n\t\t}\n\n\t\treturn createPosition(bid, childOffset, path.length > 1 ? path : undefined);\n\t}\n\n\treturn createPosition(bid, 0, path.length > 1 ? path : undefined);\n}\n\n/** Builds an array of block IDs from root to leaf by walking up from a block element. */\nfunction buildBlockPath(container: HTMLElement, leafBlockEl: HTMLElement): BlockId[] {\n\tconst path: BlockId[] = [];\n\tlet current: HTMLElement | null = leafBlockEl;\n\n\twhile (current && current !== container) {\n\t\tif (current.hasAttribute('data-block-id')) {\n\t\t\tpath.unshift(toBlockId(current.getAttribute('data-block-id') ?? ''));\n\t\t}\n\t\tcurrent = current.parentElement;\n\t}\n\n\treturn path;\n}\n\n/** Finds the closest block element ancestor. */\nfunction findBlockElement(container: HTMLElement, node: Node): HTMLElement | null {\n\tlet current: Node | null = node;\n\twhile (current && current !== container) {\n\t\tif (current instanceof HTMLElement && current.hasAttribute('data-block-id')) {\n\t\t\treturn current;\n\t\t}\n\t\tcurrent = current.parentNode;\n\t}\n\treturn null;\n}\n\n/** Checks if a node is inside a contentEditable=\"false\" inline element. */\nfunction isInsideInlineElement(node: Node, root: Element): boolean {\n\tlet parent: Node | null = node.parentNode;\n\twhile (parent && parent !== root) {\n\t\tif (parent instanceof HTMLElement && parent.getAttribute('contenteditable') === 'false') {\n\t\t\treturn true;\n\t\t}\n\t\tparent = parent.parentNode;\n\t}\n\treturn false;\n}\n\n/**\n * Creates a TreeWalker that visits text nodes and contentEditable=\"false\"\n * inline elements within a block, skipping mark wrappers and nested blocks.\n */\nfunction createInlineContentWalker(blockEl: Element): TreeWalker {\n\treturn document.createTreeWalker(blockEl, NodeFilter.SHOW_ALL, {\n\t\tacceptNode: (n: Node) => {\n\t\t\t// Skip anything inside an inline element (contentEditable=\"false\")\n\t\t\tif (isInsideInlineElement(n, blockEl)) return NodeFilter.FILTER_REJECT;\n\t\t\t// Skip nested block elements and their descendants\n\t\t\tif (n instanceof HTMLElement && n.hasAttribute('data-block-id') && n !== blockEl) {\n\t\t\t\treturn NodeFilter.FILTER_REJECT;\n\t\t\t}\n\t\t\t// Accept text nodes\n\t\t\tif (n.nodeType === Node.TEXT_NODE) return NodeFilter.FILTER_ACCEPT;\n\t\t\t// Accept inline elements (contentEditable=\"false\")\n\t\t\tif (n instanceof HTMLElement && n.getAttribute('contenteditable') === 'false') {\n\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t}\n\t\t\t// Skip other elements (mark wrappers, decoration wrappers) — descend\n\t\t\treturn NodeFilter.FILTER_SKIP;\n\t\t},\n\t});\n}\n\n/** Returns the child index of a node within its parent. */\nfunction childIndexOf(parent: Node, child: Node): number {\n\tlet idx = 0;\n\tfor (const c of Array.from(parent.childNodes)) {\n\t\tif (c === child) return idx;\n\t\tidx++;\n\t}\n\treturn idx;\n}\n\n/** Counts the inline content width of a DOM node (text length + 1 per inline element). */\nfunction inlineContentWidth(node: Node): number {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent?.length ?? 0;\n\t}\n\tif (node instanceof HTMLElement && node.getAttribute('contenteditable') === 'false') {\n\t\treturn 1;\n\t}\n\t// Mark wrapper or other element — sum children\n\tlet width = 0;\n\tfor (const child of Array.from(node.childNodes)) {\n\t\twidth += inlineContentWidth(child);\n\t}\n\treturn width;\n}\n","/**\n * EditorView: orchestrates input handling, reconciliation, and selection sync.\n */\n\nimport { DecorationSet } from '../decorations/Decoration.js';\nimport { InputHandler } from '../input/InputHandler.js';\nimport { KeyboardHandler } from '../input/KeyboardHandler.js';\nimport { PasteHandler } from '../input/PasteHandler.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport { HistoryManager } from '../state/History.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport type { NodeView } from './NodeView.js';\nimport { reconcile } from './Reconciler.js';\nimport { readSelectionFromDOM, syncSelectionToDOM } from './SelectionSync.js';\n\nexport type StateChangeCallback = (\n\toldState: EditorState,\n\tnewState: EditorState,\n\ttr: Transaction,\n) => void;\n\nexport interface EditorViewOptions {\n\tstate: EditorState;\n\tschemaRegistry?: SchemaRegistry;\n\tmaxHistoryDepth?: number;\n\tonStateChange?: StateChangeCallback;\n\tgetDecorations?: (state: EditorState, tr?: Transaction) => DecorationSet;\n}\n\nexport class EditorView {\n\tprivate state: EditorState;\n\tprivate readonly contentElement: HTMLElement;\n\tprivate readonly inputHandler: InputHandler;\n\tprivate readonly keyboardHandler: KeyboardHandler;\n\tprivate readonly pasteHandler: PasteHandler;\n\treadonly history: HistoryManager;\n\tprivate readonly stateChangeCallbacks: StateChangeCallback[] = [];\n\tprivate readonly handleSelectionChange: () => void;\n\tprivate isUpdating = false;\n\tprivate readonly schemaRegistry?: SchemaRegistry;\n\tprivate readonly nodeViews = new Map<string, NodeView>();\n\tprivate decorations: DecorationSet = DecorationSet.empty;\n\tprivate readonly getDecorations?: (state: EditorState, tr?: Transaction) => DecorationSet;\n\n\tconstructor(contentElement: HTMLElement, options: EditorViewOptions) {\n\t\tthis.state = options.state;\n\t\tthis.contentElement = contentElement;\n\t\tthis.schemaRegistry = options.schemaRegistry;\n\t\tthis.getDecorations = options.getDecorations;\n\n\t\tthis.history = new HistoryManager({\n\t\t\tmaxDepth: options.maxHistoryDepth ?? 100,\n\t\t});\n\n\t\tif (options.onStateChange) {\n\t\t\tthis.stateChangeCallbacks.push(options.onStateChange);\n\t\t}\n\n\t\tthis.inputHandler = new InputHandler(contentElement, {\n\t\t\tgetState: () => this.state,\n\t\t\tdispatch: (tr: Transaction) => this.dispatch(tr),\n\t\t\tsyncSelection: () => this.syncSelectionFromDOM(),\n\t\t\tschemaRegistry: this.schemaRegistry,\n\t\t});\n\t\tthis.keyboardHandler = new KeyboardHandler(contentElement, {\n\t\t\tgetState: () => this.state,\n\t\t\tdispatch: (tr: Transaction) => this.dispatch(tr),\n\t\t\tundo: () => this.undo(),\n\t\t\tredo: () => this.redo(),\n\t\t\tschemaRegistry: this.schemaRegistry,\n\t\t});\n\t\tthis.pasteHandler = new PasteHandler(contentElement, {\n\t\t\tgetState: () => this.state,\n\t\t\tdispatch: (tr: Transaction) => this.dispatch(tr),\n\t\t\tschemaRegistry: this.schemaRegistry,\n\t\t});\n\n\t\tthis.handleSelectionChange = this.onSelectionChange.bind(this);\n\t\tdocument.addEventListener('selectionchange', this.handleSelectionChange);\n\n\t\t// Initial render\n\t\tthis.decorations = this.getDecorations?.(this.state) ?? DecorationSet.empty;\n\t\treconcile(contentElement, null, this.state, {\n\t\t\t...this.reconcileOptions(),\n\t\t\tdecorations: this.decorations,\n\t\t});\n\t\tsyncSelectionToDOM(contentElement, this.state.selection);\n\t}\n\n\t/** Returns the current editor state. */\n\tgetState(): EditorState {\n\t\treturn this.state;\n\t}\n\n\t/**\n\t * Central update cycle: sets state, collects decorations, reconciles DOM,\n\t * syncs selection, and notifies listeners. Guarded against re-entrancy.\n\t */\n\tprivate applyUpdate(\n\t\tnewState: EditorState,\n\t\ttr: Transaction,\n\t\toptions?: { readonly pushHistory?: boolean },\n\t): void {\n\t\tif (this.isUpdating) return;\n\t\tthis.isUpdating = true;\n\t\ttry {\n\t\t\tconst oldState = this.state;\n\t\t\tthis.state = newState;\n\n\t\t\tif (options?.pushHistory && tr.metadata.origin !== 'history') {\n\t\t\t\tthis.history.push(tr);\n\t\t\t}\n\n\t\t\tconst oldDecorations = this.decorations;\n\t\t\tconst newDecorations = this.getDecorations?.(newState, tr) ?? DecorationSet.empty;\n\t\t\tthis.decorations = newDecorations;\n\n\t\t\treconcile(this.contentElement, oldState, newState, {\n\t\t\t\t...this.reconcileOptions(),\n\t\t\t\tdecorations: newDecorations,\n\t\t\t\toldDecorations,\n\t\t\t});\n\t\t\tsyncSelectionToDOM(this.contentElement, newState.selection);\n\n\t\t\tfor (const cb of this.stateChangeCallbacks) {\n\t\t\t\tcb(oldState, newState, tr);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.isUpdating = false;\n\t\t}\n\t}\n\n\t/** Dispatches a transaction, updates state, reconciles DOM, syncs selection. */\n\tdispatch(tr: Transaction): void {\n\t\tconst newState = this.state.apply(tr);\n\t\tthis.applyUpdate(newState, tr, { pushHistory: true });\n\t}\n\n\t/** Performs undo. */\n\tundo(): void {\n\t\t// Guard needed here: history.undo() mutates stacks before applyUpdate runs\n\t\tif (this.isUpdating) return;\n\t\tconst result = this.history.undo(this.state);\n\t\tif (!result) return;\n\t\tthis.applyUpdate(result.state, result.transaction);\n\t}\n\n\t/** Performs redo. */\n\tredo(): void {\n\t\t// Guard needed here: history.redo() mutates stacks before applyUpdate runs\n\t\tif (this.isUpdating) return;\n\t\tconst result = this.history.redo(this.state);\n\t\tif (!result) return;\n\t\tthis.applyUpdate(result.state, result.transaction);\n\t}\n\n\t/** Registers a state change callback. */\n\tonStateChange(callback: StateChangeCallback): () => void {\n\t\tthis.stateChangeCallbacks.push(callback);\n\t\treturn () => {\n\t\t\tconst idx = this.stateChangeCallbacks.indexOf(callback);\n\t\t\tif (idx !== -1) this.stateChangeCallbacks.splice(idx, 1);\n\t\t};\n\t}\n\n\t/** Replaces the editor state without destroying handlers or history. */\n\treplaceState(newState: EditorState): void {\n\t\tif (this.isUpdating) return;\n\t\tthis.isUpdating = true;\n\t\ttry {\n\t\t\tconst oldState = this.state;\n\t\t\tthis.state = newState;\n\t\t\tthis.history.clear();\n\n\t\t\tconst oldDecorations = this.decorations;\n\t\t\tconst newDecorations = this.getDecorations?.(newState) ?? DecorationSet.empty;\n\t\t\tthis.decorations = newDecorations;\n\n\t\t\treconcile(this.contentElement, oldState, newState, {\n\t\t\t\t...this.reconcileOptions(),\n\t\t\t\tdecorations: newDecorations,\n\t\t\t\toldDecorations,\n\t\t\t});\n\t\t\tsyncSelectionToDOM(this.contentElement, newState.selection);\n\t\t} finally {\n\t\t\tthis.isUpdating = false;\n\t\t}\n\t}\n\n\t/** Syncs the DOM selection to the editor state. */\n\tprivate syncSelectionFromDOM(): void {\n\t\tconst sel = readSelectionFromDOM(this.contentElement);\n\t\tif (!sel) return;\n\n\t\t// Check if selection actually changed\n\t\tconst currentSel = this.state.selection;\n\t\tif (\n\t\t\tsel.anchor.blockId === currentSel.anchor.blockId &&\n\t\t\tsel.anchor.offset === currentSel.anchor.offset &&\n\t\t\tsel.head.blockId === currentSel.head.blockId &&\n\t\t\tsel.head.offset === currentSel.head.offset\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Update state with new selection (clear stored marks on selection change)\n\t\tconst tr = this.state\n\t\t\t.transaction('input')\n\t\t\t.setSelection(sel)\n\t\t\t.setStoredMarks(null, this.state.storedMarks)\n\t\t\t.build();\n\n\t\tconst newState = this.state.apply(tr);\n\t\tthis.applyUpdate(newState, tr);\n\t}\n\n\t/** Handles DOM selection changes (clicks, arrow keys). */\n\tprivate onSelectionChange(): void {\n\t\tif (this.isUpdating) return;\n\n\t\t// Only process if our content element is focused\n\t\tconst shadowRoot = this.contentElement.getRootNode() as ShadowRoot | Document;\n\t\tconst activeEl =\n\t\t\t'activeElement' in shadowRoot ? shadowRoot.activeElement : document.activeElement;\n\t\tif (!this.contentElement.contains(activeEl) && activeEl !== this.contentElement) return;\n\n\t\tthis.syncSelectionFromDOM();\n\t}\n\n\tprivate reconcileOptions() {\n\t\treturn {\n\t\t\tregistry: this.schemaRegistry,\n\t\t\tnodeViews: this.nodeViews,\n\t\t\tgetState: () => this.state,\n\t\t\tdispatch: (tr: Transaction) => this.dispatch(tr),\n\t\t};\n\t}\n\n\t/** Cleans up all event listeners and handlers. */\n\tdestroy(): void {\n\t\tthis.inputHandler.destroy();\n\t\tthis.keyboardHandler.destroy();\n\t\tthis.pasteHandler.destroy();\n\t\tdocument.removeEventListener('selectionchange', this.handleSelectionChange);\n\t\t// Destroy all NodeViews\n\t\tfor (const nv of this.nodeViews.values()) {\n\t\t\tnv.destroy?.();\n\t\t}\n\t\tthis.nodeViews.clear();\n\t}\n}\n","/**\n * Editor styles using Adopted Stylesheets for Shadow DOM.\n */\n\nconst EDITOR_CSS = `\n:host {\n\tdisplay: block;\n\tfont-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\tfont-size: 16px;\n\tline-height: 1.6;\n\tcolor: #1a1a1a;\n}\n\n.notectl-editor {\n\tdisplay: flex;\n\tflex-direction: column;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 6px;\n\toverflow: hidden;\n\tbackground: #fff;\n}\n\n.notectl-editor:focus-within {\n\tborder-color: #4a90d9;\n\tbox-shadow: 0 0 0 2px rgba(74, 144, 217, 0.2);\n}\n\n/* Toolbar */\n.notectl-plugin-container--top {\n\tdisplay: flex;\n\talign-items: center;\n\tborder-bottom: 1px solid #e0e0e0;\n\tbackground: #f8f8f8;\n\tmin-height: 40px;\n}\n\n.notectl-toolbar {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 2px;\n\tpadding: 4px 8px;\n}\n\n.notectl-toolbar-btn {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 32px;\n\theight: 32px;\n\tborder: 1px solid transparent;\n\tborder-radius: 4px;\n\tbackground: transparent;\n\tcursor: pointer;\n\tcolor: #444;\n\tfont-size: 14px;\n\tline-height: 1;\n\tpadding: 0;\n\ttransition: background 0.1s, border-color 0.1s;\n}\n\n.notectl-toolbar-btn:hover {\n\tbackground: #e8e8e8;\n\tborder-color: #d0d0d0;\n}\n\n.notectl-toolbar-btn--active {\n\tbackground: #d0e0f0;\n\tborder-color: #a0c0e0;\n\tcolor: #1a5fa0;\n}\n\n.notectl-toolbar-btn:disabled {\n\topacity: 0.4;\n\tcursor: not-allowed;\n}\n\n.notectl-toolbar-btn:disabled:hover {\n\tbackground: transparent;\n\tborder-color: transparent;\n}\n\n.notectl-toolbar-btn__icon {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpointer-events: none;\n}\n\n.notectl-toolbar-btn__icon svg {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tfill: currentColor;\n}\n\n/* Tooltip (rendered as fixed-position element in shadow root) */\n.notectl-toolbar-tooltip {\n\tposition: fixed;\n\tpadding: 4px 8px;\n\tborder-radius: 4px;\n\tbackground: #1a1a1a;\n\tcolor: #fff;\n\tfont-size: 11px;\n\tfont-weight: 500;\n\twhite-space: nowrap;\n\tpointer-events: none;\n\tz-index: 10001;\n\tline-height: 1.4;\n\tletter-spacing: 0.01em;\n\tfont-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.notectl-toolbar-separator {\n\tdisplay: inline-block;\n\twidth: 1px;\n\theight: 20px;\n\tbackground: #d0d0d0;\n\tmargin: 0 4px;\n\tvertical-align: middle;\n}\n\n/* Toolbar Popups */\n.notectl-toolbar-popup {\n\tbackground: #fff;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 6px;\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n\toverflow: hidden;\n}\n\n/* Dropdown */\n.notectl-dropdown {\n\tmin-width: 160px;\n\tpadding: 4px 0;\n}\n\n.notectl-dropdown__item {\n\tdisplay: flex;\n\talign-items: center;\n\twidth: 100%;\n\tpadding: 8px 12px;\n\ttext-align: left;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: #333;\n\tline-height: 1.4;\n\tfont-family: inherit;\n\twhite-space: nowrap;\n}\n\n.notectl-dropdown__item:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-dropdown__item-icon {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 28px;\n\tfont-weight: 600;\n\tcolor: #555;\n\tflex-shrink: 0;\n}\n\n.notectl-dropdown__item-label {\n\tflex: 1;\n}\n\n/* Content Area */\n.notectl-content {\n\tflex: 1;\n\tpadding: 12px 16px;\n\toutline: none;\n\tmin-height: var(--notectl-content-min-height, 400px);\n\tcursor: text;\n\tposition: relative;\n}\n\n.notectl-content p {\n\tmargin: 0;\n\tpadding: 2px 0;\n\tmin-height: 1.6em;\n}\n\n.notectl-content p + p {\n\tmargin-top: 0;\n}\n\n/* List Items */\n.notectl-list-item {\n\tmargin: 0;\n\tpadding: 2px 0 2px 24px;\n\tmin-height: 1.6em;\n\tposition: relative;\n}\n\n.notectl-list-item::before {\n\tposition: absolute;\n\tleft: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n}\n\n/* Bullet List */\n.notectl-list-item--bullet::before {\n\tcontent: '\\\\2022';\n\tcolor: #444;\n}\n\n/* Ordered List — uses CSS counters to auto-number */\n.notectl-content {\n\tcounter-reset: notectl-ordered;\n}\n\n.notectl-list-item--ordered {\n\tcounter-increment: notectl-ordered;\n}\n\n/* Reset counter when a non-ordered item breaks the sequence */\n.notectl-list-item:not(.notectl-list-item--ordered) + .notectl-list-item--ordered {\n\tcounter-reset: notectl-ordered;\n\tcounter-increment: notectl-ordered;\n}\n\n:not(.notectl-list-item--ordered) + .notectl-list-item--ordered,\n.notectl-content > .notectl-list-item--ordered:first-child {\n\tcounter-reset: notectl-ordered;\n\tcounter-increment: notectl-ordered;\n}\n\n.notectl-list-item--ordered::before {\n\tcontent: counter(notectl-ordered) '.';\n\tcolor: #444;\n\tfont-size: 14px;\n}\n\n/* Checklist */\n.notectl-list-item--checklist::before {\n\tcontent: '\\\\2610';\n\tfont-size: 16px;\n\tcolor: #666;\n\tcursor: pointer;\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"]::before {\n\tcontent: '\\\\2611';\n\tcolor: #1a8c1a;\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] {\n\tcolor: #888;\n\ttext-decoration: line-through;\n}\n\n/* Horizontal Rule */\n.notectl-content hr {\n\tborder: none;\n\tborder-top: 1px solid #d0d0d0;\n\tmargin: 8px 0;\n\tpadding: 0;\n\tcursor: default;\n\tuser-select: none;\n}\n\n/* Placeholder */\n.notectl-content.notectl-content--empty::before {\n\tcontent: attr(data-placeholder);\n\tcolor: #999;\n\tpointer-events: none;\n\tposition: absolute;\n\ttop: 12px;\n\tleft: 16px;\n}\n\n/* Plugin container bottom */\n.notectl-plugin-container--bottom {\n\tborder-top: 1px solid #e0e0e0;\n}\n\n/* Color Picker Popup */\n.notectl-color-picker {\n\tpadding: 8px;\n\tmin-width: 240px;\n}\n\n.notectl-color-picker__default {\n\tdisplay: block;\n\twidth: 100%;\n\tpadding: 6px 12px;\n\tmargin-bottom: 8px;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 4px;\n\tbackground: #fff;\n\tcursor: pointer;\n\tfont-size: 13px;\n\tcolor: #333;\n\ttext-align: center;\n}\n\n.notectl-color-picker__default:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-color-picker__grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(10, 1fr);\n\tgap: 3px;\n}\n\n.notectl-color-picker__swatch {\n\twidth: 22px;\n\theight: 22px;\n\tborder: 1px solid transparent;\n\tborder-radius: 3px;\n\tpadding: 0;\n\tcursor: pointer;\n\ttransition: transform 0.1s;\n}\n\n.notectl-color-picker__swatch:hover {\n\ttransform: scale(1.25);\n\tz-index: 1;\n}\n\n.notectl-color-picker__swatch--active {\n\tborder: 2px solid #1a5fa0;\n\tborder-radius: 3px;\n}\n\n.notectl-toolbar-btn--textColor .notectl-toolbar-btn__color-indicator {\n\tdisplay: block;\n\twidth: 16px;\n\theight: 3px;\n\tmargin-top: 1px;\n\tborder-radius: 1px;\n}\n\n/* Font Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--font {\n\twidth: auto;\n\tmin-width: 100px;\n\tmax-width: 160px;\n\tpadding: 0 8px;\n\tgap: 4px;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 4px;\n\tbackground: #fff;\n}\n\n.notectl-toolbar-btn--font:hover {\n\tbackground: #f5f5f5;\n\tborder-color: #b0b0b0;\n}\n\n.notectl-toolbar-btn--font.notectl-toolbar-btn--active {\n\tbackground: #fff;\n\tborder-color: #a0c0e0;\n}\n\n.notectl-toolbar-btn--font .notectl-toolbar-btn__icon {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\twidth: 100%;\n\toverflow: hidden;\n}\n\n.notectl-toolbar-btn--font .notectl-toolbar-btn__icon svg {\n\tdisplay: none;\n}\n\n.notectl-font-select__label {\n\tflex: 1;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: #333;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\ttext-align: left;\n\tline-height: 30px;\n}\n\n.notectl-font-select__arrow {\n\tflex-shrink: 0;\n\tfont-size: 11px;\n\tcolor: #888;\n\tline-height: 30px;\n}\n\n/* Font Picker Popup */\n.notectl-font-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-font-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-font-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: #333;\n\tline-height: 1.4;\n\ttext-align: left;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n.notectl-font-picker__item:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-font-picker__item--active {\n\tbackground: #e8f0fb;\n\tcolor: #1a5fa0;\n}\n\n.notectl-font-picker__item--active:hover {\n\tbackground: #d0e0f0;\n}\n\n.notectl-font-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: #1a5fa0;\n}\n\n.notectl-font-picker__label {\n\tflex: 1;\n}\n\n.notectl-font-picker__separator {\n\theight: 1px;\n\tbackground: #e0e0e0;\n\tmargin: 4px 8px;\n}\n\n/* Heading Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--heading {\n\twidth: auto;\n\tmin-width: 100px;\n\tmax-width: 160px;\n\tpadding: 0 8px;\n\tgap: 4px;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 4px;\n\tbackground: #fff;\n}\n\n.notectl-toolbar-btn--heading:hover {\n\tbackground: #f5f5f5;\n\tborder-color: #b0b0b0;\n}\n\n.notectl-toolbar-btn--heading.notectl-toolbar-btn--active {\n\tbackground: #fff;\n\tborder-color: #a0c0e0;\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\twidth: 100%;\n\toverflow: hidden;\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon svg {\n\tdisplay: none;\n}\n\n.notectl-heading-select__label {\n\tflex: 1;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: #333;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\ttext-align: left;\n\tline-height: 30px;\n}\n\n.notectl-heading-select__arrow {\n\tflex-shrink: 0;\n\tfont-size: 11px;\n\tcolor: #888;\n\tline-height: 30px;\n}\n\n/* Heading Picker Popup */\n.notectl-heading-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-heading-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-heading-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: #333;\n\ttext-align: left;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n.notectl-heading-picker__item:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-heading-picker__item--active {\n\tbackground: #e8f0fb;\n\tcolor: #1a5fa0;\n}\n\n.notectl-heading-picker__item--active:hover {\n\tbackground: #d0e0f0;\n}\n\n.notectl-heading-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: #1a5fa0;\n}\n\n.notectl-heading-picker__label {\n\tflex: 1;\n}\n\n/* Screen reader announcements */\n.notectl-sr-only {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip: rect(0, 0, 0, 0);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n/* Table */\n.notectl-table-wrapper {\n\tmargin: 8px 0;\n\toverflow-x: auto;\n\tposition: relative;\n}\n\n.notectl-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n\ttable-layout: fixed;\n}\n\n.notectl-table td {\n\tborder: 1px solid #d0d0d0;\n\tpadding: 8px 12px;\n\tmin-width: 60px;\n\tvertical-align: top;\n\tmin-height: 1.6em;\n}\n\n.notectl-table td:focus-within {\n\toutline: 2px solid #4a90d9;\n\toutline-offset: -2px;\n}\n\n.notectl-table-cell--selected {\n\tbackground: rgba(74, 144, 217, 0.15);\n}\n\n/* Table Context Menu */\n.notectl-table-context-menu {\n\tposition: fixed;\n\tbackground: #fff;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 6px;\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n\tpadding: 4px 0;\n\tmin-width: 180px;\n\tz-index: 10000;\n}\n\n.notectl-table-context-menu button {\n\tdisplay: block;\n\twidth: 100%;\n\tpadding: 8px 12px;\n\ttext-align: left;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: #333;\n\tfont-family: inherit;\n}\n\n.notectl-table-context-menu button:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-table-context-menu hr {\n\tborder: none;\n\tborder-top: 1px solid #e0e0e0;\n\tmargin: 4px 0;\n}\n\n/* === Table Controls === */\n\n/* Outer container for table + controls */\n.ntbl-container {\n\tposition: relative;\n\tmargin: 8px 0;\n\tpadding: 24px 0 0 24px;\n}\n\n.ntbl-container .notectl-table-wrapper {\n\tmargin: 0;\n}\n\n/* --- Column Handle Bar --- */\n.ntbl-col-bar {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 24px;\n\theight: 20px;\n\tdisplay: flex;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-col-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Row Handle Bar --- */\n.ntbl-row-bar {\n\tposition: absolute;\n\ttop: 24px;\n\tleft: 0;\n\twidth: 20px;\n\tdisplay: flex;\n\tflex-direction: column;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-row-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Handle (shared base) --- */\n.ntbl-handle {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\ttransition: background 0.15s ease;\n\tborder-radius: 3px;\n}\n\n.ntbl-col-handle {\n\theight: 100%;\n\tbackground: #edf0f4;\n\tborder-radius: 4px 4px 0 0;\n}\n\n.ntbl-col-handle:hover {\n\tbackground: #dce3ed;\n}\n\n.ntbl-row-handle {\n\twidth: 100%;\n\tbackground: #edf0f4;\n\tborder-radius: 4px 0 0 4px;\n}\n\n.ntbl-row-handle:hover {\n\tbackground: #dce3ed;\n}\n\n/* --- Handle Delete Button --- */\n.ntbl-handle-delete {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\theight: 16px;\n\tborder: none;\n\tbackground: transparent;\n\tcolor: #999;\n\tcursor: pointer;\n\tborder-radius: 3px;\n\tpadding: 0;\n\topacity: 0;\n\ttransform: scale(0.7);\n\ttransition: opacity 0.15s, transform 0.15s,\n\t\tbackground 0.15s, color 0.15s;\n}\n\n.ntbl-handle:hover .ntbl-handle-delete {\n\topacity: 1;\n\ttransform: scale(1);\n}\n\n.ntbl-handle-delete:hover {\n\tbackground: #fee2e2;\n\tcolor: #dc2626;\n}\n\n/* --- Insert Lines --- */\n.ntbl-insert-line {\n\tposition: absolute;\n\tpointer-events: none;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n\tz-index: 6;\n}\n\n.ntbl-insert-line--visible {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-insert-line--horizontal {\n\theight: 2px;\n\tbackground: linear-gradient(\n\t\t90deg,\n\t\ttransparent,\n\t\t#4a90d9 8%,\n\t\t#4a90d9 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px rgba(74, 144, 217, 0.35);\n}\n\n.ntbl-insert-line--vertical {\n\twidth: 2px;\n\tbackground: linear-gradient(\n\t\t180deg,\n\t\ttransparent,\n\t\t#4a90d9 8%,\n\t\t#4a90d9 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px rgba(74, 144, 217, 0.35);\n}\n\n/* --- Insert Button on Line --- */\n.ntbl-insert-btn {\n\tposition: absolute;\n\twidth: 20px;\n\theight: 20px;\n\tborder-radius: 50%;\n\tbackground: #fff;\n\tborder: 2px solid #4a90d9;\n\tcolor: #4a90d9;\n\tcursor: pointer;\n\tpointer-events: all;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tbox-shadow: 0 2px 8px rgba(74, 144, 217, 0.25);\n\ttransition: background 0.15s, color 0.15s,\n\t\ttransform 0.15s, box-shadow 0.15s;\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn {\n\tleft: 50%;\n\ttop: -9px;\n\ttransform: translateX(-50%);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn {\n\ttop: 50%;\n\tleft: -9px;\n\ttransform: translateY(-50%);\n}\n\n.ntbl-insert-btn:hover {\n\tbackground: #4a90d9;\n\tcolor: #fff;\n\tbox-shadow: 0 2px 12px rgba(74, 144, 217, 0.45);\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn:hover {\n\ttransform: translateX(-50%) scale(1.2);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn:hover {\n\ttransform: translateY(-50%) scale(1.2);\n}\n\n/* --- Add Row / Add Column Zones --- */\n.ntbl-add-zone {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\tuser-select: none;\n\topacity: 0;\n\ttransition: opacity 0.2s ease, background 0.2s ease,\n\t\tborder-color 0.2s ease;\n}\n\n.ntbl-container:hover .ntbl-add-zone {\n\topacity: 1;\n}\n\n.ntbl-add-row {\n\tbottom: 0;\n\theight: 24px;\n\tborder: 1px dashed #d0d0d0;\n\tborder-radius: 0 0 6px 6px;\n\tborder-top: none;\n\tcolor: #aaa;\n\ttransform: translateY(100%);\n}\n\n.ntbl-add-row:hover {\n\tbackground: #f0f6ff;\n\tborder-color: #4a90d9;\n\tcolor: #4a90d9;\n}\n\n.ntbl-add-col {\n\tright: 0;\n\ttop: 24px;\n\twidth: 24px;\n\tborder: 1px dashed #d0d0d0;\n\tborder-radius: 0 6px 6px 0;\n\tborder-left: none;\n\tcolor: #aaa;\n\ttransform: translateX(100%);\n}\n\n.ntbl-add-col:hover {\n\tbackground: #f0f6ff;\n\tborder-color: #4a90d9;\n\tcolor: #4a90d9;\n}\n\n.ntbl-add-icon {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\ttransition: transform 0.2s ease;\n}\n\n.ntbl-add-zone:hover .ntbl-add-icon {\n\ttransform: scale(1.15);\n}\n\n/* Font Size Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--fontSize {\n\twidth: auto;\n\tmin-width: 60px;\n\tmax-width: 80px;\n\tpadding: 0 8px;\n\tgap: 4px;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 4px;\n\tbackground: #fff;\n}\n\n.notectl-toolbar-btn--fontSize:hover {\n\tbackground: #f5f5f5;\n\tborder-color: #b0b0b0;\n}\n\n.notectl-toolbar-btn--fontSize.notectl-toolbar-btn--active {\n\tbackground: #fff;\n\tborder-color: #a0c0e0;\n}\n\n.notectl-toolbar-btn--fontSize .notectl-toolbar-btn__icon {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\twidth: 100%;\n\toverflow: hidden;\n}\n\n.notectl-toolbar-btn--fontSize .notectl-toolbar-btn__icon svg {\n\tdisplay: none;\n}\n\n.notectl-font-size-select__label {\n\tflex: 1;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: #333;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\ttext-align: left;\n\tline-height: 30px;\n}\n\n.notectl-font-size-select__arrow {\n\tflex-shrink: 0;\n\tfont-size: 11px;\n\tcolor: #888;\n\tline-height: 30px;\n}\n\n/* Font Size Picker Popup */\n.notectl-font-size-picker {\n\tmin-width: 140px;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.notectl-font-size-picker__input-wrapper {\n\tpadding: 8px 8px 4px;\n}\n\n.notectl-font-size-picker__input {\n\twidth: 100%;\n\tpadding: 6px 8px;\n\tborder: 1px solid #d0d0d0;\n\tborder-radius: 4px;\n\tfont-size: 13px;\n\tfont-family: inherit;\n\tcolor: #333;\n\toutline: none;\n\tbox-sizing: border-box;\n\t-moz-appearance: textfield;\n}\n\n.notectl-font-size-picker__input::-webkit-inner-spin-button,\n.notectl-font-size-picker__input::-webkit-outer-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n\n.notectl-font-size-picker__input:focus {\n\tborder-color: #4a90d9;\n\tbox-shadow: 0 0 0 2px rgba(74, 144, 217, 0.2);\n}\n\n.notectl-font-size-picker__list {\n\tmax-height: 280px;\n\toverflow-y: auto;\n\tpadding: 4px 0;\n}\n\n.notectl-font-size-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: #333;\n\tline-height: 1.4;\n\ttext-align: left;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n\toutline: none;\n}\n\n.notectl-font-size-picker__item:hover {\n\tbackground: #f0f0f0;\n}\n\n.notectl-font-size-picker__item--active {\n\tbackground: #e8f0fb;\n\tcolor: #1a5fa0;\n}\n\n.notectl-font-size-picker__item--active:hover {\n\tbackground: #d0e0f0;\n}\n\n.notectl-font-size-picker__item--focused {\n\toutline: 2px solid #4a90d9;\n\toutline-offset: -2px;\n}\n\n.notectl-font-size-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: #1a5fa0;\n}\n\n.notectl-font-size-picker__label {\n\tflex: 1;\n}\n`;\n\nlet cachedStyleSheet: CSSStyleSheet | null = null;\n\n/** Returns the shared editor stylesheet. */\nexport function getEditorStyleSheet(): CSSStyleSheet {\n\tif (!cachedStyleSheet) {\n\t\tcachedStyleSheet = new CSSStyleSheet();\n\t\tcachedStyleSheet.replaceSync(EDITOR_CSS);\n\t}\n\treturn cachedStyleSheet;\n}\n","/**\n * NotectlEditor Web Component — the public-facing editor element.\n */\n\nimport DOMPurify from 'dompurify';\nimport { isMarkActive, selectAll } from '../commands/Commands.js';\nimport { DecorationSet } from '../decorations/Decoration.js';\nimport { isMarkOfType, isNodeOfType } from '../model/AttrRegistry.js';\nimport { registerBuiltinSpecs } from '../model/BuiltinSpecs.js';\nimport {\n\ttype BlockNode,\n\ttype Document,\n\ttype Mark,\n\ttype TextNode,\n\tcreateBlockNode,\n\tcreateDocument,\n\tcreateTextNode,\n\tgetBlockText,\n\tgetTextChildren,\n} from '../model/Document.js';\nimport { schemaFromRegistry } from '../model/Schema.js';\nimport { isMarkAllowed } from '../model/Schema.js';\nimport { createCollapsedSelection } from '../model/Selection.js';\nimport { blockId, nodeType, markType as toMarkType } from '../model/TypeBrands.js';\nimport type { Plugin, PluginConfig } from '../plugins/Plugin.js';\nimport { PluginManager } from '../plugins/PluginManager.js';\nimport { TextFormattingPlugin } from '../plugins/text-formatting/TextFormattingPlugin.js';\nimport type { TextFormattingConfig } from '../plugins/text-formatting/TextFormattingPlugin.js';\nimport { ToolbarPlugin } from '../plugins/toolbar/ToolbarPlugin.js';\nimport type { ToolbarLayoutConfig } from '../plugins/toolbar/ToolbarPlugin.js';\nimport { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { EditorView } from '../view/EditorView.js';\nimport { getEditorStyleSheet } from './styles.js';\n\n// --- Config Types ---\n\nexport interface NotectlEditorConfig {\n\t/** Controls which inline marks are enabled. Used to auto-configure TextFormattingPlugin. */\n\tfeatures?: Partial<TextFormattingConfig>;\n\tplugins?: Plugin[];\n\t/**\n\t * Declarative toolbar layout. Each inner array is a visual group;\n\t * separators are rendered between groups. Order = array order.\n\t * When set, a ToolbarPlugin is created internally — do not add one to `plugins`.\n\t */\n\ttoolbar?: ReadonlyArray<ReadonlyArray<Plugin>>;\n\tplaceholder?: string;\n\treadonly?: boolean;\n\tautofocus?: boolean;\n\tmaxHistoryDepth?: number;\n}\n\n// --- Event Types ---\n\nexport interface StateChangeEvent {\n\toldState: EditorState;\n\tnewState: EditorState;\n\ttransaction: Transaction;\n}\n\ntype EventMap = {\n\tstateChange: StateChangeEvent;\n\tselectionChange: { selection: import('../model/Selection.js').Selection };\n\tfocus: undefined;\n\tblur: undefined;\n\tready: undefined;\n};\n\ntype EventCallback<T> = (payload: T) => void;\n\n// --- Web Component ---\n\nexport class NotectlEditor extends HTMLElement {\n\tprivate view: EditorView | null = null;\n\tprivate pluginManager: PluginManager | null = null;\n\tprivate contentElement: HTMLElement | null = null;\n\tprivate editorWrapper: HTMLElement | null = null;\n\tprivate topPluginContainer: HTMLElement | null = null;\n\tprivate bottomPluginContainer: HTMLElement | null = null;\n\tprivate announcer: HTMLElement | null = null;\n\tprivate config: NotectlEditorConfig = {};\n\tprivate eventListeners: Map<string, Set<EventCallback<unknown>>> = new Map();\n\tprivate readyPromiseResolve: (() => void) | null = null;\n\tprivate readonly readyPromise: Promise<void>;\n\tprivate initialized = false;\n\tprivate preInitPlugins: Plugin[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.readyPromise = new Promise((resolve) => {\n\t\t\tthis.readyPromiseResolve = resolve;\n\t\t});\n\t\tthis.attachShadow({ mode: 'open' });\n\t}\n\n\tstatic get observedAttributes(): string[] {\n\t\treturn ['placeholder', 'readonly'];\n\t}\n\n\tconnectedCallback(): void {\n\t\tif (this.initialized) return;\n\t\tthis.init();\n\t}\n\n\tdisconnectedCallback(): void {\n\t\tthis.destroy();\n\t}\n\n\tattributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n\t\tif (name === 'placeholder' && this.contentElement) {\n\t\t\tthis.contentElement.setAttribute('data-placeholder', newValue ?? '');\n\t\t}\n\t\tif (name === 'readonly' && this.contentElement) {\n\t\t\tthis.contentElement.contentEditable = newValue === null ? 'true' : 'false';\n\t\t}\n\t}\n\n\t/** Registers a plugin before initialization. */\n\tregisterPlugin(plugin: Plugin): void {\n\t\tif (this.initialized) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot register plugins after initialization. Register before calling init() or adding to DOM.',\n\t\t\t);\n\t\t}\n\t\tthis.preInitPlugins.push(plugin);\n\t}\n\n\t/** Initializes the editor with the given config. */\n\tasync init(config?: NotectlEditorConfig): Promise<void> {\n\t\tif (this.initialized) return;\n\t\tthis.initialized = true;\n\n\t\tif (config) this.config = config;\n\n\t\tconst shadow = this.shadowRoot;\n\t\tif (!shadow) return;\n\t\tshadow.adoptedStyleSheets = [getEditorStyleSheet()];\n\n\t\t// 1. Build DOM structure\n\t\tthis.editorWrapper = document.createElement('div');\n\t\tthis.editorWrapper.className = 'notectl-editor';\n\n\t\tthis.topPluginContainer = document.createElement('div');\n\t\tthis.topPluginContainer.className = 'notectl-plugin-container--top';\n\n\t\tthis.contentElement = document.createElement('div');\n\t\tthis.contentElement.className = 'notectl-content';\n\t\tthis.contentElement.contentEditable = this.config.readonly ? 'false' : 'true';\n\t\tthis.contentElement.setAttribute('role', 'textbox');\n\t\tthis.contentElement.setAttribute('aria-multiline', 'true');\n\t\tthis.contentElement.setAttribute('aria-label', 'Rich text editor');\n\t\tthis.contentElement.setAttribute(\n\t\t\t'data-placeholder',\n\t\t\tthis.config.placeholder ?? 'Start typing...',\n\t\t);\n\n\t\tthis.bottomPluginContainer = document.createElement('div');\n\t\tthis.bottomPluginContainer.className = 'notectl-plugin-container--bottom';\n\n\t\t// Screen reader announcer\n\t\tthis.announcer = document.createElement('div');\n\t\tthis.announcer.className = 'notectl-sr-only';\n\t\tthis.announcer.setAttribute('aria-live', 'polite');\n\t\tthis.announcer.setAttribute('aria-atomic', 'true');\n\n\t\tthis.editorWrapper.appendChild(this.topPluginContainer);\n\t\tthis.editorWrapper.appendChild(this.contentElement);\n\t\tthis.editorWrapper.appendChild(this.bottomPluginContainer);\n\t\tthis.editorWrapper.appendChild(this.announcer);\n\n\t\tshadow.appendChild(this.editorWrapper);\n\n\t\t// 2. Create PluginManager (SchemaRegistry is available)\n\t\tthis.pluginManager = new PluginManager();\n\n\t\t// 3. Register built-in specs on the registry\n\t\tregisterBuiltinSpecs(this.pluginManager.schemaRegistry);\n\n\t\t// Process declarative toolbar config (registers ToolbarPlugin + toolbar plugins)\n\t\tthis.processToolbarConfig();\n\n\t\t// Register plugins from config\n\t\tfor (const plugin of this.config.plugins ?? []) {\n\t\t\tthis.pluginManager.register(plugin);\n\t\t}\n\n\t\t// Register plugins from registerPlugin() calls\n\t\tfor (const plugin of this.preInitPlugins) {\n\t\t\tthis.pluginManager.register(plugin);\n\t\t}\n\t\tthis.preInitPlugins = [];\n\n\t\t// Auto-register TextFormattingPlugin if none was explicitly provided\n\t\tthis.ensureTextFormattingPlugin();\n\n\t\t// Set up DOM events before plugin init\n\t\tthis.contentElement.addEventListener('focus', () => this.emit('focus', undefined));\n\t\tthis.contentElement.addEventListener('blur', () => this.emit('blur', undefined));\n\n\t\t// 4. Initialize plugins — specs are registered during init().\n\t\t// onBeforeReady fires after all init() but before onReady(),\n\t\t// so the schema is complete and the view renders once.\n\t\tconst contentEl = this.contentElement;\n\t\tconst pluginMgr = this.pluginManager;\n\t\tconst topContainer = this.topPluginContainer;\n\t\tconst bottomContainer = this.bottomPluginContainer;\n\t\tif (!contentEl || !pluginMgr || !topContainer || !bottomContainer) return;\n\n\t\tawait pluginMgr.init({\n\t\t\tgetState: () => {\n\t\t\t\tif (!this.view) throw new Error('View not initialized');\n\t\t\t\treturn this.view.getState();\n\t\t\t},\n\t\t\tdispatch: (tr) => this.dispatch(tr),\n\t\t\tgetContainer: () => contentEl,\n\t\t\tgetPluginContainer: (position) => (position === 'top' ? topContainer : bottomContainer),\n\t\t\tonBeforeReady: () => {\n\t\t\t\tconst schema = schemaFromRegistry(pluginMgr.schemaRegistry);\n\t\t\t\tconst state = EditorState.create({ schema });\n\t\t\t\tthis.view = new EditorView(contentEl, {\n\t\t\t\t\tstate,\n\t\t\t\t\tschemaRegistry: pluginMgr.schemaRegistry,\n\t\t\t\t\tmaxHistoryDepth: this.config.maxHistoryDepth,\n\t\t\t\t\tgetDecorations: (s, tr) =>\n\t\t\t\t\t\tthis.pluginManager?.collectDecorations(s, tr) ?? DecorationSet.empty,\n\t\t\t\t\tonStateChange: (oldState, newState, tr) => {\n\t\t\t\t\t\tthis.onStateChange(oldState, newState, tr);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tthis.updateEmptyState();\n\t\t\t},\n\t\t});\n\n\t\tif (this.config.autofocus) {\n\t\t\trequestAnimationFrame(() => this.contentElement?.focus());\n\t\t}\n\n\t\tthis.readyPromiseResolve?.();\n\t\tthis.emit('ready', undefined);\n\t}\n\n\t// --- Content API ---\n\n\t/** Returns the document as JSON. */\n\tgetJSON(): Document {\n\t\tif (!this.view) throw new Error('Editor not initialized');\n\t\treturn this.view.getState().doc;\n\t}\n\n\t/** Sets the document from JSON. */\n\tsetJSON(doc: Document): void {\n\t\tconst schema = this.pluginManager\n\t\t\t? schemaFromRegistry(this.pluginManager.schemaRegistry)\n\t\t\t: undefined;\n\t\tconst state = EditorState.create({\n\t\t\tdoc,\n\t\t\tschema,\n\t\t\tselection: createCollapsedSelection(doc.children[0]?.id ?? blockId(''), 0),\n\t\t});\n\t\tthis.replaceState(state);\n\t}\n\n\t/** Returns sanitized HTML representation of the document. */\n\tgetHTML(): string {\n\t\tif (!this.view) throw new Error('Editor not initialized');\n\t\tconst doc = this.view.getState().doc;\n\t\tconst parts: string[] = [];\n\t\tlet currentListTag: string | null = null;\n\n\t\tfor (const block of doc.children) {\n\t\t\tif (isNodeOfType(block, 'list_item')) {\n\t\t\t\tconst listType = block.attrs.listType;\n\t\t\t\tconst tag = listType === 'ordered' ? 'ol' : 'ul';\n\n\t\t\t\tif (currentListTag !== tag) {\n\t\t\t\t\tif (currentListTag) parts.push(`</${currentListTag}>`);\n\t\t\t\t\tparts.push(`<${tag}>`);\n\t\t\t\t\tcurrentListTag = tag;\n\t\t\t\t}\n\n\t\t\t\tconst inner = getTextChildren(block)\n\t\t\t\t\t.map((c) => this.textNodeToHTML(c))\n\t\t\t\t\t.join('');\n\t\t\t\tparts.push(`<li>${inner || '<br>'}</li>`);\n\t\t\t} else {\n\t\t\t\tif (currentListTag) {\n\t\t\t\t\tparts.push(`</${currentListTag}>`);\n\t\t\t\t\tcurrentListTag = null;\n\t\t\t\t}\n\t\t\t\tparts.push(this.blockToHTML(block));\n\t\t\t}\n\t\t}\n\n\t\tif (currentListTag) parts.push(`</${currentListTag}>`);\n\n\t\treturn DOMPurify.sanitize(parts.join(''), {\n\t\t\tALLOWED_TAGS: [\n\t\t\t\t'p',\n\t\t\t\t'strong',\n\t\t\t\t'em',\n\t\t\t\t'u',\n\t\t\t\t'b',\n\t\t\t\t'i',\n\t\t\t\t'br',\n\t\t\t\t'div',\n\t\t\t\t'hr',\n\t\t\t\t'h1',\n\t\t\t\t'h2',\n\t\t\t\t'h3',\n\t\t\t\t'h4',\n\t\t\t\t'h5',\n\t\t\t\t'h6',\n\t\t\t\t'ul',\n\t\t\t\t'ol',\n\t\t\t\t'li',\n\t\t\t\t'a',\n\t\t\t\t's',\n\t\t\t\t'span',\n\t\t\t\t'blockquote',\n\t\t\t],\n\t\t\tALLOWED_ATTR: ['href', 'target', 'rel', 'style'],\n\t\t});\n\t}\n\n\t/** Sets content from HTML (sanitized). */\n\tsetHTML(html: string): void {\n\t\tconst sanitized = DOMPurify.sanitize(html, {\n\t\t\tALLOWED_TAGS: [\n\t\t\t\t'p',\n\t\t\t\t'strong',\n\t\t\t\t'em',\n\t\t\t\t'u',\n\t\t\t\t'b',\n\t\t\t\t'i',\n\t\t\t\t'br',\n\t\t\t\t'div',\n\t\t\t\t'hr',\n\t\t\t\t'h1',\n\t\t\t\t'h2',\n\t\t\t\t'h3',\n\t\t\t\t'h4',\n\t\t\t\t'h5',\n\t\t\t\t'h6',\n\t\t\t\t'ul',\n\t\t\t\t'ol',\n\t\t\t\t'li',\n\t\t\t\t'a',\n\t\t\t\t's',\n\t\t\t\t'span',\n\t\t\t\t'blockquote',\n\t\t\t],\n\t\t\tALLOWED_ATTR: ['href', 'target', 'rel', 'style'],\n\t\t});\n\n\t\tconst doc = this.parseHTMLToDocument(sanitized);\n\t\tthis.setJSON(doc);\n\t}\n\n\t/** Returns plain text content. */\n\tgetText(): string {\n\t\tif (!this.view) throw new Error('Editor not initialized');\n\t\tconst doc = this.view.getState().doc;\n\t\treturn doc.children.map((b) => getBlockText(b)).join('\\n');\n\t}\n\n\t/** Returns true if the editor is empty (single empty paragraph). */\n\tisEmpty(): boolean {\n\t\tif (!this.view) return true;\n\t\tconst doc = this.view.getState().doc;\n\t\tif (doc.children.length === 0) return true;\n\t\tif (doc.children.length > 1) return false;\n\t\tconst block = doc.children[0];\n\t\tif (!block) return true;\n\t\treturn block.type === 'paragraph' && getBlockText(block) === '';\n\t}\n\n\t// --- Command API ---\n\n\treadonly commands = {\n\t\ttoggleBold: () => this.executeCommand('toggleBold'),\n\t\ttoggleItalic: () => this.executeCommand('toggleItalic'),\n\t\ttoggleUnderline: () => this.executeCommand('toggleUnderline'),\n\t\tundo: () => this.view?.undo(),\n\t\tredo: () => this.view?.redo(),\n\t\tselectAll: () => {\n\t\t\tif (!this.view) return;\n\t\t\tconst tr = selectAll(this.view.getState());\n\t\t\tthis.dispatch(tr);\n\t\t},\n\t};\n\n\t/** Checks whether a command can be executed. */\n\tcan(): {\n\t\ttoggleBold: () => boolean;\n\t\ttoggleItalic: () => boolean;\n\t\ttoggleUnderline: () => boolean;\n\t\tundo: () => boolean;\n\t\tredo: () => boolean;\n\t} {\n\t\tconst schema = this.view?.getState().schema;\n\t\treturn {\n\t\t\ttoggleBold: () => (schema ? isMarkAllowed(schema, 'bold') : false),\n\t\t\ttoggleItalic: () => (schema ? isMarkAllowed(schema, 'italic') : false),\n\t\t\ttoggleUnderline: () => (schema ? isMarkAllowed(schema, 'underline') : false),\n\t\t\tundo: () => this.view?.history.canUndo() ?? false,\n\t\t\tredo: () => this.view?.history.canRedo() ?? false,\n\t\t};\n\t}\n\n\t/** Executes a named command registered by a plugin. */\n\texecuteCommand(name: string): boolean {\n\t\treturn this.pluginManager?.executeCommand(name) ?? false;\n\t}\n\n\t/** Configures a plugin at runtime. */\n\tconfigurePlugin(pluginId: string, config: PluginConfig): void {\n\t\tthis.pluginManager?.configurePlugin(pluginId, config);\n\t}\n\n\t// --- State API ---\n\n\t/** Returns the current editor state. */\n\tgetState(): EditorState {\n\t\tif (!this.view) throw new Error('Editor not initialized');\n\t\treturn this.view.getState();\n\t}\n\n\t/** Dispatches a transaction (routed through middleware if any). */\n\tdispatch(tr: Transaction): void {\n\t\tif (!this.view || !this.pluginManager) return;\n\t\tthis.pluginManager.dispatchWithMiddleware(tr, this.view.getState(), (finalTr) =>\n\t\t\tthis.view?.dispatch(finalTr),\n\t\t);\n\t}\n\n\t// --- Event API ---\n\n\t/** Registers an event listener. */\n\ton<K extends keyof EventMap>(event: K, callback: EventCallback<EventMap[K]>): void {\n\t\tif (!this.eventListeners.has(event)) {\n\t\t\tthis.eventListeners.set(event, new Set());\n\t\t}\n\t\tthis.eventListeners.get(event)?.add(callback as EventCallback<unknown>);\n\t}\n\n\t/** Removes an event listener. */\n\toff<K extends keyof EventMap>(event: K, callback: EventCallback<EventMap[K]>): void {\n\t\tthis.eventListeners.get(event)?.delete(callback as EventCallback<unknown>);\n\t}\n\n\t// --- Lifecycle ---\n\n\t/** Waits for the editor to be ready. */\n\twhenReady(): Promise<void> {\n\t\treturn this.readyPromise;\n\t}\n\n\t/** Updates configuration at runtime. */\n\tconfigure(config: Partial<NotectlEditorConfig>): void {\n\t\tif (config.placeholder !== undefined && this.contentElement) {\n\t\t\tthis.contentElement.setAttribute('data-placeholder', config.placeholder);\n\t\t}\n\n\t\tif (config.readonly !== undefined && this.contentElement) {\n\t\t\tthis.contentElement.contentEditable = config.readonly ? 'false' : 'true';\n\t\t}\n\n\t\tthis.config = { ...this.config, ...config };\n\t}\n\n\t/** Cleans up the editor. Awaiting ensures async plugin teardown completes. */\n\tdestroy(): Promise<void> {\n\t\tthis.view?.destroy();\n\t\tconst pluginTeardown = this.pluginManager?.destroy() ?? Promise.resolve();\n\t\tthis.view = null;\n\t\tthis.pluginManager = null;\n\t\tthis.initialized = false;\n\t\treturn pluginTeardown;\n\t}\n\n\t// --- Private ---\n\n\t/**\n\t * Processes the declarative `toolbar` config: registers a ToolbarPlugin\n\t * with layout groups, then registers all plugins from the toolbar groups.\n\t */\n\tprivate processToolbarConfig(): void {\n\t\tif (!this.pluginManager || !this.config.toolbar) return;\n\n\t\tconst groups: string[][] = [];\n\t\tfor (const group of this.config.toolbar) {\n\t\t\tconst pluginIds: string[] = [];\n\t\t\tfor (const plugin of group) {\n\t\t\t\tpluginIds.push(plugin.id);\n\t\t\t\tthis.pluginManager.register(plugin);\n\t\t\t}\n\t\t\tgroups.push(pluginIds);\n\t\t}\n\n\t\tconst layoutConfig: ToolbarLayoutConfig = { groups };\n\t\tthis.pluginManager.register(new ToolbarPlugin(layoutConfig));\n\t}\n\n\t/**\n\t * Auto-registers TextFormattingPlugin if no plugin with id 'text-formatting'\n\t * was explicitly registered. Uses the `features` config to determine which marks to enable.\n\t */\n\tprivate ensureTextFormattingPlugin(): void {\n\t\tif (!this.pluginManager) return;\n\n\t\tconst hasTextFormatting = this.pluginManager.get('text-formatting') !== undefined;\n\t\tif (hasTextFormatting) return;\n\n\t\tconst features: TextFormattingConfig = {\n\t\t\tbold: this.config.features?.bold ?? true,\n\t\t\titalic: this.config.features?.italic ?? true,\n\t\t\tunderline: this.config.features?.underline ?? true,\n\t\t};\n\n\t\tthis.pluginManager.register(new TextFormattingPlugin(features));\n\t}\n\n\tprivate emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n\t\tconst listeners = this.eventListeners.get(event);\n\t\tif (listeners) {\n\t\t\tfor (const cb of listeners) {\n\t\t\t\t(cb as EventCallback<EventMap[K]>)(payload);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onStateChange(oldState: EditorState, newState: EditorState, tr: Transaction): void {\n\t\t// Notify plugins (with transaction)\n\t\tthis.pluginManager?.notifyStateChange(oldState, newState, tr);\n\n\t\t// Update empty state\n\t\tthis.updateEmptyState();\n\n\t\t// Emit events\n\t\tthis.emit('stateChange', { oldState, newState, transaction: tr });\n\n\t\tif (\n\t\t\toldState.selection.anchor.blockId !== newState.selection.anchor.blockId ||\n\t\t\toldState.selection.anchor.offset !== newState.selection.anchor.offset ||\n\t\t\toldState.selection.head.blockId !== newState.selection.head.blockId ||\n\t\t\toldState.selection.head.offset !== newState.selection.head.offset\n\t\t) {\n\t\t\tthis.emit('selectionChange', { selection: newState.selection });\n\t\t}\n\n\t\t// Announce formatting changes for screen readers\n\t\tthis.announceFormatChange(oldState, newState);\n\t}\n\n\tprivate updateEmptyState(): void {\n\t\tif (!this.contentElement) return;\n\t\tthis.contentElement.classList.toggle('notectl-content--empty', this.isEmpty());\n\t}\n\n\tprivate announceFormatChange(oldState: EditorState, newState: EditorState): void {\n\t\tif (!this.announcer) return;\n\n\t\t// Announce changes for all mark types in the schema\n\t\tconst markTypes = newState.schema.markTypes;\n\t\tfor (const mt of markTypes) {\n\t\t\tconst branded = toMarkType(mt);\n\t\t\tconst wasActive = isMarkActive(oldState, branded);\n\t\t\tconst nowActive = isMarkActive(newState, branded);\n\t\t\tif (wasActive !== nowActive) {\n\t\t\t\tthis.announcer.textContent = `${mt} ${nowActive ? 'on' : 'off'}`;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate replaceState(newState: EditorState): void {\n\t\tif (!this.view) return;\n\n\t\tthis.view.replaceState(newState);\n\t\tthis.updateEmptyState();\n\t}\n\n\tprivate blockToHTML(block: BlockNode): string {\n\t\tif (block.type === 'horizontal_rule') {\n\t\t\treturn '<hr>';\n\t\t}\n\n\t\tconst inner = getTextChildren(block)\n\t\t\t.map((child) => this.textNodeToHTML(child))\n\t\t\t.join('');\n\t\tconst content = inner || '<br>';\n\n\t\tconst align: string | undefined = (block.attrs as Record<string, unknown>)?.textAlign as\n\t\t\t| string\n\t\t\t| undefined;\n\t\tconst style: string = align && align !== 'left' ? ` style=\"text-align: ${align}\"` : '';\n\n\t\tif (isNodeOfType(block, 'heading')) {\n\t\t\tconst level = block.attrs.level;\n\t\t\tconst tag: string = `h${Math.max(1, Math.min(6, level))}`;\n\t\t\treturn `<${tag}${style}>${content}</${tag}>`;\n\t\t}\n\n\t\tif (block.type === 'blockquote') {\n\t\t\treturn `<blockquote${style}>${content}</blockquote>`;\n\t\t}\n\n\t\treturn `<p${style}>${content}</p>`;\n\t}\n\n\tprivate textNodeToHTML(node: TextNode): string {\n\t\tif (node.text === '') return '';\n\n\t\tlet html = this.escapeHTML(node.text);\n\n\t\t// Sort marks by MarkSpec.rank from the schema registry (lower = closer to text)\n\t\tconst markOrder = this.getMarkOrder();\n\t\tconst sortedMarks = [...node.marks].sort(\n\t\t\t(a, b) => (markOrder.get(a.type) ?? 99) - (markOrder.get(b.type) ?? 99),\n\t\t);\n\n\t\tfor (const mark of sortedMarks) {\n\t\t\tif (isMarkOfType(mark, 'bold')) {\n\t\t\t\thtml = `<strong>${html}</strong>`;\n\t\t\t} else if (isMarkOfType(mark, 'italic')) {\n\t\t\t\thtml = `<em>${html}</em>`;\n\t\t\t} else if (isMarkOfType(mark, 'underline')) {\n\t\t\t\thtml = `<u>${html}</u>`;\n\t\t\t} else if (isMarkOfType(mark, 'strikethrough')) {\n\t\t\t\thtml = `<s>${html}</s>`;\n\t\t\t} else if (isMarkOfType(mark, 'textColor')) {\n\t\t\t\tconst color = this.escapeHTML(mark.attrs.color);\n\t\t\t\thtml = `<span style=\"color: ${color}\">${html}</span>`;\n\t\t\t} else if (isMarkOfType(mark, 'font')) {\n\t\t\t\tconst family: string = mark.attrs?.family ?? '';\n\t\t\t\tif (family) {\n\t\t\t\t\thtml = `<span style=\"font-family: ${this.escapeHTML(family)}\">${html}</span>`;\n\t\t\t\t}\n\t\t\t} else if (isMarkOfType(mark, 'link')) {\n\t\t\t\tconst href = this.escapeHTML(mark.attrs.href);\n\t\t\t\thtml = `<a href=\"${href}\">${html}</a>`;\n\t\t\t}\n\t\t}\n\n\t\treturn html;\n\t}\n\n\tprivate getMarkOrder(): Map<string, number> {\n\t\tconst registry = this.pluginManager?.schemaRegistry;\n\t\tif (!registry) return new Map();\n\t\tconst types = registry.getMarkTypes();\n\t\tconst order = new Map<string, number>();\n\t\tfor (const t of types) {\n\t\t\tconst spec = registry.getMarkSpec(t);\n\t\t\tif (spec) order.set(t, spec.rank ?? 99);\n\t\t}\n\t\treturn order;\n\t}\n\n\tprivate escapeHTML(text: string): string {\n\t\treturn text\n\t\t\t.replace(/&/g, '&')\n\t\t\t.replace(/</g, '<')\n\t\t\t.replace(/>/g, '>')\n\t\t\t.replace(/\"/g, '"');\n\t}\n\n\tprivate parseHTMLToDocument(html: string): Document {\n\t\tconst template = document.createElement('template');\n\t\ttemplate.innerHTML = DOMPurify.sanitize(html);\n\t\tconst root = template.content;\n\n\t\tconst blocks: BlockNode[] = [];\n\n\t\tfor (const child of Array.from(root.childNodes)) {\n\t\t\tif (child.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\tconst el = child as HTMLElement;\n\t\t\t\tconst tag = el.tagName.toLowerCase();\n\n\t\t\t\t// Headings\n\t\t\t\tconst headingMatch = /^h([1-6])$/.exec(tag);\n\t\t\t\tif (headingMatch) {\n\t\t\t\t\tconst level = Number(headingMatch[1]);\n\t\t\t\t\tconst textNodes = this.parseElementToTextNodes(el);\n\t\t\t\t\tblocks.push(createBlockNode(nodeType('heading'), textNodes, undefined, { level }));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Horizontal Rule\n\t\t\t\tif (tag === 'hr') {\n\t\t\t\t\tblocks.push(createBlockNode(nodeType('horizontal_rule')));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Lists\n\t\t\t\tif (tag === 'ul' || tag === 'ol') {\n\t\t\t\t\tconst listType = tag === 'ol' ? 'ordered' : 'bullet';\n\t\t\t\t\tfor (const li of Array.from(el.querySelectorAll('li'))) {\n\t\t\t\t\t\tconst textNodes = this.parseElementToTextNodes(li as HTMLElement);\n\t\t\t\t\t\tblocks.push(\n\t\t\t\t\t\t\tcreateBlockNode(nodeType('list_item'), textNodes, undefined, {\n\t\t\t\t\t\t\t\tlistType,\n\t\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\t\tchecked: false,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Regular blocks (p, div, etc.)\n\t\t\t\tconst textNodes = this.parseElementToTextNodes(el);\n\t\t\t\tblocks.push(createBlockNode(nodeType('paragraph'), textNodes));\n\t\t\t} else if (child.nodeType === Node.TEXT_NODE && child.textContent?.trim()) {\n\t\t\t\tblocks.push(\n\t\t\t\t\tcreateBlockNode(nodeType('paragraph'), [createTextNode(child.textContent.trim())]),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (blocks.length === 0) {\n\t\t\treturn createDocument();\n\t\t}\n\n\t\treturn createDocument(blocks);\n\t}\n\n\tprivate parseElementToTextNodes(el: HTMLElement): TextNode[] {\n\t\tconst result: TextNode[] = [];\n\t\tthis.walkElement(el, [], result);\n\t\treturn result.length > 0 ? result : [createTextNode('')];\n\t}\n\n\tprivate walkElement(node: Node, currentMarks: Mark[], result: TextNode[]): void {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? '';\n\t\t\tif (text) {\n\t\t\t\tresult.push(createTextNode(text, [...currentMarks]));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (node.nodeType !== Node.ELEMENT_NODE) return;\n\n\t\tconst el = node as HTMLElement;\n\t\tconst tag = el.tagName.toLowerCase();\n\n\t\tconst marks = [...currentMarks];\n\t\tif (tag === 'strong' || tag === 'b') {\n\t\t\tif (!marks.some((m) => m.type === 'bold')) marks.push({ type: toMarkType('bold') });\n\t\t}\n\t\tif (tag === 'em' || tag === 'i') {\n\t\t\tif (!marks.some((m) => m.type === 'italic')) marks.push({ type: toMarkType('italic') });\n\t\t}\n\t\tif (tag === 'u') {\n\t\t\tif (!marks.some((m) => m.type === 'underline')) marks.push({ type: toMarkType('underline') });\n\t\t}\n\t\tif (tag === 's') {\n\t\t\tif (!marks.some((m) => m.type === 'strikethrough'))\n\t\t\t\tmarks.push({ type: toMarkType('strikethrough') });\n\t\t}\n\t\tif (tag === 'span') {\n\t\t\tconst color = el.style.color;\n\t\t\tif (color && !marks.some((m) => m.type === 'textColor')) {\n\t\t\t\tmarks.push({ type: toMarkType('textColor'), attrs: { color } });\n\t\t\t}\n\t\t\tconst fontFamily = el.style.fontFamily;\n\t\t\tif (fontFamily && !marks.some((m) => m.type === 'font')) {\n\t\t\t\tmarks.push({ type: toMarkType('font'), attrs: { family: fontFamily } });\n\t\t\t}\n\t\t}\n\t\tif (tag === 'a') {\n\t\t\tconst href = (el as HTMLAnchorElement).getAttribute('href') ?? '';\n\t\t\tif (!marks.some((m) => m.type === 'link'))\n\t\t\t\tmarks.push({ type: toMarkType('link'), attrs: { href } });\n\t\t}\n\n\t\tfor (const child of Array.from(el.childNodes)) {\n\t\t\tthis.walkElement(child, marks, result);\n\t\t}\n\t}\n}\n\n// Register custom element\nif (!customElements.get('notectl-editor')) {\n\tcustomElements.define('notectl-editor', NotectlEditor);\n}\n\n/** Factory function to create and configure a NotectlEditor instance. */\nexport async function createEditor(config?: NotectlEditorConfig): Promise<NotectlEditor> {\n\tconst editor = document.createElement('notectl-editor') as NotectlEditor;\n\tawait editor.init(config);\n\treturn editor;\n}\n"],"names":["getBlockSegmentsInRange","block","from","to","inlineChildren","getInlineChildren","segments","pos","child","childWidth","isInlineNode","childEnd","sliceFrom","sliceTo","text","isTextNode","node","isBlockNode","isLeafBlock","c","getTextChildren","getBlockChildren","generateBlockId","createDocument","children","createBlockNode","type","id","attrs","createTextNode","marks","createInlineNode","inlineType","getBlockText","getBlockLength","len","getBlockMarksAtOffset","offset","end","i","marksEqual","a","b","aAttrs","bAttrs","aKeys","bKeys","key","markSetsEqual","markA","markB","hasMark","markType","m","addMarkToSet","mark","removeMarkFromSet","normalizeTextNodes","nodes","result","prev","normalizeInlineContent","cleaned","next","walkInlineContent","width","getContentAtOffset","localOffset","createPosition","blockId","path","createSelection","anchor","head","createCollapsedSelection","isCollapsed","sel","isForward","blockOrder","anchorIdx","headIdx","selectionRange","defaultSchema","schemaFromRegistry","registry","isMarkAllowed","schema","nodeType","name","pluginId","commandName","isNodeOfType","isMarkOfType","isInlineNodeOfType","inlineNodeType","createBlockElement","tag","el","SchemaRegistry","__publicField","spec","factory","keymap","existing","idx","rule","item","ids","items","resolveNodeByPath","doc","current","childId","resolveParentByPath","index","parentPath","parent","findNodePath","nodeId","subPath","findNodePathInBlock","walkNodes","callback","walkNodeRecursive","findNode","found","findNodeInBlock","findNodeWithPath","canContain","parentType","childType","parentSpec","childSpec","childGroup","allowed","validateContent","childTypes","min","max","blockChildTypes","t","registerBuiltinSpecs","applyStep","step","applyInsertText","applyDeleteText","applySplitBlock","applyMergeBlocks","applyAddMark","applyRemoveMark","applySetBlockType","applyInsertNode","applyRemoveNode","applySetNodeAttr","applyInsertInlineNode","applyRemoveInlineNode","applySetInlineNodeAttr","mapBlock","newChildren","insertSegmentsIntoInlineContent","insertTextIntoInlineContent","replaceInlineChildren","deleteFromInlineContent","blockIndex","nodesBeforeSplit","sliceInlineContent","nodesAfterSplit","updatedBlock","newBlock","splitBlockRecursive","changed","mapped","targetIndex","sourceIndex","target","source","targetInline","sourceInline","mergedChildren","mergedBlock","mergeBlocksRecursive","targetIdx","sourceIdx","applyMarkToInlineContent","insertInlineNodeAtOffset","removeInlineNodeAtOffset","setInlineNodeAttrsAtOffset","fn","mapBlockInChildren","mappedChildren","original","newInlineChildren","blockChildren","inserted","nodeEnd","before","after","seg","deleteFrom","deleteTo","remaining","add","newMarks","overlapStart","overlapEnd","beforeText","insideText","afterText","inlineNode","mapNodeByPath","rootId","mapNodeByPathRecursive","depth","targetId","invertStep","invertTransaction","tr","TransactionBuilder","currentSelection","currentStoredMarks","origin","deletedText","deletedMarks","deletedSegments","newBlockId","targetBlockId","sourceBlockId","targetLengthBefore","targetBlock","removedNode","resolveRemovedNode","content","selection","previousMarks","EditorState","storedMarks","options","firstBlock","validateSelection","buildBlockMap","buildBlockOrder","parentId","json","validatePosition","length","map","walk","blocks","order","DEFAULT_GROUP_TIMEOUT_MS","DEFAULT_MAX_DEPTH","HistoryManager","now","lastGroup","state","group","currentState","allSteps","inverted","transaction","incoming","lastTr","lastStepType","_a","incomingStepType","_b","defaultFeatures","toggleMark","features","isFeatureGated","anchorBlock","currentMarks","range","builder","fromIdx","toIdx","shouldRemove","isMarkActiveInRange","blockLen","isMarkActiveInBlock","toggleBold","toggleItalic","toggleUnderline","insertTextCommand","resolveActiveMarks","addDeleteSelectionSteps","insertBlockId","insertOffset","deleteSelectionCommand","deleteBackward","mergeBlockBackward","deleteForward","mergeBlockForward","deleteWordBackward","wordStart","findWordBoundaryBackward","deleteWordForward","wordEnd","findWordBoundaryForward","deleteSoftLineBackward","deleteSoftLineForward","splitBlockCommand","sharesParent","blockIdA","blockIdB","pathA","pathB","isInsideIsolating","getNodeSpec","ancestorId","ancestor","blockIdx","prevBlockId","prevBlock","prevLen","nextBlockId","selectAll","lastBlock","lastBlockLen","isMarkActive","firstLen","midBlockId","midBlock","midLen","KeyboardHandler","element","e","descriptor","normalizeKeyDescriptor","keymaps","handler","parts","EventKey","ServiceKey","EventBus","payload","set","listener","err","mapDecorationThroughStep","deco","mapInline","mapWidget","mapNode","mapInlineInsert","mapInlineDelete","mapInlineSplit","mapInlineMerge","removeIfBlockDeleted","mapWidgetInsert","mapWidgetDelete","mapWidgetSplit","mapWidgetMerge","mapNodeMerge","newFrom","newTo","delLen","clampAndShift","left","right","delFrom","delTo","inline","widget","toDOM","_DecorationSet","byBlock","decorations","decos","d","bid","predicate","filtered","other","otherDecos","decorationArraysEqual","r","DecorationSet","ai","bi","decorationsEqual","attrsEqual","bn","bw","DEFAULT_PRIORITY","PluginManager","plugin","context","oldState","newState","finalDispatch","sorted","dispatched","currentTr","entry","called","guardedNext","config","reversed","reg","serviceId","unsub","itemId","pluginEventBus","middleware","priority","service","dep","inDegree","dependents","deps","depList","queue","deg","pa","pb","newDeg","missing","ToolbarServiceKey","ToolbarPlugin","layoutConfig","_oldState","_tr","value","button","root","rect","container","btn","sep","firstGroup","groupPluginIds","groupItems","pId","groups","list","span","popup","grid","label","cell","cells","otherR","otherC","iconSpan","labelSpan","active","enabled","_d","_c","formatShortcut","binding","DEFAULT_CONFIG","MARK_DEFINITIONS","TextFormattingPlugin","enabledMarks","def","lastVisibleMark","isSeparatorTarget","separatorAfter","toCommandName","toolbarVisible","featureEnabled","configKey","HEADING_TAGS","HEADING_LABELS","TITLE_LABEL","SUBTITLE_LABEL","PARAGRAPH_LABEL","HeadingPlugin","level","hashes","pattern","_match","start","_end","icon","ctx","currentType","activeLevel","addItem","command","style","isActive","check","LinkPlugin","openInNewTab","href","sum","textChildren","cursorIdx","cursorEntry","startIdx","endIdx","startEntry","endEntry","linkStart","linkEnd","removeBtn","input","applyBtn","LIST_TYPE_DEFINITIONS","ListPlugin","listType","indent","checked","li","enabledTypes","match","matchStr","matchLen","lastType","BlockquotePlugin","StrikethroughPlugin","HEX_COLOR_PATTERN","isValidHexColor","resolveColors","colors","COLOR_PALETTE","invalid","seen","unique","color","normalized","TextColorPlugin","activeColor","defaultBtn","swatch","HorizontalRulePlugin","_start","newParagraph","hrBlock","ALIGNMENT_LABELS","ALIGNMENT_ICONS","TextAlignmentPlugin","originalToDOM","applyAlignment","alignment","capitalize","bindings","dropdownItems","_state","patched","patchedSteps","prevAlign","newAttrs","align","s","FontPlugin","family","f","first","activeFamily","displayName","fontMark","rules","font","face","declarations","activeFont","defaultFamily","isDefault","DEFAULT_FONT_SIZES","DEFAULT_FONT_SIZE","MIN_CUSTOM_SIZE","MAX_CUSTOM_SIZE","FontSizePlugin","resolveSizes","resolveDefaultSize","size","activeSize","raw","parsed","direction","currentSize","focusedIndex","inputWrapper","activeIdx","activeItem","setFocusedIndex","focused","val","selectedSize","sizes","n","FIRA_CODE_WOFF2_DATA","FIRA_SANS_WOFF2_DATA","FIRA_CODE","FIRA_SANS","STARTER_FONTS","createTable","rows","cols","tableId","rowNodes","cellNodes","createTableRow","createTableCell","findTableContext","tableNode","tableIndex","cellId","rowId","rowIndex","rowNode","colIndex","totalCols","totalRows","getCellAt","table","row","isInsideTable","insertTable","currentBlockId","rootIndex","rootBlock","paragraphAfter","insertIndex","firstRow","firstCell","addRowAbove","tableCtx","newRow","addRowBelow","addColumnLeft","addColumn","addColumnRight","side","insertColIndex","newCell","deleteRow","deleteTable","targetRowIndex","targetCellId","deleteColumn","targetColIndex","blockAfterIndex","blockBeforeIndex","afterBlock","beforeBlock","registerTableCommands","registerTableKeymaps","handleTab","handleShiftTab","handleEnter","handleBackspace","handleDelete","handleArrowDown","handleArrowUp","handleArrowRight","handleArrowLeft","handleEscape","moveToCellAndSelect","moveToCellAtEnd","nextIndex","nextBlock","cellLen","reconcile","oldBlocks","newBlocks","nodeViews","oldBlockMap","newBlockIds","nv","oldBlockById","previousSibling","existingEl","oldBlock","oldDecos","newDecos","blockChanged","existingNv","_e","newEl","renderBlock","oldAttrs","oldKeys","newKeys","oldChild","newChild","inlineAttrsEqual","oldArr","newArr","inlineDecos","contentDOM","childEl","applyNodeDecorations","renderBlockContent","renderParagraphFallback","renderTextNode","renderInlineNode","renderDecoratedContent","p","preserveSpaces","textNode","sortedMarks","markOrder","createMarkElement","globalOffset","textFrom","textTo","splitSet","dFrom","dTo","splits","localFrom","localTo","activeDecos","j","createDecorationElement","tagName","cls","nodeDecos","PLUS_SVG","DELETE_SVG","BORDER_THRESHOLD","insertRowAtIndex","getState","dispatch","numCols","insertColumnAtIndex","deleteRowAtIndex","deleteEntireTable","targetRow","deleteColumnAtIndex","targetCol","createButton","className","innerHTML","title","buildInsertLine","orientation","line","buildAddButton","buildHandleBar","bar","buildHandle","onDelete","handle","deleteBtn","createTableControls","tableEl","initialNode","numRows","countRows","countCols","colBar","rowBar","insertLineH","insertLineV","addRowZone","addColZone","activeRowIndex","activeColIndex","rebuildColHandles","rebuildRowHandles","insertBtnH","insertBtnV","onMouseMove","onMouseLeave","observer","positionControls","getTableOffset","top","measureRowBorders","trs","tableTop","borders","measureColBorders","colWidth","positionColHandles","positionRowHandles","positionAddButtons","handles","tableWidth","h","totalHeight","height","tableHeight","tableRect","x","y","hideInsertLines","rowBorders","nearestRowDist","nearestRowBorder","border","dist","colBorders","nearestColDist","nearestColBorder","showHorizontalLine","hideVerticalLine","showVerticalLine","hideHorizontalLine","newRows","newCols","createTableNodeViewFactory","_registry","wrapper","tbody","liveRegion","controls","updatedNode","updatedRows","newTotalRows","newTotalCols","createTableRowNodeViewFactory","_getState","_dispatch","createTableCellNodeViewFactory","td","colspan","rowspan","newColspan","newRowspan","TableSelectionServiceKey","createTableSelectionService","selectedRange","cachedCellIds","cachedCellIdSet","updateCache","minRow","maxRow","minCol","maxCol","updateCellHighlights","selectedIds","installMouseSelection","anchorCell","isDragging","handleMouseDown","cellEl","handleMouseMove","handleMouseUp","TABLE_ICON","TablePlugin","maxRows","maxCols","HIGHLIGHT_PALETTE","HighlightPlugin","SUPERSCRIPT_ICON","SUBSCRIPT_ICON","SuperSubPlugin","markName","removeStep","storedMarksAfter","hasSup","hasSub","lastSupIdx","lastSubIdx","removeType","InputHandler","composedText","textBefore","PasteHandler","clipboardData","html","sanitized","DOMPurify","template","getSelection","syncSelectionToDOM","domSel","anchorPos","statePositionToDOM","headPos","readSelectionFromDOM","anchorNode","focusNode","domPositionToState","blockEl","walker","createInlineContentWalker","childIndex","childIndexOf","lastChild","domOffset","findBlockElement","rawBlockId","buildBlockPath","childOffset","childIdx","inlineContentWidth","walkerNode","leafBlockEl","isInsideInlineElement","EditorView","contentElement","oldDecorations","newDecorations","cb","currentSel","shadowRoot","activeEl","EDITOR_CSS","cachedStyleSheet","getEditorStyleSheet","NotectlEditor","resolve","_oldValue","newValue","shadow","contentEl","pluginMgr","topContainer","bottomContainer","position","currentListTag","inner","finalTr","event","pluginTeardown","pluginIds","listeners","markTypes","mt","branded","wasActive","nowActive","types","headingMatch","textNodes","fontFamily","createEditor","editor"],"mappings":"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AAA;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;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;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;AAAA;AAAA;A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"}
|