@inkami/blx 0.17.3
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/README.md +98 -0
- package/dist/attributed-string/attributed-string.d.ts +37 -0
- package/dist/attributed-string/index.d.ts +2 -0
- package/dist/attributed-string/types.d.ts +13 -0
- package/dist/autocomplete/autocomplete-menu.d.ts +24 -0
- package/dist/autocomplete/index.d.ts +2 -0
- package/dist/autocomplete/types.d.ts +29 -0
- package/dist/blob-store/index.d.ts +32 -0
- package/dist/blob-store/types.d.ts +24 -0
- package/dist/block/block-controller.d.ts +205 -0
- package/dist/block/index.d.ts +2 -0
- package/dist/block/types.d.ts +15 -0
- package/dist/block-action-menu/block-action-menu.d.ts +62 -0
- package/dist/block-action-menu/index.d.ts +2 -0
- package/dist/block-context-menu/block-context-menu.d.ts +33 -0
- package/dist/block-context-menu/index.d.ts +2 -0
- package/dist/blx.js +16245 -0
- package/dist/blx.js.map +1 -0
- package/dist/caret/custom-caret.d.ts +30 -0
- package/dist/clipboard/clipboard-manager.d.ts +28 -0
- package/dist/clipboard/index.d.ts +2 -0
- package/dist/clipboard/paste-parser.d.ts +30 -0
- package/dist/commands/command-registry.d.ts +26 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/crdt/automerge-sync.d.ts +157 -0
- package/dist/crdt/crdt-log.d.ts +57 -0
- package/dist/crdt/index.d.ts +8 -0
- package/dist/crdt/remote-cursor-renderer.d.ts +28 -0
- package/dist/crdt/replay-ui.d.ts +34 -0
- package/dist/crdt/types.d.ts +47 -0
- package/dist/date-picker/agenda-utils.d.ts +37 -0
- package/dist/date-picker/date-parser.d.ts +25 -0
- package/dist/date-picker/date-picker.d.ts +115 -0
- package/dist/date-picker/index.d.ts +6 -0
- package/dist/drag-handle/drag-handle.d.ts +105 -0
- package/dist/drag-handle/index.d.ts +1 -0
- package/dist/editor.d.ts +864 -0
- package/dist/emoji-picker/emoji-data.d.ts +22 -0
- package/dist/emoji-picker/emoji-picker.d.ts +43 -0
- package/dist/emoji-picker/index.d.ts +3 -0
- package/dist/event-bus/event-bus.d.ts +14 -0
- package/dist/event-bus/index.d.ts +2 -0
- package/dist/event-bus/types.d.ts +320 -0
- package/dist/fold/fold-manager.d.ts +27 -0
- package/dist/fold/index.d.ts +2 -0
- package/dist/grapheme.d.ts +28 -0
- package/dist/index.d.ts +62 -0
- package/dist/inline-toolbar/highlight-picker.d.ts +41 -0
- package/dist/inline-toolbar/index.d.ts +5 -0
- package/dist/inline-toolbar/inline-toolbar.d.ts +97 -0
- package/dist/inline-toolbar/link-popover.d.ts +24 -0
- package/dist/keybindings/defaults.d.ts +2 -0
- package/dist/keybindings/index.d.ts +4 -0
- package/dist/keybindings/key-matcher.d.ts +41 -0
- package/dist/keybindings/types.d.ts +6 -0
- package/dist/keybindings/vim.d.ts +2 -0
- package/dist/markdown/block-shortcuts.d.ts +35 -0
- package/dist/markdown/emoticon-substitutions.d.ts +22 -0
- package/dist/markdown/export.d.ts +5 -0
- package/dist/markdown/index.d.ts +4 -0
- package/dist/markdown/inline-shortcuts.d.ts +13 -0
- package/dist/markdown/types.d.ts +29 -0
- package/dist/plugins/blockquote.d.ts +6 -0
- package/dist/plugins/checklist.d.ts +18 -0
- package/dist/plugins/code.d.ts +50 -0
- package/dist/plugins/excalidraw.d.ts +26 -0
- package/dist/plugins/heading.d.ts +20 -0
- package/dist/plugins/horizontal-rule.d.ts +5 -0
- package/dist/plugins/image.d.ts +19 -0
- package/dist/plugins/index.d.ts +28 -0
- package/dist/plugins/list.d.ts +18 -0
- package/dist/plugins/mermaid.d.ts +11 -0
- package/dist/plugins/paragraph.d.ts +18 -0
- package/dist/plugins/prism-loader.d.ts +16 -0
- package/dist/plugins/render-utils.d.ts +43 -0
- package/dist/plugins/table.d.ts +22 -0
- package/dist/plugins/youtube.d.ts +21 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/schema-registry.d.ts +35 -0
- package/dist/schema/types.d.ts +67 -0
- package/dist/search/index.d.ts +4 -0
- package/dist/search/search-engine.d.ts +39 -0
- package/dist/search/search-ui.d.ts +59 -0
- package/dist/selection/index.d.ts +3 -0
- package/dist/selection/selection-manager.d.ts +41 -0
- package/dist/selection/types.d.ts +20 -0
- package/dist/slash-menu/index.d.ts +2 -0
- package/dist/slash-menu/slash-menu.d.ts +27 -0
- package/dist/table-of-contents/index.d.ts +1 -0
- package/dist/table-of-contents/table-of-contents.d.ts +74 -0
- package/dist/transaction/index.d.ts +2 -0
- package/dist/transaction/transaction.d.ts +29 -0
- package/dist/transaction/types.d.ts +40 -0
- package/dist/types.d.ts +21 -0
- package/dist/ui/context-menu.d.ts +103 -0
- package/dist/ui/dismiss.d.ts +33 -0
- package/dist/ui/dropdown.d.ts +81 -0
- package/dist/ui/floating-scroll-manager.d.ts +50 -0
- package/dist/ui/index.d.ts +18 -0
- package/dist/ui/modal.d.ts +109 -0
- package/dist/ui/popover.d.ts +59 -0
- package/dist/ui/position-fixed.d.ts +35 -0
- package/dist/ui/toast.d.ts +60 -0
- package/dist/ui/tooltip.d.ts +64 -0
- package/dist/undo/index.d.ts +5 -0
- package/dist/undo/jump-list.d.ts +37 -0
- package/dist/undo/types.d.ts +49 -0
- package/dist/undo/undo-manager.d.ts +47 -0
- package/dist/util/icons.d.ts +13 -0
- package/dist/util/id.d.ts +10 -0
- package/dist/viewport/block-viewport.d.ts +106 -0
- package/dist/viewport/index.d.ts +2 -0
- package/package.json +66 -0
- package/style.css +4670 -0
package/dist/blx.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blx.js","sources":["../lib/attributed-string/attributed-string.ts","../lib/types.ts","../lib/event-bus/event-bus.ts","../lib/schema/schema-registry.ts","../lib/transaction/transaction.ts","../lib/markdown/inline-shortcuts.ts","../lib/markdown/block-shortcuts.ts","../lib/markdown/emoticon-substitutions.ts","../lib/grapheme.ts","../lib/emoji-picker/emoji-data.ts","../lib/emoji-picker/emoji-picker.ts","../lib/block/block-controller.ts","../lib/plugins/render-utils.ts","../lib/date-picker/agenda-utils.ts","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/check.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/chevron-down.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/chevrons-left.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/chevrons-right.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/circle-check-big.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/clipboard-paste.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/clock-fading.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/clock-plus.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/code.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/copy.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/grip-vertical.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/heading-1.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/heading-2.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/heading-3.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/heading-4.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/history.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/image.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/link.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/list-checks.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/list-ordered.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/list.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/pause.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/pencil.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/pilcrow.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/play.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/plus.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/repeat-2.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/scissors.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/sparkles.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/text-quote.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/trash-2.js","../../../node_modules/.pnpm/lucide@0.575.0/node_modules/lucide/dist/esm/icons/x.js","../lib/util/icons.ts","../lib/plugins/paragraph.ts","../lib/ui/position-fixed.ts","../lib/ui/context-menu.ts","../lib/ui/dismiss.ts","../lib/plugins/heading.ts","../lib/plugins/list.ts","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/prism.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-markup.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-css.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-clike.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-javascript.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-typescript.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-python.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-java.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-c.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-cpp.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-go.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-rust.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-sql.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-yaml.js","../../../node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-json.js","../lib/plugins/prism-loader.ts","../lib/ui/dropdown.ts","../lib/plugins/code.ts","../lib/plugins/horizontal-rule.ts","../lib/plugins/checklist.ts","../lib/plugins/youtube.ts","../lib/blob-store/index.ts","../lib/plugins/image.ts","../lib/plugins/table.ts","../lib/plugins/blockquote.ts","../lib/plugins/mermaid.ts","../lib/plugins/excalidraw.ts","../lib/plugins/index.ts","../lib/markdown/export.ts","../lib/util/id.ts","../lib/slash-menu/slash-menu.ts","../lib/autocomplete/autocomplete-menu.ts","../lib/date-picker/date-picker.ts","../lib/date-picker/date-parser.ts","../lib/drag-handle/drag-handle.ts","../lib/ui/popover.ts","../lib/inline-toolbar/inline-toolbar.ts","../lib/inline-toolbar/link-popover.ts","../lib/inline-toolbar/highlight-picker.ts","../lib/block-action-menu/block-action-menu.ts","../lib/keybindings/key-matcher.ts","../lib/keybindings/defaults.ts","../lib/keybindings/vim.ts","../lib/search/search-engine.ts","../lib/search/search-ui.ts","../lib/undo/undo-manager.ts","../lib/undo/jump-list.ts","../lib/viewport/block-viewport.ts","../lib/crdt/crdt-log.ts","../lib/crdt/replay-ui.ts","../lib/crdt/remote-cursor-renderer.ts","../lib/crdt/automerge-sync.ts","../lib/table-of-contents/table-of-contents.ts","../lib/fold/fold-manager.ts","../lib/commands/command-registry.ts","../lib/ui/floating-scroll-manager.ts","../lib/block-context-menu/block-context-menu.ts","../lib/caret/custom-caret.ts","../lib/clipboard/clipboard-manager.ts","../lib/clipboard/paste-parser.ts","../lib/ui/toast.ts","../lib/editor.ts","../lib/selection/types.ts","../lib/selection/selection-manager.ts","../lib/crdt/types.ts"],"sourcesContent":["import type { Attributes, AttributedStringJSON, Span } from \"./types\";\n\n/**\n * Immutable attributed string — every mutation returns a new instance.\n * Internally stores an array of non-overlapping, ordered Spans that cover\n * the full string. Adjacent spans with identical attributes are always merged.\n */\nexport class AttributedString {\n readonly spans: ReadonlyArray<Span>;\n\n private constructor(spans: ReadonlyArray<Span>) {\n this.spans = spans;\n }\n\n // ── Constructors ──────────────────────────────────────────────────\n\n static empty(): AttributedString {\n return new AttributedString([]);\n }\n\n static fromPlain(text: string, attrs: Attributes = {}): AttributedString {\n if (text.length === 0) return AttributedString.empty();\n return new AttributedString(normalize([{ text, attributes: { ...attrs } }]));\n }\n\n static fromSpans(spans: ReadonlyArray<Span>): AttributedString {\n const copied = spans.map((s) => ({\n text: s.text,\n attributes: { ...s.attributes },\n }));\n return new AttributedString(normalize(copied));\n }\n\n static fromJSON(json: AttributedStringJSON): AttributedString {\n return AttributedString.fromSpans(json.spans);\n }\n\n // ── Accessors ─────────────────────────────────────────────────────\n\n get length(): number {\n let len = 0;\n for (const s of this.spans) len += s.text.length;\n return len;\n }\n\n get text(): string {\n return this.spans.map((s) => s.text).join(\"\");\n }\n\n isEmpty(): boolean {\n return this.spans.length === 0;\n }\n\n /**\n * Get attributes at a character offset.\n *\n * @param side - Which side's attributes to prefer at a boundary:\n * - `'right'` (default): return the attributes of the span that starts at\n * or contains the offset — this is the classic behavior.\n * - `'left'`: return the attributes of the span to the *left* of the\n * cursor. At position 0 this means \"nothing to the left\" → `{}`.\n * Use `'left'` for text insertion so that typing before a formatted\n * span does not inherit its formatting.\n */\n attributesAt(offset: number, side: \"left\" | \"right\" = \"right\"): Attributes {\n if (offset < 0 || this.isEmpty()) return {};\n\n if (side === \"left\") {\n // At position 0 there is nothing to the left — return no attributes\n if (offset === 0) return {};\n\n // Walk spans and return the attributes of the span whose *end*\n // boundary is at or just past the offset (i.e. the span the cursor\n // sits at the end of).\n let pos = 0;\n let prev: Attributes = {};\n for (const span of this.spans) {\n const spanEnd = pos + span.text.length;\n if (offset <= pos) {\n // offset is exactly at this span's start — return previous span's attrs\n return { ...prev };\n }\n if (offset < spanEnd) {\n // offset is inside this span — return this span's attrs\n return { ...span.attributes };\n }\n prev = span.attributes;\n pos = spanEnd;\n }\n // offset at or past end — return attributes of last span\n if (this.spans.length > 0) {\n return { ...this.spans[this.spans.length - 1].attributes };\n }\n return {};\n }\n\n // side === 'right' (original behavior)\n let pos = 0;\n for (const span of this.spans) {\n if (offset < pos + span.text.length) {\n return { ...span.attributes };\n }\n pos += span.text.length;\n }\n // offset at or past end — return attributes of last span\n if (this.spans.length > 0) {\n return { ...this.spans[this.spans.length - 1].attributes };\n }\n return {};\n }\n\n // ── Operations (all return new instances) ─────────────────────────\n\n insertAt(offset: number, text: string, attrs?: Attributes): AttributedString {\n if (text.length === 0) return this;\n const clamped = clamp(offset, 0, this.length);\n\n // Determine attributes for inserted text.\n // Use 'left' affinity so that inserting at a span boundary (including\n // position 0) inherits from the span to the left rather than the right.\n // This prevents typed text from picking up formatting of the following span.\n const insertAttrs = attrs ?? this.attributesAt(clamped, \"left\");\n\n const { before, after } = splitSpans(this.spans, clamped);\n const inserted: Span = { text, attributes: { ...insertAttrs } };\n return new AttributedString(normalize([...before, inserted, ...after]));\n }\n\n deleteRange(start: number, end: number): AttributedString {\n const s = clamp(start, 0, this.length);\n const e = clamp(end, 0, this.length);\n if (s >= e) return this;\n\n const { before } = splitSpans(this.spans, s);\n const { after } = splitSpans(this.spans, e);\n return new AttributedString(normalize([...before, ...after]));\n }\n\n applyAttributes(start: number, end: number, attrs: Attributes): AttributedString {\n const s = clamp(start, 0, this.length);\n const e = clamp(end, 0, this.length);\n if (s >= e || Object.keys(attrs).length === 0) return this;\n\n const result: Span[] = [];\n let pos = 0;\n\n for (const span of this.spans) {\n const spanEnd = pos + span.text.length;\n\n if (spanEnd <= s || pos >= e) {\n // Entirely outside range\n result.push({ text: span.text, attributes: { ...span.attributes } });\n } else {\n // Some overlap\n if (pos < s) {\n // Part before range\n result.push({\n text: span.text.slice(0, s - pos),\n attributes: { ...span.attributes },\n });\n }\n\n const overlapStart = Math.max(s, pos);\n const overlapEnd = Math.min(e, spanEnd);\n result.push({\n text: span.text.slice(overlapStart - pos, overlapEnd - pos),\n attributes: { ...span.attributes, ...attrs },\n });\n\n if (spanEnd > e) {\n // Part after range\n result.push({\n text: span.text.slice(e - pos),\n attributes: { ...span.attributes },\n });\n }\n }\n\n pos = spanEnd;\n }\n\n return new AttributedString(normalize(result));\n }\n\n removeAttributes(start: number, end: number, keys: string[]): AttributedString {\n const s = clamp(start, 0, this.length);\n const e = clamp(end, 0, this.length);\n if (s >= e || keys.length === 0) return this;\n\n const result: Span[] = [];\n let pos = 0;\n\n for (const span of this.spans) {\n const spanEnd = pos + span.text.length;\n\n if (spanEnd <= s || pos >= e) {\n result.push({ text: span.text, attributes: { ...span.attributes } });\n } else {\n if (pos < s) {\n result.push({\n text: span.text.slice(0, s - pos),\n attributes: { ...span.attributes },\n });\n }\n\n const overlapStart = Math.max(s, pos);\n const overlapEnd = Math.min(e, spanEnd);\n const newAttrs = { ...span.attributes };\n for (const key of keys) delete newAttrs[key];\n result.push({\n text: span.text.slice(overlapStart - pos, overlapEnd - pos),\n attributes: newAttrs,\n });\n\n if (spanEnd > e) {\n result.push({\n text: span.text.slice(e - pos),\n attributes: { ...span.attributes },\n });\n }\n }\n\n pos = spanEnd;\n }\n\n return new AttributedString(normalize(result));\n }\n\n slice(start: number, end: number): AttributedString {\n const s = clamp(start, 0, this.length);\n const e = clamp(end, 0, this.length);\n if (s >= e) return AttributedString.empty();\n\n const { after: afterStart } = splitSpans(this.spans, s);\n // afterStart covers from s to end-of-string, so we need to take (e - s) chars\n const { before } = splitSpans(afterStart, e - s);\n return new AttributedString(normalize(before));\n }\n\n concat(other: AttributedString): AttributedString {\n const combined = [\n ...this.spans.map((s) => ({ text: s.text, attributes: { ...s.attributes } })),\n ...other.spans.map((s) => ({ text: s.text, attributes: { ...s.attributes } })),\n ];\n return new AttributedString(normalize(combined));\n }\n\n // ── Serialization ─────────────────────────────────────────────────\n\n toJSON(): AttributedStringJSON {\n return {\n spans: this.spans.map((s) => ({\n text: s.text,\n attributes: { ...s.attributes },\n })),\n };\n }\n\n equals(other: AttributedString): boolean {\n if (this.spans.length !== other.spans.length) return false;\n for (let i = 0; i < this.spans.length; i++) {\n const a = this.spans[i];\n const b = other.spans[i];\n if (a.text !== b.text) return false;\n if (!attrsEqual(a.attributes, b.attributes)) return false;\n }\n return true;\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────\n\nfunction clamp(val: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, val));\n}\n\nfunction attrsEqual(a: Attributes, b: Attributes): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if (a[k] !== b[k]) return false;\n }\n return true;\n}\n\n/**\n * Merge adjacent spans with identical attributes and remove empty spans.\n */\nfunction normalize(spans: Span[]): Span[] {\n const result: Span[] = [];\n for (const span of spans) {\n if (span.text.length === 0) continue;\n const last = result[result.length - 1];\n if (last && attrsEqual(last.attributes, span.attributes)) {\n // Merge into previous\n result[result.length - 1] = {\n text: last.text + span.text,\n attributes: last.attributes,\n };\n } else {\n result.push(span);\n }\n }\n return result;\n}\n\n/**\n * Split spans at a character offset, returning { before, after }.\n */\nfunction splitSpans(\n spans: ReadonlyArray<Span>,\n offset: number,\n): { before: Span[]; after: Span[] } {\n const before: Span[] = [];\n const after: Span[] = [];\n let pos = 0;\n\n for (const span of spans) {\n const spanEnd = pos + span.text.length;\n\n if (spanEnd <= offset) {\n before.push({ text: span.text, attributes: { ...span.attributes } });\n } else if (pos >= offset) {\n after.push({ text: span.text, attributes: { ...span.attributes } });\n } else {\n // Split within this span\n before.push({\n text: span.text.slice(0, offset - pos),\n attributes: { ...span.attributes },\n });\n after.push({\n text: span.text.slice(offset - pos),\n attributes: { ...span.attributes },\n });\n }\n\n pos = spanEnd;\n }\n\n return { before, after };\n}\n","import { AttributedString } from \"./attributed-string\";\nimport type { AttributedStringJSON } from \"./attributed-string\";\nimport type { BlockMetadata } from \"./schema\";\n\n/** A block of content in the editor */\nexport interface Block {\n id: string;\n type: string;\n content: AttributedString;\n metadata: BlockMetadata;\n}\n\n/** JSON-serializable representation of a Block */\nexport interface BlockJSON {\n id: string;\n type: string;\n content: AttributedStringJSON;\n metadata: BlockMetadata;\n}\n\n/** Convert a Block to its JSON representation */\nexport function blockToJSON(block: Block): BlockJSON {\n return {\n id: block.id,\n type: block.type,\n content: block.content.toJSON(),\n metadata: { ...block.metadata },\n };\n}\n\n/** Restore a Block from its JSON representation */\nexport function blockFromJSON(json: BlockJSON): Block {\n return {\n id: json.id,\n type: json.type,\n content: AttributedString.fromJSON(json.content),\n metadata: { ...json.metadata },\n };\n}\n","import type { EventHandler, Unsubscribe } from \"./types\";\n\n/**\n * Typed event bus — generic over an event map.\n * Handlers that throw do not break other handlers.\n */\nexport class EventBus<TEventMap = Record<string, unknown>> {\n private handlers = new Map<keyof TEventMap, Set<EventHandler<unknown>>>();\n\n on<K extends keyof TEventMap>(event: K, handler: EventHandler<TEventMap[K]>): Unsubscribe {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n const set = this.handlers.get(event)!;\n set.add(handler as EventHandler<unknown>);\n\n return () => {\n set.delete(handler as EventHandler<unknown>);\n if (set.size === 0) this.handlers.delete(event);\n };\n }\n\n once<K extends keyof TEventMap>(event: K, handler: EventHandler<TEventMap[K]>): Unsubscribe {\n const unsub = this.on(event, ((payload: TEventMap[K]) => {\n unsub();\n return handler(payload);\n }) as EventHandler<TEventMap[K]>);\n return unsub;\n }\n\n off<K extends keyof TEventMap>(event: K, handler: EventHandler<TEventMap[K]>): void {\n const set = this.handlers.get(event);\n if (!set) return;\n set.delete(handler as EventHandler<unknown>);\n if (set.size === 0) this.handlers.delete(event);\n }\n\n emit<K extends keyof TEventMap>(event: K, payload: TEventMap[K]): void {\n const set = this.handlers.get(event);\n if (!set) return;\n for (const handler of [...set]) {\n try {\n handler(payload);\n } catch (err) {\n console.error(`EventBus: handler for \"${String(event)}\" threw:`, err);\n }\n }\n }\n\n async emitAsync<K extends keyof TEventMap>(event: K, payload: TEventMap[K]): Promise<void> {\n const set = this.handlers.get(event);\n if (!set) return;\n for (const handler of [...set]) {\n try {\n await handler(payload);\n } catch (err) {\n console.error(`EventBus: async handler for \"${String(event)}\" threw:`, err);\n }\n }\n }\n\n clear(): void {\n this.handlers.clear();\n }\n}\n","import type { BlockTypePlugin, BlockMetadata, ConversionTarget } from \"./types\";\nimport type { BlockJSON } from \"../types\";\n\n/**\n * Registry for block type plugins.\n */\nexport class SchemaRegistry {\n private plugins = new Map<string, BlockTypePlugin>();\n private aliases = new Map<string, string>();\n\n register(plugin: BlockTypePlugin<BlockMetadata>): void {\n if (this.plugins.has(plugin.type)) {\n throw new Error(`Block type \"${plugin.type}\" is already registered`);\n }\n this.plugins.set(plugin.type, plugin);\n }\n\n unregister(type: string): boolean {\n return this.plugins.delete(type);\n }\n\n /**\n * Register an alias so that old/renamed block types resolve to a current plugin.\n * When blocks are loaded with `oldType`, they will be treated as `newType`.\n */\n registerAlias(oldType: string, newType: string): void {\n this.aliases.set(oldType, newType);\n }\n\n get(type: string): BlockTypePlugin | undefined {\n return this.plugins.get(type) ?? this.plugins.get(this.aliases.get(type) ?? \"\");\n }\n\n has(type: string): boolean {\n return this.plugins.has(type) || this.plugins.has(this.aliases.get(type) ?? \"\");\n }\n\n /**\n * Resolve a block type through aliases. Returns the canonical type name.\n */\n resolveType(type: string): string {\n return this.aliases.get(type) ?? type;\n }\n\n /**\n * Migrate an array of block JSON objects, rewriting any aliased types\n * to their canonical names. Returns true if any blocks were modified.\n */\n migrateBlocks(blocks: BlockJSON[]): boolean {\n let migrated = false;\n for (const block of blocks) {\n const resolved = this.resolveType(block.type);\n if (resolved !== block.type) {\n block.type = resolved;\n migrated = true;\n }\n }\n return migrated;\n }\n\n getAll(): ReadonlyArray<BlockTypePlugin> {\n return [...this.plugins.values()];\n }\n\n getTypes(): ReadonlyArray<string> {\n return [...this.plugins.keys()];\n }\n\n /**\n * Get the conversion targets for a given block type.\n * If the plugin defines `convertibleTo()`, use that.\n * Otherwise, build a default list from all registered text-content plugins.\n */\n getConversionTargets(type: string): ConversionTarget[] {\n const plugin = this.plugins.get(type);\n if (!plugin) return [];\n\n if (plugin.convertibleTo) {\n return plugin.convertibleTo();\n }\n\n // Default: all text-content plugins except the current type\n // (skip inconvertible plugins like \"title\" — they shouldn't appear as targets)\n const targets: ConversionTarget[] = [];\n for (const p of this.plugins.values()) {\n if (p.type === type) continue;\n if (!p.hasTextContent) continue;\n if (p.inconvertible) continue;\n targets.push({\n type: p.type,\n label: p.label,\n });\n }\n return targets;\n }\n}\n","import type { AttributedString, Attributes } from \"../attributed-string\";\nimport type { BlockMetadata } from \"../schema\";\nimport type { Operation, TransactionResult } from \"./types\";\n\n/**\n * Transaction builder — accumulates operations via a builder pattern,\n * then applies them all in order to produce new content and metadata.\n *\n * A transaction can only be applied once.\n */\nexport class Transaction {\n readonly blockId: string;\n private ops: Operation[] = [];\n private committed = false;\n\n constructor(blockId: string) {\n this.blockId = blockId;\n }\n\n get operations(): ReadonlyArray<Operation> {\n return this.ops;\n }\n\n get isEmpty(): boolean {\n return this.ops.length === 0;\n }\n\n insertText(offset: number, text: string, attributes?: Attributes): this {\n this.guardCommitted();\n this.ops.push({ type: \"insertText\", offset, text, attributes });\n return this;\n }\n\n deleteRange(start: number, end: number): this {\n this.guardCommitted();\n this.ops.push({ type: \"deleteRange\", start, end });\n return this;\n }\n\n applyAttributes(start: number, end: number, attributes: Attributes): this {\n this.guardCommitted();\n this.ops.push({ type: \"applyAttributes\", start, end, attributes });\n return this;\n }\n\n removeAttributes(start: number, end: number, keys: string[]): this {\n this.guardCommitted();\n this.ops.push({ type: \"removeAttributes\", start, end, keys });\n return this;\n }\n\n setMetadata(key: string, value: unknown): this {\n this.guardCommitted();\n this.ops.push({ type: \"setMetadata\", key, value });\n return this;\n }\n\n replaceContent(content: AttributedString): this {\n this.guardCommitted();\n this.ops.push({ type: \"replaceContent\", content });\n return this;\n }\n\n /**\n * Apply all operations in order. Returns new content and metadata.\n * Marks the transaction as committed — cannot be applied again.\n */\n apply(content: AttributedString, metadata: BlockMetadata): TransactionResult {\n this.guardCommitted();\n this.committed = true;\n\n let currentContent = content;\n let currentMetadata = { ...metadata };\n\n for (const op of this.ops) {\n switch (op.type) {\n case \"insertText\":\n currentContent = currentContent.insertAt(op.offset, op.text, op.attributes);\n break;\n case \"deleteRange\":\n currentContent = currentContent.deleteRange(op.start, op.end);\n break;\n case \"applyAttributes\":\n currentContent = currentContent.applyAttributes(op.start, op.end, op.attributes);\n break;\n case \"removeAttributes\":\n currentContent = currentContent.removeAttributes(op.start, op.end, op.keys);\n break;\n case \"setMetadata\":\n currentMetadata = { ...currentMetadata, [op.key]: op.value };\n break;\n case \"replaceContent\":\n currentContent = op.content;\n break;\n }\n }\n\n return { content: currentContent, metadata: currentMetadata };\n }\n\n private guardCommitted(): void {\n if (this.committed) {\n throw new Error(\"Transaction has already been committed\");\n }\n }\n}\n","import type { InlineShortcutMatch } from \"./types\";\n\n/**\n * Detect an inline markdown shortcut being completed.\n *\n * Called BEFORE the character is inserted into the content.\n * Scans backward for a matching opening marker:\n * - `charBeingTyped === \"*\"` + `existingText[cursorOffset-1] === \"*\"` → bold (`**`)\n * - `charBeingTyped === \"_\"` → italic (`_`)\n * - `charBeingTyped === \"\\`\"` → code (`` ` ``)\n *\n * There must be at least 1 character between the markers.\n */\nexport function detectInlineShortcut(\n existingText: string,\n cursorOffset: number,\n charBeingTyped: string,\n): InlineShortcutMatch | null {\n if (charBeingTyped === \"*\") {\n // Try bold (**) first, then italic (*)\n return detectBold(existingText, cursorOffset)\n ?? detectItalicAsterisk(existingText, cursorOffset);\n }\n if (charBeingTyped === \"_\") {\n return detectItalic(existingText, cursorOffset);\n }\n if (charBeingTyped === \"`\") {\n return detectCode(existingText, cursorOffset);\n }\n if (charBeingTyped === \"~\") {\n return detectStrikethrough(existingText, cursorOffset);\n }\n if (charBeingTyped === \")\") {\n return detectLink(existingText, cursorOffset);\n }\n return null;\n}\n\n/**\n * Bold: the user is typing the second `*` of a closing `**`.\n * So existingText[cursorOffset-1] must be `*` (the first closing star),\n * and we scan backward for `**` opening marker.\n *\n * Text state: `before**content*` with cursor at end, typing `*`\n * - cursorOffset points after the first closing `*`\n * - The first closing `*` is at cursorOffset-1\n * - Content is between openMarkerEnd and the first closing `*`\n */\nfunction detectBold(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n // The char just before cursor must be `*` (first char of closing `**`)\n if (cursorOffset < 1 || existingText[cursorOffset - 1] !== \"*\") {\n return null;\n }\n\n // Content ends at the first closing `*` position\n const contentEnd = cursorOffset - 1;\n\n // Scan backward from contentEnd for the opening `**`\n for (let i = contentEnd - 1; i >= 1; i--) {\n if (existingText[i] === \"*\" && existingText[i - 1] === \"*\") {\n const openMarkerStart = i - 1;\n const openMarkerEnd = i + 1;\n const contentStart = openMarkerEnd;\n\n // Must have at least 1 char of content\n if (contentEnd - contentStart < 1) continue;\n\n return {\n kind: \"bold\",\n attribute: { bold: true },\n openMarkerStart,\n openMarkerEnd,\n contentStart,\n contentEnd,\n // closeMarkerEnd includes the `*` being typed\n closeMarkerEnd: cursorOffset + 1,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Italic: the user is typing the closing `_`.\n * Scan backward for the opening `_`.\n *\n * Text state: `before_content` with cursor at end, typing `_`\n */\nfunction detectItalic(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n const contentEnd = cursorOffset;\n\n // Scan backward for opening `_`\n for (let i = contentEnd - 1; i >= 0; i--) {\n if (existingText[i] === \"_\") {\n const openMarkerStart = i;\n const openMarkerEnd = i + 1;\n const contentStart = openMarkerEnd;\n\n // Must have at least 1 char of content\n if (contentEnd - contentStart < 1) continue;\n\n return {\n kind: \"italic\",\n attribute: { italic: true },\n openMarkerStart,\n openMarkerEnd,\n contentStart,\n contentEnd,\n // closeMarkerEnd includes the `_` being typed\n closeMarkerEnd: cursorOffset + 1,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Italic (*): the user is typing the closing `*`.\n * Scan backward for the opening `*`, ensuring it's not part of `**`.\n *\n * Text state: `before*content` with cursor at end, typing `*`\n * Only called when bold detection has already failed (preceding char is not `*`).\n */\nfunction detectItalicAsterisk(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n const contentEnd = cursorOffset;\n\n // Scan backward for opening `*`\n for (let i = contentEnd - 1; i >= 0; i--) {\n if (existingText[i] === \"*\") {\n // Skip if this `*` is part of `**` (adjacent to another `*`)\n if (i > 0 && existingText[i - 1] === \"*\") continue;\n if (i < existingText.length - 1 && existingText[i + 1] === \"*\") continue;\n\n const openMarkerStart = i;\n const openMarkerEnd = i + 1;\n const contentStart = openMarkerEnd;\n\n // Must have at least 1 char of content\n if (contentEnd - contentStart < 1) continue;\n\n return {\n kind: \"italic\",\n attribute: { italic: true },\n openMarkerStart,\n openMarkerEnd,\n contentStart,\n contentEnd,\n closeMarkerEnd: cursorOffset + 1,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Strikethrough: the user is typing the second `~` of a closing `~~`.\n * So existingText[cursorOffset-1] must be `~` (the first closing tilde),\n * and we scan backward for `~~` opening marker.\n *\n * Text state: `before~~content~` with cursor at end, typing `~`\n */\nfunction detectStrikethrough(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n // The char just before cursor must be `~` (first char of closing `~~`)\n if (cursorOffset < 1 || existingText[cursorOffset - 1] !== \"~\") {\n return null;\n }\n\n // Content ends at the first closing `~` position\n const contentEnd = cursorOffset - 1;\n\n // Scan backward from contentEnd for the opening `~~`\n for (let i = contentEnd - 1; i >= 1; i--) {\n if (existingText[i] === \"~\" && existingText[i - 1] === \"~\") {\n const openMarkerStart = i - 1;\n const openMarkerEnd = i + 1;\n const contentStart = openMarkerEnd;\n\n // Must have at least 1 char of content\n if (contentEnd - contentStart < 1) continue;\n\n return {\n kind: \"strikethrough\",\n attribute: { strikethrough: true },\n openMarkerStart,\n openMarkerEnd,\n contentStart,\n contentEnd,\n closeMarkerEnd: cursorOffset + 1,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Code: the user is typing the closing backtick.\n * Scan backward for the opening backtick.\n *\n * Text state: `before\\`content` with cursor at end, typing `` ` ``\n */\nfunction detectCode(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n const contentEnd = cursorOffset;\n\n // Don't match when the char just before the closing backtick is also a\n // backtick — this allows typing ``` for code-block shortcuts without the\n // second backtick being swallowed as an inline-code match of \"`\".\n if (cursorOffset >= 1 && existingText[cursorOffset - 1] === \"`\") {\n return null;\n }\n\n // Scan backward for opening backtick\n for (let i = contentEnd - 1; i >= 0; i--) {\n if (existingText[i] === \"`\") {\n const openMarkerStart = i;\n const openMarkerEnd = i + 1;\n const contentStart = openMarkerEnd;\n\n // Must have at least 1 char of content\n if (contentEnd - contentStart < 1) continue;\n\n return {\n kind: \"code\",\n attribute: { code: true },\n openMarkerStart,\n openMarkerEnd,\n contentStart,\n contentEnd,\n // closeMarkerEnd includes the backtick being typed\n closeMarkerEnd: cursorOffset + 1,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Link: the user is typing the closing `)`.\n * Pattern: `[text](url)`\n *\n * Text state: `before[text](url` with cursor at end, typing `)`\n * The content to keep is \"text\", with { href: url } applied.\n */\nfunction detectLink(\n existingText: string,\n cursorOffset: number,\n): InlineShortcutMatch | null {\n // Scan backward from cursor for `](`\n let bracketCloseParenIdx = -1;\n for (let i = cursorOffset - 1; i >= 1; i--) {\n if (existingText[i] === \"(\" && existingText[i - 1] === \"]\") {\n bracketCloseParenIdx = i - 1; // position of `]`\n break;\n }\n }\n\n if (bracketCloseParenIdx === -1) return null;\n\n // URL is between `](` and cursor\n const urlStart = bracketCloseParenIdx + 2; // after `](`\n const urlEnd = cursorOffset;\n const url = existingText.slice(urlStart, urlEnd).trim();\n if (!url) return null;\n\n // Scan backward from `]` for the opening `[`\n let bracketOpenIdx = -1;\n for (let i = bracketCloseParenIdx - 1; i >= 0; i--) {\n if (existingText[i] === \"[\") {\n bracketOpenIdx = i;\n break;\n }\n }\n\n if (bracketOpenIdx === -1) return null;\n\n const textStart = bracketOpenIdx + 1; // after `[`\n const textEnd = bracketCloseParenIdx; // before `]`\n\n // Must have at least 1 char of link text\n if (textEnd - textStart < 1) return null;\n\n return {\n kind: \"link\",\n attribute: { href: url },\n openMarkerStart: bracketOpenIdx, // start of `[`\n openMarkerEnd: textStart, // after `[`\n contentStart: textStart, // link text start\n contentEnd: textEnd, // link text end (before `]`)\n closeMarkerEnd: cursorOffset + 1, // after `)` being typed\n };\n}\n","import type { BlockShortcutMatch } from \"./types\";\n\nconst LANG_ALIASES: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n py: \"python\",\n};\n\n/**\n * Match a block shortcut pattern without checking the trigger character.\n *\n * Matches:\n * - `#` → h1, `##` → h2, `###` → h3, `####` → h4\n * - `-`, `*`, `+` → unordered list\n * - `1.`, `1)` → ordered list\n * - `[a-zA-Z][.)]` → ordered list (lettered)\n * - `` ``` `` or `` ```lang `` → code block\n * - `---` → horizontal rule\n * - `>` → blockquote\n */\nexport function matchBlockShortcutPattern(prefix: string): BlockShortcutMatch | null {\n // Task heading: #[] → task h1, ##[] → task h2, etc.\n const taskHeadingMatch = /^(#{1,4})\\[\\]$/.exec(prefix);\n if (taskHeadingMatch) {\n const level = taskHeadingMatch[1].length;\n return {\n kind: \"heading\",\n newType: \"heading\",\n metadata: { level, taskStatus: \"todo\" },\n prefixLength: prefix.length,\n };\n }\n\n // Heading: # → h1, ## → h2, ### → h3, #### → h4\n const headingMatch = /^(#{1,4})$/.exec(prefix);\n if (headingMatch) {\n const level = headingMatch[1].length;\n return {\n kind: \"heading\",\n newType: \"heading\",\n metadata: { level },\n prefixLength: prefix.length,\n };\n }\n\n // Unordered list: -, *, +\n if (prefix === \"-\" || prefix === \"*\" || prefix === \"+\") {\n return {\n kind: \"unordered-list\",\n newType: \"list\",\n metadata: { ordered: false },\n prefixLength: prefix.length,\n };\n }\n\n // Task list: []\n if (prefix === \"[]\") {\n return {\n kind: \"checklist\",\n newType: \"checklist\",\n metadata: { checked: false },\n prefixLength: prefix.length,\n };\n }\n\n // Ordered list (numeric): 1. or 1)\n const numericListMatch = /^(\\d+)[.)]$/.exec(prefix);\n if (numericListMatch) {\n return {\n kind: \"ordered-list\",\n newType: \"list\",\n metadata: { ordered: true },\n prefixLength: prefix.length,\n };\n }\n\n // Ordered list (lettered): a. a) A. A)\n const letteredListMatch = /^[a-zA-Z][.)]$/.exec(prefix);\n if (letteredListMatch) {\n return {\n kind: \"ordered-list\",\n newType: \"list\",\n metadata: { ordered: true },\n prefixLength: prefix.length,\n };\n }\n\n // Code block: ``` or ```lang\n const codeMatch = /^```(\\w*)$/.exec(prefix);\n if (codeMatch) {\n const raw = codeMatch[1].toLowerCase();\n const language = LANG_ALIASES[raw] ?? (raw || \"plain\");\n return {\n kind: \"code-block\",\n newType: \"code\",\n metadata: { language },\n prefixLength: prefix.length,\n };\n }\n\n // Horizontal rule: ---\n if (prefix === \"---\") {\n return {\n kind: \"horizontal-rule\",\n newType: \"horizontal-rule\",\n metadata: {},\n prefixLength: 3,\n };\n }\n\n // Blockquote: >\n if (prefix === \">\") {\n return {\n kind: \"blockquote\",\n newType: \"blockquote\",\n metadata: {},\n prefixLength: prefix.length,\n };\n }\n\n return null;\n}\n\n/**\n * Detect a block-level markdown shortcut being completed by a space.\n *\n * Called BEFORE the character is inserted. Fires when:\n * - `charBeingTyped === \" \"`\n * - The text before the cursor matches a block shortcut pattern\n *\n * Works both on empty blocks (cursor at end) and blocks with existing\n * text (e.g. typing `# ` at the beginning of \"Hello\" → heading).\n */\nexport function detectBlockShortcut(\n existingText: string,\n cursorOffset: number,\n charBeingTyped: string,\n): BlockShortcutMatch | null {\n if (charBeingTyped !== \" \") {\n return null;\n }\n const prefix = existingText.slice(0, cursorOffset);\n const match = matchBlockShortcutPattern(prefix);\n if (match) {\n // +1 for the space being typed\n return { ...match, prefixLength: match.prefixLength + 1 };\n }\n return null;\n}\n\n/**\n * Detect a block shortcut that fires immediately when the pattern is complete\n * and unambiguous (no possible extensions exist).\n *\n * Currently only `---` → horizontal rule qualifies: no `----` pattern exists,\n * so the third dash completes the pattern.\n *\n * Called BEFORE the character is inserted.\n */\nexport function detectImmediateBlockShortcut(\n existingText: string,\n cursorOffset: number,\n charBeingTyped: string,\n): BlockShortcutMatch | null {\n if (cursorOffset !== existingText.length) return null;\n const fullText = existingText + charBeingTyped;\n if (fullText === \"---\") {\n return { kind: \"horizontal-rule\", newType: \"horizontal-rule\", metadata: {}, prefixLength: 3 };\n }\n return null;\n}\n","/** Map of emoticon text patterns to their emoji replacements */\nexport const EMOTICON_MAP: Record<string, string> = {\n \":)\": \"😊\",\n \":(\": \"😢\",\n \":D\": \"😁\",\n \":P\": \"😜\",\n \":/\": \"😕\",\n \":O\": \"😮\",\n \";)\": \"😉\",\n \"<3\": \"❤️\",\n \":'(\": \"😭\",\n \">:(\": \"😡\",\n \"XD\": \"🤣\",\n \"B)\": \"😎\",\n \":*\": \"😘\",\n};\n\n/** Emoticon patterns sorted longest-first for greedy matching */\nconst SORTED_PATTERNS = Object.keys(EMOTICON_MAP).sort(\n (a, b) => b.length - a.length,\n);\n\n/** Maximum emoticon length (used to limit backward scan) */\nconst MAX_LEN = Math.max(...SORTED_PATTERNS.map((p) => p.length));\n\nexport interface EmoticonMatch {\n /** The emoji character to insert */\n emoji: string;\n /** Start offset in existingText where the emoticon prefix begins */\n start: number;\n /** End offset in existingText (exclusive) — the cursor position */\n end: number;\n}\n\n/**\n * Detect an emoticon being completed by the character about to be typed.\n *\n * Called BEFORE the character is inserted into the content (same convention\n * as `detectInlineShortcut`). Builds a candidate string from the last\n * N characters of `existingText` (up to `cursorOffset`) plus `charBeingTyped`,\n * then checks longest-first against the emoticon map.\n *\n * Safety: only triggers when the emoticon is preceded by whitespace or\n * is at the start of text, to avoid false positives like `http:/`.\n */\nexport function detectEmoticon(\n existingText: string,\n cursorOffset: number,\n charBeingTyped: string,\n): EmoticonMatch | null {\n // Only single-char typing triggers emoticons\n if (charBeingTyped.length !== 1) return null;\n\n for (const pattern of SORTED_PATTERNS) {\n const patLen = pattern.length;\n // The last char of the pattern must be `charBeingTyped`\n if (pattern[patLen - 1] !== charBeingTyped) continue;\n\n // The prefix (everything except the last char) must match the end of existingText\n const prefixLen = patLen - 1;\n const startInText = cursorOffset - prefixLen;\n if (startInText < 0) continue;\n\n const prefixInText = existingText.slice(startInText, cursorOffset);\n if (prefixInText !== pattern.slice(0, prefixLen)) continue;\n\n // Safety: must be preceded by whitespace or be at start of text\n if (startInText > 0) {\n const charBefore = existingText[startInText - 1];\n if (charBefore !== \" \" && charBefore !== \"\\n\") continue;\n }\n\n return {\n emoji: EMOTICON_MAP[pattern],\n start: startInText,\n end: cursorOffset,\n };\n }\n\n return null;\n}\n","/**\n * Grapheme-cluster boundary utilities.\n *\n * JavaScript string `.length` counts UTF-16 code units, so multi-codepoint\n * characters like ❤️ (U+2764 + U+FE0F, length 2) or 👨👩👧 (length 8)\n * span more than 1 unit. When deleting \"one character\" on backspace or\n * forward-delete we must remove the entire grapheme cluster, not just a\n * single code unit.\n *\n * Uses `Intl.Segmenter` (supported in all modern browsers and Node 16+).\n */\n\nconst segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\n/**\n * Return the UTF-16 offset of the start of the grapheme cluster that\n * ends at (or contains) `offset`. If `offset` is 0, returns 0.\n *\n * Example: for text \"a❤️b\" (UTF-16 units: a ❤ \\uFE0F b),\n * prevGraphemeBoundary(text, 3) → 1 (skips both code units of ❤️)\n */\nexport function prevGraphemeBoundary(text: string, offset: number): number {\n if (offset <= 0) return 0;\n\n let prev = 0;\n for (const { index, segment } of segmenter.segment(text)) {\n const end = index + segment.length;\n if (end >= offset) return index;\n prev = end;\n }\n return prev;\n}\n\n/**\n * Return the UTF-16 offset just past the grapheme cluster that starts\n * at (or contains) `offset`. If `offset` is at/past the end, returns\n * `text.length`.\n *\n * Example: for text \"a❤️b\" (UTF-16 units: a ❤ \\uFE0F b),\n * nextGraphemeBoundary(text, 1) → 3 (skips both code units of ❤️)\n */\nexport function nextGraphemeBoundary(text: string, offset: number): number {\n if (offset >= text.length) return text.length;\n\n for (const { index, segment } of segmenter.segment(text)) {\n const end = index + segment.length;\n if (end > offset) return end;\n }\n return text.length;\n}\n","export interface EmojiEntry {\n emoji: string;\n name: string;\n keywords: string[];\n}\n\nexport const EMOJI_LIST: EmojiEntry[] = [\n // Faces — smiling\n { emoji: \"😀\", name: \"grinning\", keywords: [\"smile\", \"happy\", \"face\"] },\n { emoji: \"😃\", name: \"smiley\", keywords: [\"smile\", \"happy\", \"face\"] },\n { emoji: \"😄\", name: \"smile\", keywords: [\"happy\", \"face\", \"grin\"] },\n { emoji: \"😁\", name: \"grin\", keywords: [\"smile\", \"happy\", \"face\"] },\n { emoji: \"😆\", name: \"laughing\", keywords: [\"smile\", \"happy\", \"lol\"] },\n { emoji: \"😅\", name: \"sweat_smile\", keywords: [\"laugh\", \"nervous\"] },\n { emoji: \"🤣\", name: \"rofl\", keywords: [\"laugh\", \"lol\", \"rolling\"] },\n { emoji: \"😂\", name: \"joy\", keywords: [\"laugh\", \"happy\", \"tears\"] },\n { emoji: \"🙂\", name: \"slightly_smiling_face\", keywords: [\"smile\"] },\n { emoji: \"😉\", name: \"wink\", keywords: [\"face\", \"flirt\"] },\n { emoji: \"😊\", name: \"blush\", keywords: [\"smile\", \"happy\", \"shy\"] },\n { emoji: \"😇\", name: \"innocent\", keywords: [\"angel\", \"halo\"] },\n\n // Faces — affection\n { emoji: \"🥰\", name: \"smiling_face_with_hearts\", keywords: [\"love\", \"adore\"] },\n { emoji: \"😍\", name: \"heart_eyes\", keywords: [\"love\", \"crush\", \"face\"] },\n { emoji: \"🤩\", name: \"star_struck\", keywords: [\"wow\", \"excited\", \"star\"] },\n { emoji: \"😘\", name: \"kissing_heart\", keywords: [\"love\", \"kiss\", \"face\"] },\n { emoji: \"😋\", name: \"yum\", keywords: [\"tongue\", \"delicious\", \"tasty\"] },\n\n // Faces — tongue\n { emoji: \"😜\", name: \"stuck_out_tongue_winking_eye\", keywords: [\"silly\", \"playful\"] },\n { emoji: \"🤪\", name: \"zany_face\", keywords: [\"crazy\", \"wild\", \"silly\"] },\n { emoji: \"😝\", name: \"stuck_out_tongue_closed_eyes\", keywords: [\"silly\"] },\n\n // Faces — hand\n { emoji: \"🤗\", name: \"hugs\", keywords: [\"hug\", \"embrace\"] },\n { emoji: \"🤔\", name: \"thinking\", keywords: [\"think\", \"hmm\", \"ponder\"] },\n { emoji: \"🤫\", name: \"shushing_face\", keywords: [\"quiet\", \"secret\", \"shh\"] },\n { emoji: \"🤭\", name: \"face_with_hand_over_mouth\", keywords: [\"oops\", \"giggle\"] },\n\n // Faces — neutral / skeptical\n { emoji: \"😐\", name: \"neutral_face\", keywords: [\"meh\", \"blank\"] },\n { emoji: \"😑\", name: \"expressionless\", keywords: [\"blank\", \"meh\"] },\n { emoji: \"😶\", name: \"no_mouth\", keywords: [\"silent\", \"mute\"] },\n { emoji: \"🙄\", name: \"roll_eyes\", keywords: [\"eyeroll\", \"annoyed\"] },\n { emoji: \"😏\", name: \"smirk\", keywords: [\"sly\", \"smug\"] },\n { emoji: \"😬\", name: \"grimacing\", keywords: [\"awkward\", \"nervous\"] },\n\n // Faces — sleepy\n { emoji: \"😴\", name: \"sleeping\", keywords: [\"sleep\", \"zzz\", \"tired\"] },\n { emoji: \"🥱\", name: \"yawning_face\", keywords: [\"tired\", \"bored\", \"sleepy\"] },\n\n // Faces — unwell\n { emoji: \"😷\", name: \"mask\", keywords: [\"sick\", \"ill\", \"covid\"] },\n { emoji: \"🤒\", name: \"face_with_thermometer\", keywords: [\"sick\", \"fever\"] },\n { emoji: \"🤮\", name: \"vomiting_face\", keywords: [\"sick\", \"gross\", \"puke\"] },\n\n // Faces — concerned\n { emoji: \"😕\", name: \"confused\", keywords: [\"puzzled\"] },\n { emoji: \"😟\", name: \"worried\", keywords: [\"concern\", \"anxious\"] },\n { emoji: \"😮\", name: \"open_mouth\", keywords: [\"surprise\", \"gasp\"] },\n { emoji: \"😲\", name: \"astonished\", keywords: [\"surprise\", \"shock\"] },\n { emoji: \"😳\", name: \"flushed\", keywords: [\"embarrassed\", \"blush\"] },\n { emoji: \"🥺\", name: \"pleading_face\", keywords: [\"puppy\", \"cute\", \"sad\"] },\n { emoji: \"😢\", name: \"cry\", keywords: [\"sad\", \"tear\"] },\n { emoji: \"😭\", name: \"sob\", keywords: [\"cry\", \"sad\", \"tears\"] },\n { emoji: \"😱\", name: \"scream\", keywords: [\"fear\", \"shock\", \"horror\"] },\n { emoji: \"😤\", name: \"triumph\", keywords: [\"angry\", \"huff\"] },\n { emoji: \"😡\", name: \"rage\", keywords: [\"angry\", \"mad\"] },\n { emoji: \"🤬\", name: \"cursing_face\", keywords: [\"angry\", \"swear\"] },\n\n // Faces — costume / fantasy\n { emoji: \"💀\", name: \"skull\", keywords: [\"death\", \"dead\"] },\n { emoji: \"👻\", name: \"ghost\", keywords: [\"spooky\", \"halloween\"] },\n { emoji: \"👽\", name: \"alien\", keywords: [\"ufo\", \"space\"] },\n { emoji: \"🤖\", name: \"robot\", keywords: [\"bot\", \"ai\", \"machine\"] },\n { emoji: \"🎃\", name: \"jack_o_lantern\", keywords: [\"halloween\", \"pumpkin\"] },\n\n // Faces — other\n { emoji: \"🤡\", name: \"clown_face\", keywords: [\"clown\", \"silly\"] },\n { emoji: \"💩\", name: \"poop\", keywords: [\"shit\", \"crap\"] },\n\n // Hands\n { emoji: \"👋\", name: \"wave\", keywords: [\"hello\", \"hi\", \"bye\"] },\n { emoji: \"🤚\", name: \"raised_back_of_hand\", keywords: [\"hand\", \"stop\"] },\n { emoji: \"✋\", name: \"raised_hand\", keywords: [\"hand\", \"stop\", \"high5\"] },\n { emoji: \"🖖\", name: \"vulcan_salute\", keywords: [\"spock\", \"trek\"] },\n { emoji: \"👌\", name: \"ok_hand\", keywords: [\"perfect\", \"okay\"] },\n { emoji: \"🤌\", name: \"pinched_fingers\", keywords: [\"italian\", \"chef\"] },\n { emoji: \"✌️\", name: \"v\", keywords: [\"peace\", \"victory\"] },\n { emoji: \"🤞\", name: \"crossed_fingers\", keywords: [\"luck\", \"hope\"] },\n { emoji: \"🤟\", name: \"love_you_gesture\", keywords: [\"love\", \"rock\"] },\n { emoji: \"🤘\", name: \"metal\", keywords: [\"rock\", \"horns\"] },\n { emoji: \"👈\", name: \"point_left\", keywords: [\"left\", \"direction\"] },\n { emoji: \"👉\", name: \"point_right\", keywords: [\"right\", \"direction\"] },\n { emoji: \"👆\", name: \"point_up\", keywords: [\"up\", \"direction\"] },\n { emoji: \"👇\", name: \"point_down\", keywords: [\"down\", \"direction\"] },\n { emoji: \"☝️\", name: \"point_up_2\", keywords: [\"up\", \"one\", \"attention\"] },\n { emoji: \"👍\", name: \"thumbsup\", keywords: [\"yes\", \"good\", \"like\", \"+1\"] },\n { emoji: \"👎\", name: \"thumbsdown\", keywords: [\"no\", \"bad\", \"dislike\", \"-1\"] },\n { emoji: \"✊\", name: \"fist\", keywords: [\"punch\", \"power\"] },\n { emoji: \"👊\", name: \"facepunch\", keywords: [\"punch\", \"hit\"] },\n { emoji: \"👏\", name: \"clap\", keywords: [\"applause\", \"bravo\"] },\n { emoji: \"🙌\", name: \"raised_hands\", keywords: [\"celebration\", \"hooray\"] },\n { emoji: \"🤝\", name: \"handshake\", keywords: [\"deal\", \"agree\"] },\n { emoji: \"🙏\", name: \"pray\", keywords: [\"thanks\", \"please\", \"hope\"] },\n { emoji: \"💪\", name: \"muscle\", keywords: [\"strong\", \"flex\", \"bicep\"] },\n\n // Hearts\n { emoji: \"❤️\", name: \"heart\", keywords: [\"love\", \"red\"] },\n { emoji: \"🧡\", name: \"orange_heart\", keywords: [\"love\"] },\n { emoji: \"💛\", name: \"yellow_heart\", keywords: [\"love\"] },\n { emoji: \"💚\", name: \"green_heart\", keywords: [\"love\"] },\n { emoji: \"💙\", name: \"blue_heart\", keywords: [\"love\"] },\n { emoji: \"💜\", name: \"purple_heart\", keywords: [\"love\"] },\n { emoji: \"🖤\", name: \"black_heart\", keywords: [\"love\", \"dark\"] },\n { emoji: \"🤍\", name: \"white_heart\", keywords: [\"love\", \"pure\"] },\n { emoji: \"💔\", name: \"broken_heart\", keywords: [\"sad\", \"heartbreak\"] },\n { emoji: \"❤️🔥\", name: \"heart_on_fire\", keywords: [\"love\", \"passion\"] },\n\n // Animals\n { emoji: \"🐶\", name: \"dog\", keywords: [\"puppy\", \"pet\", \"animal\"] },\n { emoji: \"🐱\", name: \"cat\", keywords: [\"kitten\", \"pet\", \"animal\"] },\n { emoji: \"🐭\", name: \"mouse\", keywords: [\"animal\", \"rodent\"] },\n { emoji: \"🐹\", name: \"hamster\", keywords: [\"pet\", \"animal\"] },\n { emoji: \"🐰\", name: \"rabbit\", keywords: [\"bunny\", \"animal\"] },\n { emoji: \"🦊\", name: \"fox\", keywords: [\"animal\", \"clever\"] },\n { emoji: \"🐻\", name: \"bear\", keywords: [\"animal\"] },\n { emoji: \"🐼\", name: \"panda\", keywords: [\"animal\", \"bear\"] },\n { emoji: \"🐨\", name: \"koala\", keywords: [\"animal\", \"australia\"] },\n { emoji: \"🦁\", name: \"lion\", keywords: [\"animal\", \"king\"] },\n { emoji: \"🐸\", name: \"frog\", keywords: [\"animal\", \"toad\"] },\n { emoji: \"🐙\", name: \"octopus\", keywords: [\"animal\", \"sea\"] },\n { emoji: \"🦋\", name: \"butterfly\", keywords: [\"insect\", \"pretty\"] },\n { emoji: \"🐛\", name: \"bug\", keywords: [\"insect\", \"caterpillar\"] },\n { emoji: \"🐝\", name: \"bee\", keywords: [\"insect\", \"honey\"] },\n { emoji: \"🦄\", name: \"unicorn\", keywords: [\"fantasy\", \"magic\", \"horse\"] },\n\n // Food & drink\n { emoji: \"🍎\", name: \"apple\", keywords: [\"fruit\", \"red\"] },\n { emoji: \"🍕\", name: \"pizza\", keywords: [\"food\", \"slice\"] },\n { emoji: \"🍔\", name: \"hamburger\", keywords: [\"food\", \"burger\"] },\n { emoji: \"🌮\", name: \"taco\", keywords: [\"food\", \"mexican\"] },\n { emoji: \"🍿\", name: \"popcorn\", keywords: [\"food\", \"movie\", \"snack\"] },\n { emoji: \"🍩\", name: \"doughnut\", keywords: [\"food\", \"donut\", \"sweet\"] },\n { emoji: \"🍪\", name: \"cookie\", keywords: [\"food\", \"sweet\", \"snack\"] },\n { emoji: \"🎂\", name: \"birthday\", keywords: [\"cake\", \"party\"] },\n { emoji: \"🍰\", name: \"cake\", keywords: [\"food\", \"dessert\", \"sweet\"] },\n { emoji: \"☕\", name: \"coffee\", keywords: [\"drink\", \"cafe\", \"hot\"] },\n { emoji: \"🍺\", name: \"beer\", keywords: [\"drink\", \"alcohol\"] },\n { emoji: \"🍷\", name: \"wine_glass\", keywords: [\"drink\", \"alcohol\"] },\n { emoji: \"🧃\", name: \"juice\", keywords: [\"drink\", \"box\"] },\n\n // Nature\n { emoji: \"🌸\", name: \"cherry_blossom\", keywords: [\"flower\", \"spring\", \"pink\"] },\n { emoji: \"🌹\", name: \"rose\", keywords: [\"flower\", \"love\", \"red\"] },\n { emoji: \"🌻\", name: \"sunflower\", keywords: [\"flower\", \"yellow\", \"sun\"] },\n { emoji: \"🌈\", name: \"rainbow\", keywords: [\"color\", \"weather\"] },\n { emoji: \"⭐\", name: \"star\", keywords: [\"night\", \"sky\", \"favorite\"] },\n { emoji: \"🌙\", name: \"crescent_moon\", keywords: [\"night\", \"moon\"] },\n { emoji: \"☀️\", name: \"sunny\", keywords: [\"sun\", \"weather\", \"bright\"] },\n { emoji: \"🔥\", name: \"fire\", keywords: [\"hot\", \"flame\", \"lit\"] },\n { emoji: \"💧\", name: \"droplet\", keywords: [\"water\", \"rain\", \"tear\"] },\n { emoji: \"❄️\", name: \"snowflake\", keywords: [\"cold\", \"winter\", \"snow\"] },\n { emoji: \"⚡\", name: \"zap\", keywords: [\"lightning\", \"electric\", \"power\"] },\n { emoji: \"🌊\", name: \"ocean\", keywords: [\"wave\", \"water\", \"sea\"] },\n\n // Objects & symbols\n { emoji: \"💡\", name: \"bulb\", keywords: [\"idea\", \"light\", \"lamp\"] },\n { emoji: \"📌\", name: \"pushpin\", keywords: [\"pin\", \"location\"] },\n { emoji: \"📎\", name: \"paperclip\", keywords: [\"attachment\", \"clip\"] },\n { emoji: \"🔗\", name: \"link\", keywords: [\"chain\", \"url\"] },\n { emoji: \"🔑\", name: \"key\", keywords: [\"lock\", \"password\"] },\n { emoji: \"🔒\", name: \"lock\", keywords: [\"secure\", \"closed\"] },\n { emoji: \"📦\", name: \"package\", keywords: [\"box\", \"shipping\", \"delivery\"] },\n { emoji: \"📝\", name: \"memo\", keywords: [\"note\", \"write\", \"pencil\"] },\n { emoji: \"📚\", name: \"books\", keywords: [\"reading\", \"library\"] },\n { emoji: \"💻\", name: \"computer\", keywords: [\"laptop\", \"tech\", \"mac\"] },\n { emoji: \"📱\", name: \"iphone\", keywords: [\"phone\", \"mobile\", \"cell\"] },\n { emoji: \"⏰\", name: \"alarm_clock\", keywords: [\"time\", \"clock\", \"wake\"] },\n { emoji: \"🎵\", name: \"musical_note\", keywords: [\"music\", \"song\"] },\n { emoji: \"🎬\", name: \"clapper\", keywords: [\"movie\", \"film\"] },\n { emoji: \"🎮\", name: \"video_game\", keywords: [\"game\", \"controller\", \"play\"] },\n { emoji: \"🏆\", name: \"trophy\", keywords: [\"win\", \"award\", \"prize\"] },\n { emoji: \"🎯\", name: \"dart\", keywords: [\"target\", \"bullseye\", \"goal\"] },\n { emoji: \"🧩\", name: \"puzzle_piece\", keywords: [\"jigsaw\", \"piece\"] },\n { emoji: \"💎\", name: \"gem\", keywords: [\"diamond\", \"jewel\", \"precious\"] },\n { emoji: \"🛠️\", name: \"hammer_and_wrench\", keywords: [\"tools\", \"fix\", \"build\"] },\n { emoji: \"⚙️\", name: \"gear\", keywords: [\"settings\", \"config\", \"cog\"] },\n { emoji: \"🧪\", name: \"test_tube\", keywords: [\"science\", \"experiment\", \"lab\"] },\n\n // Symbols\n { emoji: \"✅\", name: \"white_check_mark\", keywords: [\"check\", \"done\", \"yes\"] },\n { emoji: \"❌\", name: \"x\", keywords: [\"cross\", \"no\", \"wrong\", \"delete\"] },\n { emoji: \"⚠️\", name: \"warning\", keywords: [\"alert\", \"caution\", \"danger\"] },\n { emoji: \"❓\", name: \"question\", keywords: [\"what\", \"help\", \"confused\"] },\n { emoji: \"❗\", name: \"exclamation\", keywords: [\"important\", \"bang\", \"alert\"] },\n { emoji: \"💯\", name: \"100\", keywords: [\"percent\", \"perfect\", \"score\"] },\n { emoji: \"🚀\", name: \"rocket\", keywords: [\"launch\", \"ship\", \"fast\", \"space\"] },\n { emoji: \"✨\", name: \"sparkles\", keywords: [\"magic\", \"shiny\", \"new\", \"clean\"] },\n { emoji: \"🎉\", name: \"tada\", keywords: [\"party\", \"celebration\", \"congrats\"] },\n { emoji: \"🎊\", name: \"confetti_ball\", keywords: [\"party\", \"celebration\"] },\n { emoji: \"👀\", name: \"eyes\", keywords: [\"look\", \"see\", \"watch\"] },\n { emoji: \"🧠\", name: \"brain\", keywords: [\"think\", \"smart\", \"mind\"] },\n { emoji: \"💬\", name: \"speech_balloon\", keywords: [\"comment\", \"talk\", \"chat\"] },\n { emoji: \"💭\", name: \"thought_balloon\", keywords: [\"think\", \"bubble\"] },\n { emoji: \"🏠\", name: \"house\", keywords: [\"home\", \"building\"] },\n { emoji: \"🚗\", name: \"car\", keywords: [\"vehicle\", \"drive\", \"auto\"] },\n { emoji: \"✈️\", name: \"airplane\", keywords: [\"fly\", \"travel\", \"plane\"] },\n { emoji: \"🕐\", name: \"clock1\", keywords: [\"time\", \"one\"] },\n { emoji: \"🔔\", name: \"bell\", keywords: [\"notification\", \"alert\", \"ring\"] },\n { emoji: \"📣\", name: \"mega\", keywords: [\"megaphone\", \"announce\", \"loud\"] },\n { emoji: \"🏳️\", name: \"white_flag\", keywords: [\"flag\", \"surrender\"] },\n { emoji: \"🏁\", name: \"checkered_flag\", keywords: [\"flag\", \"finish\", \"race\"] },\n];\n\n/** Emoji category — defines a slice of EMOJI_LIST for browsing. */\nexport interface EmojiCategory {\n key: string;\n icon: string;\n start: number;\n end: number;\n}\n\n/** Category definitions matching the order of EMOJI_LIST. */\nexport const EMOJI_CATEGORIES: EmojiCategory[] = [\n { key: \"faces\", icon: \"😀\", start: 0, end: 54 },\n { key: \"hands\", icon: \"👋\", start: 54, end: 78 },\n { key: \"hearts\", icon: \"❤️\", start: 78, end: 88 },\n { key: \"animals\", icon: \"🐶\", start: 88, end: 104 },\n { key: \"food\", icon: \"🍎\", start: 104, end: 117 },\n { key: \"nature\", icon: \"🌸\", start: 117, end: 129 },\n { key: \"objects\", icon: \"💡\", start: 129, end: 151 },\n { key: \"symbols\", icon: \"✨\", start: 151, end: 173 },\n];\n\n/** Get emoji entries for a category. */\nexport function getEmojiByCategory(category: EmojiCategory): EmojiEntry[] {\n return EMOJI_LIST.slice(category.start, category.end);\n}\n\n/**\n * Search emoji by name/keyword prefix match.\n * Returns top N results (default 8).\n */\nexport function searchEmoji(query: string, limit = 8): EmojiEntry[] {\n const q = query.toLowerCase().trim();\n if (q === \"\") {\n // Return popular/common emoji when query is empty\n return EMOJI_LIST.slice(0, limit);\n }\n\n const results: EmojiEntry[] = [];\n // Prioritize name matches first, then keyword matches\n for (const entry of EMOJI_LIST) {\n if (entry.name.startsWith(q)) {\n results.push(entry);\n if (results.length >= limit) return results;\n }\n }\n for (const entry of EMOJI_LIST) {\n if (results.includes(entry)) continue;\n if (\n entry.name.includes(q) ||\n entry.keywords.some((kw) => kw.startsWith(q))\n ) {\n results.push(entry);\n if (results.length >= limit) return results;\n }\n }\n return results;\n}\n","import type { EmojiEntry } from \"./emoji-data\";\nimport { EMOJI_CATEGORIES, getEmojiByCategory } from \"./emoji-data\";\n\n/** Number of columns in the emoji grid. */\nconst GRID_COLS = 8;\n\nexport class EmojiPicker {\n private el: HTMLElement;\n private items: EmojiEntry[] = [];\n private selectedIndex = 0;\n private onSelect: (emoji: string) => void;\n private onClose: () => void;\n\n /** Whether the picker is showing browse mode (all categories) vs search results. */\n private browseMode = false;\n private activeCategoryIndex = 0;\n\n // DOM elements\n private tabBar: HTMLElement;\n private grid: HTMLElement;\n private tooltip: HTMLElement;\n\n constructor(\n onSelect: (emoji: string) => void,\n onClose: () => void,\n ) {\n this.onSelect = onSelect;\n this.onClose = onClose;\n\n this.el = document.createElement(\"div\");\n this.el.classList.add(\"blx-emoji-picker\");\n this.el.style.display = \"none\";\n\n // Category tab bar (hidden during search)\n this.tabBar = document.createElement(\"div\");\n this.tabBar.classList.add(\"blx-emoji-tabs\");\n this.el.appendChild(this.tabBar);\n\n // Emoji grid\n this.grid = document.createElement(\"div\");\n this.grid.classList.add(\"blx-emoji-grid\");\n this.el.appendChild(this.grid);\n\n // Hover tooltip (shows name on hover)\n this.tooltip = document.createElement(\"div\");\n this.tooltip.classList.add(\"blx-emoji-tooltip\");\n this.el.appendChild(this.tooltip);\n\n this.buildTabBar();\n }\n\n get element(): HTMLElement {\n return this.el;\n }\n\n show(anchorRect: DOMRect): void {\n this.selectedIndex = 0;\n this.renderGrid();\n this.el.style.display = \"\";\n this.el.style.position = \"fixed\";\n this.el.style.left = `${anchorRect.left}px`;\n // Position above the caret by default — tabs on top (farthest from caret)\n this.el.style.top = \"auto\";\n this.el.style.bottom = `${window.innerHeight - anchorRect.top + 4}px`;\n this.el.style.flexDirection = \"column\";\n\n // Ensure it stays within the viewport\n requestAnimationFrame(() => {\n const menuRect = this.el.getBoundingClientRect();\n // If off the top, flip to below the caret — tabs on bottom (farthest from caret)\n if (menuRect.top < 0) {\n this.el.style.bottom = \"auto\";\n this.el.style.top = `${anchorRect.bottom + 4}px`;\n this.el.style.flexDirection = \"column-reverse\";\n }\n // If off the right, nudge left\n if (menuRect.right > window.innerWidth) {\n this.el.style.left = `${window.innerWidth - menuRect.width - 8}px`;\n }\n // If off the left, nudge right\n if (menuRect.left < 0) {\n this.el.style.left = \"8px\";\n }\n });\n }\n\n /** Reposition the picker to follow a new anchor rect (e.g. on scroll) */\n reposition(anchorRect: DOMRect): void {\n this.el.style.left = `${anchorRect.left}px`;\n this.el.style.top = \"auto\";\n this.el.style.bottom = `${window.innerHeight - anchorRect.top + 4}px`;\n this.el.style.flexDirection = \"column\";\n\n const menuRect = this.el.getBoundingClientRect();\n if (menuRect.top < 0) {\n this.el.style.bottom = \"auto\";\n this.el.style.top = `${anchorRect.bottom + 4}px`;\n this.el.style.flexDirection = \"column-reverse\";\n }\n if (menuRect.right > window.innerWidth) {\n this.el.style.left = `${window.innerWidth - menuRect.width - 8}px`;\n }\n if (menuRect.left < 0) {\n this.el.style.left = \"8px\";\n }\n }\n\n hide(): void {\n this.el.style.display = \"none\";\n this.tooltip.style.display = \"none\";\n }\n\n get visible(): boolean {\n return this.el.style.display !== \"none\";\n }\n\n updateResults(entries: EmojiEntry[]): void {\n this.items = entries;\n this.selectedIndex = 0;\n if (entries.length === 0) {\n this.hide();\n } else {\n this.renderGrid();\n }\n }\n\n /**\n * Switch to browse mode — show all emoji in the active category.\n * Called when the query is empty (user just typed `:` with nothing after).\n */\n enterBrowseMode(): void {\n this.browseMode = true;\n this.tabBar.style.display = \"\";\n this.grid.classList.add(\"blx-emoji-grid-browse\");\n this.items = getEmojiByCategory(EMOJI_CATEGORIES[this.activeCategoryIndex]);\n this.selectedIndex = 0;\n this.updateTabSelection();\n this.renderGrid();\n }\n\n /**\n * Switch to search mode — show filtered results.\n * Called when the query has text.\n */\n enterSearchMode(entries: EmojiEntry[]): void {\n this.browseMode = false;\n this.tabBar.style.display = \"none\";\n this.grid.classList.remove(\"blx-emoji-grid-browse\");\n this.items = entries;\n this.selectedIndex = 0;\n if (entries.length === 0) {\n this.hide();\n } else {\n this.renderGrid();\n }\n }\n\n /** Handle keyboard events. Returns true if the event was consumed. */\n handleKeyDown(e: KeyboardEvent): boolean {\n if (this.items.length === 0) return false;\n\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n if (this.browseMode && e.altKey) {\n // Alt+Right: next category\n this.switchCategory((this.activeCategoryIndex + 1) % EMOJI_CATEGORIES.length);\n return true;\n }\n this.selectedIndex = (this.selectedIndex + 1) % this.items.length;\n this.updateSelection();\n return true;\n }\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n if (this.browseMode && e.altKey) {\n // Alt+Left: prev category\n this.switchCategory(\n (this.activeCategoryIndex - 1 + EMOJI_CATEGORIES.length) % EMOJI_CATEGORIES.length,\n );\n return true;\n }\n this.selectedIndex = (this.selectedIndex - 1 + this.items.length) % this.items.length;\n this.updateSelection();\n return true;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n const next = this.selectedIndex + GRID_COLS;\n if (next < this.items.length) {\n this.selectedIndex = next;\n } else if (this.browseMode) {\n // Jump to next category\n const nextCat = (this.activeCategoryIndex + 1) % EMOJI_CATEGORIES.length;\n this.switchCategory(nextCat);\n }\n this.updateSelection();\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n const prev = this.selectedIndex - GRID_COLS;\n if (prev >= 0) {\n this.selectedIndex = prev;\n } else if (this.browseMode) {\n // Jump to prev category\n const prevCat =\n (this.activeCategoryIndex - 1 + EMOJI_CATEGORIES.length) % EMOJI_CATEGORIES.length;\n this.switchCategory(prevCat);\n // Select last row, same column\n const col = this.selectedIndex % GRID_COLS;\n const lastRow = Math.floor((this.items.length - 1) / GRID_COLS);\n this.selectedIndex = Math.min(lastRow * GRID_COLS + col, this.items.length - 1);\n }\n this.updateSelection();\n return true;\n }\n if (e.key === \"Enter\" || e.key === \"Tab\") {\n e.preventDefault();\n this.onSelect(this.items[this.selectedIndex].emoji);\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.onClose();\n return true;\n }\n // Other keys are NOT consumed — they pass through to BlockController\n return false;\n }\n\n /** Get the currently selected entry, or null */\n getSelectedEntry(): EmojiEntry | null {\n return this.items[this.selectedIndex] ?? null;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n // ── Private ──\n\n private buildTabBar(): void {\n this.tabBar.innerHTML = \"\";\n EMOJI_CATEGORIES.forEach((cat, i) => {\n const tab = document.createElement(\"button\");\n tab.type = \"button\";\n tab.classList.add(\"blx-emoji-tab\");\n tab.textContent = cat.icon;\n tab.title = cat.key;\n if (i === this.activeCategoryIndex) {\n tab.classList.add(\"blx-emoji-tab-active\");\n }\n tab.addEventListener(\"mousedown\", (e) => {\n e.preventDefault(); // prevent blur\n this.switchCategory(i);\n });\n this.tabBar.appendChild(tab);\n });\n }\n\n private switchCategory(index: number): void {\n this.activeCategoryIndex = index;\n this.items = getEmojiByCategory(EMOJI_CATEGORIES[index]);\n this.selectedIndex = 0;\n this.updateTabSelection();\n this.renderGrid();\n }\n\n private updateTabSelection(): void {\n const tabs = this.tabBar.querySelectorAll(\".blx-emoji-tab\");\n tabs.forEach((tab, i) => {\n tab.classList.toggle(\"blx-emoji-tab-active\", i === this.activeCategoryIndex);\n });\n }\n\n private renderGrid(): void {\n this.grid.innerHTML = \"\";\n this.tooltip.style.display = \"none\";\n\n this.items.forEach((entry, i) => {\n const btn = document.createElement(\"button\");\n btn.classList.add(\"blx-emoji-cell\");\n if (i === this.selectedIndex) {\n btn.classList.add(\"blx-emoji-cell-selected\");\n }\n btn.type = \"button\";\n btn.textContent = entry.emoji;\n btn.title = entry.name;\n\n btn.addEventListener(\"mouseenter\", () => {\n this.selectedIndex = i;\n this.updateSelection();\n this.showTooltip(entry.name, btn);\n });\n btn.addEventListener(\"mouseleave\", () => {\n this.tooltip.style.display = \"none\";\n });\n btn.addEventListener(\"mousedown\", (e) => {\n e.preventDefault(); // prevent blur\n this.onSelect(entry.emoji);\n });\n\n this.grid.appendChild(btn);\n });\n }\n\n private updateSelection(): void {\n const cells = this.grid.querySelectorAll(\".blx-emoji-cell\");\n cells.forEach((cell, i) => {\n cell.classList.toggle(\"blx-emoji-cell-selected\", i === this.selectedIndex);\n });\n // Scroll selected cell into view within the grid\n const selected = cells[this.selectedIndex] as HTMLElement | undefined;\n selected?.scrollIntoView({ block: \"nearest\" });\n }\n\n private showTooltip(name: string, anchor: HTMLElement): void {\n this.tooltip.textContent = name;\n this.tooltip.style.display = \"\";\n // Position tooltip below the anchor cell\n const gridRect = this.grid.getBoundingClientRect();\n const cellRect = anchor.getBoundingClientRect();\n this.tooltip.style.left = `${cellRect.left - gridRect.left + cellRect.width / 2}px`;\n }\n}\n","import type { Block } from \"../types\";\nimport type { BlockView } from \"./types\";\nimport type { EventBus } from \"../event-bus\";\nimport type { EditorEventMap } from \"../event-bus\";\nimport type { BlockTypePlugin } from \"../schema\";\nimport { Transaction } from \"../transaction\";\nimport { AttributedString } from \"../attributed-string\";\nimport { detectInlineShortcut } from \"../markdown/inline-shortcuts\";\nimport { detectBlockShortcut, detectImmediateBlockShortcut, matchBlockShortcutPattern } from \"../markdown/block-shortcuts\";\nimport { detectEmoticon } from \"../markdown/emoticon-substitutions\";\nimport { prevGraphemeBoundary, nextGraphemeBoundary } from \"../grapheme\";\nimport { searchEmoji } from \"../emoji-picker\";\n\n/**\n * Per-block controller that bridges model and DOM.\n *\n * Strategy:\n * - `beforeinput` → preventDefault → create Transaction → apply → re-render\n * - MutationObserver as fallback for IME / spell-check\n * - Model is always source of truth\n */\nexport class BlockController implements BlockView {\n readonly blockId: string;\n readonly container: HTMLElement;\n private _contentEditable: HTMLElement | null = null;\n private _mounted = false;\n private _contentRendered = false;\n private _listenersAttached = false;\n private block: Block;\n private plugin: BlockTypePlugin;\n private bus: EventBus<EditorEventMap>;\n private observer: MutationObserver | null = null;\n private suppressObserver = false;\n /** One-shot attribute override for the next insertText, set after inline shortcuts */\n private nextInsertAttrs: Record<string, unknown> | null = null;\n /**\n * Persistent attribute overrides set by format shortcuts (Ctrl-B/I/U) on a\n * collapsed cursor. Unlike nextInsertAttrs, these persist across multiple\n * character inserts until the cursor moves or a non-insert action occurs.\n * Keys are attribute names, values indicate desired state (true = add, false = remove).\n */\n private _pendingMarks: Record<string, boolean> | null = null;\n /** Flag to suppress clearing pendingMarks on the next selectionchange event */\n private _suppressPendingMarksClear = false;\n /** Offset of the opening ':' for emoji picker, or null when inactive */\n private emojiColonOffset: number | null = null;\n /** Offset of the opening '/' for slash command menu, or null when inactive */\n private slashCommandOffset: number | null = null;\n /** Offset of a pending first '[' for autocomplete trigger */\n private pendingBracketOffset: number | null = null;\n /** Offset of the opening '[[' for autocomplete menu, or null when inactive */\n private autoCompleteOffset: number | null = null;\n /** Offset of the '@' that triggered the agenda picker, or null when inactive */\n private agendaAtOffset: number | null = null;\n /** Detected role prefix from inline syntax like @due( or @scheduled( */\n private agendaRole: \"due\" | \"scheduled\" | \"event\" | undefined = undefined;\n /** Length of the prefix portion (e.g., \"due(\" = 4) that has been typed, used to strip from query */\n private agendaPrefixLen = 0;\n\n constructor(\n block: Block,\n plugin: BlockTypePlugin,\n bus: EventBus<EditorEventMap>,\n ) {\n this.block = block;\n this.blockId = block.id;\n this.plugin = plugin;\n this.bus = bus;\n this.container = document.createElement(\"div\");\n this.container.classList.add(\"blx-block\");\n this.container.dataset.blockId = block.id;\n this.container.dataset.blockType = block.type;\n // Prevent the browser's built-in scroll anchoring from selecting this\n // element as an anchor. BlockViewport does its own scroll compensation\n // when mounting/unmounting content, and browser anchoring would\n // double-compensate, causing a reverse stutter.\n this.container.style.overflowAnchor = \"none\";\n }\n\n get contentEditable(): HTMLElement | null {\n return this._contentEditable;\n }\n\n get mounted(): boolean {\n return this._mounted;\n }\n\n /** Whether block content is currently rendered into the container */\n get contentRendered(): boolean {\n return this._contentRendered;\n }\n\n /** Mount this block — render into container and attach event listeners */\n mount(parent: HTMLElement, before?: HTMLElement | null): void {\n if (this._mounted) return;\n this.mountContainer(parent, before);\n this.mountContent();\n }\n\n /**\n * Insert the container element into the DOM without rendering content.\n * Used by the viewport system to place all block containers for scroll\n * position stability while deferring expensive content rendering.\n */\n mountContainer(parent: HTMLElement | DocumentFragment, before?: HTMLElement | null): void {\n if (this._mounted) return;\n\n if (before) {\n parent.insertBefore(this.container, before);\n } else {\n parent.appendChild(this.container);\n }\n\n this._mounted = true;\n }\n\n /**\n * Render content into an already-mounted container and attach event\n * listeners. If the block was previously ejected (content hidden but\n * still in the DOM), restores it without re-rendering.\n */\n mountContent(): void {\n if (!this._mounted) return;\n\n // Fast path: block was ejected — just restore visibility + listeners\n if (this._contentRendered && !this._listenersAttached) {\n this.restoreContent();\n return;\n }\n\n if (this._contentRendered) return;\n\n this._contentEditable = this.plugin.render(\n this.container,\n this.block.content,\n this.block.metadata,\n );\n\n this._contentRendered = true;\n // Don't clear minHeight here — the viewport manages it after scroll\n // compensation to avoid layout shift during first-mount batches.\n this.attachListeners();\n this._listenersAttached = true;\n this.applyIndentation();\n }\n\n /**\n * Eject block content: detach listeners and hide rendering via CSS.\n * The DOM stays intact so the container height is perfectly preserved —\n * no layout shift, no scroll compensation needed.\n */\n ejectContent(preReadHeight?: number): void {\n if (!this._contentRendered || !this._listenersAttached) return;\n // Capture real height before ejecting — content-visibility: hidden\n // collapses to 0 without an explicit height (contain-intrinsic-size\n // auto only remembers size for content-visibility: auto, not hidden).\n const h = preReadHeight ?? this.container.offsetHeight;\n this.container.style.height = `${h}px`;\n this.detachListeners();\n this._listenersAttached = false;\n this.container.classList.add(\"blx-block-ejected\");\n }\n\n /**\n * Restore a previously ejected block: re-attach listeners and show content.\n * Since the DOM was never cleared, this is a zero-cost operation with no\n * layout shift.\n */\n restoreContent(): void {\n if (!this._contentRendered || this._listenersAttached) return;\n this.container.classList.remove(\"blx-block-ejected\");\n this.container.style.height = \"\";\n this.attachListeners();\n this._listenersAttached = true;\n }\n\n /**\n * Remove rendered content and event listeners but keep the container\n * in the DOM. Saves the current height as minHeight for scroll stability.\n * The block data model is preserved — only the DOM representation is removed.\n *\n * Used for full cleanup (block deletion, deep eviction). For normal\n * viewport cycling, prefer ejectContent/restoreContent which preserve\n * the DOM and avoid layout shifts.\n *\n * @param preReadHeight — If provided, skip the offsetHeight read and use\n * this value instead. This avoids forced layout when the caller has\n * already batched height reads (e.g. BlockViewport.handleIntersection).\n */\n unmountContent(preReadHeight?: number): void {\n if (!this._contentRendered) return;\n\n // Save current height to prevent scroll jumps\n const height = preReadHeight ?? this.container.offsetHeight;\n this.detachListeners();\n this._listenersAttached = false;\n this.container.classList.remove(\"blx-block-ejected\");\n this.container.innerHTML = \"\";\n this.container.style.minHeight = height > 0 ? `${height}px` : \"\";\n this._contentRendered = false;\n this._contentEditable = null;\n }\n\n /** Apply a transaction — updates the model and re-renders */\n applyTransaction(tx: Transaction): void {\n const previousContent = this.block.content;\n const previousMetadata = { ...this.block.metadata };\n const previousCursorOffset = this.getCursorOffset() ?? 0;\n const result = tx.apply(this.block.content, this.block.metadata);\n this.block = {\n ...this.block,\n content: result.content,\n metadata: result.metadata,\n };\n this.renderContent();\n this.bus.emit(\"block:contentChanged\", {\n blockId: this.blockId,\n content: this.block.content,\n metadata: this.block.metadata,\n previousContent,\n previousMetadata,\n previousCursorOffset,\n });\n\n // Ensure caret stays visible after content changes\n this.scrollCaretIntoView();\n }\n\n /** Get current block data (read-only snapshot) */\n getBlock(): Block {\n return { ...this.block };\n }\n\n /** Update the block data directly (used by editor for split/merge/type-change) */\n updateBlock(updates: Partial<Pick<Block, \"content\" | \"metadata\" | \"type\">>): void {\n this.block = { ...this.block, ...updates };\n if (updates.type && updates.type !== this.container.dataset.blockType) {\n this.container.dataset.blockType = updates.type;\n }\n }\n\n /** Re-render with a new plugin (after type change) */\n setPlugin(plugin: BlockTypePlugin): void {\n this.plugin = plugin;\n if (!this._contentRendered) return;\n this.detachListeners();\n this._contentEditable = this.plugin.render(\n this.container,\n this.block.content,\n this.block.metadata,\n );\n this.attachListeners();\n this.applyIndentation();\n }\n\n /**\n * Re-render block content with cursor preservation.\n * Used by remote sync (AutomergeSync) to update content without losing\n * the user's cursor position or triggering spurious MutationObserver events.\n */\n rerender(): void {\n this.renderContent();\n }\n\n /** Ensure the contenteditable is visible (e.g. mermaid blocks hide their editor). */\n private ensureEditable(): void {\n if (this.block.type === \"mermaid\" && this._contentEditable) {\n const wrapper = this._contentEditable.closest(\".blx-mermaid\");\n if (wrapper) wrapper.classList.add(\"blx-mermaid--editing\");\n }\n }\n\n focus(offset?: number): void {\n if (!this._contentEditable) return;\n this.ensureEditable();\n this._contentEditable.focus();\n\n if (offset !== undefined) {\n this.setCursorOffset(offset);\n }\n }\n\n /** Returns the bounding rect of the current caret, or null if layout unavailable (jsdom). */\n getCaretRect(): DOMRect | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n try {\n const range = sel.getRangeAt(0).cloneRange();\n range.collapse(true);\n const rect = range.getBoundingClientRect();\n // jsdom returns all-zero rects or may not support this\n if (rect.width === 0 && rect.height === 0 && rect.top === 0 && rect.left === 0) {\n return null;\n }\n // Empty contenteditable: range has no height but the element does — use element rect\n // for top/height so goalX (left) is still preserved for X-affinity tracking\n if (rect.height === 0 && this._contentEditable) {\n const elRect = this._contentEditable.getBoundingClientRect();\n if (elRect.height > 0) {\n return new DOMRect(rect.left || elRect.left, elRect.top, 0, elRect.height);\n }\n }\n return rect;\n } catch {\n return null;\n }\n }\n\n /** Is the caret on the first visual line of this block? Returns true when layout is unavailable. */\n isCaretOnFirstLine(): boolean {\n if (!this._contentEditable) return true;\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return true;\n\n // For pre-formatted blocks (code, mermaid), lines are \\n-delimited —\n // use character offsets which are reliable even on empty lines where\n // getBoundingClientRect returns zero-height rects.\n if (this.block.type === \"code\" || this.block.type === \"mermaid\") {\n const offset = this.getCursorOffset() ?? 0;\n const textBefore = this.block.content.text.slice(0, offset);\n return !textBefore.includes(\"\\n\");\n }\n\n try {\n const caretRange = sel.getRangeAt(0).cloneRange();\n caretRange.collapse(true);\n const caretRect = caretRange.getBoundingClientRect();\n\n // Find the first text node for a reliable rect\n const walker = document.createTreeWalker(this._contentEditable, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode();\n if (!firstTextNode) return true;\n\n const startRange = document.createRange();\n startRange.setStart(firstTextNode, 0);\n startRange.collapse(true);\n const startRect = startRange.getBoundingClientRect();\n\n // Layout unavailable (zero rects) → treat as first line\n if (caretRect.height === 0 && startRect.height === 0) return true;\n\n // Same visual line if tops are close (within 2px tolerance for subpixel)\n return Math.abs(caretRect.top - startRect.top) < 2;\n } catch {\n // getBoundingClientRect not available (jsdom) → treat as first line\n return true;\n }\n }\n\n /** Is the caret on the last visual line of this block? Returns true when layout is unavailable. */\n isCaretOnLastLine(): boolean {\n if (!this._contentEditable) return true;\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return true;\n\n // For pre-formatted blocks (code, mermaid), lines are \\n-delimited —\n // use character offsets which are reliable even on empty lines where\n // getBoundingClientRect returns zero-height rects.\n if (this.block.type === \"code\" || this.block.type === \"mermaid\") {\n const offset = this.getCursorOffset() ?? 0;\n const textAfter = this.block.content.text.slice(offset);\n return !textAfter.includes(\"\\n\");\n }\n\n try {\n const caretRange = sel.getRangeAt(0).cloneRange();\n // Collapse to END (false) so we check the focus/end of an extended selection,\n // not the anchor/start. This matters for Shift+Down extending text selection.\n caretRange.collapse(false);\n const caretRect = caretRange.getBoundingClientRect();\n\n // Find the last text node for a reliable rect\n const walker = document.createTreeWalker(this._contentEditable, NodeFilter.SHOW_TEXT);\n let lastTextNode: Node | null = null;\n let node: Node | null;\n while ((node = walker.nextNode())) lastTextNode = node;\n if (!lastTextNode) return true;\n\n const endRange = document.createRange();\n endRange.setStart(lastTextNode, lastTextNode.textContent?.length ?? 0);\n endRange.collapse(true);\n const endRect = endRange.getBoundingClientRect();\n\n // Layout unavailable (zero rects) → treat as last line\n if (caretRect.height === 0 && endRect.height === 0) return true;\n\n return Math.abs(caretRect.top - endRect.top) < 2;\n } catch {\n // getBoundingClientRect not available (jsdom) → treat as last line\n return true;\n }\n }\n\n /** Focus this block and position cursor at horizontal X on the first or last line. */\n focusAtX(x: number, line: \"first\" | \"last\"): void {\n if (!this._contentEditable) return;\n this.ensureEditable();\n this._contentEditable.focus();\n\n // Try caretRangeFromPoint if available\n if (typeof document.caretRangeFromPoint === \"function\") {\n // Find the actual Y of the target text line by positioning a range\n // at the first or last text node and reading its rect center.\n const y = this.getLineY(line);\n if (y !== null) {\n const range = document.caretRangeFromPoint(x, y);\n if (range && this._contentEditable.contains(range.startContainer)) {\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n }\n }\n\n // Fallback: position at start or end\n this.setCursorOffset(line === \"first\" ? 0 : this.block.content.length);\n }\n\n /**\n * Focus this block and position cursor at the character nearest to (x, y).\n * Uses caretRangeFromPoint with the raw click coordinates; if the point\n * falls outside the text lines it clamps to the nearest (first/last) line.\n * If the click is outside the contenteditable's horizontal bounds, x is\n * clamped inside so caretRangeFromPoint returns the nearest line edge rather\n * than falling through to an offset-0 fallback.\n */\n focusAtPoint(x: number, y: number): void {\n if (!this._contentEditable) return;\n this.ensureEditable();\n this._contentEditable.focus();\n\n if (typeof document.caretRangeFromPoint === \"function\") {\n const ceRect = this._contentEditable.getBoundingClientRect();\n const style = getComputedStyle(this._contentEditable);\n const paddingTop = parseFloat(style.paddingTop) || 0;\n const paddingBottom = parseFloat(style.paddingBottom) || 0;\n\n // Clamp x to within the contenteditable's horizontal bounds so that\n // left/right gutter clicks map to the start/end of the nearest line.\n const clampedX = Math.max(ceRect.left + 1, Math.min(x, ceRect.right - 1));\n\n // Only use the raw y when it is within the text content area (not in the\n // top/bottom padding). In the padding there is no text at that y, so\n // caretRangeFromPoint snaps to offset 0 regardless of x.\n const yInTextArea = y >= ceRect.top + paddingTop && y <= ceRect.bottom - paddingBottom;\n if (yInTextArea) {\n const range = document.caretRangeFromPoint(clampedX, y);\n if (range && this._contentEditable.contains(range.startContainer)) {\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n }\n\n // y is in the padding or outside the contenteditable — clamp to the\n // nearest line's actual y so caretRangeFromPoint can use x correctly.\n const line: \"first\" | \"last\" = y < ceRect.top + ceRect.height / 2 ? \"first\" : \"last\";\n const lineY = this.getLineY(line);\n if (lineY !== null) {\n const clamped = document.caretRangeFromPoint(clampedX, lineY);\n if (clamped && this._contentEditable.contains(clamped.startContainer)) {\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(clamped);\n return;\n }\n }\n }\n }\n\n // Final fallback: start or end based on x position within the contenteditable.\n const ceRect = this._contentEditable.getBoundingClientRect();\n const atEnd = x >= ceRect.left + ceRect.width / 2;\n this.setCursorOffset(atEnd ? this.block.content.length : 0);\n }\n\n /** Get the vertical center of the first or last text line in this block, or null. */\n private getLineY(line: \"first\" | \"last\"): number | null {\n if (!this._contentEditable) return null;\n try {\n const walker = document.createTreeWalker(this._contentEditable, NodeFilter.SHOW_TEXT);\n let textNode: Node | null = null;\n if (line === \"first\") {\n textNode = walker.nextNode();\n } else {\n let node: Node | null;\n while ((node = walker.nextNode())) textNode = node;\n }\n if (!textNode) return null;\n\n const range = document.createRange();\n if (line === \"first\") {\n range.setStart(textNode, 0);\n } else {\n range.setStart(textNode, textNode.textContent?.length ?? 0);\n }\n range.collapse(true);\n const rect = range.getBoundingClientRect();\n if (rect.height === 0) return null;\n return rect.top + rect.height / 2;\n } catch {\n return null;\n }\n }\n\n /**\n * Wrap characters [start, end) in a <mark> element with the given CSS class.\n * Handles ranges that span across multiple inline elements (bold, italic, etc.)\n * by wrapping each text node portion separately.\n * Must suppress MutationObserver to avoid treating marks as user edits.\n */\n highlightRange(start: number, end: number, className: string): void {\n if (!this._contentEditable || !this._contentRendered) return;\n if (start >= end) return;\n\n this.suppressObserver = true;\n try {\n // Collect text nodes and their character offsets\n const walker = document.createTreeWalker(\n this._contentEditable,\n NodeFilter.SHOW_TEXT,\n );\n const textNodes: { node: Text; start: number; end: number }[] = [];\n let pos = 0;\n let node = walker.nextNode() as Text | null;\n while (node) {\n const len = node.textContent?.length ?? 0;\n textNodes.push({ node, start: pos, end: pos + len });\n pos += len;\n node = walker.nextNode() as Text | null;\n }\n\n // Find text nodes that overlap with [start, end)\n for (const tn of textNodes) {\n const overlapStart = Math.max(start, tn.start);\n const overlapEnd = Math.min(end, tn.end);\n if (overlapStart >= overlapEnd) continue;\n\n const localStart = overlapStart - tn.start;\n const localEnd = overlapEnd - tn.start;\n const textNode = tn.node;\n\n // Split the text node to isolate the match portion\n const mark = document.createElement(\"mark\");\n mark.className = className;\n\n if (localEnd < (textNode.textContent?.length ?? 0)) {\n textNode.splitText(localEnd);\n }\n const matchNode = localStart > 0 ? textNode.splitText(localStart) : textNode;\n matchNode.parentNode!.insertBefore(mark, matchNode);\n mark.appendChild(matchNode);\n }\n } finally {\n this.suppressObserver = false;\n }\n }\n\n /**\n * Remove all <mark> elements with the given CSS class, restoring the original\n * text nodes. Normalizes the parent to merge adjacent text nodes.\n */\n clearHighlights(className: string): void {\n if (!this._contentEditable) return;\n\n this.suppressObserver = true;\n try {\n const marks = this._contentEditable.querySelectorAll(`mark.${className}`);\n for (const mark of marks) {\n const parent = mark.parentNode;\n while (mark.firstChild) {\n parent!.insertBefore(mark.firstChild, mark);\n }\n parent!.removeChild(mark);\n parent!.normalize();\n }\n } finally {\n this.suppressObserver = false;\n }\n }\n\n destroy(): void {\n if (!this._mounted) return;\n if (this._contentRendered) {\n if (this._listenersAttached) {\n this.detachListeners();\n this._listenersAttached = false;\n }\n this._contentRendered = false;\n }\n this.container.classList.remove(\"blx-block-ejected\");\n this.container.remove();\n this._mounted = false;\n this._contentEditable = null;\n }\n\n /** Scroll the current caret position into view if needed */\n private scrollCaretIntoView(): void {\n if (!this._contentEditable) return;\n\n try {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n\n const range = sel.getRangeAt(0);\n if (!this._contentEditable.contains(range.startContainer)) return;\n\n const rect = range.getBoundingClientRect();\n if (rect.height === 0) return;\n\n // Check if caret is visible in the visible viewport.\n // Use visualViewport.height when available so the check accounts for\n // the on-screen keyboard on mobile (window.innerHeight stays at the\n // layout viewport height and does not shrink when the keyboard opens).\n const viewportHeight = window.visualViewport?.height ?? window.innerHeight;\n const isAboveViewport = rect.top < 0;\n const isBelowViewport = rect.bottom > viewportHeight;\n\n if (isAboveViewport || isBelowViewport) {\n // Use scrollIntoView with smooth behavior for better UX\n const target = range.startContainer.nodeType === Node.TEXT_NODE\n ? range.startContainer.parentElement\n : range.startContainer as HTMLElement;\n\n if (target) {\n target.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\",\n inline: \"nearest\"\n });\n }\n }\n } catch {\n // Ignore errors in environments without full DOM support\n }\n }\n\n // ── Private ─────────────────────────────────────────────────────\n\n private renderContent(): void {\n // Skip DOM rendering if content is not mounted (model is still updated)\n if (!this._contentRendered) return;\n\n // Non-text blocks (image, youtube, hr): re-render from the plugin,\n // but skip if focus is inside the container (e.g. image caption editing)\n // since the DOM already reflects the user's input.\n if (!this.plugin.hasTextContent) {\n if (!this.container.contains(document.activeElement)) {\n this.plugin.render(this.container, this.block.content, this.block.metadata);\n }\n return;\n }\n if (!this._contentEditable) return;\n\n // Save cursor position and focus state BEFORE update (innerHTML may blur)\n const cursorOffset = this.getCursorOffset();\n const hadFocus =\n document.activeElement === this._contentEditable ||\n this._contentEditable.contains(document.activeElement);\n\n this.suppressObserver = true;\n if (this.plugin.update) {\n this.plugin.update(\n this.container,\n this._contentEditable,\n this.block.content,\n this.block.metadata,\n );\n // update might replace the contentEditable (e.g., heading level change)\n const newCE = this.container.querySelector<HTMLElement>('[contenteditable=\"true\"]');\n if (newCE && newCE !== this._contentEditable) {\n this.detachListeners();\n this._contentEditable = newCE;\n this.attachListeners();\n }\n } else {\n this._contentEditable = this.plugin.render(\n this.container,\n this.block.content,\n this.block.metadata,\n );\n }\n this.suppressObserver = false;\n\n this.applyIndentation();\n\n // Restore cursor position (use saved hadFocus since innerHTML may have blurred)\n if (cursorOffset !== null && hadFocus) {\n this._contentEditable?.focus();\n this.setCursorOffset(cursorOffset);\n }\n }\n\n private attachListeners(): void {\n if (!this._contentEditable) return;\n\n this._contentEditable.addEventListener(\"beforeinput\", this.handleBeforeInput);\n this._contentEditable.addEventListener(\"keydown\", this.handleKeyDown);\n this._contentEditable.addEventListener(\"paste\", this.handlePaste);\n this._contentEditable.addEventListener(\"focus\", this.handleFocus);\n this._contentEditable.addEventListener(\"blur\", this.handleBlur);\n this.container.addEventListener(\"blx:codeLanguageChange\", this.handleCodeLanguageChange as EventListener);\n this.container.addEventListener(\"blx:checklistToggle\", this.handleChecklistToggle as EventListener);\n this.container.addEventListener(\"blx:headingTaskToggle\", this.handleHeadingTaskToggle as EventListener);\n this.container.addEventListener(\"blx:agendaEdit\", this.handleAgendaEdit as EventListener);\n\n // MutationObserver is attached lazily on focus and disconnected on blur\n // to avoid thousands of observers watching the DOM in large documents.\n }\n\n private detachListeners(): void {\n if (this._contentEditable) {\n this._contentEditable.removeEventListener(\"beforeinput\", this.handleBeforeInput);\n this._contentEditable.removeEventListener(\"keydown\", this.handleKeyDown);\n this._contentEditable.removeEventListener(\"paste\", this.handlePaste);\n this._contentEditable.removeEventListener(\"focus\", this.handleFocus);\n this._contentEditable.removeEventListener(\"blur\", this.handleBlur);\n }\n this.container.removeEventListener(\"blx:codeLanguageChange\", this.handleCodeLanguageChange as EventListener);\n this.container.removeEventListener(\"blx:checklistToggle\", this.handleChecklistToggle as EventListener);\n this.container.removeEventListener(\"blx:headingTaskToggle\", this.handleHeadingTaskToggle as EventListener);\n this.container.removeEventListener(\"blx:agendaEdit\", this.handleAgendaEdit as EventListener);\n this.disconnectObserver();\n }\n\n /** Connect the MutationObserver to the contentEditable element */\n private connectObserver(): void {\n if (this.observer || !this._contentEditable) return;\n this.observer = new MutationObserver(this.handleMutation);\n this.observer.observe(this._contentEditable, {\n childList: true,\n characterData: true,\n subtree: true,\n });\n }\n\n /** Disconnect the MutationObserver */\n private disconnectObserver(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n }\n\n private handleBeforeInput = (e: InputEvent): void => {\n // Let IME composition through — we handle it via MutationObserver.\n // Exception: block-boundary deletions (merge) are structural operations\n // that MutationObserver can't handle, so we intercept them even during\n // composition. This is critical for mobile virtual keyboards that wrap\n // all input (including backspace) in composition mode.\n if (e.isComposing) {\n const inputType = e.inputType;\n // Block-boundary deletions → merge (MutationObserver can't handle cross-block ops)\n if (inputType === \"deleteContentBackward\" || inputType === \"deleteContentForward\") {\n const sel = window.getSelection();\n if (sel?.isCollapsed) {\n const offset = this.getCursorOffset() ?? 0;\n if (inputType === \"deleteContentBackward\" && offset === 0) {\n e.preventDefault();\n this.bus.emit(\"block:merge\", {\n blockId: this.blockId,\n direction: \"backward\",\n });\n return;\n }\n if (inputType === \"deleteContentForward\" && offset >= this.block.content.length) {\n e.preventDefault();\n this.bus.emit(\"block:merge\", {\n blockId: this.blockId,\n direction: \"forward\",\n });\n return;\n }\n }\n }\n // Enter → split (some mobile keyboards fire insertParagraph during composition)\n if (inputType === \"insertParagraph\") {\n e.preventDefault();\n const offset = this.getCursorOffset() ?? this.block.content.length;\n this.bus.emit(\"block:split\", { blockId: this.blockId, offset });\n return;\n }\n return;\n }\n\n const inputType = e.inputType;\n\n // Clear stored attributes on any non-insertText action\n if (inputType !== \"insertText\") {\n this.nextInsertAttrs = null;\n this._pendingMarks = null;\n }\n\n if (inputType === \"insertText\" && e.data) {\n e.preventDefault();\n\n // If there's a selection, delete it first (type-over-selection)\n const { start: selStart, end: selEnd } = this.getSelectionRange();\n if (selStart !== selEnd) {\n const delTx = new Transaction(this.blockId).deleteRange(selStart, selEnd);\n this.applyTransaction(delTx);\n this.setCursorOffset(selStart);\n }\n\n const offset = this.getCursorOffset() ?? this.block.content.length;\n const text = this.block.content.text;\n const char = e.data;\n\n // Consume one-shot attribute override (set by inline shortcuts)\n const storedAttrs = this.nextInsertAttrs;\n this.nextInsertAttrs = null;\n\n // 0. Slash command menu: \"/\" on any empty block\n if (\n this.block.content.isEmpty() &&\n char === \"/\" &&\n this.slashCommandOffset === null\n ) {\n // Insert the \"/\" so the user can see it and type a filter query\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n this.slashCommandOffset = offset;\n this.bus.emit(\"block:slashMenu\", {\n blockId: this.blockId,\n query: \"\",\n slashOffset: offset,\n });\n return;\n }\n\n // 0b. Slash menu filter-as-you-type: active slash search\n if (this.slashCommandOffset !== null) {\n if (char === \" \") {\n // Space cancels the slash menu; let the space be inserted normally below\n this.slashCommandOffset = null;\n this.bus.emit(\"block:slashClose\", { blockId: this.blockId });\n // Fall through to default insertText\n } else {\n // Insert the char, then emit updated query\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n const newText = this.block.content.text;\n const query = newText.slice(this.slashCommandOffset + 1, offset + char.length);\n this.bus.emit(\"block:slashMenu\", {\n blockId: this.blockId,\n query,\n slashOffset: this.slashCommandOffset,\n });\n return;\n }\n }\n\n // 1. Block shortcuts (paragraph blocks only)\n if (this.block.type === \"paragraph\") {\n // Immediate-completion patterns (e.g. --- → HR)\n const immediateMatch = detectImmediateBlockShortcut(text, offset, char);\n if (immediateMatch) {\n const remaining = this.block.content.slice(offset, this.block.content.length);\n const tx = new Transaction(this.blockId).replaceContent(remaining);\n this.applyTransaction(tx);\n this.bus.emit(\"block:convertType\", {\n blockId: this.blockId,\n newType: immediateMatch.newType,\n metadata: immediateMatch.metadata,\n });\n return;\n }\n\n const blockMatch = detectBlockShortcut(text, offset, char);\n if (blockMatch) {\n const remaining = this.block.content.slice(offset, this.block.content.length);\n const tx = new Transaction(this.blockId).replaceContent(remaining);\n this.applyTransaction(tx);\n this.bus.emit(\"block:convertType\", {\n blockId: this.blockId,\n newType: blockMatch.newType,\n metadata: blockMatch.metadata,\n });\n return;\n }\n }\n\n // 1b. Task shortcut in heading blocks: typing \"[] \" at start adds taskStatus\n if (\n this.block.type === \"heading\" &&\n !this.block.metadata.taskStatus &&\n char === \" \" &&\n offset === 2 &&\n text.startsWith(\"[]\")\n ) {\n // Remove the \"[]\" prefix, keep the rest of the heading content\n const remaining = this.block.content.slice(2, this.block.content.length);\n const tx = new Transaction(this.blockId).replaceContent(remaining);\n tx.setMetadata(\"taskStatus\", \"todo\");\n this.applyTransaction(tx);\n return;\n }\n\n // 2. Inline shortcuts (not in code blocks)\n const inlineMatch = this.block.type !== \"code\" ? detectInlineShortcut(text, offset, char) : null;\n if (inlineMatch) {\n const content = this.block.content;\n const before = content.slice(0, inlineMatch.openMarkerStart);\n const middle = content\n .slice(inlineMatch.contentStart, inlineMatch.contentEnd)\n .applyAttributes(\n 0,\n inlineMatch.contentEnd - inlineMatch.contentStart,\n inlineMatch.attribute,\n );\n // \"after\" starts from cursorOffset: for bold the first closing `*` is\n // in existingText but we skip it; for italic/code the closing marker\n // is only the char being typed. Either way, cursorOffset is correct.\n const after = content.slice(offset, content.length);\n const newContent = before.concat(middle).concat(after);\n const tx = new Transaction(this.blockId).replaceContent(newContent);\n this.applyTransaction(tx);\n this.setCursorOffset(\n inlineMatch.openMarkerStart +\n (inlineMatch.contentEnd - inlineMatch.contentStart),\n );\n // Next insert should not inherit the shortcut's formatting\n this.nextInsertAttrs = {};\n return;\n }\n\n // 2b. Emoticon substitutions (not in code blocks)\n if (this.block.type !== \"code\") {\n const emoticon = detectEmoticon(text, offset, char);\n if (emoticon) {\n // Delete the emoticon prefix already in text\n if (emoticon.start < emoticon.end) {\n const delTx = new Transaction(this.blockId).deleteRange(emoticon.start, emoticon.end);\n this.applyTransaction(delTx);\n }\n // Insert the emoji at the start position\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(emoticon.start, emoticon.emoji, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(emoticon.start + emoticon.emoji.length);\n // Close emoji picker if it was open (e.g., user typed \":\" which opened picker, then \")\")\n if (this.emojiColonOffset !== null) {\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n }\n return;\n }\n }\n\n // 3. Autocomplete menu: [[ trigger and filter-as-you-type (not in code blocks)\n if (this.block.type !== \"code\") {\n // Active autocomplete search — filter-as-you-type\n if (this.autoCompleteOffset !== null) {\n // Closing ]] commits — don't insert second ], emit close and let editor commit\n if (char === \"]\") {\n const prevChar = offset > 0 ? this.block.content.text[offset - 1] : \"\";\n if (prevChar === \"]\") {\n // User typed ]], but first ] was already inserted. Remove it and close.\n // Delete the first ], then emit close (editor handles the commit)\n this.autoCompleteOffset = null;\n this.pendingBracketOffset = null;\n this.bus.emit(\"block:autoCompleteClose\", { blockId: this.blockId });\n return;\n }\n }\n\n if (char === \" \") {\n // Space still filters — block references can contain spaces\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n const newText = this.block.content.text;\n const query = newText.slice(this.autoCompleteOffset + 2, offset + char.length);\n this.bus.emit(\"block:autoCompleteMenu\", {\n blockId: this.blockId,\n query,\n bracketOffset: this.autoCompleteOffset,\n });\n return;\n }\n\n // Insert the char, then emit updated query\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n const newText = this.block.content.text;\n const query = newText.slice(this.autoCompleteOffset + 2, offset + char.length);\n this.bus.emit(\"block:autoCompleteMenu\", {\n blockId: this.blockId,\n query,\n bracketOffset: this.autoCompleteOffset,\n });\n return;\n }\n\n // Second '[' — activate autocomplete\n if (char === \"[\" && this.pendingBracketOffset !== null && offset === this.pendingBracketOffset + 1) {\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n this.autoCompleteOffset = this.pendingBracketOffset;\n this.pendingBracketOffset = null;\n this.bus.emit(\"block:autoCompleteMenu\", {\n blockId: this.blockId,\n query: \"\",\n bracketOffset: this.autoCompleteOffset,\n });\n return;\n }\n\n // First '[' — set pending state\n if (char === \"[\" && this.autoCompleteOffset === null) {\n this.pendingBracketOffset = offset;\n // Fall through to normal insert — the '[' is inserted below\n } else {\n // Any other char clears the pending bracket\n this.pendingBracketOffset = null;\n }\n }\n\n // 4. Emoji picker: colon trigger and filter-as-you-type (not in code blocks)\n if (this.block.type !== \"code\") {\n // Closing colon with active emoji search → try to commit\n if (this.emojiColonOffset !== null && char === \":\") {\n const query = text.slice(this.emojiColonOffset + 1, offset);\n const match = searchEmoji(query, 1);\n if (match.length > 0 && query.length > 0) {\n // Commit: don't insert the closing colon; emit commit event\n this.bus.emit(\"block:emojiCommit\", {\n blockId: this.blockId,\n colonOffset: this.emojiColonOffset,\n cursorOffset: offset,\n emoji: match[0].emoji,\n });\n this.emojiColonOffset = null;\n return;\n }\n // No match — cancel emoji picker, let colon be inserted normally\n // (it may start a new emoji search below)\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n }\n\n // Active emoji search — filter-as-you-type\n if (this.emojiColonOffset !== null && char !== \":\") {\n if (char === \" \") {\n // Space cancels the emoji picker\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n // Fall through to insert the space normally\n } else {\n // Insert the char, then emit updated query\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n const newText = this.block.content.text;\n const query = newText.slice(this.emojiColonOffset + 1, offset + char.length);\n this.bus.emit(\"block:emojiSearch\", {\n blockId: this.blockId,\n query,\n colonOffset: this.emojiColonOffset,\n });\n return;\n }\n }\n\n // Opening colon detection — start emoji search\n if (char === \":\" && this.emojiColonOffset === null) {\n const charBefore = offset > 0 ? text[offset - 1] : undefined;\n if (offset === 0 || charBefore === \" \" || charBefore === \"\\n\") {\n // Insert the colon normally, then start tracking\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n this.emojiColonOffset = offset;\n this.bus.emit(\"block:emojiSearch\", {\n blockId: this.blockId,\n query: \"\",\n colonOffset: offset,\n });\n return;\n }\n }\n }\n\n // 4b. Agenda picker: \"@\" trigger in blocks that support agenda dates\n const agendaTypes = new Set([\"heading\", \"checklist\", \"paragraph\", \"list\"]);\n if (agendaTypes.has(this.block.type) && this.agendaAtOffset === null) {\n if (char === \"@\") {\n const charBefore = offset > 0 ? text[offset - 1] : undefined;\n if (offset === 0 || charBefore === \" \" || charBefore === \"\\n\") {\n // Insert the \"@\" so user sees it, then emit open event\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n this.agendaAtOffset = offset;\n this.bus.emit(\"block:agendaOpen\", {\n blockId: this.blockId,\n atOffset: offset,\n });\n return;\n }\n }\n }\n\n // 4c. Active agenda search — filter-as-you-type after \"@\"\n if (this.agendaAtOffset !== null) {\n // Insert the char, then emit updated query\n const attrs2 = storedAttrs as Record<string, string | number | boolean> | undefined;\n const tx2 = new Transaction(this.blockId).insertText(offset, char, attrs2 ?? undefined);\n this.applyTransaction(tx2);\n this.setCursorOffset(offset + char.length);\n const newText = this.block.content.text;\n // Full text after the \"@\"\n const rawAfterAt = newText.slice(this.agendaAtOffset + 1, offset + char.length);\n\n // Detect role prefixes: @due(, @scheduled(, @(\n const { role, query, prefixLen } = parseAgendaRolePrefix(rawAfterAt);\n this.agendaRole = role;\n this.agendaPrefixLen = prefixLen;\n\n // Handle closing paren: @due(next friday) → auto-confirm\n if (role && prefixLen > 0 && char === \")\") {\n this.bus.emit(\"block:agendaAutoConfirm\", {\n blockId: this.blockId,\n query,\n role,\n });\n return;\n }\n\n this.bus.emit(\"block:agendaSearch\", {\n blockId: this.blockId,\n query,\n atOffset: this.agendaAtOffset,\n role,\n });\n return;\n }\n\n // 5. Default: insertText\n let attrs = storedAttrs as Record<string, string | number | boolean> | undefined;\n // Apply persistent pending marks (from Ctrl-B/I/U on collapsed cursor)\n if (!attrs && this._pendingMarks) {\n // Use 'left' affinity so that at position 0 (or any span boundary)\n // we don't inherit formatting from the following span.\n const inherited = this.block.content.attributesAt(offset, \"left\");\n const effective: Record<string, string | number | boolean> = {};\n for (const [k, v] of Object.entries(inherited)) {\n if (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\") {\n effective[k] = v;\n }\n }\n for (const [k, v] of Object.entries(this._pendingMarks)) {\n if (v) {\n effective[k] = true;\n } else {\n delete effective[k];\n }\n }\n attrs = effective;\n }\n const tx = new Transaction(this.blockId).insertText(offset, char, attrs ?? undefined);\n this.applyTransaction(tx);\n // Suppress the selectionchange clear since we're moving cursor programmatically\n if (this._pendingMarks) this._suppressPendingMarksClear = true;\n this.setCursorOffset(offset + char.length);\n } else if (\n inputType === \"deleteContentBackward\" ||\n inputType === \"deleteContentForward\"\n ) {\n e.preventDefault();\n const offset = this.getCursorOffset() ?? 0;\n const sel = window.getSelection();\n const hasSelection = sel && !sel.isCollapsed;\n\n if (hasSelection) {\n const { start, end } = this.getSelectionRange();\n const tx = new Transaction(this.blockId).deleteRange(start, end);\n this.applyTransaction(tx);\n this.setCursorOffset(start);\n } else if (inputType === \"deleteContentBackward\") {\n if (offset === 0) {\n // Backspace at beginning — emit merge\n this.bus.emit(\"block:merge\", {\n blockId: this.blockId,\n direction: \"backward\",\n });\n return;\n }\n const delStart = prevGraphemeBoundary(this.block.content.text, offset);\n const tx = new Transaction(this.blockId).deleteRange(delStart, offset);\n this.applyTransaction(tx);\n this.setCursorOffset(delStart);\n\n // Emoji picker: check if we backspaced past the opening colon\n if (this.emojiColonOffset !== null) {\n if (delStart <= this.emojiColonOffset) {\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n } else {\n const newText = this.block.content.text;\n const query = newText.slice(this.emojiColonOffset + 1, delStart);\n this.bus.emit(\"block:emojiSearch\", {\n blockId: this.blockId,\n query,\n colonOffset: this.emojiColonOffset,\n });\n }\n }\n\n // Autocomplete: check if we backspaced past the opening [[\n if (this.autoCompleteOffset !== null) {\n // Backspace past the first '[' of '[['\n if (delStart <= this.autoCompleteOffset) {\n this.autoCompleteOffset = null;\n this.bus.emit(\"block:autoCompleteClose\", { blockId: this.blockId });\n } else {\n const newText = this.block.content.text;\n const query = newText.slice(this.autoCompleteOffset + 2, delStart);\n this.bus.emit(\"block:autoCompleteMenu\", {\n blockId: this.blockId,\n query,\n bracketOffset: this.autoCompleteOffset,\n });\n }\n }\n\n // Slash menu: check if we backspaced past the opening slash\n if (this.slashCommandOffset !== null) {\n if (delStart <= this.slashCommandOffset) {\n this.slashCommandOffset = null;\n this.bus.emit(\"block:slashClose\", { blockId: this.blockId });\n } else {\n const newText = this.block.content.text;\n const query = newText.slice(this.slashCommandOffset + 1, delStart);\n this.bus.emit(\"block:slashMenu\", {\n blockId: this.blockId,\n query,\n slashOffset: this.slashCommandOffset,\n });\n }\n }\n\n // Agenda search: check if we backspaced past the opening @\n if (this.agendaAtOffset !== null) {\n if (delStart <= this.agendaAtOffset) {\n this.agendaAtOffset = null;\n this.agendaRole = undefined;\n this.agendaPrefixLen = 0;\n this.bus.emit(\"block:agendaClose\", { blockId: this.blockId });\n } else {\n const newText = this.block.content.text;\n const rawAfterAt = newText.slice(this.agendaAtOffset + 1, delStart);\n const { role, query, prefixLen } = parseAgendaRolePrefix(rawAfterAt);\n this.agendaRole = role;\n this.agendaPrefixLen = prefixLen;\n this.bus.emit(\"block:agendaSearch\", {\n blockId: this.blockId,\n query,\n atOffset: this.agendaAtOffset,\n role,\n });\n }\n }\n } else {\n // deleteContentForward\n if (offset >= this.block.content.length) {\n this.bus.emit(\"block:merge\", {\n blockId: this.blockId,\n direction: \"forward\",\n });\n return;\n }\n const delEnd = nextGraphemeBoundary(this.block.content.text, offset);\n const tx = new Transaction(this.blockId).deleteRange(offset, delEnd);\n this.applyTransaction(tx);\n this.setCursorOffset(offset);\n }\n } else if (inputType === \"insertParagraph\" || inputType === \"insertLineBreak\") {\n e.preventDefault();\n const offset = this.getCursorOffset() ?? this.block.content.length;\n const text = this.block.content.text;\n\n // Block shortcuts triggered by Enter (paragraph blocks only)\n if (this.block.type === \"paragraph\" && offset === text.length) {\n const blockMatch = matchBlockShortcutPattern(text);\n if (blockMatch) {\n const tx = new Transaction(this.blockId).replaceContent(\n AttributedString.empty(),\n );\n this.applyTransaction(tx);\n this.bus.emit(\"block:convertType\", {\n blockId: this.blockId,\n newType: blockMatch.newType,\n metadata: blockMatch.metadata,\n });\n return;\n }\n }\n\n if (this.block.type === \"code\" || this.block.type === \"mermaid\") {\n // Normal Enter: insert newline with auto-indent\n const beforeCursor = text.slice(0, offset);\n const lastNewline = beforeCursor.lastIndexOf(\"\\n\");\n const currentLine = beforeCursor.slice(lastNewline + 1);\n const indentMatch = /^(\\s*)/.exec(currentLine);\n const indent = indentMatch ? indentMatch[1] : \"\";\n const insertion = \"\\n\" + indent;\n const tx = new Transaction(this.blockId).insertText(offset, insertion);\n this.applyTransaction(tx);\n this.setCursorOffset(offset + insertion.length);\n return;\n }\n\n this.bus.emit(\"block:split\", { blockId: this.blockId, offset });\n } else if (inputType === \"insertReplacementText\") {\n // Spell-check / autocorrect: the browser wants to replace a range of text.\n // We intercept this and apply it as a model edit so formatting is preserved.\n e.preventDefault();\n const replacement = e.dataTransfer?.getData(\"text/plain\") ?? e.data ?? \"\";\n if (!replacement || !this._contentEditable) return;\n\n const targetRanges = e.getTargetRanges();\n if (targetRanges.length === 0) return;\n\n const target = targetRanges[0];\n // Convert DOM range to character offsets (same technique as getCursorOffset)\n const startRange = document.createRange();\n startRange.selectNodeContents(this._contentEditable);\n startRange.setEnd(target.startContainer, target.startOffset);\n const start = startRange.toString().length;\n\n const endRange = document.createRange();\n endRange.selectNodeContents(this._contentEditable);\n endRange.setEnd(target.endContainer, target.endOffset);\n const end = endRange.toString().length;\n\n const tx = new Transaction(this.blockId)\n .deleteRange(start, end)\n .insertText(start, replacement);\n this.applyTransaction(tx);\n this.setCursorOffset(start + replacement.length);\n } else if (inputType === \"insertFromPaste\" && e.dataTransfer) {\n e.preventDefault();\n const text = e.dataTransfer.getData(\"text/plain\");\n if (text) {\n const offset = this.getCursorOffset() ?? this.block.content.length;\n const { start, end } = this.getSelectionRange();\n const tx = new Transaction(this.blockId);\n if (start !== end) {\n tx.deleteRange(start, end);\n }\n tx.insertText(start, text);\n this.applyTransaction(tx);\n this.setCursorOffset(start + text.length);\n }\n }\n };\n\n // For code/mermaid blocks, handle paste directly and stop propagation so\n // editor-level and app-level paste handlers don't convert it into blocks.\n private handlePaste = (e: ClipboardEvent): void => {\n if (this.block.type !== \"code\" && this.block.type !== \"mermaid\") return;\n\n const text = e.clipboardData?.getData(\"text/plain\");\n if (!text) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n const { start, end } = this.getSelectionRange();\n const tx = new Transaction(this.blockId);\n if (start !== end) {\n tx.deleteRange(start, end);\n }\n tx.insertText(start, text);\n this.applyTransaction(tx);\n this.setCursorOffset(start + text.length);\n };\n\n private handleKeyDown = (e: KeyboardEvent): void => {\n if (e.isComposing) return;\n\n // Shift+Enter: exit code/mermaid block → split to new paragraph below\n if (e.key === \"Enter\" && e.shiftKey && (this.block.type === \"code\" || this.block.type === \"mermaid\")) {\n e.preventDefault();\n const offset = this.getCursorOffset() ?? this.block.content.length;\n this.bus.emit(\"block:split\", { blockId: this.blockId, offset });\n return;\n }\n\n // Escape: enter block-level selection mode\n if (e.key === \"Escape\") {\n e.preventDefault();\n // Close emoji picker / slash menu / agenda search if open before entering block select\n if (this.emojiColonOffset !== null) {\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n }\n if (this.slashCommandOffset !== null) {\n this.slashCommandOffset = null;\n this.bus.emit(\"block:slashClose\", { blockId: this.blockId });\n }\n if (this.agendaAtOffset !== null) {\n this.agendaAtOffset = null;\n this.agendaRole = undefined;\n this.agendaPrefixLen = 0;\n this.bus.emit(\"block:agendaClose\", { blockId: this.blockId });\n }\n this.bus.emit(\"block:enterBlockSelect\", { blockId: this.blockId });\n return;\n }\n\n // Alt+Arrow: block reordering\n if (e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n e.preventDefault();\n this.bus.emit(e.key === \"ArrowUp\" ? \"block:moveUp\" : \"block:moveDown\", { blockId: this.blockId });\n return;\n }\n\n // Shift+Arrow: block selection when crossing block boundaries\n if (e.shiftKey && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n const shouldIntercept =\n (e.key === \"ArrowUp\" && this.isCaretOnFirstLine()) ||\n (e.key === \"ArrowDown\" && this.isCaretOnLastLine());\n if (shouldIntercept) {\n e.preventDefault();\n this.bus.emit(\"block:selectTo\", {\n blockId: this.blockId,\n direction: e.key === \"ArrowUp\" ? \"up\" : \"down\",\n });\n }\n // Always return for Shift+Arrow — either we intercepted, or browser handles intra-block text selection\n return;\n }\n\n const offset = this.getCursorOffset() ?? 0;\n const sel = window.getSelection();\n const isCollapsed = sel?.isCollapsed ?? true;\n\n // Shift+Left/Right: cross-block selection at boundaries\n if (e.shiftKey && e.key === \"ArrowLeft\" && offset === 0 && isCollapsed) {\n e.preventDefault();\n this.bus.emit(\"block:selectTo\", {\n blockId: this.blockId,\n direction: \"up\",\n });\n return;\n }\n if (e.shiftKey && e.key === \"ArrowRight\" && offset >= this.block.content.length && isCollapsed) {\n e.preventDefault();\n this.bus.emit(\"block:selectTo\", {\n blockId: this.blockId,\n direction: \"down\",\n });\n return;\n }\n\n // Mod+Home/End: document-level navigation\n const mod = e.metaKey || e.ctrlKey;\n if (mod && !e.altKey && (e.key === \"Home\" || e.key === \"End\")) {\n e.preventDefault();\n if (e.shiftKey) {\n this.bus.emit(e.key === \"Home\" ? \"block:selectToDocStart\" : \"block:selectToDocEnd\", {\n blockId: this.blockId,\n });\n } else {\n this.bus.emit(e.key === \"Home\" ? \"block:jumpToDocStart\" : \"block:jumpToDocEnd\", {\n blockId: this.blockId,\n });\n }\n return;\n }\n\n // PageUp/PageDown\n if (e.key === \"PageUp\" || e.key === \"PageDown\") {\n e.preventDefault();\n this.bus.emit(e.key === \"PageUp\" ? \"block:pageUp\" : \"block:pageDown\", {\n blockId: this.blockId,\n });\n return;\n }\n\n if (e.key === \"ArrowLeft\") {\n // Cancel emoji picker on cursor movement (if not consumed by picker)\n if (this.emojiColonOffset !== null) {\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n }\n // Cancel slash menu on cursor movement\n if (this.slashCommandOffset !== null) {\n this.slashCommandOffset = null;\n this.bus.emit(\"block:slashClose\", { blockId: this.blockId });\n }\n if (offset === 0 && isCollapsed) {\n e.preventDefault();\n this.bus.emit(\"block:focus\", { blockId: this.blockId, offset: -1 });\n }\n } else if (e.key === \"ArrowRight\") {\n // Cancel emoji picker on cursor movement (if not consumed by picker)\n if (this.emojiColonOffset !== null) {\n this.emojiColonOffset = null;\n this.bus.emit(\"block:emojiClose\", { blockId: this.blockId });\n }\n // Cancel slash menu on cursor movement\n if (this.slashCommandOffset !== null) {\n this.slashCommandOffset = null;\n this.bus.emit(\"block:slashClose\", { blockId: this.blockId });\n }\n if (offset >= this.block.content.length && isCollapsed) {\n e.preventDefault();\n this.bus.emit(\"block:focus\", { blockId: this.blockId, offset: 1 });\n }\n } else if (e.key === \"ArrowUp\") {\n if (isCollapsed && this.isCaretOnFirstLine()) {\n e.preventDefault();\n const rect = this.getCaretRect();\n const payload: EditorEventMap[\"block:focus\"] = { blockId: this.blockId, offset: -1 };\n if (rect) payload.caretX = rect.left;\n this.bus.emit(\"block:focus\", payload);\n }\n // else: not on first line, let browser handle intra-block movement\n } else if (e.key === \"ArrowDown\") {\n if (isCollapsed && this.isCaretOnLastLine()) {\n e.preventDefault();\n const rect = this.getCaretRect();\n const payload: EditorEventMap[\"block:focus\"] = { blockId: this.blockId, offset: 1 };\n if (rect) payload.caretX = rect.left;\n this.bus.emit(\"block:focus\", payload);\n }\n // else: not on last line, let browser handle intra-block movement\n } else if (e.key === \"Tab\") {\n e.preventDefault();\n if (this.plugin.indentable === false) {\n // Some non-indentable blocks (e.g. code, mermaid) want Tab to insert spaces\n if (this.plugin.tabInsertsSpaces) {\n const tabOffset = this.getCursorOffset() ?? this.block.content.length;\n const tx = new Transaction(this.blockId).insertText(tabOffset, \" \");\n this.applyTransaction(tx);\n this.setCursorOffset(tabOffset + 2);\n }\n } else {\n if (e.shiftKey) {\n this.bus.emit(\"block:outdent\", { blockId: this.blockId });\n } else {\n this.bus.emit(\"block:indent\", { blockId: this.blockId });\n }\n }\n }\n };\n\n private handleFocus = (): void => {\n // Lazily connect MutationObserver only when this block has focus.\n // This avoids thousands of observers in large documents — only the\n // focused block needs IME/spell-check fallback via MutationObserver.\n this.connectObserver();\n };\n\n private handleBlur = (): void => {\n // Disconnect the observer when the block loses focus to free resources.\n this.disconnectObserver();\n this.bus.emit(\"block:blur\", { blockId: this.blockId });\n };\n\n private handleCodeLanguageChange = (e: CustomEvent<{ language: string }>): void => {\n const tx = new Transaction(this.blockId).setMetadata(\"language\", e.detail.language);\n this.applyTransaction(tx);\n };\n\n private handleChecklistToggle = (e: CustomEvent<{ checked: boolean }>): void => {\n const tx = new Transaction(this.blockId).setMetadata(\"checked\", e.detail.checked);\n this.applyTransaction(tx);\n\n // Emit event to notify editor of task completion (for reordering)\n this.bus.emit(\"block:checklistToggled\", {\n blockId: this.blockId,\n checked: e.detail.checked,\n });\n };\n\n /** Handle click on an agenda badge/label — open date picker for editing */\n private handleAgendaEdit = (e: CustomEvent<{ role: \"due\" | \"scheduled\" | \"event\"; date: string }>): void => {\n this.bus.emit(\"block:agendaEdit\", {\n blockId: this.blockId,\n role: e.detail.role,\n date: e.detail.date,\n });\n };\n\n private handleHeadingTaskToggle = (e: CustomEvent<{ taskStatus: string | null }>): void => {\n const tx = new Transaction(this.blockId);\n if (e.detail.taskStatus) {\n tx.setMetadata(\"taskStatus\", e.detail.taskStatus);\n } else {\n tx.setMetadata(\"taskStatus\", undefined);\n }\n this.applyTransaction(tx);\n };\n\n private handleMutation = (): void => {\n if (this.suppressObserver) return;\n\n // Fallback: sync DOM text back to model while preserving inline formatting.\n // We compute a prefix/suffix diff against the current model text and apply\n // deleteRange + insertAt so that spans outside the mutated region are kept.\n // This is correct for IME composition and spell-check, both of which produce\n // a single contiguous edit.\n const newText = this._contentEditable?.textContent ?? \"\";\n const oldText = this.block.content.text;\n if (newText === oldText) return;\n\n // Compute prefix length (characters shared at the start)\n let prefixLen = 0;\n const minLen = Math.min(oldText.length, newText.length);\n while (prefixLen < minLen && oldText[prefixLen] === newText[prefixLen]) {\n prefixLen++;\n }\n\n // Compute suffix length (characters shared at the end, after the prefix)\n let suffixLen = 0;\n while (\n suffixLen < minLen - prefixLen &&\n oldText[oldText.length - 1 - suffixLen] === newText[newText.length - 1 - suffixLen]\n ) {\n suffixLen++;\n }\n\n const deleteEnd = oldText.length - suffixLen;\n const inserted = newText.slice(prefixLen, newText.length - suffixLen);\n\n // Apply diff-and-patch: delete changed region, then insert new text at same position\n let newContent = this.block.content;\n if (prefixLen < deleteEnd) {\n newContent = newContent.deleteRange(prefixLen, deleteEnd);\n }\n if (inserted.length > 0) {\n // Insert with no explicit attributes so IME text does not inherit\n // the formatting of adjacent spans (e.g. inserting before a bold word\n // should not make the new characters bold). The user can apply\n // formatting explicitly afterwards.\n newContent = newContent.insertAt(prefixLen, inserted, {});\n }\n\n this.block = { ...this.block, content: newContent };\n this.bus.emit(\"block:contentChanged\", {\n blockId: this.blockId,\n content: this.block.content,\n });\n };\n\n /** Apply visual indentation based on metadata.indentLevel */\n private applyIndentation(): void {\n const level = typeof this.block.metadata.indentLevel === \"number\"\n ? this.block.metadata.indentLevel\n : 0;\n\n // Animate only when the margin is actually changing (not on initial render)\n const prevMargin = this.container.style.marginInlineStart;\n const newMargin = level > 0 ? `${level * 28}px` : \"\";\n if (prevMargin && prevMargin !== newMargin) {\n this.container.classList.add(\"blx-indent-animated\");\n }\n\n if (level > 0) {\n this.container.style.marginInlineStart = newMargin;\n this.container.dataset.indentLevel = String(level);\n } else {\n this.container.style.marginInlineStart = \"\";\n delete this.container.dataset.indentLevel;\n }\n }\n\n /** Clear emoji picker state (called when picker is closed externally) */\n clearEmojiState(): void {\n this.emojiColonOffset = null;\n }\n\n /** Clear slash menu state (called when menu is closed externally) */\n clearSlashState(): void {\n this.slashCommandOffset = null;\n }\n\n /** Clear autocomplete state (called when menu is closed/committed externally) */\n clearAutoCompleteState(): void {\n this.autoCompleteOffset = null;\n this.pendingBracketOffset = null;\n }\n\n /** Clear agenda picker state (called when picker is closed externally) */\n clearAgendaState(): void {\n this.agendaAtOffset = null;\n this.agendaRole = undefined;\n this.agendaPrefixLen = 0;\n }\n\n /** Get the offset of the '@' that triggered the agenda picker */\n getAgendaAtOffset(): number | null {\n return this.agendaAtOffset;\n }\n\n /**\n * Set a one-shot attribute override for the next inserted character.\n * Pass `{}` to force no attributes (preventing inheritance from adjacent spans).\n */\n setNextInsertAttrs(attrs: Record<string, unknown>): void {\n this.nextInsertAttrs = attrs;\n // One-shot overrides supersede persistent pending marks\n this._pendingMarks = null;\n }\n\n /**\n * Toggle a pending mark for format shortcuts on collapsed cursor.\n * Computes the effective state (pending override or inherited) and flips it.\n * If the new desired state matches what would be inherited, the pending\n * override is removed (since inheritance already produces the right result).\n */\n togglePendingMark(attr: string, cursorOffset: number): void {\n if (!this._pendingMarks) {\n this._pendingMarks = {};\n }\n\n // Use 'left' affinity so that at position 0 (or any span boundary)\n // we don't see formatting from the following span as \"inherited\".\n const inherited = this.block.content.attributesAt(cursorOffset, \"left\");\n const inheritedOn = !!inherited[attr];\n\n // Determine current effective state\n const effectiveOn = (attr in this._pendingMarks)\n ? this._pendingMarks[attr]\n : inheritedOn;\n\n // Flip to the opposite\n const desired = !effectiveOn;\n\n if (desired === inheritedOn) {\n // No override needed — inheritance already gives the right result\n delete this._pendingMarks[attr];\n if (Object.keys(this._pendingMarks).length === 0) {\n this._pendingMarks = null;\n }\n } else {\n this._pendingMarks[attr] = desired;\n }\n }\n\n /** Get the current pending marks (for UI feedback), or null if none. */\n getPendingMarks(): Record<string, boolean> | null {\n return this._pendingMarks;\n }\n\n /** Clear all pending marks. */\n clearPendingMarks(): void {\n this._pendingMarks = null;\n }\n\n /**\n * Called by selectionchange handler. Clears pending marks unless the\n * clear was suppressed (e.g. because we just inserted text).\n */\n selectionDidChange(): void {\n if (this._suppressPendingMarksClear) {\n this._suppressPendingMarksClear = false;\n return;\n }\n this._pendingMarks = null;\n }\n\n /** Get current cursor offset within the block's text content */\n getCursorOffset(): number | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || !this._contentEditable) return null;\n\n const range = sel.getRangeAt(0);\n if (!this._contentEditable.contains(range.startContainer)) return null;\n\n const preRange = document.createRange();\n preRange.selectNodeContents(this._contentEditable);\n preRange.setEnd(range.startContainer, range.startOffset);\n return preRange.toString().length;\n }\n\n /** Set cursor to a specific offset */\n private setCursorOffset(offset: number): void {\n if (!this._contentEditable) return;\n\n const clamped = Math.max(0, Math.min(offset, this.block.content.length));\n const sel = window.getSelection();\n if (!sel) return;\n\n const { node, offset: nodeOffset } = this.findTextPosition(clamped);\n if (node) {\n const range = document.createRange();\n\n // When at the end of a text node ending with \\n (e.g. code blocks),\n // browsers render the caret at end-of-line instead of start-of-next-line.\n // If a <br> follows (used to make the trailing empty line visible),\n // position the cursor after the <br> so the caret appears on the new line.\n if (\n node.nodeType === Node.TEXT_NODE &&\n nodeOffset === (node.textContent?.length ?? 0) &&\n node.textContent?.endsWith(\"\\n\") &&\n node.nextSibling?.nodeName === \"BR\"\n ) {\n range.setStartAfter(node.nextSibling);\n } else {\n range.setStart(node, nodeOffset);\n }\n\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n\n private getSelectionRange(): { start: number; end: number } {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || !this._contentEditable) {\n return { start: 0, end: 0 };\n }\n\n const range = sel.getRangeAt(0);\n\n const startRange = document.createRange();\n startRange.selectNodeContents(this._contentEditable);\n startRange.setEnd(range.startContainer, range.startOffset);\n const start = startRange.toString().length;\n\n const endRange = document.createRange();\n endRange.selectNodeContents(this._contentEditable);\n endRange.setEnd(range.endContainer, range.endOffset);\n const end = endRange.toString().length;\n\n return { start: Math.min(start, end), end: Math.max(start, end) };\n }\n\n private findTextPosition(offset: number): { node: Node | null; offset: number } {\n if (!this._contentEditable) return { node: null, offset: 0 };\n\n const walker = document.createTreeWalker(\n this._contentEditable,\n NodeFilter.SHOW_TEXT,\n );\n let remaining = offset;\n let node = walker.nextNode();\n\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n return { node, offset: remaining };\n }\n remaining -= len;\n node = walker.nextNode();\n }\n\n // Past end — position at end of last text node\n const lastChild = this._contentEditable.lastChild;\n if (lastChild && lastChild.nodeType === Node.TEXT_NODE) {\n return { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n }\n\n return { node: this._contentEditable, offset: 0 };\n }\n\n}\n\n/**\n * Known role prefix patterns for inline agenda syntax.\n * Each entry maps a prefix string (after the '@') to its role.\n * The prefix must end with '(' to be detected.\n *\n * Examples:\n * @due(next friday) → role: \"due\", query: \"next friday\"\n * @scheduled(march 20) → role: \"scheduled\", query: \"march 20\"\n * @(tomorrow) → role: \"event\", query: \"tomorrow\"\n * @tomorrow → role: \"event\", query: \"tomorrow\" (backward compat, no parens)\n */\nconst AGENDA_ROLE_PREFIXES: { prefix: string; role: \"due\" | \"scheduled\" | \"event\" }[] = [\n { prefix: \"due(\", role: \"due\" },\n { prefix: \"scheduled(\", role: \"scheduled\" },\n { prefix: \"(\", role: \"event\" },\n];\n\n/**\n * Parse the text after '@' to detect a role prefix.\n *\n * Returns the detected role, the cleaned query (text after the prefix),\n * and the prefix length (0 if no prefix matched).\n *\n * Detection is incremental:\n * - \"d\" → no prefix yet, query is \"d\", role is undefined\n * - \"due\" → no prefix yet, query is \"due\", role is undefined\n * - \"due(\" → prefix matched! query is \"\", role is \"due\", prefixLen is 4\n * - \"due(next\" → query is \"next\", role is \"due\", prefixLen is 4\n * - \"(\" → prefix matched! query is \"\", role is \"event\", prefixLen is 1\n * - \"(tomorrow\" → query is \"tomorrow\", role is \"event\", prefixLen is 1\n */\nfunction parseAgendaRolePrefix(textAfterAt: string): {\n role: \"due\" | \"scheduled\" | \"event\" | undefined;\n query: string;\n prefixLen: number;\n} {\n // Check if the text starts with one of the known prefixes\n for (const { prefix, role } of AGENDA_ROLE_PREFIXES) {\n if (textAfterAt.startsWith(prefix)) {\n // Strip trailing ')' from query if present (for auto-confirm)\n const afterPrefix = textAfterAt.slice(prefix.length);\n const query = afterPrefix.endsWith(\")\") ? afterPrefix.slice(0, -1) : afterPrefix;\n return { role, query, prefixLen: prefix.length };\n }\n }\n // No prefix matched — default behavior (backward compat: no role, full text as query)\n return { role: undefined, query: textAfterAt, prefixLen: 0 };\n}\n","import type { AttributedString } from \"../attributed-string\";\nimport type { Attributes } from \"../attributed-string/types\";\n\n// ── URL resolution ─────────────────────────────────────────────\n\n/**\n * Default URL resolver: prepends `https://` to URLs that lack a protocol\n * and don't look like internal references (# anchors, / paths, mailto:, tel:).\n */\nfunction defaultResolveUrl(url: string): string {\n if (/^(https?:\\/\\/|mailto:|tel:|#|\\/)/i.test(url)) return url;\n return `https://${url}`;\n}\n\nlet urlResolver: (url: string) => string = defaultResolveUrl;\n\n/**\n * Override the URL resolver used when rendering link elements.\n * The resolver receives the raw `href` string from the content model\n * and should return a fully-qualified URL for the `<a>` element.\n *\n * Pass `undefined` to reset to the default resolver.\n */\nexport function setUrlResolver(resolver: ((url: string) => string) | undefined): void {\n urlResolver = resolver ?? defaultResolveUrl;\n}\n\n/** Resolve a URL using the configured resolver. */\nexport function resolveUrl(url: string): string {\n return urlResolver(url);\n}\n\n// ── Block ref render decorator ──────────────────────────────────\n\nlet blockRefRenderCallback: ((element: HTMLElement, refId: string) => void) | null = null;\n\n/**\n * Set a callback that is invoked after each blockRef span is rendered.\n * Use it to add CSS classes or data attributes for app-specific styling\n * (e.g. broken-link indicators).\n *\n * Pass `undefined` to clear the callback.\n */\nexport function setBlockRefRenderCallback(\n cb: ((element: HTMLElement, refId: string) => void) | undefined,\n): void {\n blockRefRenderCallback = cb ?? null;\n}\n\n/**\n * Returns the `dir` attribute value for a block's contenteditable element.\n * Defaults to \"auto\" which lets the browser's Unicode Bidi Algorithm detect\n * text direction from the first strong character.\n */\nexport function getBlockDir(metadata: Record<string, unknown>): string {\n return typeof metadata.dir === \"string\" ? metadata.dir : \"auto\";\n}\n\n/**\n * Toggle the empty state class and placeholder attribute on an element.\n * When the content is empty, adds `blx-empty` class and sets `data-placeholder`.\n * When non-empty, removes both.\n */\nexport function updateEmptyState(\n el: HTMLElement,\n content: AttributedString,\n placeholder?: string,\n): void {\n if (content.isEmpty() && placeholder) {\n el.classList.add(\"blx-empty\");\n el.dataset.placeholder = placeholder;\n } else {\n el.classList.remove(\"blx-empty\");\n delete el.dataset.placeholder;\n }\n}\n\n/**\n * Apply inline formatting attributes (bold, italic, etc.) to an element.\n */\nfunction applySpanAttributes(el: HTMLElement, attributes: Attributes): void {\n if (attributes.bold) {\n el.style.fontWeight = \"bold\";\n }\n if (attributes.italic) {\n el.style.fontStyle = \"italic\";\n }\n if (attributes.underline) {\n el.style.textDecoration = \"underline\";\n }\n if (attributes.strikethrough) {\n el.style.textDecoration =\n (el.style.textDecoration ? el.style.textDecoration + \" \" : \"\") +\n \"line-through\";\n }\n if (attributes.code) {\n el.classList.add(\"blx-inline-code\");\n }\n if (typeof attributes.color === \"string\") {\n el.style.color = attributes.color;\n }\n if (typeof attributes.blockRef === \"string\") {\n el.classList.add(\"blx-block-ref\");\n el.dataset.blockRef = attributes.blockRef;\n if (blockRefRenderCallback) {\n blockRefRenderCallback(el, attributes.blockRef);\n }\n }\n if (typeof attributes.backgroundColor === \"string\") {\n const color = attributes.backgroundColor;\n el.classList.add(\"blx-highlight\");\n if (HIGHLIGHT_COLOR_NAMES.has(color)) {\n el.classList.add(`blx-highlight-${color}`);\n } else {\n // Arbitrary color value — use inline style\n el.style.backgroundColor = color;\n }\n }\n}\n\n/**\n * Check whether the block is rendered inside a read-only context.\n * Returns true when the nearest editor root (or any ancestor) has the\n * `.blx-readonly` or `.blx-replay-mode` CSS class.\n */\nexport function isBlockReadOnly(container: HTMLElement): boolean {\n return !!container.closest(\".blx-readonly, .blx-replay-mode\");\n}\n\n/** Recognised semantic highlight color names (used for CSS class rendering). */\nconst HIGHLIGHT_COLOR_NAMES = new Set([\n \"yellow\", \"green\", \"blue\", \"pink\", \"orange\", \"purple\",\n]);\n\n/**\n * Create an anchor element for inline links.\n * The raw href is resolved through the configured URL resolver.\n * Click behaviour is NOT wired here — it is handled via event delegation\n * in `Editor` so that the container app can override link navigation.\n */\nfunction createLinkElement(rawHref: string): HTMLAnchorElement {\n const resolved = resolveUrl(rawHref);\n const a = document.createElement(\"a\");\n a.href = resolved;\n a.target = \"_blank\";\n a.rel = \"noopener noreferrer\";\n a.classList.add(\"blx-link\");\n // Prevent default so that clicking inside contenteditable doesn't\n // navigate away. Actual open-link behaviour is delegated to Editor.\n a.addEventListener(\"click\", (e) => {\n e.preventDefault();\n });\n return a;\n}\n\n/**\n * Render an AttributedString into a target element.\n * Clears existing content and creates inline spans for each attributed span.\n * Emoji characters render natively via the platform's emoji font.\n */\nexport function renderAttributedString(\n target: HTMLElement,\n content: AttributedString,\n): void {\n target.innerHTML = \"\";\n // Preserve whitespace so trailing/consecutive spaces are visible and the\n // caret advances correctly when the user types a space character.\n target.style.whiteSpace = \"pre-wrap\";\n // Allow long words to break so lines still wrap within the container.\n target.style.overflowWrap = \"break-word\";\n\n if (content.isEmpty()) {\n // Empty blocks need a <br> for the cursor to be placeable\n target.appendChild(document.createElement(\"br\"));\n return;\n }\n\n for (const span of content.spans) {\n const href = typeof span.attributes.href === \"string\" ? span.attributes.href : null;\n const el = href ? createLinkElement(href) : document.createElement(\"span\");\n el.textContent = span.text;\n applySpanAttributes(el, span.attributes);\n target.appendChild(el);\n }\n}\n","/**\n * Utilities for agenda date formatting and state classification.\n *\n * All dates are ISO 8601 date-only strings (\"YYYY-MM-DD\").\n * No time component, no timezone — dates are interpreted in the user's local timezone.\n */\n\n/** Agenda item urgency states, used for badge/label styling. */\nexport type AgendaState =\n | \"overdue\"\n | \"today\"\n | \"tomorrow\"\n | \"upcoming\" // 2–7 days away (shows day name)\n | \"future\" // > 7 days away (shows date)\n | \"past\" // past event (not overdue — informational only)\n | \"ongoing\"; // scheduled item past its date (still active)\n\nexport interface AgendaDisplay {\n /** Human-readable label for the badge/label (e.g. \"Tomorrow\", \"Mar 15\", \"Overdue: Mar 1\"). */\n label: string;\n /** CSS class suffix for styling (e.g. \"blx-agenda-overdue\"). */\n state: AgendaState;\n}\n\n/**\n * Parse an ISO date string (\"YYYY-MM-DD\") into a Date at midnight local time.\n * Returns null for invalid inputs.\n */\nexport function parseAgendaDate(iso: string): Date | null {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(iso)) return null;\n const [y, m, d] = iso.split(\"-\").map(Number);\n const date = new Date(y, m - 1, d);\n // Validate the parsed date matches the input (catches invalid dates like Feb 30)\n if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) {\n return null;\n }\n return date;\n}\n\n/**\n * Format a Date as \"YYYY-MM-DD\" (ISO 8601 date-only).\n */\nexport function formatAgendaDateISO(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, \"0\");\n const d = String(date.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${d}`;\n}\n\n/** Day names for \"upcoming\" state (2–7 days away). */\nconst DAY_NAMES = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n\n/** Short month names for display. */\nconst MONTH_NAMES = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n\n/** Full month names for calendar header. */\nexport const MONTH_NAMES_FULL = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n];\n\n/**\n * Format a date for short display (e.g. \"Mar 15\" or \"Mar 15, 2025\" if different year).\n */\nfunction formatShortDate(date: Date, referenceDate: Date): string {\n const month = MONTH_NAMES[date.getMonth()];\n const day = date.getDate();\n if (date.getFullYear() !== referenceDate.getFullYear()) {\n return `${month} ${day}, ${date.getFullYear()}`;\n }\n return `${month} ${day}`;\n}\n\n/**\n * Compute the number of calendar days between two dates.\n * Positive = target is in the future, negative = target is in the past.\n */\nfunction daysBetween(from: Date, to: Date): number {\n const fromMidnight = new Date(from.getFullYear(), from.getMonth(), from.getDate());\n const toMidnight = new Date(to.getFullYear(), to.getMonth(), to.getDate());\n return Math.round((toMidnight.getTime() - fromMidnight.getTime()) / (1000 * 60 * 60 * 24));\n}\n\n/**\n * Classify an agenda date and produce a display label + state.\n *\n * @param agendaDate - ISO date string (\"YYYY-MM-DD\")\n * @param now - Reference date (defaults to current date). Pass explicitly for testability.\n * @param role - Date role: \"due\" (default), \"scheduled\", or \"event\". Affects past-date classification.\n */\nexport function classifyAgendaDate(\n agendaDate: string,\n now?: Date,\n role?: \"due\" | \"scheduled\" | \"event\",\n): AgendaDisplay {\n const date = parseAgendaDate(agendaDate);\n if (!date) {\n return { label: agendaDate, state: \"future\" };\n }\n\n const reference = now ?? new Date();\n const days = daysBetween(reference, date);\n\n if (days < 0) {\n // Past dates: state depends on role\n if (role === \"event\") {\n return {\n label: formatShortDate(date, reference),\n state: \"past\",\n };\n }\n if (role === \"scheduled\") {\n return {\n label: formatShortDate(date, reference),\n state: \"ongoing\",\n };\n }\n // Default (due): overdue\n return {\n label: `Overdue: ${formatShortDate(date, reference)}`,\n state: \"overdue\",\n };\n }\n\n if (days === 0) {\n return { label: \"Today\", state: \"today\" };\n }\n\n if (days === 1) {\n return { label: \"Tomorrow\", state: \"tomorrow\" };\n }\n\n if (days <= 7) {\n return { label: DAY_NAMES[date.getDay()], state: \"upcoming\" };\n }\n\n return {\n label: formatShortDate(date, reference),\n state: \"future\",\n };\n}\n\n/**\n * CSS class for a given agenda state.\n */\nexport function agendaStateClass(state: AgendaState): string {\n return `blx-agenda-${state}`;\n}\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Check = [[\"path\", { d: \"M20 6 9 17l-5-5\" }]];\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ChevronDown = [[\"path\", { d: \"m6 9 6 6 6-6\" }]];\n\nexport { ChevronDown as default };\n//# sourceMappingURL=chevron-down.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ChevronsLeft = [\n [\"path\", { d: \"m11 17-5-5 5-5\" }],\n [\"path\", { d: \"m18 17-5-5 5-5\" }]\n];\n\nexport { ChevronsLeft as default };\n//# sourceMappingURL=chevrons-left.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ChevronsRight = [\n [\"path\", { d: \"m6 17 5-5-5-5\" }],\n [\"path\", { d: \"m13 17 5-5-5-5\" }]\n];\n\nexport { ChevronsRight as default };\n//# sourceMappingURL=chevrons-right.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst CircleCheckBig = [\n [\"path\", { d: \"M21.801 10A10 10 0 1 1 17 3.335\" }],\n [\"path\", { d: \"m9 11 3 3L22 4\" }]\n];\n\nexport { CircleCheckBig as default };\n//# sourceMappingURL=circle-check-big.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ClipboardPaste = [\n [\"path\", { d: \"M11 14h10\" }],\n [\"path\", { d: \"M16 4h2a2 2 0 0 1 2 2v1.344\" }],\n [\"path\", { d: \"m17 18 4-4-4-4\" }],\n [\"path\", { d: \"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 1.793-1.113\" }],\n [\"rect\", { x: \"8\", y: \"2\", width: \"8\", height: \"4\", rx: \"1\" }]\n];\n\nexport { ClipboardPaste as default };\n//# sourceMappingURL=clipboard-paste.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ClockFading = [\n [\"path\", { d: \"M12 2a10 10 0 0 1 7.38 16.75\" }],\n [\"path\", { d: \"M12 6v6l4 2\" }],\n [\"path\", { d: \"M2.5 8.875a10 10 0 0 0-.5 3\" }],\n [\"path\", { d: \"M2.83 16a10 10 0 0 0 2.43 3.4\" }],\n [\"path\", { d: \"M4.636 5.235a10 10 0 0 1 .891-.857\" }],\n [\"path\", { d: \"M8.644 21.42a10 10 0 0 0 7.631-.38\" }]\n];\n\nexport { ClockFading as default };\n//# sourceMappingURL=clock-fading.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ClockPlus = [\n [\"path\", { d: \"M12 6v6l3.644 1.822\" }],\n [\"path\", { d: \"M16 19h6\" }],\n [\"path\", { d: \"M19 16v6\" }],\n [\"path\", { d: \"M21.92 13.267a10 10 0 1 0-8.653 8.653\" }]\n];\n\nexport { ClockPlus as default };\n//# sourceMappingURL=clock-plus.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Code = [\n [\"path\", { d: \"m16 18 6-6-6-6\" }],\n [\"path\", { d: \"m8 6-6 6 6 6\" }]\n];\n\nexport { Code as default };\n//# sourceMappingURL=code.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Copy = [\n [\"rect\", { width: \"14\", height: \"14\", x: \"8\", y: \"8\", rx: \"2\", ry: \"2\" }],\n [\"path\", { d: \"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" }]\n];\n\nexport { Copy as default };\n//# sourceMappingURL=copy.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst GripVertical = [\n [\"circle\", { cx: \"9\", cy: \"12\", r: \"1\" }],\n [\"circle\", { cx: \"9\", cy: \"5\", r: \"1\" }],\n [\"circle\", { cx: \"9\", cy: \"19\", r: \"1\" }],\n [\"circle\", { cx: \"15\", cy: \"12\", r: \"1\" }],\n [\"circle\", { cx: \"15\", cy: \"5\", r: \"1\" }],\n [\"circle\", { cx: \"15\", cy: \"19\", r: \"1\" }]\n];\n\nexport { GripVertical as default };\n//# sourceMappingURL=grip-vertical.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Heading1 = [\n [\"path\", { d: \"M4 12h8\" }],\n [\"path\", { d: \"M4 18V6\" }],\n [\"path\", { d: \"M12 18V6\" }],\n [\"path\", { d: \"m17 12 3-2v8\" }]\n];\n\nexport { Heading1 as default };\n//# sourceMappingURL=heading-1.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Heading2 = [\n [\"path\", { d: \"M4 12h8\" }],\n [\"path\", { d: \"M4 18V6\" }],\n [\"path\", { d: \"M12 18V6\" }],\n [\"path\", { d: \"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1\" }]\n];\n\nexport { Heading2 as default };\n//# sourceMappingURL=heading-2.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Heading3 = [\n [\"path\", { d: \"M4 12h8\" }],\n [\"path\", { d: \"M4 18V6\" }],\n [\"path\", { d: \"M12 18V6\" }],\n [\"path\", { d: \"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2\" }],\n [\"path\", { d: \"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2\" }]\n];\n\nexport { Heading3 as default };\n//# sourceMappingURL=heading-3.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Heading4 = [\n [\"path\", { d: \"M12 18V6\" }],\n [\"path\", { d: \"M17 10v3a1 1 0 0 0 1 1h3\" }],\n [\"path\", { d: \"M21 10v8\" }],\n [\"path\", { d: \"M4 12h8\" }],\n [\"path\", { d: \"M4 18V6\" }]\n];\n\nexport { Heading4 as default };\n//# sourceMappingURL=heading-4.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst History = [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" }],\n [\"path\", { d: \"M3 3v5h5\" }],\n [\"path\", { d: \"M12 7v5l4 2\" }]\n];\n\nexport { History as default };\n//# sourceMappingURL=history.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Image = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" }]\n];\n\nexport { Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Link = [\n [\"path\", { d: \"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" }],\n [\"path\", { d: \"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" }]\n];\n\nexport { Link as default };\n//# sourceMappingURL=link.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ListChecks = [\n [\"path\", { d: \"M13 5h8\" }],\n [\"path\", { d: \"M13 12h8\" }],\n [\"path\", { d: \"M13 19h8\" }],\n [\"path\", { d: \"m3 17 2 2 4-4\" }],\n [\"path\", { d: \"m3 7 2 2 4-4\" }]\n];\n\nexport { ListChecks as default };\n//# sourceMappingURL=list-checks.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst ListOrdered = [\n [\"path\", { d: \"M11 5h10\" }],\n [\"path\", { d: \"M11 12h10\" }],\n [\"path\", { d: \"M11 19h10\" }],\n [\"path\", { d: \"M4 4h1v5\" }],\n [\"path\", { d: \"M4 9h2\" }],\n [\"path\", { d: \"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\" }]\n];\n\nexport { ListOrdered as default };\n//# sourceMappingURL=list-ordered.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst List = [\n [\"path\", { d: \"M3 5h.01\" }],\n [\"path\", { d: \"M3 12h.01\" }],\n [\"path\", { d: \"M3 19h.01\" }],\n [\"path\", { d: \"M8 5h13\" }],\n [\"path\", { d: \"M8 12h13\" }],\n [\"path\", { d: \"M8 19h13\" }]\n];\n\nexport { List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Pause = [\n [\"rect\", { x: \"14\", y: \"3\", width: \"5\", height: \"18\", rx: \"1\" }],\n [\"rect\", { x: \"5\", y: \"3\", width: \"5\", height: \"18\", rx: \"1\" }]\n];\n\nexport { Pause as default };\n//# sourceMappingURL=pause.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Pencil = [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\"\n }\n ],\n [\"path\", { d: \"m15 5 4 4\" }]\n];\n\nexport { Pencil as default };\n//# sourceMappingURL=pencil.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Pilcrow = [\n [\"path\", { d: \"M13 4v16\" }],\n [\"path\", { d: \"M17 4v16\" }],\n [\"path\", { d: \"M19 4H9.5a4.5 4.5 0 0 0 0 9H13\" }]\n];\n\nexport { Pilcrow as default };\n//# sourceMappingURL=pilcrow.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Play = [\n [\n \"path\",\n { d: \"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" }\n ]\n];\n\nexport { Play as default };\n//# sourceMappingURL=play.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Plus = [\n [\"path\", { d: \"M5 12h14\" }],\n [\"path\", { d: \"M12 5v14\" }]\n];\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Repeat2 = [\n [\"path\", { d: \"m2 9 3-3 3 3\" }],\n [\"path\", { d: \"M13 18H7a2 2 0 0 1-2-2V6\" }],\n [\"path\", { d: \"m22 15-3 3-3-3\" }],\n [\"path\", { d: \"M11 6h6a2 2 0 0 1 2 2v10\" }]\n];\n\nexport { Repeat2 as default };\n//# sourceMappingURL=repeat-2.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Scissors = [\n [\"circle\", { cx: \"6\", cy: \"6\", r: \"3\" }],\n [\"path\", { d: \"M8.12 8.12 12 12\" }],\n [\"path\", { d: \"M20 4 8.12 15.88\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\" }],\n [\"path\", { d: \"M14.8 14.8 20 20\" }]\n];\n\nexport { Scissors as default };\n//# sourceMappingURL=scissors.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Sparkles = [\n [\n \"path\",\n {\n d: \"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\"\n }\n ],\n [\"path\", { d: \"M20 2v4\" }],\n [\"path\", { d: \"M22 4h-4\" }],\n [\"circle\", { cx: \"4\", cy: \"20\", r: \"2\" }]\n];\n\nexport { Sparkles as default };\n//# sourceMappingURL=sparkles.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst TextQuote = [\n [\"path\", { d: \"M17 5H3\" }],\n [\"path\", { d: \"M21 12H8\" }],\n [\"path\", { d: \"M21 19H8\" }],\n [\"path\", { d: \"M3 12v7\" }]\n];\n\nexport { TextQuote as default };\n//# sourceMappingURL=text-quote.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst Trash2 = [\n [\"path\", { d: \"M10 11v6\" }],\n [\"path\", { d: \"M14 11v6\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" }],\n [\"path\", { d: \"M3 6h18\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" }]\n];\n\nexport { Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst X = [\n [\"path\", { d: \"M18 6 6 18\" }],\n [\"path\", { d: \"m6 6 12 12\" }]\n];\n\nexport { X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * Icon utilities — thin wrapper around lucide icon definitions.\n *\n * Usage:\n * import { iconHtml, X, Plus } from \"../util/icons\";\n * el.innerHTML = iconHtml(X, 14);\n */\n\nimport type { IconNode } from \"lucide\";\n\nexport {\n Check,\n ChevronDown,\n CircleCheckBig,\n ChevronsLeft,\n ChevronsRight,\n Clipboard,\n ClipboardPaste,\n ClockFading,\n ClockPlus,\n Code,\n Copy,\n GripVertical,\n Heading1,\n Heading2,\n Heading3,\n Heading4,\n History,\n Image,\n Link,\n List,\n ListChecks,\n ListOrdered,\n Pause,\n Pencil,\n Pilcrow,\n Play,\n Plus,\n Repeat2,\n Scissors,\n Sparkles,\n TextQuote,\n Trash2,\n Ban,\n X,\n} from \"lucide\";\n\n/**\n * Return an HTML string for a lucide icon (for innerHTML contexts).\n */\nexport function iconHtml(\n def: IconNode,\n size: number = 16,\n attrs: Record<string, string> = {},\n): string {\n const mergedAttrs: Record<string, string | number> = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: size,\n height: size,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": \"2\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n ...attrs,\n };\n\n const attrStr = Object.entries(mergedAttrs)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(\" \");\n\n const children = def\n .map(([tag, a]) => {\n const tagAttrs = Object.entries(a)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(\" \");\n return `<${tag} ${tagAttrs}/>`;\n })\n .join(\"\");\n\n return `<svg ${attrStr}>${children}</svg>`;\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { renderAttributedString, updateEmptyState, getBlockDir, isBlockReadOnly } from \"./render-utils\";\nimport { classifyAgendaDate, agendaStateClass } from \"../date-picker/agenda-utils\";\nimport { iconHtml, Repeat2 } from \"../util/icons\";\n\nexport interface ParagraphMetadata {\n [key: string]: unknown;\n align?: \"left\" | \"center\" | \"right\" | \"start\" | \"end\";\n dueDate?: string; // ISO 8601 date — task deadline\n scheduledDate?: string; // ISO 8601 date — planned start/work date\n eventDate?: string; // ISO 8601 date — calendar event\n recurrence?: {\n interval: number;\n unit: \"day\" | \"week\" | \"month\" | \"year\";\n anchor?: string;\n fromCompletion?: boolean;\n };\n /** @deprecated — migrated to dueDate/scheduledDate/eventDate by deserializeMetadata */\n agendaDate?: string;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n}\n\nexport const paragraphPlugin: BlockTypePlugin<ParagraphMetadata> = {\n type: \"paragraph\",\n label: \"Paragraph\",\n hasTextContent: true,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): ParagraphMetadata {\n return {};\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n const p = document.createElement(\"p\");\n p.classList.add(\"blx-paragraph\");\n p.setAttribute(\"contenteditable\", \"true\");\n p.setAttribute(\"dir\", getBlockDir(metadata));\n if (metadata.align) {\n p.style.textAlign = metadata.align;\n }\n renderAttributedString(p, content);\n updateEmptyState(p, content, \"Type / for commands\");\n container.appendChild(p);\n\n // Agenda badge (right-aligned, contenteditable=false) — paragraphs only show eventDate\n const dateInfo = resolveParagraphDisplayDate(metadata);\n if (dateInfo) {\n container.style.display = \"flex\";\n container.style.alignItems = \"baseline\";\n p.style.flex = \"1\";\n container.appendChild(renderParagraphAgendaBadge(dateInfo.date, dateInfo.role, !!metadata.recurrence, container));\n }\n\n return p;\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n { type: \"checklist\", label: \"Checklist\", description: \"Checklist with checkboxes\", metadata: { checked: false } },\n { type: \"blockquote\", label: \"Quote\", description: \"Blockquote text\" },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n ];\n },\n\n metadataFromConversion(_fromType: string, fromMetadata: BlockMetadata): ParagraphMetadata {\n const result: ParagraphMetadata = {};\n // Preserve date role fields across type conversions\n if (fromMetadata.dueDate !== undefined) result.dueDate = fromMetadata.dueDate as string;\n if (fromMetadata.scheduledDate !== undefined) result.scheduledDate = fromMetadata.scheduledDate as string;\n if (fromMetadata.eventDate !== undefined) result.eventDate = fromMetadata.eventDate as string;\n if (fromMetadata.recurrence !== undefined) result.recurrence = fromMetadata.recurrence as ParagraphMetadata[\"recurrence\"];\n // Keep agendaDate in case conversion happens before migration\n if (fromMetadata.agendaDate !== undefined) result.agendaDate = fromMetadata.agendaDate as string;\n return result;\n },\n\n update(container, contentEditable, content, metadata) {\n if (!contentEditable) return;\n contentEditable.setAttribute(\"dir\", getBlockDir(metadata));\n if (metadata.align) {\n contentEditable.style.textAlign = metadata.align;\n } else {\n contentEditable.style.textAlign = \"\";\n }\n\n // Update agenda badge — paragraphs only show eventDate\n const existingBadge = container.querySelector(\".blx-agenda-badge\");\n const dateInfo = resolveParagraphDisplayDate(metadata);\n if (dateInfo) {\n if (existingBadge) {\n // Update existing badge\n const display = classifyAgendaDate(dateInfo.date, undefined, dateInfo.role);\n existingBadge.textContent = display.label;\n existingBadge.className = `blx-agenda-badge ${agendaStateClass(display.state)}`;\n if (metadata.recurrence) existingBadge.classList.add(\"blx-agenda-recurring\");\n (existingBadge as HTMLElement).dataset.agendaDate = dateInfo.date;\n (existingBadge as HTMLElement).dataset.agendaRole = dateInfo.role;\n // Update recurrence indicator\n const existingRecur = existingBadge.querySelector(\".blx-agenda-recurrence\");\n if (metadata.recurrence && !existingRecur) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n existingBadge.appendChild(recur);\n } else if (!metadata.recurrence && existingRecur) {\n existingRecur.remove();\n }\n } else {\n // Add new badge\n container.style.display = \"flex\";\n container.style.alignItems = \"baseline\";\n contentEditable.style.flex = \"1\";\n container.appendChild(renderParagraphAgendaBadge(dateInfo.date, dateInfo.role, !!metadata.recurrence, container));\n }\n } else if (existingBadge) {\n // Remove badge and reset container styles\n existingBadge.remove();\n container.style.display = \"\";\n container.style.alignItems = \"\";\n contentEditable.style.flex = \"\";\n }\n\n renderAttributedString(contentEditable, content);\n updateEmptyState(contentEditable, content, \"Type / for commands\");\n },\n\n serializeMetadata(m) {\n const out: Record<string, unknown> = {};\n if (m.dueDate) out.dueDate = m.dueDate;\n if (m.scheduledDate) out.scheduledDate = m.scheduledDate;\n if (m.eventDate) out.eventDate = m.eventDate;\n if (m.recurrence) out.recurrence = m.recurrence;\n if (m.agendaDate) out.agendaDate = m.agendaDate;\n return out;\n },\n\n deserializeMetadata(raw) {\n // Migrate legacy agendaDate → eventDate (paragraphs are non-tasks)\n if (raw.agendaDate && !raw.dueDate && !raw.scheduledDate && !raw.eventDate) {\n raw.eventDate = raw.agendaDate;\n delete raw.agendaDate;\n }\n\n const result: ParagraphMetadata = {};\n if (typeof raw.dueDate === \"string\") result.dueDate = raw.dueDate;\n if (typeof raw.scheduledDate === \"string\") result.scheduledDate = raw.scheduledDate;\n if (typeof raw.eventDate === \"string\") result.eventDate = raw.eventDate;\n if (raw.recurrence && typeof raw.recurrence === \"object\") {\n result.recurrence = raw.recurrence as ParagraphMetadata[\"recurrence\"];\n }\n // Keep agendaDate if it wasn't migrated (i.e., new fields already present)\n if (typeof raw.agendaDate === \"string\") result.agendaDate = raw.agendaDate;\n return result;\n },\n};\n\n/**\n * Resolve the display date for paragraphs — only eventDate (or legacy agendaDate).\n */\nfunction resolveParagraphDisplayDate(metadata: ParagraphMetadata): { date: string; role: \"due\" | \"scheduled\" | \"event\" } | null {\n if (metadata.eventDate) return { date: typeof metadata.eventDate === \"string\" ? metadata.eventDate : String(metadata.eventDate), role: \"event\" };\n // Legacy fallback\n if (metadata.agendaDate) return { date: typeof metadata.agendaDate === \"string\" ? metadata.agendaDate : String(metadata.agendaDate), role: \"event\" };\n return null;\n}\n\n/** Create an agenda badge element for paragraph blocks. */\nfunction renderParagraphAgendaBadge(\n dateStr: string,\n role: \"due\" | \"scheduled\" | \"event\",\n recurring: boolean,\n container: HTMLElement,\n): HTMLElement {\n const display = classifyAgendaDate(dateStr, undefined, role);\n const badge = document.createElement(\"span\");\n badge.classList.add(\"blx-agenda-badge\", agendaStateClass(display.state));\n if (recurring) badge.classList.add(\"blx-agenda-recurring\");\n badge.setAttribute(\"contenteditable\", \"false\");\n badge.dataset.agendaDate = dateStr;\n badge.dataset.agendaRole = role;\n badge.textContent = display.label;\n\n // Recurrence indicator\n if (recurring) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n badge.appendChild(recur);\n }\n\n // Click to edit agenda item (disabled in read-only mode)\n if (!isBlockReadOnly(container)) {\n badge.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n container.dispatchEvent(new CustomEvent(\"blx:agendaEdit\", {\n bubbles: true,\n detail: { role: badge.dataset.agendaRole ?? role, date: badge.dataset.agendaDate ?? dateStr },\n }));\n });\n }\n\n return badge;\n}\n","/**\n * Shared positioning utility for floating UI elements.\n * Sets `position: fixed` and places the element relative to an anchor rect,\n * flipping vertically if it overflows and clamping horizontally.\n * Constrains max-height to available viewport space so menus scroll\n * instead of bleeding outside the viewport.\n */\n\n/** Options for {@link positionFixed}. */\nexport interface PositionFixedOptions {\n /** Pixel gap between anchor and element (default: 4) */\n gap?: number;\n /** Horizontal alignment relative to anchor (default: \"start\") */\n align?: \"start\" | \"center\";\n /** Preferred vertical placement (default: \"below\") */\n placement?: \"above\" | \"below\";\n /** Viewport edge padding in px (default: 4) */\n viewportPadding?: number;\n /**\n * Called after final placement is determined.\n * Receives the actual placement used (`\"above\"` or `\"below\"`), which may\n * differ from `options.placement` if a flip was necessary.\n */\n onPlaced?: (placement: \"above\" | \"below\") => void;\n}\n\n/**\n * Position `el` with `position: fixed` relative to `anchor`.\n *\n * Measures the element and places it in a single synchronous pass so the\n * final position is painted on the first frame (no flash/jump).\n *\n * @param el - The floating element to position (must be in the DOM and visible).\n * @param anchor - The anchor bounding rect (e.g. from `getBoundingClientRect()`).\n * @param options - Placement preferences and callbacks.\n */\nexport function positionFixed(\n el: HTMLElement,\n anchor: DOMRect,\n options?: PositionFixedOptions,\n): void {\n const gap = options?.gap ?? 4;\n const align = options?.align ?? \"start\";\n const preferred = options?.placement ?? \"below\";\n const pad = options?.viewportPadding ?? 4;\n\n el.style.position = \"fixed\";\n\n // Set initial left so the element lays out at roughly the right width\n if (align === \"center\") {\n el.style.left = `${anchor.left + anchor.width / 2}px`;\n } else {\n el.style.left = `${anchor.left}px`;\n }\n\n // Use visualViewport when available so floating elements stay inside\n // the visible area on mobile (window.innerHeight is the layout viewport\n // and does not shrink when the on-screen keyboard opens).\n const vp = window.visualViewport;\n const vh = vp ? vp.height : window.innerHeight;\n const rect = el.getBoundingClientRect();\n let finalPlacement = preferred;\n\n const spaceBelow = vh - anchor.bottom - gap - pad;\n const spaceAbove = anchor.top - gap - pad;\n\n if (preferred === \"below\") {\n if (rect.height <= spaceBelow) {\n // Fits below — keep it\n el.style.top = `${anchor.bottom + gap}px`;\n } else if (spaceAbove > spaceBelow) {\n // More room above — flip\n finalPlacement = \"above\";\n if (spaceAbove < rect.height) el.style.maxHeight = `${spaceAbove}px`;\n const h = Math.min(rect.height, spaceAbove);\n el.style.top = `${anchor.top - h - gap}px`;\n } else {\n // Below is best (or equal) — constrain height\n if (spaceBelow < rect.height) el.style.maxHeight = `${spaceBelow}px`;\n el.style.top = `${anchor.bottom + gap}px`;\n }\n } else {\n // preferred === \"above\"\n if (rect.height <= spaceAbove) {\n // Fits above\n el.style.top = `${anchor.top - rect.height - gap}px`;\n } else if (spaceBelow > spaceAbove) {\n // More room below — flip\n finalPlacement = \"below\";\n if (spaceBelow < rect.height) el.style.maxHeight = `${spaceBelow}px`;\n el.style.top = `${anchor.bottom + gap}px`;\n } else {\n // Above is best — constrain height\n if (spaceAbove < rect.height) el.style.maxHeight = `${spaceAbove}px`;\n const h = Math.min(rect.height, spaceAbove);\n el.style.top = `${anchor.top - h - gap}px`;\n }\n }\n\n // Horizontal: center alignment needs centering offset\n let left: number;\n if (align === \"center\") {\n left = anchor.left + (anchor.width - rect.width) / 2;\n } else {\n left = rect.left; // already set\n }\n\n // Clamp to viewport edges (use visualViewport width when available)\n const vw = vp ? vp.width : window.innerWidth;\n left = Math.max(pad, Math.min(left, vw - rect.width - pad));\n el.style.left = `${left}px`;\n\n options?.onPlaced?.(finalPlacement);\n}\n","/**\n * Reusable floating context menu component.\n * Renders a list of selectable items with keyboard navigation,\n * mouse interaction, sections, disabled/danger states, and viewport-aware positioning.\n *\n * Used internally by SlashMenu, AutoCompleteMenu, BlockActionMenu, and table context menu.\n */\n\nimport { positionFixed } from \"./position-fixed\";\n\n/** A single item in a {@link ContextMenu}. */\nexport interface MenuItem {\n /** Unique identifier for this item — returned in {@link ContextMenu.onSelect}. */\n id: string;\n /** Human-readable display name. */\n label: string;\n /** Optional secondary description displayed below the label. */\n description?: string;\n /**\n * Optional icon: either an HTML string or a render function.\n * Render functions receive the icon container element and may append\n * arbitrary DOM nodes (e.g. SVGs).\n */\n icon?: string | ((container: HTMLElement) => void);\n /** Group key — separator inserted between different sections */\n section?: string;\n /** When true, the item is rendered dimmed and cannot be selected. */\n disabled?: boolean;\n /** When true, the label is rendered in danger (red) color. */\n danger?: boolean;\n /** Keyboard shortcut hint displayed right-aligned, e.g. \"⌫\" or \"Del\" */\n hint?: string;\n /** Arbitrary payload passed back in onSelect */\n data?: unknown;\n}\n\n/** Construction options for {@link ContextMenu}. */\nexport interface ContextMenuOptions {\n /** Additional CSS class on the container (e.g. \"blx-slash-menu\") */\n className?: string;\n /** If set, shows empty state when items is empty */\n emptyText?: string;\n /** Arrow nav skips disabled items (default: true) */\n skipDisabled?: boolean;\n /**\n * ARIA role for the container and its items.\n * - \"menu\" (default): container gets role=\"menu\", items get implicit button role\n * - \"listbox\": container gets role=\"listbox\", items get role=\"option\"\n * Used by Dropdown widget for accessible select-like behavior.\n */\n role?: \"menu\" | \"listbox\";\n}\n\nexport class ContextMenu {\n /** The root DOM element of the menu. Append to the document before calling {@link show}. */\n readonly el: HTMLElement;\n\n private items: MenuItem[] = [];\n private selectedIndex = 0;\n private _visible = false;\n private opts: Required<Pick<ContextMenuOptions, \"skipDisabled\">> & ContextMenuOptions;\n /** Remembered placement so reposition() doesn't flicker */\n private placement: \"above\" | \"below\" = \"below\";\n /** Stored anchor rect for repositioning after content changes */\n private anchorRect: DOMRect | null = null;\n\n /** Called when the user selects an item (click, Enter, or Tab). */\n onSelect: ((item: MenuItem) => void) | null = null;\n /** Called when Escape is pressed while the menu is visible. */\n onClose: (() => void) | null = null;\n\n constructor(options?: ContextMenuOptions) {\n this.opts = {\n skipDisabled: true,\n ...options,\n };\n\n this.el = document.createElement(\"div\");\n this.el.classList.add(\"blx-menu\");\n if (this.opts.className) {\n this.el.classList.add(this.opts.className);\n }\n if (this.opts.role === \"listbox\") {\n this.el.setAttribute(\"role\", \"listbox\");\n }\n this.el.style.display = \"none\";\n }\n\n /** Whether the menu is currently visible. */\n get visible(): boolean {\n return this._visible;\n }\n\n /** Whether the menu has at least one item. */\n get hasItems(): boolean {\n return this.items.length > 0;\n }\n\n /** The currently highlighted {@link MenuItem}, or `undefined` if empty. */\n get selectedItem(): MenuItem | undefined {\n return this.items[this.selectedIndex];\n }\n\n /**\n * Show the menu anchored to `anchorRect` and populate it with `items`.\n * The menu is positioned below the anchor by default and flips above if\n * it would overflow the viewport bottom.\n * @param anchorRect - Bounding rect of the element to anchor to.\n * @param items - List of items to render.\n */\n show(anchorRect: DOMRect, items: MenuItem[]): void {\n this.items = items;\n this.selectedIndex = this.findFirstEnabled(0, 1);\n this.placement = \"below\";\n this.anchorRect = anchorRect;\n this.renderItems();\n this.el.style.display = \"block\";\n this.el.style.maxHeight = \"\"; // reset so positionFixed can constrain\n this._visible = true;\n\n positionFixed(this.el, anchorRect, {\n placement: \"below\",\n onPlaced: (p) => { this.placement = p; },\n });\n }\n\n /** Hide the menu. Does not remove it from the DOM. */\n hide(): void {\n this.el.style.display = \"none\";\n this._visible = false;\n this.placement = \"below\";\n this.anchorRect = null;\n }\n\n /** Hide the menu and remove its element from the DOM. */\n destroy(): void {\n this.hide();\n this.el.remove();\n }\n\n /** Replace items and reanchor when placed above (used for filter-as-you-type) */\n setItems(items: MenuItem[]): void {\n this.items = items;\n this.selectedIndex = this.findFirstEnabled(0, 1);\n this.renderItems();\n\n // When placed above the caret, the menu's bottom must stay anchored.\n // Re-derive top from the new height so items don't drift away.\n if (this.placement === \"above\" && this.anchorRect) {\n this.reposition(this.anchorRect);\n }\n }\n\n /** Reposition relative to a new anchor rect (e.g. caret moved or content resized) */\n reposition(anchorRect: DOMRect): void {\n if (!this._visible) return;\n this.anchorRect = anchorRect;\n this.el.style.left = `${anchorRect.left}px`;\n if (this.placement === \"above\") {\n const menuHeight = this.el.getBoundingClientRect().height;\n this.el.style.top = `${anchorRect.top - menuHeight - 4}px`;\n } else {\n this.el.style.top = `${anchorRect.bottom + 4}px`;\n }\n }\n\n /**\n * Handle keyboard events for menu navigation.\n * @param e - The keyboard event to process.\n * @returns `true` if the event was consumed (ArrowUp, ArrowDown, Enter, Tab, Escape),\n * `false` otherwise. When `true`, callers should stop further event processing.\n */\n handleKeyDown(e: KeyboardEvent): boolean {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (this.items.length === 0) return true;\n this.moveSelection(1);\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n if (this.items.length === 0) return true;\n this.moveSelection(-1);\n return true;\n }\n if (e.key === \"Enter\" || e.key === \"Tab\") {\n e.preventDefault();\n const item = this.items[this.selectedIndex];\n if (item && !item.disabled) {\n this.onSelect?.(item);\n }\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.onClose?.();\n return true;\n }\n return false;\n }\n\n /**\n * Programmatically select item by index.\n * Used by Dropdown type-ahead to highlight the matching item.\n */\n selectIndex(index: number): void {\n if (index < 0 || index >= this.items.length) return;\n this.selectedIndex = index;\n this.updateSelection();\n }\n\n // ── Internal ──────────────────────────────────────────────\n\n private moveSelection(direction: 1 | -1): void {\n const next = this.findFirstEnabled(\n (this.selectedIndex + direction + this.items.length) % this.items.length,\n direction,\n );\n this.selectedIndex = next;\n this.updateSelection();\n }\n\n private findFirstEnabled(start: number, direction: 1 | -1): number {\n if (this.items.length === 0) return 0;\n if (!this.opts.skipDisabled) return start;\n let idx = start;\n for (let i = 0; i < this.items.length; i++) {\n if (!this.items[idx]?.disabled) return idx;\n idx = (idx + direction + this.items.length) % this.items.length;\n }\n return start; // all disabled — stay put\n }\n\n private renderItems(): void {\n this.el.innerHTML = \"\";\n\n if (this.items.length === 0 && this.opts.emptyText) {\n const empty = document.createElement(\"div\");\n empty.classList.add(\"blx-menu-empty\");\n empty.textContent = this.opts.emptyText;\n this.el.appendChild(empty);\n return;\n }\n\n let lastSection: string | undefined;\n\n this.items.forEach((item, i) => {\n // Section separator\n if (item.section && lastSection && item.section !== lastSection) {\n const sep = document.createElement(\"div\");\n sep.classList.add(\"blx-menu-sep\");\n this.el.appendChild(sep);\n }\n lastSection = item.section;\n\n const btn = document.createElement(\"button\");\n btn.classList.add(\"blx-menu-item\");\n if (i === this.selectedIndex) btn.classList.add(\"blx-menu-item-selected\");\n if (item.disabled) btn.classList.add(\"blx-menu-item-disabled\");\n if (item.danger) btn.classList.add(\"blx-menu-item-danger\");\n btn.type = \"button\";\n if (this.opts.role === \"listbox\") {\n btn.setAttribute(\"role\", \"option\");\n btn.setAttribute(\"aria-selected\", i === this.selectedIndex ? \"true\" : \"false\");\n }\n\n // Icon\n if (item.icon) {\n const iconEl = document.createElement(\"span\");\n iconEl.classList.add(\"blx-menu-icon\");\n if (typeof item.icon === \"function\") {\n item.icon(iconEl);\n } else {\n iconEl.innerHTML = item.icon;\n }\n btn.appendChild(iconEl);\n }\n\n // Text container (label + optional description)\n const textWrap = document.createElement(\"div\");\n textWrap.classList.add(\"blx-menu-text\");\n\n const label = document.createElement(\"span\");\n label.classList.add(\"blx-menu-label\");\n label.textContent = item.label;\n textWrap.appendChild(label);\n\n if (item.description) {\n const desc = document.createElement(\"span\");\n desc.classList.add(\"blx-menu-description\");\n desc.textContent = item.description;\n textWrap.appendChild(desc);\n }\n\n btn.appendChild(textWrap);\n\n if (item.hint) {\n const hintEl = document.createElement(\"span\");\n hintEl.classList.add(\"blx-menu-hint\");\n hintEl.textContent = item.hint;\n btn.appendChild(hintEl);\n }\n\n // Mouse/touch interaction\n btn.addEventListener(\"mouseenter\", () => {\n if (!item.disabled) {\n this.selectedIndex = i;\n this.updateSelection();\n }\n });\n\n btn.addEventListener(\"mousedown\", (e) => {\n e.preventDefault(); // prevent blur\n if (item.disabled) return;\n this.onSelect?.(item);\n });\n\n btn.addEventListener(\"touchend\", (e) => {\n e.preventDefault();\n if (item.disabled) return;\n this.onSelect?.(item);\n });\n\n this.el.appendChild(btn);\n });\n }\n\n private updateSelection(): void {\n const buttons = this.el.querySelectorAll(\".blx-menu-item\");\n const isListbox = this.opts.role === \"listbox\";\n buttons.forEach((btn, i) => {\n btn.classList.toggle(\"blx-menu-item-selected\", i === this.selectedIndex);\n if (isListbox) {\n btn.setAttribute(\"aria-selected\", i === this.selectedIndex ? \"true\" : \"false\");\n }\n });\n\n // Scroll selected item into view within the menu (without affecting ancestors)\n const selected = this.el.querySelector(\".blx-menu-item-selected\") as HTMLElement | null;\n if (selected) {\n const menuRect = this.el.getBoundingClientRect();\n const itemRect = selected.getBoundingClientRect();\n if (itemRect.bottom > menuRect.bottom) {\n this.el.scrollTop += itemRect.bottom - menuRect.bottom;\n } else if (itemRect.top < menuRect.top) {\n this.el.scrollTop += itemRect.top - menuRect.top;\n }\n }\n }\n}\n","/**\n * Shared dismiss utility: click-outside + optional Escape key.\n * Used internally by Popover, and directly by BlockActionMenu.\n */\n\n/**\n * Handle returned by {@link dismissOnClickOutside}.\n * Call {@link remove} to cancel all installed listeners.\n */\nexport interface DismissHandle {\n /** Cancel all event listeners installed by {@link dismissOnClickOutside}. */\n remove(): void;\n}\n\n/**\n * Install click-outside and optional Escape-key dismiss handlers for a floating element.\n *\n * The click-outside listener is installed via a capture-phase `mousedown` + `touchstart`\n * on `document`, so it fires before the element's own handlers. Use `defer: true`\n * (the default) to skip the listener installation for one tick, preventing the same\n * click that opened the element from immediately closing it.\n *\n * @param el - The floating element. Clicks inside it will NOT trigger dismiss.\n * @param onDismiss - Callback invoked when a dismiss condition is met.\n * @param options - Configuration options.\n * @returns A {@link DismissHandle} whose {@link DismissHandle.remove} cancels all listeners.\n */\nexport function dismissOnClickOutside(\n el: HTMLElement,\n onDismiss: () => void,\n options?: {\n /** Listen for Escape key (default: true) */\n escapeKey?: boolean;\n /** setTimeout(0) guard to avoid instant dismiss from triggering click (default: true) */\n defer?: boolean;\n /** Extra elements that should not trigger dismiss */\n ignoreElements?: HTMLElement[];\n },\n): DismissHandle {\n const escapeKey = options?.escapeKey ?? true;\n const defer = options?.defer ?? true;\n\n let mouseHandler: ((e: MouseEvent | TouchEvent) => void) | null = null;\n let keyHandler: ((e: KeyboardEvent) => void) | null = null;\n let deferTimer: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n // Cancel any pending deferred install so it doesn't add listeners\n // after cleanup (e.g. if close() is called before the timeout fires).\n if (deferTimer !== null) {\n clearTimeout(deferTimer);\n deferTimer = null;\n }\n if (mouseHandler) {\n document.removeEventListener(\"mousedown\", mouseHandler, true);\n document.removeEventListener(\"touchstart\", mouseHandler, true);\n mouseHandler = null;\n }\n if (keyHandler) {\n document.removeEventListener(\"keydown\", keyHandler, true);\n keyHandler = null;\n }\n };\n\n mouseHandler = (e: MouseEvent | TouchEvent) => {\n const target = (e instanceof TouchEvent ? e.touches[0]?.target : e.target) as HTMLElement | null;\n if (!target) return;\n if (el.contains(target)) return;\n if (options?.ignoreElements?.some((ig) => ig.contains(target))) return;\n onDismiss();\n };\n\n if (escapeKey) {\n keyHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onDismiss();\n }\n };\n document.addEventListener(\"keydown\", keyHandler, true);\n }\n\n const install = () => {\n if (mouseHandler) {\n document.addEventListener(\"mousedown\", mouseHandler, true);\n document.addEventListener(\"touchstart\", mouseHandler, true);\n }\n };\n\n if (defer) {\n deferTimer = setTimeout(() => {\n deferTimer = null;\n install();\n }, 0);\n } else {\n install();\n }\n\n return { remove: cleanup };\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { renderAttributedString, getBlockDir, isBlockReadOnly } from \"./render-utils\";\nimport { ContextMenu, type MenuItem } from \"../ui/context-menu\";\nimport { dismissOnClickOutside, type DismissHandle } from \"../ui/dismiss\";\nimport { classifyAgendaDate, agendaStateClass } from \"../date-picker/agenda-utils\";\nimport { iconHtml, Repeat2 } from \"../util/icons\";\n\nexport type TaskStatus = \"todo\" | \"in-progress\" | \"done\";\n\nexport interface HeadingMetadata {\n [key: string]: unknown;\n level: 1 | 2 | 3 | 4;\n taskStatus?: TaskStatus;\n dueDate?: string; // ISO 8601 date — task deadline\n scheduledDate?: string; // ISO 8601 date — planned start/work date\n eventDate?: string; // ISO 8601 date — calendar event\n recurrence?: {\n interval: number;\n unit: \"day\" | \"week\" | \"month\" | \"year\";\n anchor?: string;\n fromCompletion?: boolean;\n };\n /** @deprecated — migrated to dueDate/scheduledDate/eventDate by deserializeMetadata */\n agendaDate?: string;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n}\n\nconst TASK_STATUS_CYCLE: Record<TaskStatus, TaskStatus> = {\n \"todo\": \"in-progress\",\n \"in-progress\": \"done\",\n \"done\": \"todo\",\n};\n\nconst TASK_STATUS_ITEMS: { id: TaskStatus | \"remove\"; label: string; section: string }[] = [\n { id: \"todo\", label: \"To Do\", section: \"status\" },\n { id: \"in-progress\", label: \"In Progress\", section: \"status\" },\n { id: \"done\", label: \"Done\", section: \"status\" },\n { id: \"remove\", label: \"Remove status\", section: \"danger\" },\n];\n\n/**\n * Open a context menu on the task indicator to pick a specific status.\n * Dispatches `blx:headingTaskToggle` on select.\n */\nfunction openTaskStatusMenu(e: MouseEvent, container: HTMLElement): void {\n e.preventDefault();\n e.stopPropagation();\n\n const menu = new ContextMenu({ className: \"blx-task-status-menu\" });\n // Find editor root to append menu for CSS variable inheritance\n const editorRoot = container.closest(\".blx-editor\") ?? document.body;\n editorRoot.appendChild(menu.el);\n\n let dismissHandle: DismissHandle | null = null;\n\n const cleanup = () => {\n menu.destroy();\n dismissHandle?.remove();\n dismissHandle = null;\n };\n\n menu.onSelect = (item: MenuItem) => {\n cleanup();\n const status = item.id === \"remove\" ? null : item.id;\n container.dispatchEvent(new CustomEvent(\"blx:headingTaskToggle\", {\n bubbles: true,\n detail: { taskStatus: status },\n }));\n };\n\n menu.onClose = cleanup;\n\n const items: MenuItem[] = TASK_STATUS_ITEMS.map((s) => ({\n id: s.id,\n label: s.label,\n section: s.section,\n danger: s.id === \"remove\",\n }));\n\n const anchorRect = new DOMRect(e.clientX, e.clientY, 0, 0);\n menu.show(anchorRect, items);\n\n dismissHandle = dismissOnClickOutside(menu.el, cleanup);\n}\n\n/** Fold indicator bar shown below folded headings. Hidden by default via CSS,\n * becomes visible when the block has `.blx-heading-folded`. Clicking it unfolds. */\nfunction createFoldIndicator(container: HTMLElement): HTMLElement {\n const bar = document.createElement(\"div\");\n bar.classList.add(\"blx-fold-indicator\");\n bar.setAttribute(\"contenteditable\", \"false\");\n bar.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n e.preventDefault();\n container.dispatchEvent(new CustomEvent(\"blx:headingFoldToggle\", {\n bubbles: true,\n detail: { blockId: container.dataset?.blockId },\n }));\n });\n return bar;\n}\n\nexport const headingPlugin: BlockTypePlugin<HeadingMetadata> = {\n type: \"heading\",\n label: \"Heading\",\n hasTextContent: true,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): HeadingMetadata {\n return { level: 1 };\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\", shortcutHint: \"Ctrl+Shift+0\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n { type: \"checklist\", label: \"Checklist\", description: \"Checklist with checkboxes\", metadata: { checked: false } },\n { type: \"blockquote\", label: \"Quote\", description: \"Blockquote text\" },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n ];\n },\n\n metadataFromConversion(fromType: string, fromMetadata: BlockMetadata): HeadingMetadata {\n // Preserve heading level and taskStatus when converting from another heading\n if (fromType === \"heading\" && typeof fromMetadata.level === \"number\") {\n const result: HeadingMetadata = { level: fromMetadata.level as HeadingMetadata[\"level\"] };\n if (fromMetadata.taskStatus === \"todo\" || fromMetadata.taskStatus === \"in-progress\" || fromMetadata.taskStatus === \"done\") {\n result.taskStatus = fromMetadata.taskStatus;\n }\n // Preserve date role fields across conversions\n if (fromMetadata.dueDate !== undefined) result.dueDate = fromMetadata.dueDate as string;\n if (fromMetadata.scheduledDate !== undefined) result.scheduledDate = fromMetadata.scheduledDate as string;\n if (fromMetadata.eventDate !== undefined) result.eventDate = fromMetadata.eventDate as string;\n if (fromMetadata.recurrence !== undefined) result.recurrence = fromMetadata.recurrence as HeadingMetadata[\"recurrence\"];\n // Keep agendaDate in case conversion happens before migration\n if (fromMetadata.agendaDate !== undefined) result.agendaDate = fromMetadata.agendaDate as string;\n return result;\n }\n // Preserve date fields when converting from other types to heading\n const result: HeadingMetadata = { level: 1 };\n if (fromMetadata.dueDate !== undefined) result.dueDate = fromMetadata.dueDate as string;\n if (fromMetadata.scheduledDate !== undefined) result.scheduledDate = fromMetadata.scheduledDate as string;\n if (fromMetadata.eventDate !== undefined) result.eventDate = fromMetadata.eventDate as string;\n if (fromMetadata.recurrence !== undefined) result.recurrence = fromMetadata.recurrence as HeadingMetadata[\"recurrence\"];\n // Keep agendaDate in case conversion happens before migration\n if (fromMetadata.agendaDate !== undefined) result.agendaDate = fromMetadata.agendaDate as string;\n return result;\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n\n const tag = `h${metadata.level}` as keyof HTMLElementTagNameMap;\n\n // When taskStatus is set, wrap in a flex container with a clickable indicator\n const readOnly = isBlockReadOnly(container);\n if (metadata.taskStatus) {\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-heading-wrapper\");\n\n const indicator = document.createElement(\"button\");\n indicator.classList.add(\"blx-heading-task-indicator\", `blx-task-${metadata.taskStatus}`);\n indicator.setAttribute(\"contenteditable\", \"false\");\n indicator.setAttribute(\"tabindex\", \"-1\");\n indicator.setAttribute(\"aria-label\", `Task: ${metadata.taskStatus}`);\n indicator.dataset.taskStatus = metadata.taskStatus;\n\n if (!readOnly) {\n indicator.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n e.preventDefault();\n const current = (e.currentTarget as HTMLButtonElement).dataset.taskStatus as TaskStatus;\n const next = TASK_STATUS_CYCLE[current];\n container.dispatchEvent(new CustomEvent(\"blx:headingTaskToggle\", {\n bubbles: true,\n detail: { taskStatus: next },\n }));\n });\n\n indicator.addEventListener(\"contextmenu\", (e) => {\n openTaskStatusMenu(e, container);\n });\n\n // Long-press on mobile: some browsers don't fire contextmenu on long-press,\n // so detect it via touch events with a 500ms threshold.\n let longPressTimer: ReturnType<typeof setTimeout> | null = null;\n indicator.addEventListener(\"touchstart\", (e) => {\n longPressTimer = setTimeout(() => {\n longPressTimer = null;\n const touch = e.touches[0];\n if (!touch) return;\n // Synthesize a MouseEvent at the touch position for the menu\n const synth = new MouseEvent(\"contextmenu\", {\n bubbles: true,\n cancelable: true,\n clientX: touch.clientX,\n clientY: touch.clientY,\n });\n openTaskStatusMenu(synth, container);\n }, 500);\n }, { passive: true });\n indicator.addEventListener(\"touchend\", () => {\n if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; }\n }, { passive: true });\n indicator.addEventListener(\"touchmove\", () => {\n if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; }\n }, { passive: true });\n } // end if (!readOnly)\n\n // Agenda label — positioned above heading text in the margin\n const dateInfo = resolveDisplayDate(metadata);\n if (dateInfo) {\n wrapper.appendChild(renderAgendaLabel(dateInfo.date, dateInfo.role, metadata.taskStatus === \"done\", !!metadata.recurrence, container));\n }\n\n wrapper.appendChild(indicator);\n\n const el = document.createElement(tag);\n el.classList.add(\"blx-heading\", `blx-heading-${metadata.level}`, \"blx-heading-task\", `blx-heading-task-${metadata.taskStatus}`);\n el.setAttribute(\"contenteditable\", \"true\");\n el.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(el, content);\n\n wrapper.appendChild(el);\n container.appendChild(wrapper);\n container.appendChild(createFoldIndicator(container));\n return el;\n }\n\n // Standard heading without task status\n const dateInfo = resolveDisplayDate(metadata);\n if (dateInfo) {\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-heading-wrapper\");\n wrapper.appendChild(renderAgendaLabel(dateInfo.date, dateInfo.role, false, !!metadata.recurrence, container));\n const el = document.createElement(tag);\n el.classList.add(\"blx-heading\", `blx-heading-${metadata.level}`);\n el.setAttribute(\"contenteditable\", \"true\");\n el.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(el, content);\n wrapper.appendChild(el);\n container.appendChild(wrapper);\n container.appendChild(createFoldIndicator(container));\n return el;\n }\n\n const el = document.createElement(tag);\n el.classList.add(\"blx-heading\", `blx-heading-${metadata.level}`);\n el.setAttribute(\"contenteditable\", \"true\");\n el.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(el, content);\n container.appendChild(el);\n container.appendChild(createFoldIndicator(container));\n return el;\n },\n\n update(container, contentEditable, content, metadata) {\n const currentTag = contentEditable?.tagName.toLowerCase();\n const hasIndicator = !!container.querySelector(\".blx-heading-task-indicator\");\n const needsIndicator = !!metadata.taskStatus;\n\n // Re-render if level changed, indicator presence changed, or wrapper presence\n // changed due to a date being added/removed on a non-task heading\n const hasWrapper = !!container.querySelector(\".blx-heading-wrapper\");\n const needsWrapper = needsIndicator || !!resolveDisplayDate(metadata);\n if (!contentEditable || currentTag !== `h${metadata.level}` || hasIndicator !== needsIndicator || hasWrapper !== needsWrapper) {\n this.render(container, content, metadata);\n return;\n }\n\n // Update indicator status class and data attribute if present\n if (needsIndicator) {\n const indicator = container.querySelector<HTMLButtonElement>(\".blx-heading-task-indicator\");\n if (indicator) {\n indicator.className = `blx-heading-task-indicator blx-task-${metadata.taskStatus}`;\n indicator.setAttribute(\"aria-label\", `Task: ${metadata.taskStatus}`);\n indicator.dataset.taskStatus = metadata.taskStatus;\n }\n contentEditable.className = `blx-heading blx-heading-${metadata.level} blx-heading-task blx-heading-task-${metadata.taskStatus}`;\n }\n\n // Update agenda label\n const existingLabel = container.querySelector(\".blx-agenda-label\");\n const dateInfo = resolveDisplayDate(metadata);\n if (dateInfo) {\n const wrapper = container.querySelector(\".blx-heading-wrapper\");\n if (existingLabel) {\n const display = classifyAgendaDate(dateInfo.date, undefined, dateInfo.role);\n const textEl = existingLabel.querySelector(\".blx-agenda-label-text\");\n if (textEl) {\n // Update text without wiping child elements — set first text node only\n textEl.childNodes.forEach(n => { if (n.nodeType === Node.TEXT_NODE) n.remove(); });\n textEl.insertBefore(document.createTextNode(display.label), textEl.firstChild);\n }\n existingLabel.className = `blx-agenda-label ${agendaStateClass(display.state)}`;\n if (metadata.taskStatus === \"done\") existingLabel.classList.add(\"blx-agenda-done\");\n if (metadata.recurrence) existingLabel.classList.add(\"blx-agenda-recurring\");\n (existingLabel as HTMLElement).dataset.agendaDate = dateInfo.date;\n (existingLabel as HTMLElement).dataset.agendaRole = dateInfo.role;\n // Update recurrence indicator — lives inside label-text so pill covers it\n const existingRecur = existingLabel.querySelector(\".blx-agenda-recurrence\");\n if (metadata.recurrence && !existingRecur && textEl) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n textEl.appendChild(recur);\n } else if (!metadata.recurrence && existingRecur) {\n existingRecur.remove();\n }\n } else if (wrapper) {\n wrapper.insertBefore(\n renderAgendaLabel(dateInfo.date, dateInfo.role, metadata.taskStatus === \"done\", !!metadata.recurrence, container),\n wrapper.firstChild,\n );\n }\n } else if (existingLabel) {\n existingLabel.remove();\n }\n\n contentEditable.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(contentEditable, content);\n },\n\n serializeMetadata(m) {\n const out: Record<string, unknown> = { level: m.level };\n if (m.taskStatus) out.taskStatus = m.taskStatus;\n if (m.dueDate) out.dueDate = m.dueDate;\n if (m.scheduledDate) out.scheduledDate = m.scheduledDate;\n if (m.eventDate) out.eventDate = m.eventDate;\n if (m.recurrence) out.recurrence = m.recurrence;\n if (m.agendaDate) out.agendaDate = m.agendaDate;\n return out;\n },\n\n deserializeMetadata(raw) {\n // Migrate legacy agendaDate → dueDate (headings are tasks)\n if (raw.agendaDate && !raw.dueDate && !raw.scheduledDate && !raw.eventDate) {\n raw.dueDate = raw.agendaDate;\n delete raw.agendaDate;\n }\n\n const level = typeof raw.level === \"number\" ? raw.level : 1;\n const result: HeadingMetadata = {\n level: Math.max(1, Math.min(4, level)) as HeadingMetadata[\"level\"],\n };\n if (raw.taskStatus === \"todo\" || raw.taskStatus === \"in-progress\" || raw.taskStatus === \"done\") {\n result.taskStatus = raw.taskStatus;\n }\n if (typeof raw.dueDate === \"string\") result.dueDate = raw.dueDate;\n if (typeof raw.scheduledDate === \"string\") result.scheduledDate = raw.scheduledDate;\n if (typeof raw.eventDate === \"string\") result.eventDate = raw.eventDate;\n if (raw.recurrence && typeof raw.recurrence === \"object\") {\n result.recurrence = raw.recurrence as HeadingMetadata[\"recurrence\"];\n }\n // Keep agendaDate if it wasn't migrated (i.e., new fields already present)\n if (typeof raw.agendaDate === \"string\") result.agendaDate = raw.agendaDate;\n return result;\n },\n};\n\n/**\n * Resolve the most relevant date from metadata for display.\n * Priority: dueDate > scheduledDate > eventDate > (legacy) agendaDate.\n * Returns the date string and its role, or null if no date is set.\n */\nfunction resolveDisplayDate(metadata: HeadingMetadata): { date: string; role: \"due\" | \"scheduled\" | \"event\" } | null {\n if (metadata.dueDate) return { date: typeof metadata.dueDate === \"string\" ? metadata.dueDate : String(metadata.dueDate), role: \"due\" };\n if (metadata.scheduledDate) return { date: typeof metadata.scheduledDate === \"string\" ? metadata.scheduledDate : String(metadata.scheduledDate), role: \"scheduled\" };\n if (metadata.eventDate) return { date: typeof metadata.eventDate === \"string\" ? metadata.eventDate : String(metadata.eventDate), role: \"event\" };\n // Legacy fallback\n if (metadata.agendaDate) return { date: typeof metadata.agendaDate === \"string\" ? metadata.agendaDate : String(metadata.agendaDate), role: \"due\" };\n return null;\n}\n\n/** Create an agenda label element for task headings (positioned above in margin).\n * Structure: outer span (flex layout) > inner span.blx-agenda-label-text (pill styling). */\nfunction renderAgendaLabel(\n dateStr: string,\n role: \"due\" | \"scheduled\" | \"event\",\n done: boolean,\n recurring: boolean,\n container: HTMLElement,\n): HTMLElement {\n const display = classifyAgendaDate(dateStr, undefined, role);\n const label = document.createElement(\"span\");\n label.classList.add(\"blx-agenda-label\", agendaStateClass(display.state));\n if (done) label.classList.add(\"blx-agenda-done\");\n if (recurring) label.classList.add(\"blx-agenda-recurring\");\n label.setAttribute(\"contenteditable\", \"false\");\n label.dataset.agendaDate = dateStr;\n label.dataset.agendaRole = role;\n\n const text = document.createElement(\"span\");\n text.className = \"blx-agenda-label-text\";\n text.textContent = display.label;\n\n // Recurrence indicator — inside label-text so pill background covers both\n if (recurring) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n text.appendChild(recur);\n }\n\n label.appendChild(text);\n\n // Click to edit agenda item (disabled in read-only mode)\n // Read from dataset so the event reflects any updates made by plugin.update()\n if (!isBlockReadOnly(container)) {\n label.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n container.dispatchEvent(new CustomEvent(\"blx:agendaEdit\", {\n bubbles: true,\n detail: { role: label.dataset.agendaRole ?? role, date: label.dataset.agendaDate ?? dateStr },\n }));\n });\n }\n\n return label;\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { renderAttributedString, getBlockDir, isBlockReadOnly } from \"./render-utils\";\nimport { classifyAgendaDate, agendaStateClass } from \"../date-picker/agenda-utils\";\nimport { iconHtml, Repeat2 } from \"../util/icons\";\n\nexport interface ListMetadata {\n [key: string]: unknown;\n ordered: boolean;\n dueDate?: string; // ISO 8601 date — task deadline\n scheduledDate?: string; // ISO 8601 date — planned start/work date\n eventDate?: string; // ISO 8601 date — calendar event\n recurrence?: {\n interval: number;\n unit: \"day\" | \"week\" | \"month\" | \"year\";\n anchor?: string;\n fromCompletion?: boolean;\n };\n /** @deprecated — migrated to dueDate/scheduledDate/eventDate by deserializeMetadata */\n agendaDate?: string;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n}\n\n/** Unordered list styles cycle: disc → circle → square */\nconst UNORDERED_STYLES = [\"disc\", \"circle\", \"square\"] as const;\n/** Ordered list styles cycle: decimal → lower-alpha → lower-roman */\nconst ORDERED_STYLES = [\"decimal\", \"lower-alpha\", \"lower-roman\"] as const;\n\nfunction applyListStyleByLevel(list: HTMLElement, ordered: boolean, indentLevel: number): void {\n const styles = ordered ? ORDERED_STYLES : UNORDERED_STYLES;\n const style = styles[indentLevel % styles.length];\n list.style.listStyleType = style;\n}\n\nexport const listPlugin: BlockTypePlugin<ListMetadata> = {\n type: \"list\",\n label: \"List\",\n hasTextContent: true,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): ListMetadata {\n return { ordered: false };\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\", shortcutHint: \"Ctrl+Shift+0\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n { type: \"checklist\", label: \"Checklist\", description: \"Checklist with checkboxes\", metadata: { checked: false } },\n { type: \"blockquote\", label: \"Quote\", description: \"Blockquote text\" },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n ];\n },\n\n metadataFromConversion(_fromType: string, fromMetadata: BlockMetadata): ListMetadata {\n const result: ListMetadata = { ordered: false };\n // Preserve date role fields across type conversions\n if (fromMetadata.dueDate !== undefined) result.dueDate = fromMetadata.dueDate as string;\n if (fromMetadata.scheduledDate !== undefined) result.scheduledDate = fromMetadata.scheduledDate as string;\n if (fromMetadata.eventDate !== undefined) result.eventDate = fromMetadata.eventDate as string;\n if (fromMetadata.recurrence !== undefined) result.recurrence = fromMetadata.recurrence as ListMetadata[\"recurrence\"];\n // Keep agendaDate in case conversion happens before migration\n if (fromMetadata.agendaDate !== undefined) result.agendaDate = fromMetadata.agendaDate as string;\n return result;\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n const list = document.createElement(metadata.ordered ? \"ol\" : \"ul\");\n list.classList.add(\"blx-list\", metadata.ordered ? \"blx-list-ordered\" : \"blx-list-unordered\");\n list.setAttribute(\"dir\", getBlockDir(metadata));\n\n // Apply list-style cycling based on indent level\n const indentLevel = typeof metadata.indentLevel === \"number\" ? metadata.indentLevel : 0;\n applyListStyleByLevel(list, metadata.ordered, indentLevel);\n\n const li = document.createElement(\"li\");\n li.setAttribute(\"contenteditable\", \"true\");\n renderAttributedString(li, content);\n list.appendChild(li);\n container.appendChild(list);\n\n // Agenda badge (right-aligned, contenteditable=false)\n const dateInfo = resolveListDisplayDate(metadata);\n if (dateInfo) {\n container.style.display = \"flex\";\n container.style.alignItems = \"baseline\";\n list.style.flex = \"1\";\n container.appendChild(renderListAgendaBadge(dateInfo.date, dateInfo.role, !!metadata.recurrence, container));\n }\n\n return li;\n },\n\n update(container, contentEditable, content, metadata) {\n // If ordered/unordered changed, re-render\n const currentList = container.querySelector(\"ol, ul\");\n if (currentList) {\n const isCurrentlyOrdered = currentList.tagName.toLowerCase() === \"ol\";\n if (isCurrentlyOrdered !== metadata.ordered) {\n this.render(container, content, metadata);\n return;\n }\n // Update list-style for indent level change\n const indentLevel = typeof metadata.indentLevel === \"number\" ? metadata.indentLevel : 0;\n applyListStyleByLevel(currentList as HTMLElement, metadata.ordered, indentLevel);\n (currentList as HTMLElement).setAttribute(\"dir\", getBlockDir(metadata));\n }\n\n // Update agenda badge\n const existingBadge = container.querySelector(\".blx-agenda-badge\");\n const dateInfo = resolveListDisplayDate(metadata);\n if (dateInfo) {\n if (existingBadge) {\n // Update existing badge\n const display = classifyAgendaDate(dateInfo.date, undefined, dateInfo.role);\n existingBadge.textContent = display.label;\n existingBadge.className = `blx-agenda-badge ${agendaStateClass(display.state)}`;\n if (metadata.recurrence) existingBadge.classList.add(\"blx-agenda-recurring\");\n (existingBadge as HTMLElement).dataset.agendaDate = dateInfo.date;\n (existingBadge as HTMLElement).dataset.agendaRole = dateInfo.role;\n // Update recurrence indicator\n const existingRecur = existingBadge.querySelector(\".blx-agenda-recurrence\");\n if (metadata.recurrence && !existingRecur) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n existingBadge.appendChild(recur);\n } else if (!metadata.recurrence && existingRecur) {\n existingRecur.remove();\n }\n } else if (currentList) {\n // Add new badge\n container.style.display = \"flex\";\n container.style.alignItems = \"baseline\";\n (currentList as HTMLElement).style.flex = \"1\";\n container.appendChild(renderListAgendaBadge(dateInfo.date, dateInfo.role, !!metadata.recurrence, container));\n }\n } else if (existingBadge) {\n // Remove badge and reset container styles\n existingBadge.remove();\n container.style.display = \"\";\n container.style.alignItems = \"\";\n if (currentList) {\n (currentList as HTMLElement).style.flex = \"\";\n }\n }\n\n if (contentEditable) {\n renderAttributedString(contentEditable, content);\n }\n },\n\n serializeMetadata(m) {\n const out: Record<string, unknown> = { ordered: m.ordered };\n if (m.dueDate) out.dueDate = m.dueDate;\n if (m.scheduledDate) out.scheduledDate = m.scheduledDate;\n if (m.eventDate) out.eventDate = m.eventDate;\n if (m.recurrence) out.recurrence = m.recurrence;\n if (m.agendaDate) out.agendaDate = m.agendaDate;\n return out;\n },\n\n deserializeMetadata(raw) {\n // Migrate legacy agendaDate → eventDate (lists are non-tasks)\n if (raw.agendaDate && !raw.dueDate && !raw.scheduledDate && !raw.eventDate) {\n raw.eventDate = raw.agendaDate;\n delete raw.agendaDate;\n }\n\n const result: ListMetadata = { ordered: raw.ordered === true };\n if (typeof raw.dueDate === \"string\") result.dueDate = raw.dueDate;\n if (typeof raw.scheduledDate === \"string\") result.scheduledDate = raw.scheduledDate;\n if (typeof raw.eventDate === \"string\") result.eventDate = raw.eventDate;\n if (raw.recurrence && typeof raw.recurrence === \"object\") {\n result.recurrence = raw.recurrence as ListMetadata[\"recurrence\"];\n }\n // Keep agendaDate if it wasn't migrated (i.e., new fields already present)\n if (typeof raw.agendaDate === \"string\") result.agendaDate = raw.agendaDate;\n return result;\n },\n};\n\n/**\n * Resolve the most relevant date from list metadata for display.\n * Priority: dueDate > scheduledDate > eventDate > (legacy) agendaDate.\n */\nfunction resolveListDisplayDate(metadata: ListMetadata): { date: string; role: \"due\" | \"scheduled\" | \"event\" } | null {\n if (metadata.dueDate) return { date: typeof metadata.dueDate === \"string\" ? metadata.dueDate : String(metadata.dueDate), role: \"due\" };\n if (metadata.scheduledDate) return { date: typeof metadata.scheduledDate === \"string\" ? metadata.scheduledDate : String(metadata.scheduledDate), role: \"scheduled\" };\n if (metadata.eventDate) return { date: typeof metadata.eventDate === \"string\" ? metadata.eventDate : String(metadata.eventDate), role: \"event\" };\n // Legacy fallback\n if (metadata.agendaDate) return { date: typeof metadata.agendaDate === \"string\" ? metadata.agendaDate : String(metadata.agendaDate), role: \"event\" };\n return null;\n}\n\n/** Create an agenda badge element for list blocks. */\nfunction renderListAgendaBadge(\n dateStr: string,\n role: \"due\" | \"scheduled\" | \"event\",\n recurring: boolean,\n container: HTMLElement,\n): HTMLElement {\n const display = classifyAgendaDate(dateStr, undefined, role);\n const badge = document.createElement(\"span\");\n badge.classList.add(\"blx-agenda-badge\", agendaStateClass(display.state));\n if (recurring) badge.classList.add(\"blx-agenda-recurring\");\n badge.setAttribute(\"contenteditable\", \"false\");\n badge.dataset.agendaDate = dateStr;\n badge.dataset.agendaRole = role;\n badge.textContent = display.label;\n\n // Recurrence indicator\n if (recurring) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n badge.appendChild(recur);\n }\n\n // Click to edit agenda item (disabled in read-only mode)\n if (!isBlockReadOnly(container)) {\n badge.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n container.dispatchEvent(new CustomEvent(\"blx:agendaEdit\", {\n bubbles: true,\n detail: { role, date: dateStr },\n }));\n });\n }\n\n return badge;\n}\n","\n/* **********************************************\n Begin prism-core.js\n********************************************** */\n\n/// <reference lib=\"WebWorker\"/>\n\nvar _self = (typeof window !== 'undefined')\n\t? window // if in browser\n\t: (\n\t\t(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)\n\t\t\t? self // if in worker\n\t\t\t: {} // if in node js\n\t);\n\n/**\n * Prism: Lightweight, robust, elegant syntax highlighting\n *\n * @license MIT <https://opensource.org/licenses/MIT>\n * @author Lea Verou <https://lea.verou.me>\n * @namespace\n * @public\n */\nvar Prism = (function (_self) {\n\n\t// Private helper vars\n\tvar lang = /(?:^|\\s)lang(?:uage)?-([\\w-]+)(?=\\s|$)/i;\n\tvar uniqueId = 0;\n\n\t// The grammar object for plaintext\n\tvar plainTextGrammar = {};\n\n\n\tvar _ = {\n\t\t/**\n\t\t * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the\n\t\t * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load\n\t\t * additional languages or plugins yourself.\n\t\t *\n\t\t * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.\n\t\t *\n\t\t * You obviously have to change this value before the automatic highlighting started. To do this, you can add an\n\t\t * empty Prism object into the global scope before loading the Prism script like this:\n\t\t *\n\t\t * ```js\n\t\t * window.Prism = window.Prism || {};\n\t\t * Prism.manual = true;\n\t\t * // add a new <script> to load Prism's script\n\t\t * ```\n\t\t *\n\t\t * @default false\n\t\t * @type {boolean}\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\tmanual: _self.Prism && _self.Prism.manual,\n\t\t/**\n\t\t * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses\n\t\t * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your\n\t\t * own worker, you don't want it to do this.\n\t\t *\n\t\t * By setting this value to `true`, Prism will not add its own listeners to the worker.\n\t\t *\n\t\t * You obviously have to change this value before Prism executes. To do this, you can add an\n\t\t * empty Prism object into the global scope before loading the Prism script like this:\n\t\t *\n\t\t * ```js\n\t\t * window.Prism = window.Prism || {};\n\t\t * Prism.disableWorkerMessageHandler = true;\n\t\t * // Load Prism's script\n\t\t * ```\n\t\t *\n\t\t * @default false\n\t\t * @type {boolean}\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\tdisableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,\n\n\t\t/**\n\t\t * A namespace for utility methods.\n\t\t *\n\t\t * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may\n\t\t * change or disappear at any time.\n\t\t *\n\t\t * @namespace\n\t\t * @memberof Prism\n\t\t */\n\t\tutil: {\n\t\t\tencode: function encode(tokens) {\n\t\t\t\tif (tokens instanceof Token) {\n\t\t\t\t\treturn new Token(tokens.type, encode(tokens.content), tokens.alias);\n\t\t\t\t} else if (Array.isArray(tokens)) {\n\t\t\t\t\treturn tokens.map(encode);\n\t\t\t\t} else {\n\t\t\t\t\treturn tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\\u00a0/g, ' ');\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the name of the type of the given value.\n\t\t\t *\n\t\t\t * @param {any} o\n\t\t\t * @returns {string}\n\t\t\t * @example\n\t\t\t * type(null) === 'Null'\n\t\t\t * type(undefined) === 'Undefined'\n\t\t\t * type(123) === 'Number'\n\t\t\t * type('foo') === 'String'\n\t\t\t * type(true) === 'Boolean'\n\t\t\t * type([1, 2]) === 'Array'\n\t\t\t * type({}) === 'Object'\n\t\t\t * type(String) === 'Function'\n\t\t\t * type(/abc+/) === 'RegExp'\n\t\t\t */\n\t\t\ttype: function (o) {\n\t\t\t\treturn Object.prototype.toString.call(o).slice(8, -1);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns a unique number for the given object. Later calls will still return the same number.\n\t\t\t *\n\t\t\t * @param {Object} obj\n\t\t\t * @returns {number}\n\t\t\t */\n\t\t\tobjId: function (obj) {\n\t\t\t\tif (!obj['__id']) {\n\t\t\t\t\tObject.defineProperty(obj, '__id', { value: ++uniqueId });\n\t\t\t\t}\n\t\t\t\treturn obj['__id'];\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Creates a deep clone of the given object.\n\t\t\t *\n\t\t\t * The main intended use of this function is to clone language definitions.\n\t\t\t *\n\t\t\t * @param {T} o\n\t\t\t * @param {Record<number, any>} [visited]\n\t\t\t * @returns {T}\n\t\t\t * @template T\n\t\t\t */\n\t\t\tclone: function deepClone(o, visited) {\n\t\t\t\tvisited = visited || {};\n\n\t\t\t\tvar clone; var id;\n\t\t\t\tswitch (_.util.type(o)) {\n\t\t\t\t\tcase 'Object':\n\t\t\t\t\t\tid = _.util.objId(o);\n\t\t\t\t\t\tif (visited[id]) {\n\t\t\t\t\t\t\treturn visited[id];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tclone = /** @type {Record<string, any>} */ ({});\n\t\t\t\t\t\tvisited[id] = clone;\n\n\t\t\t\t\t\tfor (var key in o) {\n\t\t\t\t\t\t\tif (o.hasOwnProperty(key)) {\n\t\t\t\t\t\t\t\tclone[key] = deepClone(o[key], visited);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn /** @type {any} */ (clone);\n\n\t\t\t\t\tcase 'Array':\n\t\t\t\t\t\tid = _.util.objId(o);\n\t\t\t\t\t\tif (visited[id]) {\n\t\t\t\t\t\t\treturn visited[id];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t\tvisited[id] = clone;\n\n\t\t\t\t\t\t(/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) {\n\t\t\t\t\t\t\tclone[i] = deepClone(v, visited);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn /** @type {any} */ (clone);\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn o;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.\n\t\t\t *\n\t\t\t * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.\n\t\t\t *\n\t\t\t * @param {Element} element\n\t\t\t * @returns {string}\n\t\t\t */\n\t\t\tgetLanguage: function (element) {\n\t\t\t\twhile (element) {\n\t\t\t\t\tvar m = lang.exec(element.className);\n\t\t\t\t\tif (m) {\n\t\t\t\t\t\treturn m[1].toLowerCase();\n\t\t\t\t\t}\n\t\t\t\t\telement = element.parentElement;\n\t\t\t\t}\n\t\t\t\treturn 'none';\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Sets the Prism `language-xxxx` class of the given element.\n\t\t\t *\n\t\t\t * @param {Element} element\n\t\t\t * @param {string} language\n\t\t\t * @returns {void}\n\t\t\t */\n\t\t\tsetLanguage: function (element, language) {\n\t\t\t\t// remove all `language-xxxx` classes\n\t\t\t\t// (this might leave behind a leading space)\n\t\t\t\telement.className = element.className.replace(RegExp(lang, 'gi'), '');\n\n\t\t\t\t// add the new `language-xxxx` class\n\t\t\t\t// (using `classList` will automatically clean up spaces for us)\n\t\t\t\telement.classList.add('language-' + language);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the script element that is currently executing.\n\t\t\t *\n\t\t\t * This does __not__ work for line script element.\n\t\t\t *\n\t\t\t * @returns {HTMLScriptElement | null}\n\t\t\t */\n\t\t\tcurrentScript: function () {\n\t\t\t\tif (typeof document === 'undefined') {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tif (document.currentScript && document.currentScript.tagName === 'SCRIPT' && 1 < 2 /* hack to trip TS' flow analysis */) {\n\t\t\t\t\treturn /** @type {any} */ (document.currentScript);\n\t\t\t\t}\n\n\t\t\t\t// IE11 workaround\n\t\t\t\t// we'll get the src of the current script by parsing IE11's error stack trace\n\t\t\t\t// this will not work for inline scripts\n\n\t\t\t\ttry {\n\t\t\t\t\tthrow new Error();\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// Get file src url from stack. Specifically works with the format of stack traces in IE.\n\t\t\t\t\t// A stack will look like this:\n\t\t\t\t\t//\n\t\t\t\t\t// Error\n\t\t\t\t\t// at _.util.currentScript (http://localhost/components/prism-core.js:119:5)\n\t\t\t\t\t// at Global code (http://localhost/components/prism-core.js:606:1)\n\n\t\t\t\t\tvar src = (/at [^(\\r\\n]*\\((.*):[^:]+:[^:]+\\)$/i.exec(err.stack) || [])[1];\n\t\t\t\t\tif (src) {\n\t\t\t\t\t\tvar scripts = document.getElementsByTagName('script');\n\t\t\t\t\t\tfor (var i in scripts) {\n\t\t\t\t\t\t\tif (scripts[i].src == src) {\n\t\t\t\t\t\t\t\treturn scripts[i];\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\treturn null;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns whether a given class is active for `element`.\n\t\t\t *\n\t\t\t * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated\n\t\t\t * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the\n\t\t\t * given class is just the given class with a `no-` prefix.\n\t\t\t *\n\t\t\t * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is\n\t\t\t * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its\n\t\t\t * ancestors have the given class or the negated version of it, then the default activation will be returned.\n\t\t\t *\n\t\t\t * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated\n\t\t\t * version of it, the class is considered active.\n\t\t\t *\n\t\t\t * @param {Element} element\n\t\t\t * @param {string} className\n\t\t\t * @param {boolean} [defaultActivation=false]\n\t\t\t * @returns {boolean}\n\t\t\t */\n\t\t\tisActive: function (element, className, defaultActivation) {\n\t\t\t\tvar no = 'no-' + className;\n\n\t\t\t\twhile (element) {\n\t\t\t\t\tvar classList = element.classList;\n\t\t\t\t\tif (classList.contains(className)) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tif (classList.contains(no)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\telement = element.parentElement;\n\t\t\t\t}\n\t\t\t\treturn !!defaultActivation;\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.\n\t\t *\n\t\t * @namespace\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\tlanguages: {\n\t\t\t/**\n\t\t\t * The grammar for plain, unformatted text.\n\t\t\t */\n\t\t\tplain: plainTextGrammar,\n\t\t\tplaintext: plainTextGrammar,\n\t\t\ttext: plainTextGrammar,\n\t\t\ttxt: plainTextGrammar,\n\n\t\t\t/**\n\t\t\t * Creates a deep copy of the language with the given id and appends the given tokens.\n\t\t\t *\n\t\t\t * If a token in `redef` also appears in the copied language, then the existing token in the copied language\n\t\t\t * will be overwritten at its original position.\n\t\t\t *\n\t\t\t * ## Best practices\n\t\t\t *\n\t\t\t * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)\n\t\t\t * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to\n\t\t\t * understand the language definition because, normally, the order of tokens matters in Prism grammars.\n\t\t\t *\n\t\t\t * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.\n\t\t\t * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.\n\t\t\t *\n\t\t\t * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.\n\t\t\t * @param {Grammar} redef The new tokens to append.\n\t\t\t * @returns {Grammar} The new language created.\n\t\t\t * @public\n\t\t\t * @example\n\t\t\t * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {\n\t\t\t * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token\n\t\t\t * // at its original position\n\t\t\t * 'comment': { ... },\n\t\t\t * // CSS doesn't have a 'color' token, so this token will be appended\n\t\t\t * 'color': /\\b(?:red|green|blue)\\b/\n\t\t\t * });\n\t\t\t */\n\t\t\textend: function (id, redef) {\n\t\t\t\tvar lang = _.util.clone(_.languages[id]);\n\n\t\t\t\tfor (var key in redef) {\n\t\t\t\t\tlang[key] = redef[key];\n\t\t\t\t}\n\n\t\t\t\treturn lang;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Inserts tokens _before_ another token in a language definition or any other grammar.\n\t\t\t *\n\t\t\t * ## Usage\n\t\t\t *\n\t\t\t * This helper method makes it easy to modify existing languages. For example, the CSS language definition\n\t\t\t * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded\n\t\t\t * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the\n\t\t\t * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do\n\t\t\t * this:\n\t\t\t *\n\t\t\t * ```js\n\t\t\t * Prism.languages.markup.style = {\n\t\t\t * // token\n\t\t\t * };\n\t\t\t * ```\n\t\t\t *\n\t\t\t * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens\n\t\t\t * before existing tokens. For the CSS example above, you would use it like this:\n\t\t\t *\n\t\t\t * ```js\n\t\t\t * Prism.languages.insertBefore('markup', 'cdata', {\n\t\t\t * 'style': {\n\t\t\t * // token\n\t\t\t * }\n\t\t\t * });\n\t\t\t * ```\n\t\t\t *\n\t\t\t * ## Special cases\n\t\t\t *\n\t\t\t * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar\n\t\t\t * will be ignored.\n\t\t\t *\n\t\t\t * This behavior can be used to insert tokens after `before`:\n\t\t\t *\n\t\t\t * ```js\n\t\t\t * Prism.languages.insertBefore('markup', 'comment', {\n\t\t\t * 'comment': Prism.languages.markup.comment,\n\t\t\t * // tokens after 'comment'\n\t\t\t * });\n\t\t\t * ```\n\t\t\t *\n\t\t\t * ## Limitations\n\t\t\t *\n\t\t\t * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object\n\t\t\t * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave\n\t\t\t * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily\n\t\t\t * deleting properties which is necessary to insert at arbitrary positions.\n\t\t\t *\n\t\t\t * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.\n\t\t\t * Instead, it will create a new object and replace all references to the target object with the new one. This\n\t\t\t * can be done without temporarily deleting properties, so the iteration order is well-defined.\n\t\t\t *\n\t\t\t * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if\n\t\t\t * you hold the target object in a variable, then the value of the variable will not change.\n\t\t\t *\n\t\t\t * ```js\n\t\t\t * var oldMarkup = Prism.languages.markup;\n\t\t\t * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });\n\t\t\t *\n\t\t\t * assert(oldMarkup !== Prism.languages.markup);\n\t\t\t * assert(newMarkup === Prism.languages.markup);\n\t\t\t * ```\n\t\t\t *\n\t\t\t * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the\n\t\t\t * object to be modified.\n\t\t\t * @param {string} before The key to insert before.\n\t\t\t * @param {Grammar} insert An object containing the key-value pairs to be inserted.\n\t\t\t * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the\n\t\t\t * object to be modified.\n\t\t\t *\n\t\t\t * Defaults to `Prism.languages`.\n\t\t\t * @returns {Grammar} The new grammar object.\n\t\t\t * @public\n\t\t\t */\n\t\t\tinsertBefore: function (inside, before, insert, root) {\n\t\t\t\troot = root || /** @type {any} */ (_.languages);\n\t\t\t\tvar grammar = root[inside];\n\t\t\t\t/** @type {Grammar} */\n\t\t\t\tvar ret = {};\n\n\t\t\t\tfor (var token in grammar) {\n\t\t\t\t\tif (grammar.hasOwnProperty(token)) {\n\n\t\t\t\t\t\tif (token == before) {\n\t\t\t\t\t\t\tfor (var newToken in insert) {\n\t\t\t\t\t\t\t\tif (insert.hasOwnProperty(newToken)) {\n\t\t\t\t\t\t\t\t\tret[newToken] = insert[newToken];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Do not insert token which also occur in insert. See #1525\n\t\t\t\t\t\tif (!insert.hasOwnProperty(token)) {\n\t\t\t\t\t\t\tret[token] = grammar[token];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar old = root[inside];\n\t\t\t\troot[inside] = ret;\n\n\t\t\t\t// Update references in other language definitions\n\t\t\t\t_.languages.DFS(_.languages, function (key, value) {\n\t\t\t\t\tif (value === old && key != inside) {\n\t\t\t\t\t\tthis[key] = ret;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn ret;\n\t\t\t},\n\n\t\t\t// Traverse a language definition with Depth First Search\n\t\t\tDFS: function DFS(o, callback, type, visited) {\n\t\t\t\tvisited = visited || {};\n\n\t\t\t\tvar objId = _.util.objId;\n\n\t\t\t\tfor (var i in o) {\n\t\t\t\t\tif (o.hasOwnProperty(i)) {\n\t\t\t\t\t\tcallback.call(o, i, o[i], type || i);\n\n\t\t\t\t\t\tvar property = o[i];\n\t\t\t\t\t\tvar propertyType = _.util.type(property);\n\n\t\t\t\t\t\tif (propertyType === 'Object' && !visited[objId(property)]) {\n\t\t\t\t\t\t\tvisited[objId(property)] = true;\n\t\t\t\t\t\t\tDFS(property, callback, null, visited);\n\t\t\t\t\t\t} else if (propertyType === 'Array' && !visited[objId(property)]) {\n\t\t\t\t\t\t\tvisited[objId(property)] = true;\n\t\t\t\t\t\t\tDFS(property, callback, i, visited);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tplugins: {},\n\n\t\t/**\n\t\t * This is the most high-level function in Prism’s API.\n\t\t * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on\n\t\t * each one of them.\n\t\t *\n\t\t * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.\n\t\t *\n\t\t * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.\n\t\t * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\thighlightAll: function (async, callback) {\n\t\t\t_.highlightAllUnder(document, async, callback);\n\t\t},\n\n\t\t/**\n\t\t * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls\n\t\t * {@link Prism.highlightElement} on each one of them.\n\t\t *\n\t\t * The following hooks will be run:\n\t\t * 1. `before-highlightall`\n\t\t * 2. `before-all-elements-highlight`\n\t\t * 3. All hooks of {@link Prism.highlightElement} for each element.\n\t\t *\n\t\t * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.\n\t\t * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.\n\t\t * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\thighlightAllUnder: function (container, async, callback) {\n\t\t\tvar env = {\n\t\t\t\tcallback: callback,\n\t\t\t\tcontainer: container,\n\t\t\t\tselector: 'code[class*=\"language-\"], [class*=\"language-\"] code, code[class*=\"lang-\"], [class*=\"lang-\"] code'\n\t\t\t};\n\n\t\t\t_.hooks.run('before-highlightall', env);\n\n\t\t\tenv.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));\n\n\t\t\t_.hooks.run('before-all-elements-highlight', env);\n\n\t\t\tfor (var i = 0, element; (element = env.elements[i++]);) {\n\t\t\t\t_.highlightElement(element, async === true, env.callback);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Highlights the code inside a single element.\n\t\t *\n\t\t * The following hooks will be run:\n\t\t * 1. `before-sanity-check`\n\t\t * 2. `before-highlight`\n\t\t * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.\n\t\t * 4. `before-insert`\n\t\t * 5. `after-highlight`\n\t\t * 6. `complete`\n\t\t *\n\t\t * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for\n\t\t * the element's language.\n\t\t *\n\t\t * @param {Element} element The element containing the code.\n\t\t * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.\n\t\t * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers\n\t\t * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is\n\t\t * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).\n\t\t *\n\t\t * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for\n\t\t * asynchronous highlighting to work. You can build your own bundle on the\n\t\t * [Download page](https://prismjs.com/download.html).\n\t\t * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.\n\t\t * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\thighlightElement: function (element, async, callback) {\n\t\t\t// Find language\n\t\t\tvar language = _.util.getLanguage(element);\n\t\t\tvar grammar = _.languages[language];\n\n\t\t\t// Set language on the element, if not present\n\t\t\t_.util.setLanguage(element, language);\n\n\t\t\t// Set language on the parent, for styling\n\t\t\tvar parent = element.parentElement;\n\t\t\tif (parent && parent.nodeName.toLowerCase() === 'pre') {\n\t\t\t\t_.util.setLanguage(parent, language);\n\t\t\t}\n\n\t\t\tvar code = element.textContent;\n\n\t\t\tvar env = {\n\t\t\t\telement: element,\n\t\t\t\tlanguage: language,\n\t\t\t\tgrammar: grammar,\n\t\t\t\tcode: code\n\t\t\t};\n\n\t\t\tfunction insertHighlightedCode(highlightedCode) {\n\t\t\t\tenv.highlightedCode = highlightedCode;\n\n\t\t\t\t_.hooks.run('before-insert', env);\n\n\t\t\t\tenv.element.innerHTML = env.highlightedCode;\n\n\t\t\t\t_.hooks.run('after-highlight', env);\n\t\t\t\t_.hooks.run('complete', env);\n\t\t\t\tcallback && callback.call(env.element);\n\t\t\t}\n\n\t\t\t_.hooks.run('before-sanity-check', env);\n\n\t\t\t// plugins may change/add the parent/element\n\t\t\tparent = env.element.parentElement;\n\t\t\tif (parent && parent.nodeName.toLowerCase() === 'pre' && !parent.hasAttribute('tabindex')) {\n\t\t\t\tparent.setAttribute('tabindex', '0');\n\t\t\t}\n\n\t\t\tif (!env.code) {\n\t\t\t\t_.hooks.run('complete', env);\n\t\t\t\tcallback && callback.call(env.element);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_.hooks.run('before-highlight', env);\n\n\t\t\tif (!env.grammar) {\n\t\t\t\tinsertHighlightedCode(_.util.encode(env.code));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (async && _self.Worker) {\n\t\t\t\tvar worker = new Worker(_.filename);\n\n\t\t\t\tworker.onmessage = function (evt) {\n\t\t\t\t\tinsertHighlightedCode(evt.data);\n\t\t\t\t};\n\n\t\t\t\tworker.postMessage(JSON.stringify({\n\t\t\t\t\tlanguage: env.language,\n\t\t\t\t\tcode: env.code,\n\t\t\t\t\timmediateClose: true\n\t\t\t\t}));\n\t\t\t} else {\n\t\t\t\tinsertHighlightedCode(_.highlight(env.code, env.grammar, env.language));\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Low-level function, only use if you know what you’re doing. It accepts a string of text as input\n\t\t * and the language definitions to use, and returns a string with the HTML produced.\n\t\t *\n\t\t * The following hooks will be run:\n\t\t * 1. `before-tokenize`\n\t\t * 2. `after-tokenize`\n\t\t * 3. `wrap`: On each {@link Token}.\n\t\t *\n\t\t * @param {string} text A string with the code to be highlighted.\n\t\t * @param {Grammar} grammar An object containing the tokens to use.\n\t\t *\n\t\t * Usually a language definition like `Prism.languages.markup`.\n\t\t * @param {string} language The name of the language definition passed to `grammar`.\n\t\t * @returns {string} The highlighted HTML.\n\t\t * @memberof Prism\n\t\t * @public\n\t\t * @example\n\t\t * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');\n\t\t */\n\t\thighlight: function (text, grammar, language) {\n\t\t\tvar env = {\n\t\t\t\tcode: text,\n\t\t\t\tgrammar: grammar,\n\t\t\t\tlanguage: language\n\t\t\t};\n\t\t\t_.hooks.run('before-tokenize', env);\n\t\t\tif (!env.grammar) {\n\t\t\t\tthrow new Error('The language \"' + env.language + '\" has no grammar.');\n\t\t\t}\n\t\t\tenv.tokens = _.tokenize(env.code, env.grammar);\n\t\t\t_.hooks.run('after-tokenize', env);\n\t\t\treturn Token.stringify(_.util.encode(env.tokens), env.language);\n\t\t},\n\n\t\t/**\n\t\t * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input\n\t\t * and the language definitions to use, and returns an array with the tokenized code.\n\t\t *\n\t\t * When the language definition includes nested tokens, the function is called recursively on each of these tokens.\n\t\t *\n\t\t * This method could be useful in other contexts as well, as a very crude parser.\n\t\t *\n\t\t * @param {string} text A string with the code to be highlighted.\n\t\t * @param {Grammar} grammar An object containing the tokens to use.\n\t\t *\n\t\t * Usually a language definition like `Prism.languages.markup`.\n\t\t * @returns {TokenStream} An array of strings and tokens, a token stream.\n\t\t * @memberof Prism\n\t\t * @public\n\t\t * @example\n\t\t * let code = `var foo = 0;`;\n\t\t * let tokens = Prism.tokenize(code, Prism.languages.javascript);\n\t\t * tokens.forEach(token => {\n\t\t * if (token instanceof Prism.Token && token.type === 'number') {\n\t\t * console.log(`Found numeric literal: ${token.content}`);\n\t\t * }\n\t\t * });\n\t\t */\n\t\ttokenize: function (text, grammar) {\n\t\t\tvar rest = grammar.rest;\n\t\t\tif (rest) {\n\t\t\t\tfor (var token in rest) {\n\t\t\t\t\tgrammar[token] = rest[token];\n\t\t\t\t}\n\n\t\t\t\tdelete grammar.rest;\n\t\t\t}\n\n\t\t\tvar tokenList = new LinkedList();\n\t\t\taddAfter(tokenList, tokenList.head, text);\n\n\t\t\tmatchGrammar(text, tokenList, grammar, tokenList.head, 0);\n\n\t\t\treturn toArray(tokenList);\n\t\t},\n\n\t\t/**\n\t\t * @namespace\n\t\t * @memberof Prism\n\t\t * @public\n\t\t */\n\t\thooks: {\n\t\t\tall: {},\n\n\t\t\t/**\n\t\t\t * Adds the given callback to the list of callbacks for the given hook.\n\t\t\t *\n\t\t\t * The callback will be invoked when the hook it is registered for is run.\n\t\t\t * Hooks are usually directly run by a highlight function but you can also run hooks yourself.\n\t\t\t *\n\t\t\t * One callback function can be registered to multiple hooks and the same hook multiple times.\n\t\t\t *\n\t\t\t * @param {string} name The name of the hook.\n\t\t\t * @param {HookCallback} callback The callback function which is given environment variables.\n\t\t\t * @public\n\t\t\t */\n\t\t\tadd: function (name, callback) {\n\t\t\t\tvar hooks = _.hooks.all;\n\n\t\t\t\thooks[name] = hooks[name] || [];\n\n\t\t\t\thooks[name].push(callback);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Runs a hook invoking all registered callbacks with the given environment variables.\n\t\t\t *\n\t\t\t * Callbacks will be invoked synchronously and in the order in which they were registered.\n\t\t\t *\n\t\t\t * @param {string} name The name of the hook.\n\t\t\t * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.\n\t\t\t * @public\n\t\t\t */\n\t\t\trun: function (name, env) {\n\t\t\t\tvar callbacks = _.hooks.all[name];\n\n\t\t\t\tif (!callbacks || !callbacks.length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (var i = 0, callback; (callback = callbacks[i++]);) {\n\t\t\t\t\tcallback(env);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tToken: Token\n\t};\n\t_self.Prism = _;\n\n\n\t// Typescript note:\n\t// The following can be used to import the Token type in JSDoc:\n\t//\n\t// @typedef {InstanceType<import(\"./prism-core\")[\"Token\"]>} Token\n\n\t/**\n\t * Creates a new token.\n\t *\n\t * @param {string} type See {@link Token#type type}\n\t * @param {string | TokenStream} content See {@link Token#content content}\n\t * @param {string|string[]} [alias] The alias(es) of the token.\n\t * @param {string} [matchedStr=\"\"] A copy of the full string this token was created from.\n\t * @class\n\t * @global\n\t * @public\n\t */\n\tfunction Token(type, content, alias, matchedStr) {\n\t\t/**\n\t\t * The type of the token.\n\t\t *\n\t\t * This is usually the key of a pattern in a {@link Grammar}.\n\t\t *\n\t\t * @type {string}\n\t\t * @see GrammarToken\n\t\t * @public\n\t\t */\n\t\tthis.type = type;\n\t\t/**\n\t\t * The strings or tokens contained by this token.\n\t\t *\n\t\t * This will be a token stream if the pattern matched also defined an `inside` grammar.\n\t\t *\n\t\t * @type {string | TokenStream}\n\t\t * @public\n\t\t */\n\t\tthis.content = content;\n\t\t/**\n\t\t * The alias(es) of the token.\n\t\t *\n\t\t * @type {string|string[]}\n\t\t * @see GrammarToken\n\t\t * @public\n\t\t */\n\t\tthis.alias = alias;\n\t\t// Copy of the full string this token was created from\n\t\tthis.length = (matchedStr || '').length | 0;\n\t}\n\n\t/**\n\t * A token stream is an array of strings and {@link Token Token} objects.\n\t *\n\t * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process\n\t * them.\n\t *\n\t * 1. No adjacent strings.\n\t * 2. No empty strings.\n\t *\n\t * The only exception here is the token stream that only contains the empty string and nothing else.\n\t *\n\t * @typedef {Array<string | Token>} TokenStream\n\t * @global\n\t * @public\n\t */\n\n\t/**\n\t * Converts the given token or token stream to an HTML representation.\n\t *\n\t * The following hooks will be run:\n\t * 1. `wrap`: On each {@link Token}.\n\t *\n\t * @param {string | Token | TokenStream} o The token or token stream to be converted.\n\t * @param {string} language The name of current language.\n\t * @returns {string} The HTML representation of the token or token stream.\n\t * @memberof Token\n\t * @static\n\t */\n\tToken.stringify = function stringify(o, language) {\n\t\tif (typeof o == 'string') {\n\t\t\treturn o;\n\t\t}\n\t\tif (Array.isArray(o)) {\n\t\t\tvar s = '';\n\t\t\to.forEach(function (e) {\n\t\t\t\ts += stringify(e, language);\n\t\t\t});\n\t\t\treturn s;\n\t\t}\n\n\t\tvar env = {\n\t\t\ttype: o.type,\n\t\t\tcontent: stringify(o.content, language),\n\t\t\ttag: 'span',\n\t\t\tclasses: ['token', o.type],\n\t\t\tattributes: {},\n\t\t\tlanguage: language\n\t\t};\n\n\t\tvar aliases = o.alias;\n\t\tif (aliases) {\n\t\t\tif (Array.isArray(aliases)) {\n\t\t\t\tArray.prototype.push.apply(env.classes, aliases);\n\t\t\t} else {\n\t\t\t\tenv.classes.push(aliases);\n\t\t\t}\n\t\t}\n\n\t\t_.hooks.run('wrap', env);\n\n\t\tvar attributes = '';\n\t\tfor (var name in env.attributes) {\n\t\t\tattributes += ' ' + name + '=\"' + (env.attributes[name] || '').replace(/\"/g, '"') + '\"';\n\t\t}\n\n\t\treturn '<' + env.tag + ' class=\"' + env.classes.join(' ') + '\"' + attributes + '>' + env.content + '</' + env.tag + '>';\n\t};\n\n\t/**\n\t * @param {RegExp} pattern\n\t * @param {number} pos\n\t * @param {string} text\n\t * @param {boolean} lookbehind\n\t * @returns {RegExpExecArray | null}\n\t */\n\tfunction matchPattern(pattern, pos, text, lookbehind) {\n\t\tpattern.lastIndex = pos;\n\t\tvar match = pattern.exec(text);\n\t\tif (match && lookbehind && match[1]) {\n\t\t\t// change the match to remove the text matched by the Prism lookbehind group\n\t\t\tvar lookbehindLength = match[1].length;\n\t\t\tmatch.index += lookbehindLength;\n\t\t\tmatch[0] = match[0].slice(lookbehindLength);\n\t\t}\n\t\treturn match;\n\t}\n\n\t/**\n\t * @param {string} text\n\t * @param {LinkedList<string | Token>} tokenList\n\t * @param {any} grammar\n\t * @param {LinkedListNode<string | Token>} startNode\n\t * @param {number} startPos\n\t * @param {RematchOptions} [rematch]\n\t * @returns {void}\n\t * @private\n\t *\n\t * @typedef RematchOptions\n\t * @property {string} cause\n\t * @property {number} reach\n\t */\n\tfunction matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) {\n\t\tfor (var token in grammar) {\n\t\t\tif (!grammar.hasOwnProperty(token) || !grammar[token]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar patterns = grammar[token];\n\t\t\tpatterns = Array.isArray(patterns) ? patterns : [patterns];\n\n\t\t\tfor (var j = 0; j < patterns.length; ++j) {\n\t\t\t\tif (rematch && rematch.cause == token + ',' + j) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar patternObj = patterns[j];\n\t\t\t\tvar inside = patternObj.inside;\n\t\t\t\tvar lookbehind = !!patternObj.lookbehind;\n\t\t\t\tvar greedy = !!patternObj.greedy;\n\t\t\t\tvar alias = patternObj.alias;\n\n\t\t\t\tif (greedy && !patternObj.pattern.global) {\n\t\t\t\t\t// Without the global flag, lastIndex won't work\n\t\t\t\t\tvar flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];\n\t\t\t\t\tpatternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g');\n\t\t\t\t}\n\n\t\t\t\t/** @type {RegExp} */\n\t\t\t\tvar pattern = patternObj.pattern || patternObj;\n\n\t\t\t\tfor ( // iterate the token list and keep track of the current token/string position\n\t\t\t\t\tvar currentNode = startNode.next, pos = startPos;\n\t\t\t\t\tcurrentNode !== tokenList.tail;\n\t\t\t\t\tpos += currentNode.value.length, currentNode = currentNode.next\n\t\t\t\t) {\n\n\t\t\t\t\tif (rematch && pos >= rematch.reach) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar str = currentNode.value;\n\n\t\t\t\t\tif (tokenList.length > text.length) {\n\t\t\t\t\t\t// Something went terribly wrong, ABORT, ABORT!\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (str instanceof Token) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar removeCount = 1; // this is the to parameter of removeBetween\n\t\t\t\t\tvar match;\n\n\t\t\t\t\tif (greedy) {\n\t\t\t\t\t\tmatch = matchPattern(pattern, pos, text, lookbehind);\n\t\t\t\t\t\tif (!match || match.index >= text.length) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar from = match.index;\n\t\t\t\t\t\tvar to = match.index + match[0].length;\n\t\t\t\t\t\tvar p = pos;\n\n\t\t\t\t\t\t// find the node that contains the match\n\t\t\t\t\t\tp += currentNode.value.length;\n\t\t\t\t\t\twhile (from >= p) {\n\t\t\t\t\t\t\tcurrentNode = currentNode.next;\n\t\t\t\t\t\t\tp += currentNode.value.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// adjust pos (and p)\n\t\t\t\t\t\tp -= currentNode.value.length;\n\t\t\t\t\t\tpos = p;\n\n\t\t\t\t\t\t// the current node is a Token, then the match starts inside another Token, which is invalid\n\t\t\t\t\t\tif (currentNode.value instanceof Token) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// find the last node which is affected by this match\n\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\tvar k = currentNode;\n\t\t\t\t\t\t\tk !== tokenList.tail && (p < to || typeof k.value === 'string');\n\t\t\t\t\t\t\tk = k.next\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tremoveCount++;\n\t\t\t\t\t\t\tp += k.value.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tremoveCount--;\n\n\t\t\t\t\t\t// replace with the new match\n\t\t\t\t\t\tstr = text.slice(pos, p);\n\t\t\t\t\t\tmatch.index -= pos;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmatch = matchPattern(pattern, 0, str, lookbehind);\n\t\t\t\t\t\tif (!match) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// eslint-disable-next-line no-redeclare\n\t\t\t\t\tvar from = match.index;\n\t\t\t\t\tvar matchStr = match[0];\n\t\t\t\t\tvar before = str.slice(0, from);\n\t\t\t\t\tvar after = str.slice(from + matchStr.length);\n\n\t\t\t\t\tvar reach = pos + str.length;\n\t\t\t\t\tif (rematch && reach > rematch.reach) {\n\t\t\t\t\t\trematch.reach = reach;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar removeFrom = currentNode.prev;\n\n\t\t\t\t\tif (before) {\n\t\t\t\t\t\tremoveFrom = addAfter(tokenList, removeFrom, before);\n\t\t\t\t\t\tpos += before.length;\n\t\t\t\t\t}\n\n\t\t\t\t\tremoveRange(tokenList, removeFrom, removeCount);\n\n\t\t\t\t\tvar wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr);\n\t\t\t\t\tcurrentNode = addAfter(tokenList, removeFrom, wrapped);\n\n\t\t\t\t\tif (after) {\n\t\t\t\t\t\taddAfter(tokenList, currentNode, after);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (removeCount > 1) {\n\t\t\t\t\t\t// at least one Token object was removed, so we have to do some rematching\n\t\t\t\t\t\t// this can only happen if the current pattern is greedy\n\n\t\t\t\t\t\t/** @type {RematchOptions} */\n\t\t\t\t\t\tvar nestedRematch = {\n\t\t\t\t\t\t\tcause: token + ',' + j,\n\t\t\t\t\t\t\treach: reach\n\t\t\t\t\t\t};\n\t\t\t\t\t\tmatchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch);\n\n\t\t\t\t\t\t// the reach might have been extended because of the rematching\n\t\t\t\t\t\tif (rematch && nestedRematch.reach > rematch.reach) {\n\t\t\t\t\t\t\trematch.reach = nestedRematch.reach;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @typedef LinkedListNode\n\t * @property {T} value\n\t * @property {LinkedListNode<T> | null} prev The previous node.\n\t * @property {LinkedListNode<T> | null} next The next node.\n\t * @template T\n\t * @private\n\t */\n\n\t/**\n\t * @template T\n\t * @private\n\t */\n\tfunction LinkedList() {\n\t\t/** @type {LinkedListNode<T>} */\n\t\tvar head = { value: null, prev: null, next: null };\n\t\t/** @type {LinkedListNode<T>} */\n\t\tvar tail = { value: null, prev: head, next: null };\n\t\thead.next = tail;\n\n\t\t/** @type {LinkedListNode<T>} */\n\t\tthis.head = head;\n\t\t/** @type {LinkedListNode<T>} */\n\t\tthis.tail = tail;\n\t\tthis.length = 0;\n\t}\n\n\t/**\n\t * Adds a new node with the given value to the list.\n\t *\n\t * @param {LinkedList<T>} list\n\t * @param {LinkedListNode<T>} node\n\t * @param {T} value\n\t * @returns {LinkedListNode<T>} The added node.\n\t * @template T\n\t */\n\tfunction addAfter(list, node, value) {\n\t\t// assumes that node != list.tail && values.length >= 0\n\t\tvar next = node.next;\n\n\t\tvar newNode = { value: value, prev: node, next: next };\n\t\tnode.next = newNode;\n\t\tnext.prev = newNode;\n\t\tlist.length++;\n\n\t\treturn newNode;\n\t}\n\t/**\n\t * Removes `count` nodes after the given node. The given node will not be removed.\n\t *\n\t * @param {LinkedList<T>} list\n\t * @param {LinkedListNode<T>} node\n\t * @param {number} count\n\t * @template T\n\t */\n\tfunction removeRange(list, node, count) {\n\t\tvar next = node.next;\n\t\tfor (var i = 0; i < count && next !== list.tail; i++) {\n\t\t\tnext = next.next;\n\t\t}\n\t\tnode.next = next;\n\t\tnext.prev = node;\n\t\tlist.length -= i;\n\t}\n\t/**\n\t * @param {LinkedList<T>} list\n\t * @returns {T[]}\n\t * @template T\n\t */\n\tfunction toArray(list) {\n\t\tvar array = [];\n\t\tvar node = list.head.next;\n\t\twhile (node !== list.tail) {\n\t\t\tarray.push(node.value);\n\t\t\tnode = node.next;\n\t\t}\n\t\treturn array;\n\t}\n\n\n\tif (!_self.document) {\n\t\tif (!_self.addEventListener) {\n\t\t\t// in Node.js\n\t\t\treturn _;\n\t\t}\n\n\t\tif (!_.disableWorkerMessageHandler) {\n\t\t\t// In worker\n\t\t\t_self.addEventListener('message', function (evt) {\n\t\t\t\tvar message = JSON.parse(evt.data);\n\t\t\t\tvar lang = message.language;\n\t\t\t\tvar code = message.code;\n\t\t\t\tvar immediateClose = message.immediateClose;\n\n\t\t\t\t_self.postMessage(_.highlight(code, _.languages[lang], lang));\n\t\t\t\tif (immediateClose) {\n\t\t\t\t\t_self.close();\n\t\t\t\t}\n\t\t\t}, false);\n\t\t}\n\n\t\treturn _;\n\t}\n\n\t// Get current script and highlight\n\tvar script = _.util.currentScript();\n\n\tif (script) {\n\t\t_.filename = script.src;\n\n\t\tif (script.hasAttribute('data-manual')) {\n\t\t\t_.manual = true;\n\t\t}\n\t}\n\n\tfunction highlightAutomaticallyCallback() {\n\t\tif (!_.manual) {\n\t\t\t_.highlightAll();\n\t\t}\n\t}\n\n\tif (!_.manual) {\n\t\t// If the document state is \"loading\", then we'll use DOMContentLoaded.\n\t\t// If the document state is \"interactive\" and the prism.js script is deferred, then we'll also use the\n\t\t// DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they\n\t\t// might take longer one animation frame to execute which can create a race condition where only some plugins have\n\t\t// been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.\n\t\t// See https://github.com/PrismJS/prism/issues/2102\n\t\tvar readyState = document.readyState;\n\t\tif (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {\n\t\t\tdocument.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);\n\t\t} else {\n\t\t\tif (window.requestAnimationFrame) {\n\t\t\t\twindow.requestAnimationFrame(highlightAutomaticallyCallback);\n\t\t\t} else {\n\t\t\t\twindow.setTimeout(highlightAutomaticallyCallback, 16);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn _;\n\n}(_self));\n\nif (typeof module !== 'undefined' && module.exports) {\n\tmodule.exports = Prism;\n}\n\n// hack for components to work correctly in node.js\nif (typeof global !== 'undefined') {\n\tglobal.Prism = Prism;\n}\n\n// some additional documentation/types\n\n/**\n * The expansion of a simple `RegExp` literal to support additional properties.\n *\n * @typedef GrammarToken\n * @property {RegExp} pattern The regular expression of the token.\n * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively)\n * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.\n * @property {boolean} [greedy=false] Whether the token is greedy.\n * @property {string|string[]} [alias] An optional alias or list of aliases.\n * @property {Grammar} [inside] The nested grammar of this token.\n *\n * The `inside` grammar will be used to tokenize the text value of each token of this kind.\n *\n * This can be used to make nested and even recursive language definitions.\n *\n * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into\n * each another.\n * @global\n * @public\n */\n\n/**\n * @typedef Grammar\n * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>}\n * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar.\n * @global\n * @public\n */\n\n/**\n * A function which will invoked after an element was successfully highlighted.\n *\n * @callback HighlightCallback\n * @param {Element} element The element successfully highlighted.\n * @returns {void}\n * @global\n * @public\n */\n\n/**\n * @callback HookCallback\n * @param {Object<string, any>} env The environment variables of the hook.\n * @returns {void}\n * @global\n * @public\n */\n\n\n/* **********************************************\n Begin prism-markup.js\n********************************************** */\n\nPrism.languages.markup = {\n\t'comment': {\n\t\tpattern: /<!--(?:(?!<!--)[\\s\\S])*?-->/,\n\t\tgreedy: true\n\t},\n\t'prolog': {\n\t\tpattern: /<\\?[\\s\\S]+?\\?>/,\n\t\tgreedy: true\n\t},\n\t'doctype': {\n\t\t// https://www.w3.org/TR/xml/#NT-doctypedecl\n\t\tpattern: /<!DOCTYPE(?:[^>\"'[\\]]|\"[^\"]*\"|'[^']*')+(?:\\[(?:[^<\"'\\]]|\"[^\"]*\"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\\]\\s*)?>/i,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'internal-subset': {\n\t\t\t\tpattern: /(^[^\\[]*\\[)[\\s\\S]+(?=\\]>$)/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tgreedy: true,\n\t\t\t\tinside: null // see below\n\t\t\t},\n\t\t\t'string': {\n\t\t\t\tpattern: /\"[^\"]*\"|'[^']*'/,\n\t\t\t\tgreedy: true\n\t\t\t},\n\t\t\t'punctuation': /^<!|>$|[[\\]]/,\n\t\t\t'doctype-tag': /^DOCTYPE/i,\n\t\t\t'name': /[^\\s<>'\"]+/\n\t\t}\n\t},\n\t'cdata': {\n\t\tpattern: /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/i,\n\t\tgreedy: true\n\t},\n\t'tag': {\n\t\tpattern: /<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s(?:\\s*[^\\s>\\/=]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))|(?=[\\s/>])))+)?\\s*\\/?>/,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'tag': {\n\t\t\t\tpattern: /^<\\/?[^\\s>\\/]+/,\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': /^<\\/?/,\n\t\t\t\t\t'namespace': /^[^\\s>\\/:]+:/\n\t\t\t\t}\n\t\t\t},\n\t\t\t'special-attr': [],\n\t\t\t'attr-value': {\n\t\t\t\tpattern: /=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+)/,\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpattern: /^=/,\n\t\t\t\t\t\t\talias: 'attr-equals'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpattern: /^(\\s*)[\"']|[\"']$/,\n\t\t\t\t\t\t\tlookbehind: true\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t'punctuation': /\\/?>/,\n\t\t\t'attr-name': {\n\t\t\t\tpattern: /[^\\s>\\/]+/,\n\t\t\t\tinside: {\n\t\t\t\t\t'namespace': /^[^\\s>\\/:]+:/\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t},\n\t'entity': [\n\t\t{\n\t\t\tpattern: /&[\\da-z]{1,8};/i,\n\t\t\talias: 'named-entity'\n\t\t},\n\t\t/&#x?[\\da-f]{1,8};/i\n\t]\n};\n\nPrism.languages.markup['tag'].inside['attr-value'].inside['entity'] =\n\tPrism.languages.markup['entity'];\nPrism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;\n\n// Plugin to make entity title show the real entity, idea by Roman Komarov\nPrism.hooks.add('wrap', function (env) {\n\n\tif (env.type === 'entity') {\n\t\tenv.attributes['title'] = env.content.replace(/&/, '&');\n\t}\n});\n\nObject.defineProperty(Prism.languages.markup.tag, 'addInlined', {\n\t/**\n\t * Adds an inlined language to markup.\n\t *\n\t * An example of an inlined language is CSS with `<style>` tags.\n\t *\n\t * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as\n\t * case insensitive.\n\t * @param {string} lang The language key.\n\t * @example\n\t * addInlined('style', 'css');\n\t */\n\tvalue: function addInlined(tagName, lang) {\n\t\tvar includedCdataInside = {};\n\t\tincludedCdataInside['language-' + lang] = {\n\t\t\tpattern: /(^<!\\[CDATA\\[)[\\s\\S]+?(?=\\]\\]>$)/i,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages[lang]\n\t\t};\n\t\tincludedCdataInside['cdata'] = /^<!\\[CDATA\\[|\\]\\]>$/i;\n\n\t\tvar inside = {\n\t\t\t'included-cdata': {\n\t\t\t\tpattern: /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/i,\n\t\t\t\tinside: includedCdataInside\n\t\t\t}\n\t\t};\n\t\tinside['language-' + lang] = {\n\t\t\tpattern: /[\\s\\S]+/,\n\t\t\tinside: Prism.languages[lang]\n\t\t};\n\n\t\tvar def = {};\n\t\tdef[tagName] = {\n\t\t\tpattern: RegExp(/(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[\\s\\S])*?(?=<\\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: inside\n\t\t};\n\n\t\tPrism.languages.insertBefore('markup', 'cdata', def);\n\t}\n});\nObject.defineProperty(Prism.languages.markup.tag, 'addAttribute', {\n\t/**\n\t * Adds an pattern to highlight languages embedded in HTML attributes.\n\t *\n\t * An example of an inlined language is CSS with `style` attributes.\n\t *\n\t * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as\n\t * case insensitive.\n\t * @param {string} lang The language key.\n\t * @example\n\t * addAttribute('style', 'css');\n\t */\n\tvalue: function (attrName, lang) {\n\t\tPrism.languages.markup.tag.inside['special-attr'].push({\n\t\t\tpattern: RegExp(\n\t\t\t\t/(^|[\"'\\s])/.source + '(?:' + attrName + ')' + /\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))/.source,\n\t\t\t\t'i'\n\t\t\t),\n\t\t\tlookbehind: true,\n\t\t\tinside: {\n\t\t\t\t'attr-name': /^[^\\s=]+/,\n\t\t\t\t'attr-value': {\n\t\t\t\t\tpattern: /=[\\s\\S]+/,\n\t\t\t\t\tinside: {\n\t\t\t\t\t\t'value': {\n\t\t\t\t\t\t\tpattern: /(^=\\s*([\"']|(?![\"'])))\\S[\\s\\S]*(?=\\2$)/,\n\t\t\t\t\t\t\tlookbehind: true,\n\t\t\t\t\t\t\talias: [lang, 'language-' + lang],\n\t\t\t\t\t\t\tinside: Prism.languages[lang]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'punctuation': [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpattern: /^=/,\n\t\t\t\t\t\t\t\talias: 'attr-equals'\n\t\t\t\t\t\t\t},\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}\n\t\t\t}\n\t\t});\n\t}\n});\n\nPrism.languages.html = Prism.languages.markup;\nPrism.languages.mathml = Prism.languages.markup;\nPrism.languages.svg = Prism.languages.markup;\n\nPrism.languages.xml = Prism.languages.extend('markup', {});\nPrism.languages.ssml = Prism.languages.xml;\nPrism.languages.atom = Prism.languages.xml;\nPrism.languages.rss = Prism.languages.xml;\n\n\n/* **********************************************\n Begin prism-css.js\n********************************************** */\n\n(function (Prism) {\n\n\tvar string = /(?:\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"|'(?:\\\\(?:\\r\\n|[\\s\\S])|[^'\\\\\\r\\n])*')/;\n\n\tPrism.languages.css = {\n\t\t'comment': /\\/\\*[\\s\\S]*?\\*\\//,\n\t\t'atrule': {\n\t\t\tpattern: RegExp('@[\\\\w-](?:' + /[^;{\\s\"']|\\s+(?!\\s)/.source + '|' + string.source + ')*?' + /(?:;|(?=\\s*\\{))/.source),\n\t\t\tinside: {\n\t\t\t\t'rule': /^@[\\w-]+/,\n\t\t\t\t'selector-function-argument': {\n\t\t\t\t\tpattern: /(\\bselector\\s*\\(\\s*(?![\\s)]))(?:[^()\\s]|\\s+(?![\\s)])|\\((?:[^()]|\\([^()]*\\))*\\))+(?=\\s*\\))/,\n\t\t\t\t\tlookbehind: true,\n\t\t\t\t\talias: 'selector'\n\t\t\t\t},\n\t\t\t\t'keyword': {\n\t\t\t\t\tpattern: /(^|[^\\w-])(?:and|not|only|or)(?![\\w-])/,\n\t\t\t\t\tlookbehind: true\n\t\t\t\t}\n\t\t\t\t// See rest below\n\t\t\t}\n\t\t},\n\t\t'url': {\n\t\t\t// https://drafts.csswg.org/css-values-3/#urls\n\t\t\tpattern: RegExp('\\\\burl\\\\((?:' + string.source + '|' + /(?:[^\\\\\\r\\n()\"']|\\\\[\\s\\S])*/.source + ')\\\\)', 'i'),\n\t\t\tgreedy: true,\n\t\t\tinside: {\n\t\t\t\t'function': /^url/i,\n\t\t\t\t'punctuation': /^\\(|\\)$/,\n\t\t\t\t'string': {\n\t\t\t\t\tpattern: RegExp('^' + string.source + '$'),\n\t\t\t\t\talias: 'url'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t'selector': {\n\t\t\tpattern: RegExp('(^|[{}\\\\s])[^{}\\\\s](?:[^{};\"\\'\\\\s]|\\\\s+(?![\\\\s{])|' + string.source + ')*(?=\\\\s*\\\\{)'),\n\t\t\tlookbehind: true\n\t\t},\n\t\t'string': {\n\t\t\tpattern: string,\n\t\t\tgreedy: true\n\t\t},\n\t\t'property': {\n\t\t\tpattern: /(^|[^-\\w\\xA0-\\uFFFF])(?!\\s)[-_a-z\\xA0-\\uFFFF](?:(?!\\s)[-\\w\\xA0-\\uFFFF])*(?=\\s*:)/i,\n\t\t\tlookbehind: true\n\t\t},\n\t\t'important': /!important\\b/i,\n\t\t'function': {\n\t\t\tpattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\\()/i,\n\t\t\tlookbehind: true\n\t\t},\n\t\t'punctuation': /[(){};:,]/\n\t};\n\n\tPrism.languages.css['atrule'].inside.rest = Prism.languages.css;\n\n\tvar markup = Prism.languages.markup;\n\tif (markup) {\n\t\tmarkup.tag.addInlined('style', 'css');\n\t\tmarkup.tag.addAttribute('style', 'css');\n\t}\n\n}(Prism));\n\n\n/* **********************************************\n Begin prism-clike.js\n********************************************** */\n\nPrism.languages.clike = {\n\t'comment': [\n\t\t{\n\t\t\tpattern: /(^|[^\\\\])\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^\\\\:])\\/\\/.*/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t}\n\t],\n\t'string': {\n\t\tpattern: /([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,\n\t\tgreedy: true\n\t},\n\t'class-name': {\n\t\tpattern: /(\\b(?:class|extends|implements|instanceof|interface|new|trait)\\s+|\\bcatch\\s+\\()[\\w.\\\\]+/i,\n\t\tlookbehind: true,\n\t\tinside: {\n\t\t\t'punctuation': /[.\\\\]/\n\t\t}\n\t},\n\t'keyword': /\\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\\b/,\n\t'boolean': /\\b(?:false|true)\\b/,\n\t'function': /\\b\\w+(?=\\()/,\n\t'number': /\\b0x[\\da-f]+\\b|(?:\\b\\d+(?:\\.\\d*)?|\\B\\.\\d+)(?:e[+-]?\\d+)?/i,\n\t'operator': /[<>]=?|[!=]=?=?|--?|\\+\\+?|&&?|\\|\\|?|[?*/~^%]/,\n\t'punctuation': /[{}[\\];(),.:]/\n};\n\n\n/* **********************************************\n Begin prism-javascript.js\n********************************************** */\n\nPrism.languages.javascript = Prism.languages.extend('clike', {\n\t'class-name': [\n\t\tPrism.languages.clike['class-name'],\n\t\t{\n\t\t\tpattern: /(^|[^$\\w\\xA0-\\uFFFF])(?!\\s)[_$A-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\.(?:constructor|prototype))/,\n\t\t\tlookbehind: true\n\t\t}\n\t],\n\t'keyword': [\n\t\t{\n\t\t\tpattern: /((?:^|\\})\\s*)catch\\b/,\n\t\t\tlookbehind: true\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^.]|\\.\\.\\.\\s*)\\b(?:as|assert(?=\\s*\\{)|async(?=\\s*(?:function\\b|\\(|[$\\w\\xA0-\\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\\s*(?:\\{|$))|for|from(?=\\s*(?:['\"]|$))|function|(?:get|set)(?=\\s*(?:[#\\[$\\w\\xA0-\\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\\b/,\n\t\t\tlookbehind: true\n\t\t},\n\t],\n\t// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)\n\t'function': /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*(?:\\.\\s*(?:apply|bind|call)\\s*)?\\()/,\n\t'number': {\n\t\tpattern: RegExp(\n\t\t\t/(^|[^\\w$])/.source +\n\t\t\t'(?:' +\n\t\t\t(\n\t\t\t\t// constant\n\t\t\t\t/NaN|Infinity/.source +\n\t\t\t\t'|' +\n\t\t\t\t// binary integer\n\t\t\t\t/0[bB][01]+(?:_[01]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// octal integer\n\t\t\t\t/0[oO][0-7]+(?:_[0-7]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// hexadecimal integer\n\t\t\t\t/0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// decimal bigint\n\t\t\t\t/\\d+(?:_\\d+)*n/.source +\n\t\t\t\t'|' +\n\t\t\t\t// decimal number (integer or float) but no bigint\n\t\t\t\t/(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?/.source\n\t\t\t) +\n\t\t\t')' +\n\t\t\t/(?![\\w$])/.source\n\t\t),\n\t\tlookbehind: true\n\t},\n\t'operator': /--|\\+\\+|\\*\\*=?|=>|&&=?|\\|\\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\\.{3}|\\?\\?=?|\\?\\.?|[~:]/\n});\n\nPrism.languages.javascript['class-name'][0].pattern = /(\\b(?:class|extends|implements|instanceof|interface|new)\\s+)[\\w.\\\\]+/;\n\nPrism.languages.insertBefore('javascript', 'keyword', {\n\t'regex': {\n\t\tpattern: RegExp(\n\t\t\t// lookbehind\n\t\t\t// eslint-disable-next-line regexp/no-dupe-characters-character-class\n\t\t\t/((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/.source +\n\t\t\t// Regex pattern:\n\t\t\t// There are 2 regex patterns here. The RegExp set notation proposal added support for nested character\n\t\t\t// classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible\n\t\t\t// with the only syntax, so we have to define 2 different regex patterns.\n\t\t\t/\\//.source +\n\t\t\t'(?:' +\n\t\t\t/(?:\\[(?:[^\\]\\\\\\r\\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}/.source +\n\t\t\t'|' +\n\t\t\t// `v` flag syntax. This supports 3 levels of nested character classes.\n\t\t\t/(?:\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source +\n\t\t\t')' +\n\t\t\t// lookahead\n\t\t\t/(?=(?:\\s|\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/)*(?:$|[\\r\\n,.;:})\\]]|\\/\\/))/.source\n\t\t),\n\t\tlookbehind: true,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'regex-source': {\n\t\t\t\tpattern: /^(\\/)[\\s\\S]+(?=\\/[a-z]*$)/,\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'language-regex',\n\t\t\t\tinside: Prism.languages.regex\n\t\t\t},\n\t\t\t'regex-delimiter': /^\\/|\\/$/,\n\t\t\t'regex-flags': /^[a-z]+$/,\n\t\t}\n\t},\n\t// This must be declared before keyword because we use \"function\" inside the look-forward\n\t'function-variable': {\n\t\tpattern: /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*[=:]\\s*(?:async\\s*)?(?:\\bfunction\\b|(?:\\((?:[^()]|\\([^()]*\\))*\\)|(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*)\\s*=>))/,\n\t\talias: 'function'\n\t},\n\t'parameter': [\n\t\t{\n\t\t\tpattern: /(function(?:\\s+(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*)?\\s*\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\))/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^$\\w\\xA0-\\uFFFF])(?!\\s)[_$a-z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*=>)/i,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /(\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\)\\s*=>)/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /((?:\\b|\\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\\w\\xA0-\\uFFFF]))(?:(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*\\s*)\\(\\s*|\\]\\s*\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\)\\s*\\{)/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t}\n\t],\n\t'constant': /\\b[A-Z](?:[A-Z_]|\\dx?)*\\b/\n});\n\nPrism.languages.insertBefore('javascript', 'string', {\n\t'hashbang': {\n\t\tpattern: /^#!.*/,\n\t\tgreedy: true,\n\t\talias: 'comment'\n\t},\n\t'template-string': {\n\t\tpattern: /`(?:\\\\[\\s\\S]|\\$\\{(?:[^{}]|\\{(?:[^{}]|\\{[^}]*\\})*\\})+\\}|(?!\\$\\{)[^\\\\`])*`/,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'template-punctuation': {\n\t\t\t\tpattern: /^`|`$/,\n\t\t\t\talias: 'string'\n\t\t\t},\n\t\t\t'interpolation': {\n\t\t\t\tpattern: /((?:^|[^\\\\])(?:\\\\{2})*)\\$\\{(?:[^{}]|\\{(?:[^{}]|\\{[^}]*\\})*\\})+\\}/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: {\n\t\t\t\t\t'interpolation-punctuation': {\n\t\t\t\t\t\tpattern: /^\\$\\{|\\}$/,\n\t\t\t\t\t\talias: 'punctuation'\n\t\t\t\t\t},\n\t\t\t\t\trest: Prism.languages.javascript\n\t\t\t\t}\n\t\t\t},\n\t\t\t'string': /[\\s\\S]+/\n\t\t}\n\t},\n\t'string-property': {\n\t\tpattern: /((?:^|[,{])[ \\t]*)([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\2)[^\\\\\\r\\n])*\\2(?=\\s*:)/m,\n\t\tlookbehind: true,\n\t\tgreedy: true,\n\t\talias: 'property'\n\t}\n});\n\nPrism.languages.insertBefore('javascript', 'operator', {\n\t'literal-property': {\n\t\tpattern: /((?:^|[,{])[ \\t]*)(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*:)/m,\n\t\tlookbehind: true,\n\t\talias: 'property'\n\t},\n});\n\nif (Prism.languages.markup) {\n\tPrism.languages.markup.tag.addInlined('script', 'javascript');\n\n\t// add attribute support for all DOM events.\n\t// https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events\n\tPrism.languages.markup.tag.addAttribute(\n\t\t/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,\n\t\t'javascript'\n\t);\n}\n\nPrism.languages.js = Prism.languages.javascript;\n\n\n/* **********************************************\n Begin prism-file-highlight.js\n********************************************** */\n\n(function () {\n\n\tif (typeof Prism === 'undefined' || typeof document === 'undefined') {\n\t\treturn;\n\t}\n\n\t// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill\n\tif (!Element.prototype.matches) {\n\t\tElement.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;\n\t}\n\n\tvar LOADING_MESSAGE = 'Loading…';\n\tvar FAILURE_MESSAGE = function (status, message) {\n\t\treturn '✖ Error ' + status + ' while fetching file: ' + message;\n\t};\n\tvar FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty';\n\n\tvar EXTENSIONS = {\n\t\t'js': 'javascript',\n\t\t'py': 'python',\n\t\t'rb': 'ruby',\n\t\t'ps1': 'powershell',\n\t\t'psm1': 'powershell',\n\t\t'sh': 'bash',\n\t\t'bat': 'batch',\n\t\t'h': 'c',\n\t\t'tex': 'latex'\n\t};\n\n\tvar STATUS_ATTR = 'data-src-status';\n\tvar STATUS_LOADING = 'loading';\n\tvar STATUS_LOADED = 'loaded';\n\tvar STATUS_FAILED = 'failed';\n\n\tvar SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '=\"' + STATUS_LOADED + '\"])'\n\t\t+ ':not([' + STATUS_ATTR + '=\"' + STATUS_LOADING + '\"])';\n\n\t/**\n\t * Loads the given file.\n\t *\n\t * @param {string} src The URL or path of the source file to load.\n\t * @param {(result: string) => void} success\n\t * @param {(reason: string) => void} error\n\t */\n\tfunction loadFile(src, success, error) {\n\t\tvar xhr = new XMLHttpRequest();\n\t\txhr.open('GET', src, true);\n\t\txhr.onreadystatechange = function () {\n\t\t\tif (xhr.readyState == 4) {\n\t\t\t\tif (xhr.status < 400 && xhr.responseText) {\n\t\t\t\t\tsuccess(xhr.responseText);\n\t\t\t\t} else {\n\t\t\t\t\tif (xhr.status >= 400) {\n\t\t\t\t\t\terror(FAILURE_MESSAGE(xhr.status, xhr.statusText));\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror(FAILURE_EMPTY_MESSAGE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\txhr.send(null);\n\t}\n\n\t/**\n\t * Parses the given range.\n\t *\n\t * This returns a range with inclusive ends.\n\t *\n\t * @param {string | null | undefined} range\n\t * @returns {[number, number | undefined] | undefined}\n\t */\n\tfunction parseRange(range) {\n\t\tvar m = /^\\s*(\\d+)\\s*(?:(,)\\s*(?:(\\d+)\\s*)?)?$/.exec(range || '');\n\t\tif (m) {\n\t\t\tvar start = Number(m[1]);\n\t\t\tvar comma = m[2];\n\t\t\tvar end = m[3];\n\n\t\t\tif (!comma) {\n\t\t\t\treturn [start, start];\n\t\t\t}\n\t\t\tif (!end) {\n\t\t\t\treturn [start, undefined];\n\t\t\t}\n\t\t\treturn [start, Number(end)];\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tPrism.hooks.add('before-highlightall', function (env) {\n\t\tenv.selector += ', ' + SELECTOR;\n\t});\n\n\tPrism.hooks.add('before-sanity-check', function (env) {\n\t\tvar pre = /** @type {HTMLPreElement} */ (env.element);\n\t\tif (pre.matches(SELECTOR)) {\n\t\t\tenv.code = ''; // fast-path the whole thing and go to complete\n\n\t\t\tpre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading\n\n\t\t\t// add code element with loading message\n\t\t\tvar code = pre.appendChild(document.createElement('CODE'));\n\t\t\tcode.textContent = LOADING_MESSAGE;\n\n\t\t\tvar src = pre.getAttribute('data-src');\n\n\t\t\tvar language = env.language;\n\t\t\tif (language === 'none') {\n\t\t\t\t// the language might be 'none' because there is no language set;\n\t\t\t\t// in this case, we want to use the extension as the language\n\t\t\t\tvar extension = (/\\.(\\w+)$/.exec(src) || [, 'none'])[1];\n\t\t\t\tlanguage = EXTENSIONS[extension] || extension;\n\t\t\t}\n\n\t\t\t// set language classes\n\t\t\tPrism.util.setLanguage(code, language);\n\t\t\tPrism.util.setLanguage(pre, language);\n\n\t\t\t// preload the language\n\t\t\tvar autoloader = Prism.plugins.autoloader;\n\t\t\tif (autoloader) {\n\t\t\t\tautoloader.loadLanguages(language);\n\t\t\t}\n\n\t\t\t// load file\n\t\t\tloadFile(\n\t\t\t\tsrc,\n\t\t\t\tfunction (text) {\n\t\t\t\t\t// mark as loaded\n\t\t\t\t\tpre.setAttribute(STATUS_ATTR, STATUS_LOADED);\n\n\t\t\t\t\t// handle data-range\n\t\t\t\t\tvar range = parseRange(pre.getAttribute('data-range'));\n\t\t\t\t\tif (range) {\n\t\t\t\t\t\tvar lines = text.split(/\\r\\n?|\\n/g);\n\n\t\t\t\t\t\t// the range is one-based and inclusive on both ends\n\t\t\t\t\t\tvar start = range[0];\n\t\t\t\t\t\tvar end = range[1] == null ? lines.length : range[1];\n\n\t\t\t\t\t\tif (start < 0) { start += lines.length; }\n\t\t\t\t\t\tstart = Math.max(0, Math.min(start - 1, lines.length));\n\t\t\t\t\t\tif (end < 0) { end += lines.length; }\n\t\t\t\t\t\tend = Math.max(0, Math.min(end, lines.length));\n\n\t\t\t\t\t\ttext = lines.slice(start, end).join('\\n');\n\n\t\t\t\t\t\t// add data-start for line numbers\n\t\t\t\t\t\tif (!pre.hasAttribute('data-start')) {\n\t\t\t\t\t\t\tpre.setAttribute('data-start', String(start + 1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// highlight code\n\t\t\t\t\tcode.textContent = text;\n\t\t\t\t\tPrism.highlightElement(code);\n\t\t\t\t},\n\t\t\t\tfunction (error) {\n\t\t\t\t\t// mark as failed\n\t\t\t\t\tpre.setAttribute(STATUS_ATTR, STATUS_FAILED);\n\n\t\t\t\t\tcode.textContent = error;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t});\n\n\tPrism.plugins.fileHighlight = {\n\t\t/**\n\t\t * Executes the File Highlight plugin for all matching `pre` elements under the given container.\n\t\t *\n\t\t * Note: Elements which are already loaded or currently loading will not be touched by this method.\n\t\t *\n\t\t * @param {ParentNode} [container=document]\n\t\t */\n\t\thighlight: function highlight(container) {\n\t\t\tvar elements = (container || document).querySelectorAll(SELECTOR);\n\n\t\t\tfor (var i = 0, element; (element = elements[i++]);) {\n\t\t\t\tPrism.highlightElement(element);\n\t\t\t}\n\t\t}\n\t};\n\n\tvar logged = false;\n\t/** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */\n\tPrism.fileHighlight = function () {\n\t\tif (!logged) {\n\t\t\tconsole.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.');\n\t\t\tlogged = true;\n\t\t}\n\t\tPrism.plugins.fileHighlight.highlight.apply(this, arguments);\n\t};\n\n}());\n","Prism.languages.markup = {\n\t'comment': {\n\t\tpattern: /<!--(?:(?!<!--)[\\s\\S])*?-->/,\n\t\tgreedy: true\n\t},\n\t'prolog': {\n\t\tpattern: /<\\?[\\s\\S]+?\\?>/,\n\t\tgreedy: true\n\t},\n\t'doctype': {\n\t\t// https://www.w3.org/TR/xml/#NT-doctypedecl\n\t\tpattern: /<!DOCTYPE(?:[^>\"'[\\]]|\"[^\"]*\"|'[^']*')+(?:\\[(?:[^<\"'\\]]|\"[^\"]*\"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\\]\\s*)?>/i,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'internal-subset': {\n\t\t\t\tpattern: /(^[^\\[]*\\[)[\\s\\S]+(?=\\]>$)/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tgreedy: true,\n\t\t\t\tinside: null // see below\n\t\t\t},\n\t\t\t'string': {\n\t\t\t\tpattern: /\"[^\"]*\"|'[^']*'/,\n\t\t\t\tgreedy: true\n\t\t\t},\n\t\t\t'punctuation': /^<!|>$|[[\\]]/,\n\t\t\t'doctype-tag': /^DOCTYPE/i,\n\t\t\t'name': /[^\\s<>'\"]+/\n\t\t}\n\t},\n\t'cdata': {\n\t\tpattern: /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/i,\n\t\tgreedy: true\n\t},\n\t'tag': {\n\t\tpattern: /<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s(?:\\s*[^\\s>\\/=]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))|(?=[\\s/>])))+)?\\s*\\/?>/,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'tag': {\n\t\t\t\tpattern: /^<\\/?[^\\s>\\/]+/,\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': /^<\\/?/,\n\t\t\t\t\t'namespace': /^[^\\s>\\/:]+:/\n\t\t\t\t}\n\t\t\t},\n\t\t\t'special-attr': [],\n\t\t\t'attr-value': {\n\t\t\t\tpattern: /=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+)/,\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpattern: /^=/,\n\t\t\t\t\t\t\talias: 'attr-equals'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpattern: /^(\\s*)[\"']|[\"']$/,\n\t\t\t\t\t\t\tlookbehind: true\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t'punctuation': /\\/?>/,\n\t\t\t'attr-name': {\n\t\t\t\tpattern: /[^\\s>\\/]+/,\n\t\t\t\tinside: {\n\t\t\t\t\t'namespace': /^[^\\s>\\/:]+:/\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t},\n\t'entity': [\n\t\t{\n\t\t\tpattern: /&[\\da-z]{1,8};/i,\n\t\t\talias: 'named-entity'\n\t\t},\n\t\t/&#x?[\\da-f]{1,8};/i\n\t]\n};\n\nPrism.languages.markup['tag'].inside['attr-value'].inside['entity'] =\n\tPrism.languages.markup['entity'];\nPrism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;\n\n// Plugin to make entity title show the real entity, idea by Roman Komarov\nPrism.hooks.add('wrap', function (env) {\n\n\tif (env.type === 'entity') {\n\t\tenv.attributes['title'] = env.content.replace(/&/, '&');\n\t}\n});\n\nObject.defineProperty(Prism.languages.markup.tag, 'addInlined', {\n\t/**\n\t * Adds an inlined language to markup.\n\t *\n\t * An example of an inlined language is CSS with `<style>` tags.\n\t *\n\t * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as\n\t * case insensitive.\n\t * @param {string} lang The language key.\n\t * @example\n\t * addInlined('style', 'css');\n\t */\n\tvalue: function addInlined(tagName, lang) {\n\t\tvar includedCdataInside = {};\n\t\tincludedCdataInside['language-' + lang] = {\n\t\t\tpattern: /(^<!\\[CDATA\\[)[\\s\\S]+?(?=\\]\\]>$)/i,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages[lang]\n\t\t};\n\t\tincludedCdataInside['cdata'] = /^<!\\[CDATA\\[|\\]\\]>$/i;\n\n\t\tvar inside = {\n\t\t\t'included-cdata': {\n\t\t\t\tpattern: /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/i,\n\t\t\t\tinside: includedCdataInside\n\t\t\t}\n\t\t};\n\t\tinside['language-' + lang] = {\n\t\t\tpattern: /[\\s\\S]+/,\n\t\t\tinside: Prism.languages[lang]\n\t\t};\n\n\t\tvar def = {};\n\t\tdef[tagName] = {\n\t\t\tpattern: RegExp(/(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[\\s\\S])*?(?=<\\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: inside\n\t\t};\n\n\t\tPrism.languages.insertBefore('markup', 'cdata', def);\n\t}\n});\nObject.defineProperty(Prism.languages.markup.tag, 'addAttribute', {\n\t/**\n\t * Adds an pattern to highlight languages embedded in HTML attributes.\n\t *\n\t * An example of an inlined language is CSS with `style` attributes.\n\t *\n\t * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as\n\t * case insensitive.\n\t * @param {string} lang The language key.\n\t * @example\n\t * addAttribute('style', 'css');\n\t */\n\tvalue: function (attrName, lang) {\n\t\tPrism.languages.markup.tag.inside['special-attr'].push({\n\t\t\tpattern: RegExp(\n\t\t\t\t/(^|[\"'\\s])/.source + '(?:' + attrName + ')' + /\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))/.source,\n\t\t\t\t'i'\n\t\t\t),\n\t\t\tlookbehind: true,\n\t\t\tinside: {\n\t\t\t\t'attr-name': /^[^\\s=]+/,\n\t\t\t\t'attr-value': {\n\t\t\t\t\tpattern: /=[\\s\\S]+/,\n\t\t\t\t\tinside: {\n\t\t\t\t\t\t'value': {\n\t\t\t\t\t\t\tpattern: /(^=\\s*([\"']|(?![\"'])))\\S[\\s\\S]*(?=\\2$)/,\n\t\t\t\t\t\t\tlookbehind: true,\n\t\t\t\t\t\t\talias: [lang, 'language-' + lang],\n\t\t\t\t\t\t\tinside: Prism.languages[lang]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'punctuation': [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpattern: /^=/,\n\t\t\t\t\t\t\t\talias: 'attr-equals'\n\t\t\t\t\t\t\t},\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}\n\t\t\t}\n\t\t});\n\t}\n});\n\nPrism.languages.html = Prism.languages.markup;\nPrism.languages.mathml = Prism.languages.markup;\nPrism.languages.svg = Prism.languages.markup;\n\nPrism.languages.xml = Prism.languages.extend('markup', {});\nPrism.languages.ssml = Prism.languages.xml;\nPrism.languages.atom = Prism.languages.xml;\nPrism.languages.rss = Prism.languages.xml;\n","(function (Prism) {\n\n\tvar string = /(?:\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"|'(?:\\\\(?:\\r\\n|[\\s\\S])|[^'\\\\\\r\\n])*')/;\n\n\tPrism.languages.css = {\n\t\t'comment': /\\/\\*[\\s\\S]*?\\*\\//,\n\t\t'atrule': {\n\t\t\tpattern: RegExp('@[\\\\w-](?:' + /[^;{\\s\"']|\\s+(?!\\s)/.source + '|' + string.source + ')*?' + /(?:;|(?=\\s*\\{))/.source),\n\t\t\tinside: {\n\t\t\t\t'rule': /^@[\\w-]+/,\n\t\t\t\t'selector-function-argument': {\n\t\t\t\t\tpattern: /(\\bselector\\s*\\(\\s*(?![\\s)]))(?:[^()\\s]|\\s+(?![\\s)])|\\((?:[^()]|\\([^()]*\\))*\\))+(?=\\s*\\))/,\n\t\t\t\t\tlookbehind: true,\n\t\t\t\t\talias: 'selector'\n\t\t\t\t},\n\t\t\t\t'keyword': {\n\t\t\t\t\tpattern: /(^|[^\\w-])(?:and|not|only|or)(?![\\w-])/,\n\t\t\t\t\tlookbehind: true\n\t\t\t\t}\n\t\t\t\t// See rest below\n\t\t\t}\n\t\t},\n\t\t'url': {\n\t\t\t// https://drafts.csswg.org/css-values-3/#urls\n\t\t\tpattern: RegExp('\\\\burl\\\\((?:' + string.source + '|' + /(?:[^\\\\\\r\\n()\"']|\\\\[\\s\\S])*/.source + ')\\\\)', 'i'),\n\t\t\tgreedy: true,\n\t\t\tinside: {\n\t\t\t\t'function': /^url/i,\n\t\t\t\t'punctuation': /^\\(|\\)$/,\n\t\t\t\t'string': {\n\t\t\t\t\tpattern: RegExp('^' + string.source + '$'),\n\t\t\t\t\talias: 'url'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t'selector': {\n\t\t\tpattern: RegExp('(^|[{}\\\\s])[^{}\\\\s](?:[^{};\"\\'\\\\s]|\\\\s+(?![\\\\s{])|' + string.source + ')*(?=\\\\s*\\\\{)'),\n\t\t\tlookbehind: true\n\t\t},\n\t\t'string': {\n\t\t\tpattern: string,\n\t\t\tgreedy: true\n\t\t},\n\t\t'property': {\n\t\t\tpattern: /(^|[^-\\w\\xA0-\\uFFFF])(?!\\s)[-_a-z\\xA0-\\uFFFF](?:(?!\\s)[-\\w\\xA0-\\uFFFF])*(?=\\s*:)/i,\n\t\t\tlookbehind: true\n\t\t},\n\t\t'important': /!important\\b/i,\n\t\t'function': {\n\t\t\tpattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\\()/i,\n\t\t\tlookbehind: true\n\t\t},\n\t\t'punctuation': /[(){};:,]/\n\t};\n\n\tPrism.languages.css['atrule'].inside.rest = Prism.languages.css;\n\n\tvar markup = Prism.languages.markup;\n\tif (markup) {\n\t\tmarkup.tag.addInlined('style', 'css');\n\t\tmarkup.tag.addAttribute('style', 'css');\n\t}\n\n}(Prism));\n","Prism.languages.clike = {\n\t'comment': [\n\t\t{\n\t\t\tpattern: /(^|[^\\\\])\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^\\\\:])\\/\\/.*/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t}\n\t],\n\t'string': {\n\t\tpattern: /([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,\n\t\tgreedy: true\n\t},\n\t'class-name': {\n\t\tpattern: /(\\b(?:class|extends|implements|instanceof|interface|new|trait)\\s+|\\bcatch\\s+\\()[\\w.\\\\]+/i,\n\t\tlookbehind: true,\n\t\tinside: {\n\t\t\t'punctuation': /[.\\\\]/\n\t\t}\n\t},\n\t'keyword': /\\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\\b/,\n\t'boolean': /\\b(?:false|true)\\b/,\n\t'function': /\\b\\w+(?=\\()/,\n\t'number': /\\b0x[\\da-f]+\\b|(?:\\b\\d+(?:\\.\\d*)?|\\B\\.\\d+)(?:e[+-]?\\d+)?/i,\n\t'operator': /[<>]=?|[!=]=?=?|--?|\\+\\+?|&&?|\\|\\|?|[?*/~^%]/,\n\t'punctuation': /[{}[\\];(),.:]/\n};\n","Prism.languages.javascript = Prism.languages.extend('clike', {\n\t'class-name': [\n\t\tPrism.languages.clike['class-name'],\n\t\t{\n\t\t\tpattern: /(^|[^$\\w\\xA0-\\uFFFF])(?!\\s)[_$A-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\.(?:constructor|prototype))/,\n\t\t\tlookbehind: true\n\t\t}\n\t],\n\t'keyword': [\n\t\t{\n\t\t\tpattern: /((?:^|\\})\\s*)catch\\b/,\n\t\t\tlookbehind: true\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^.]|\\.\\.\\.\\s*)\\b(?:as|assert(?=\\s*\\{)|async(?=\\s*(?:function\\b|\\(|[$\\w\\xA0-\\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\\s*(?:\\{|$))|for|from(?=\\s*(?:['\"]|$))|function|(?:get|set)(?=\\s*(?:[#\\[$\\w\\xA0-\\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\\b/,\n\t\t\tlookbehind: true\n\t\t},\n\t],\n\t// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)\n\t'function': /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*(?:\\.\\s*(?:apply|bind|call)\\s*)?\\()/,\n\t'number': {\n\t\tpattern: RegExp(\n\t\t\t/(^|[^\\w$])/.source +\n\t\t\t'(?:' +\n\t\t\t(\n\t\t\t\t// constant\n\t\t\t\t/NaN|Infinity/.source +\n\t\t\t\t'|' +\n\t\t\t\t// binary integer\n\t\t\t\t/0[bB][01]+(?:_[01]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// octal integer\n\t\t\t\t/0[oO][0-7]+(?:_[0-7]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// hexadecimal integer\n\t\t\t\t/0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?/.source +\n\t\t\t\t'|' +\n\t\t\t\t// decimal bigint\n\t\t\t\t/\\d+(?:_\\d+)*n/.source +\n\t\t\t\t'|' +\n\t\t\t\t// decimal number (integer or float) but no bigint\n\t\t\t\t/(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?/.source\n\t\t\t) +\n\t\t\t')' +\n\t\t\t/(?![\\w$])/.source\n\t\t),\n\t\tlookbehind: true\n\t},\n\t'operator': /--|\\+\\+|\\*\\*=?|=>|&&=?|\\|\\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\\.{3}|\\?\\?=?|\\?\\.?|[~:]/\n});\n\nPrism.languages.javascript['class-name'][0].pattern = /(\\b(?:class|extends|implements|instanceof|interface|new)\\s+)[\\w.\\\\]+/;\n\nPrism.languages.insertBefore('javascript', 'keyword', {\n\t'regex': {\n\t\tpattern: RegExp(\n\t\t\t// lookbehind\n\t\t\t// eslint-disable-next-line regexp/no-dupe-characters-character-class\n\t\t\t/((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/.source +\n\t\t\t// Regex pattern:\n\t\t\t// There are 2 regex patterns here. The RegExp set notation proposal added support for nested character\n\t\t\t// classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible\n\t\t\t// with the only syntax, so we have to define 2 different regex patterns.\n\t\t\t/\\//.source +\n\t\t\t'(?:' +\n\t\t\t/(?:\\[(?:[^\\]\\\\\\r\\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}/.source +\n\t\t\t'|' +\n\t\t\t// `v` flag syntax. This supports 3 levels of nested character classes.\n\t\t\t/(?:\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source +\n\t\t\t')' +\n\t\t\t// lookahead\n\t\t\t/(?=(?:\\s|\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/)*(?:$|[\\r\\n,.;:})\\]]|\\/\\/))/.source\n\t\t),\n\t\tlookbehind: true,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'regex-source': {\n\t\t\t\tpattern: /^(\\/)[\\s\\S]+(?=\\/[a-z]*$)/,\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'language-regex',\n\t\t\t\tinside: Prism.languages.regex\n\t\t\t},\n\t\t\t'regex-delimiter': /^\\/|\\/$/,\n\t\t\t'regex-flags': /^[a-z]+$/,\n\t\t}\n\t},\n\t// This must be declared before keyword because we use \"function\" inside the look-forward\n\t'function-variable': {\n\t\tpattern: /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*[=:]\\s*(?:async\\s*)?(?:\\bfunction\\b|(?:\\((?:[^()]|\\([^()]*\\))*\\)|(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*)\\s*=>))/,\n\t\talias: 'function'\n\t},\n\t'parameter': [\n\t\t{\n\t\t\tpattern: /(function(?:\\s+(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*)?\\s*\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\))/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /(^|[^$\\w\\xA0-\\uFFFF])(?!\\s)[_$a-z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*=>)/i,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /(\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\)\\s*=>)/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t},\n\t\t{\n\t\t\tpattern: /((?:\\b|\\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\\w\\xA0-\\uFFFF]))(?:(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*\\s*)\\(\\s*|\\]\\s*\\(\\s*)(?!\\s)(?:[^()\\s]|\\s+(?![\\s)])|\\([^()]*\\))+(?=\\s*\\)\\s*\\{)/,\n\t\t\tlookbehind: true,\n\t\t\tinside: Prism.languages.javascript\n\t\t}\n\t],\n\t'constant': /\\b[A-Z](?:[A-Z_]|\\dx?)*\\b/\n});\n\nPrism.languages.insertBefore('javascript', 'string', {\n\t'hashbang': {\n\t\tpattern: /^#!.*/,\n\t\tgreedy: true,\n\t\talias: 'comment'\n\t},\n\t'template-string': {\n\t\tpattern: /`(?:\\\\[\\s\\S]|\\$\\{(?:[^{}]|\\{(?:[^{}]|\\{[^}]*\\})*\\})+\\}|(?!\\$\\{)[^\\\\`])*`/,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'template-punctuation': {\n\t\t\t\tpattern: /^`|`$/,\n\t\t\t\talias: 'string'\n\t\t\t},\n\t\t\t'interpolation': {\n\t\t\t\tpattern: /((?:^|[^\\\\])(?:\\\\{2})*)\\$\\{(?:[^{}]|\\{(?:[^{}]|\\{[^}]*\\})*\\})+\\}/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: {\n\t\t\t\t\t'interpolation-punctuation': {\n\t\t\t\t\t\tpattern: /^\\$\\{|\\}$/,\n\t\t\t\t\t\talias: 'punctuation'\n\t\t\t\t\t},\n\t\t\t\t\trest: Prism.languages.javascript\n\t\t\t\t}\n\t\t\t},\n\t\t\t'string': /[\\s\\S]+/\n\t\t}\n\t},\n\t'string-property': {\n\t\tpattern: /((?:^|[,{])[ \\t]*)([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\2)[^\\\\\\r\\n])*\\2(?=\\s*:)/m,\n\t\tlookbehind: true,\n\t\tgreedy: true,\n\t\talias: 'property'\n\t}\n});\n\nPrism.languages.insertBefore('javascript', 'operator', {\n\t'literal-property': {\n\t\tpattern: /((?:^|[,{])[ \\t]*)(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*:)/m,\n\t\tlookbehind: true,\n\t\talias: 'property'\n\t},\n});\n\nif (Prism.languages.markup) {\n\tPrism.languages.markup.tag.addInlined('script', 'javascript');\n\n\t// add attribute support for all DOM events.\n\t// https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events\n\tPrism.languages.markup.tag.addAttribute(\n\t\t/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,\n\t\t'javascript'\n\t);\n}\n\nPrism.languages.js = Prism.languages.javascript;\n","(function (Prism) {\n\n\tPrism.languages.typescript = Prism.languages.extend('javascript', {\n\t\t'class-name': {\n\t\t\tpattern: /(\\b(?:class|extends|implements|instanceof|interface|new|type)\\s+)(?!keyof\\b)(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?:\\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: null // see below\n\t\t},\n\t\t'builtin': /\\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\\b/,\n\t});\n\n\t// The keywords TypeScript adds to JavaScript\n\tPrism.languages.typescript.keyword.push(\n\t\t/\\b(?:abstract|declare|is|keyof|readonly|require)\\b/,\n\t\t// keywords that have to be followed by an identifier\n\t\t/\\b(?:asserts|infer|interface|module|namespace|type)\\b(?=\\s*(?:[{_$a-zA-Z\\xA0-\\uFFFF]|$))/,\n\t\t// This is for `import type *, {}`\n\t\t/\\btype\\b(?=\\s*(?:[\\{*]|$))/\n\t);\n\n\t// doesn't work with TS because TS is too complex\n\tdelete Prism.languages.typescript['parameter'];\n\tdelete Prism.languages.typescript['literal-property'];\n\n\t// a version of typescript specifically for highlighting types\n\tvar typeInside = Prism.languages.extend('typescript', {});\n\tdelete typeInside['class-name'];\n\n\tPrism.languages.typescript['class-name'].inside = typeInside;\n\n\tPrism.languages.insertBefore('typescript', 'function', {\n\t\t'decorator': {\n\t\t\tpattern: /@[$\\w\\xA0-\\uFFFF]+/,\n\t\t\tinside: {\n\t\t\t\t'at': {\n\t\t\t\t\tpattern: /^@/,\n\t\t\t\t\talias: 'operator'\n\t\t\t\t},\n\t\t\t\t'function': /^[\\s\\S]+/\n\t\t\t}\n\t\t},\n\t\t'generic-function': {\n\t\t\t// e.g. foo<T extends \"bar\" | \"baz\">( ...\n\t\t\tpattern: /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*\\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\\s*\\()/,\n\t\t\tgreedy: true,\n\t\t\tinside: {\n\t\t\t\t'function': /^#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*/,\n\t\t\t\t'generic': {\n\t\t\t\t\tpattern: /<[\\s\\S]+/, // everything after the first <\n\t\t\t\t\talias: 'class-name',\n\t\t\t\t\tinside: typeInside\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tPrism.languages.ts = Prism.languages.typescript;\n\n}(Prism));\n","Prism.languages.python = {\n\t'comment': {\n\t\tpattern: /(^|[^\\\\])#.*/,\n\t\tlookbehind: true,\n\t\tgreedy: true\n\t},\n\t'string-interpolation': {\n\t\tpattern: /(?:f|fr|rf)(?:(\"\"\"|''')[\\s\\S]*?\\1|(\"|')(?:\\\\.|(?!\\2)[^\\\\\\r\\n])*\\2)/i,\n\t\tgreedy: true,\n\t\tinside: {\n\t\t\t'interpolation': {\n\t\t\t\t// \"{\" <expression> <optional \"!s\", \"!r\", or \"!a\"> <optional \":\" format specifier> \"}\"\n\t\t\t\tpattern: /((?:^|[^{])(?:\\{\\{)*)\\{(?!\\{)(?:[^{}]|\\{(?!\\{)(?:[^{}]|\\{(?!\\{)(?:[^{}])+\\})+\\})+\\}/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: {\n\t\t\t\t\t'format-spec': {\n\t\t\t\t\t\tpattern: /(:)[^:(){}]+(?=\\}$)/,\n\t\t\t\t\t\tlookbehind: true\n\t\t\t\t\t},\n\t\t\t\t\t'conversion-option': {\n\t\t\t\t\t\tpattern: //,\n\t\t\t\t\t\talias: 'punctuation'\n\t\t\t\t\t},\n\t\t\t\t\trest: null\n\t\t\t\t}\n\t\t\t},\n\t\t\t'string': /[\\s\\S]+/\n\t\t}\n\t},\n\t'triple-quoted-string': {\n\t\tpattern: /(?:[rub]|br|rb)?(\"\"\"|''')[\\s\\S]*?\\1/i,\n\t\tgreedy: true,\n\t\talias: 'string'\n\t},\n\t'string': {\n\t\tpattern: /(?:[rub]|br|rb)?(\"|')(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*\\1/i,\n\t\tgreedy: true\n\t},\n\t'function': {\n\t\tpattern: /((?:^|\\s)def[ \\t]+)[a-zA-Z_]\\w*(?=\\s*\\()/g,\n\t\tlookbehind: true\n\t},\n\t'class-name': {\n\t\tpattern: /(\\bclass\\s+)\\w+/i,\n\t\tlookbehind: true\n\t},\n\t'decorator': {\n\t\tpattern: /(^[\\t ]*)@\\w+(?:\\.\\w+)*/m,\n\t\tlookbehind: true,\n\t\talias: ['annotation', 'punctuation'],\n\t\tinside: {\n\t\t\t'punctuation': /\\./\n\t\t}\n\t},\n\t'keyword': /\\b(?:_(?=\\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\\b/,\n\t'builtin': /\\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\\b/,\n\t'boolean': /\\b(?:False|None|True)\\b/,\n\t'number': /\\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\\b|(?:\\b\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\B\\.\\d+(?:_\\d+)*)(?:e[+-]?\\d+(?:_\\d+)*)?j?(?!\\w)/i,\n\t'operator': /[-+%=]=?|!=|:=|\\*\\*?=?|\\/\\/?=?|<[<=>]?|>[=>]?|[&|^~]/,\n\t'punctuation': /[{}[\\];(),.:]/\n};\n\nPrism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;\n\nPrism.languages.py = Prism.languages.python;\n","(function (Prism) {\n\n\tvar keywords = /\\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\\s*[(){}[\\]<>=%~.:,;?+\\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\\b/;\n\n\t// full package (optional) + parent classes (optional)\n\tvar classNamePrefix = /(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*/.source;\n\n\t// based on the java naming conventions\n\tvar className = {\n\t\tpattern: RegExp(/(^|[^\\w.])/.source + classNamePrefix + /[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b/.source),\n\t\tlookbehind: true,\n\t\tinside: {\n\t\t\t'namespace': {\n\t\t\t\tpattern: /^[a-z]\\w*(?:\\s*\\.\\s*[a-z]\\w*)*(?:\\s*\\.)?/,\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': /\\./\n\t\t\t\t}\n\t\t\t},\n\t\t\t'punctuation': /\\./\n\t\t}\n\t};\n\n\tPrism.languages.java = Prism.languages.extend('clike', {\n\t\t'string': {\n\t\t\tpattern: /(^|[^\\\\])\"(?:\\\\.|[^\"\\\\\\r\\n])*\"/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t},\n\t\t'class-name': [\n\t\t\tclassName,\n\t\t\t{\n\t\t\t\t// variables, parameters, and constructor references\n\t\t\t\t// this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods)\n\t\t\t\tpattern: RegExp(/(^|[^\\w.])/.source + classNamePrefix + /[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)/.source),\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: className.inside\n\t\t\t},\n\t\t\t{\n\t\t\t\t// class names based on keyword\n\t\t\t\t// this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods)\n\t\t\t\tpattern: RegExp(/(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)/.source + classNamePrefix + /[A-Z]\\w*\\b/.source),\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: className.inside\n\t\t\t}\n\t\t],\n\t\t'keyword': keywords,\n\t\t'function': [\n\t\t\tPrism.languages.clike.function,\n\t\t\t{\n\t\t\t\tpattern: /(::\\s*)[a-z_]\\w*/,\n\t\t\t\tlookbehind: true\n\t\t\t}\n\t\t],\n\t\t'number': /\\b0b[01][01_]*L?\\b|\\b0x(?:\\.[\\da-f_p+-]+|[\\da-f_]+(?:\\.[\\da-f_p+-]+)?)\\b|(?:\\b\\d[\\d_]*(?:\\.[\\d_]*)?|\\B\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[dfl]?/i,\n\t\t'operator': {\n\t\t\tpattern: /(^|[^.])(?:<<=?|>>>?=?|->|--|\\+\\+|&&|\\|\\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,\n\t\t\tlookbehind: true\n\t\t},\n\t\t'constant': /\\b[A-Z][A-Z_\\d]+\\b/\n\t});\n\n\tPrism.languages.insertBefore('java', 'string', {\n\t\t'triple-quoted-string': {\n\t\t\t// http://openjdk.java.net/jeps/355#Description\n\t\t\tpattern: /\"\"\"[ \\t]*[\\r\\n](?:(?:\"|\"\")?(?:\\\\.|[^\"\\\\]))*\"\"\"/,\n\t\t\tgreedy: true,\n\t\t\talias: 'string'\n\t\t},\n\t\t'char': {\n\t\t\tpattern: /'(?:\\\\.|[^'\\\\\\r\\n]){1,6}'/,\n\t\t\tgreedy: true\n\t\t}\n\t});\n\n\tPrism.languages.insertBefore('java', 'class-name', {\n\t\t'annotation': {\n\t\t\tpattern: /(^|[^.])@\\w+(?:\\s*\\.\\s*\\w+)*/,\n\t\t\tlookbehind: true,\n\t\t\talias: 'punctuation'\n\t\t},\n\t\t'generics': {\n\t\t\tpattern: /<(?:[\\w\\s,.?]|&(?!&)|<(?:[\\w\\s,.?]|&(?!&)|<(?:[\\w\\s,.?]|&(?!&)|<(?:[\\w\\s,.?]|&(?!&))*>)*>)*>)*>/,\n\t\t\tinside: {\n\t\t\t\t'class-name': className,\n\t\t\t\t'keyword': keywords,\n\t\t\t\t'punctuation': /[<>(),.:]/,\n\t\t\t\t'operator': /[?&|]/\n\t\t\t}\n\t\t},\n\t\t'import': [\n\t\t\t{\n\t\t\t\tpattern: RegExp(/(\\bimport\\s+)/.source + classNamePrefix + /(?:[A-Z]\\w*|\\*)(?=\\s*;)/.source),\n\t\t\t\tlookbehind: true,\n\t\t\t\tinside: {\n\t\t\t\t\t'namespace': className.inside.namespace,\n\t\t\t\t\t'punctuation': /\\./,\n\t\t\t\t\t'operator': /\\*/,\n\t\t\t\t\t'class-name': /\\w+/\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tpattern: RegExp(/(\\bimport\\s+static\\s+)/.source + classNamePrefix + /(?:\\w+|\\*)(?=\\s*;)/.source),\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'static',\n\t\t\t\tinside: {\n\t\t\t\t\t'namespace': className.inside.namespace,\n\t\t\t\t\t'static': /\\b\\w+$/,\n\t\t\t\t\t'punctuation': /\\./,\n\t\t\t\t\t'operator': /\\*/,\n\t\t\t\t\t'class-name': /\\w+/\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t'namespace': {\n\t\t\tpattern: RegExp(\n\t\t\t\t/(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?/\n\t\t\t\t\t.source.replace(/<keyword>/g, function () { return keywords.source; })),\n\t\t\tlookbehind: true,\n\t\t\tinside: {\n\t\t\t\t'punctuation': /\\./,\n\t\t\t}\n\t\t}\n\t});\n}(Prism));\n","Prism.languages.c = Prism.languages.extend('clike', {\n\t'comment': {\n\t\tpattern: /\\/\\/(?:[^\\r\\n\\\\]|\\\\(?:\\r\\n?|\\n|(?![\\r\\n])))*|\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,\n\t\tgreedy: true\n\t},\n\t'string': {\n\t\t// https://en.cppreference.com/w/c/language/string_literal\n\t\tpattern: /\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"/,\n\t\tgreedy: true\n\t},\n\t'class-name': {\n\t\tpattern: /(\\b(?:enum|struct)\\s+(?:__attribute__\\s*\\(\\([\\s\\S]*?\\)\\)\\s*)?)\\w+|\\b[a-z]\\w*_t\\b/,\n\t\tlookbehind: true\n\t},\n\t'keyword': /\\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\\b/,\n\t'function': /\\b[a-z_]\\w*(?=\\s*\\()/i,\n\t'number': /(?:\\b0x(?:[\\da-f]+(?:\\.[\\da-f]*)?|\\.[\\da-f]+)(?:p[+-]?\\d+)?|(?:\\b\\d+(?:\\.\\d*)?|\\B\\.\\d+)(?:e[+-]?\\d+)?)[ful]{0,4}/i,\n\t'operator': />>=?|<<=?|->|([-+&|:])\\1|[?:~]|[-+*/%&|^!=<>]=?/\n});\n\nPrism.languages.insertBefore('c', 'string', {\n\t'char': {\n\t\t// https://en.cppreference.com/w/c/language/character_constant\n\t\tpattern: /'(?:\\\\(?:\\r\\n|[\\s\\S])|[^'\\\\\\r\\n]){0,32}'/,\n\t\tgreedy: true\n\t}\n});\n\nPrism.languages.insertBefore('c', 'string', {\n\t'macro': {\n\t\t// allow for multiline macro definitions\n\t\t// spaces after the # character compile fine with gcc\n\t\tpattern: /(^[\\t ]*)#\\s*[a-z](?:[^\\r\\n\\\\/]|\\/(?!\\*)|\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/|\\\\(?:\\r\\n|[\\s\\S]))*/im,\n\t\tlookbehind: true,\n\t\tgreedy: true,\n\t\talias: 'property',\n\t\tinside: {\n\t\t\t'string': [\n\t\t\t\t{\n\t\t\t\t\t// highlight the path of the include statement as a string\n\t\t\t\t\tpattern: /^(#\\s*include\\s*)<[^>]+>/,\n\t\t\t\t\tlookbehind: true\n\t\t\t\t},\n\t\t\t\tPrism.languages.c['string']\n\t\t\t],\n\t\t\t'char': Prism.languages.c['char'],\n\t\t\t'comment': Prism.languages.c['comment'],\n\t\t\t'macro-name': [\n\t\t\t\t{\n\t\t\t\t\tpattern: /(^#\\s*define\\s+)\\w+\\b(?!\\()/i,\n\t\t\t\t\tlookbehind: true\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpattern: /(^#\\s*define\\s+)\\w+\\b(?=\\()/i,\n\t\t\t\t\tlookbehind: true,\n\t\t\t\t\talias: 'function'\n\t\t\t\t}\n\t\t\t],\n\t\t\t// highlight macro directives as keywords\n\t\t\t'directive': {\n\t\t\t\tpattern: /^(#\\s*)[a-z]+/,\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'keyword'\n\t\t\t},\n\t\t\t'directive-hash': /^#/,\n\t\t\t'punctuation': /##|\\\\(?=[\\r\\n])/,\n\t\t\t'expression': {\n\t\t\t\tpattern: /\\S[\\s\\S]*/,\n\t\t\t\tinside: Prism.languages.c\n\t\t\t}\n\t\t}\n\t}\n});\n\nPrism.languages.insertBefore('c', 'function', {\n\t// highlight predefined macros as constants\n\t'constant': /\\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\\b/\n});\n\ndelete Prism.languages.c['boolean'];\n","(function (Prism) {\n\n\tvar keyword = /\\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\\b/;\n\tvar modName = /\\b(?!<keyword>)\\w+(?:\\s*\\.\\s*\\w+)*\\b/.source.replace(/<keyword>/g, function () { return keyword.source; });\n\n\tPrism.languages.cpp = Prism.languages.extend('c', {\n\t\t'class-name': [\n\t\t\t{\n\t\t\t\tpattern: RegExp(/(\\b(?:class|concept|enum|struct|typename)\\s+)(?!<keyword>)\\w+/.source\n\t\t\t\t\t.replace(/<keyword>/g, function () { return keyword.source; })),\n\t\t\t\tlookbehind: true\n\t\t\t},\n\t\t\t// This is intended to capture the class name of method implementations like:\n\t\t\t// void foo::bar() const {}\n\t\t\t// However! The `foo` in the above example could also be a namespace, so we only capture the class name if\n\t\t\t// it starts with an uppercase letter. This approximation should give decent results.\n\t\t\t/\\b[A-Z]\\w*(?=\\s*::\\s*\\w+\\s*\\()/,\n\t\t\t// This will capture the class name before destructors like:\n\t\t\t// Foo::~Foo() {}\n\t\t\t/\\b[A-Z_]\\w*(?=\\s*::\\s*~\\w+\\s*\\()/i,\n\t\t\t// This also intends to capture the class name of method implementations but here the class has template\n\t\t\t// parameters, so it can't be a namespace (until C++ adds generic namespaces).\n\t\t\t/\\b\\w+(?=\\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\\s*::\\s*\\w+\\s*\\()/\n\t\t],\n\t\t'keyword': keyword,\n\t\t'number': {\n\t\t\tpattern: /(?:\\b0b[01']+|\\b0x(?:[\\da-f']+(?:\\.[\\da-f']*)?|\\.[\\da-f']+)(?:p[+-]?[\\d']+)?|(?:\\b[\\d']+(?:\\.[\\d']*)?|\\B\\.[\\d']+)(?:e[+-]?[\\d']+)?)[ful]{0,4}/i,\n\t\t\tgreedy: true\n\t\t},\n\t\t'operator': />>=?|<<=?|->|--|\\+\\+|&&|\\|\\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\\b/,\n\t\t'boolean': /\\b(?:false|true)\\b/\n\t});\n\n\tPrism.languages.insertBefore('cpp', 'string', {\n\t\t'module': {\n\t\t\t// https://en.cppreference.com/w/cpp/language/modules\n\t\t\tpattern: RegExp(\n\t\t\t\t/(\\b(?:import|module)\\s+)/.source +\n\t\t\t\t'(?:' +\n\t\t\t\t// header-name\n\t\t\t\t/\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"|<[^<>\\r\\n]*>/.source +\n\t\t\t\t'|' +\n\t\t\t\t// module name or partition or both\n\t\t\t\t/<mod-name>(?:\\s*:\\s*<mod-name>)?|:\\s*<mod-name>/.source.replace(/<mod-name>/g, function () { return modName; }) +\n\t\t\t\t')'\n\t\t\t),\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: {\n\t\t\t\t'string': /^[<\"][\\s\\S]+/,\n\t\t\t\t'operator': /:/,\n\t\t\t\t'punctuation': /\\./\n\t\t\t}\n\t\t},\n\t\t'raw-string': {\n\t\t\tpattern: /R\"([^()\\\\ ]{0,16})\\([\\s\\S]*?\\)\\1\"/,\n\t\t\talias: 'string',\n\t\t\tgreedy: true\n\t\t}\n\t});\n\n\tPrism.languages.insertBefore('cpp', 'keyword', {\n\t\t'generic-function': {\n\t\t\tpattern: /\\b(?!operator\\b)[a-z_]\\w*\\s*<(?:[^<>]|<[^<>]*>)*>(?=\\s*\\()/i,\n\t\t\tinside: {\n\t\t\t\t'function': /^\\w+/,\n\t\t\t\t'generic': {\n\t\t\t\t\tpattern: /<[\\s\\S]+/,\n\t\t\t\t\talias: 'class-name',\n\t\t\t\t\tinside: Prism.languages.cpp\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tPrism.languages.insertBefore('cpp', 'operator', {\n\t\t'double-colon': {\n\t\t\tpattern: /::/,\n\t\t\talias: 'punctuation'\n\t\t}\n\t});\n\n\tPrism.languages.insertBefore('cpp', 'class-name', {\n\t\t// the base clause is an optional list of parent classes\n\t\t// https://en.cppreference.com/w/cpp/language/class\n\t\t'base-clause': {\n\t\t\tpattern: /(\\b(?:class|struct)\\s+\\w+\\s*:\\s*)[^;{}\"'\\s]+(?:\\s+[^;{}\"'\\s]+)*(?=\\s*[;{])/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: Prism.languages.extend('cpp', {})\n\t\t}\n\t});\n\n\tPrism.languages.insertBefore('inside', 'double-colon', {\n\t\t// All untokenized words that are not namespaces should be class names\n\t\t'class-name': /\\b[a-z_]\\w*\\b(?!\\s*::)/i\n\t}, Prism.languages.cpp['base-clause']);\n\n}(Prism));\n","Prism.languages.go = Prism.languages.extend('clike', {\n\t'string': {\n\t\tpattern: /(^|[^\\\\])\"(?:\\\\.|[^\"\\\\\\r\\n])*\"|`[^`]*`/,\n\t\tlookbehind: true,\n\t\tgreedy: true\n\t},\n\t'keyword': /\\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\\b/,\n\t'boolean': /\\b(?:_|false|iota|nil|true)\\b/,\n\t'number': [\n\t\t// binary and octal integers\n\t\t/\\b0(?:b[01_]+|o[0-7_]+)i?\\b/i,\n\t\t// hexadecimal integers and floats\n\t\t/\\b0x(?:[a-f\\d_]+(?:\\.[a-f\\d_]*)?|\\.[a-f\\d_]+)(?:p[+-]?\\d+(?:_\\d+)*)?i?(?!\\w)/i,\n\t\t// decimal integers and floats\n\t\t/(?:\\b\\d[\\d_]*(?:\\.[\\d_]*)?|\\B\\.\\d[\\d_]*)(?:e[+-]?[\\d_]+)?i?(?!\\w)/i\n\t],\n\t'operator': /[*\\/%^!=]=?|\\+[=+]?|-[=-]?|\\|[=|]?|&(?:=|&|\\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\\.\\.\\./,\n\t'builtin': /\\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\\b/\n});\n\nPrism.languages.insertBefore('go', 'string', {\n\t'char': {\n\t\tpattern: /'(?:\\\\.|[^'\\\\\\r\\n]){0,10}'/,\n\t\tgreedy: true\n\t}\n});\n\ndelete Prism.languages.go['class-name'];\n","(function (Prism) {\n\n\tvar multilineComment = /\\/\\*(?:[^*/]|\\*(?!\\/)|\\/(?!\\*)|<self>)*\\*\\//.source;\n\tfor (var i = 0; i < 2; i++) {\n\t\t// support 4 levels of nested comments\n\t\tmultilineComment = multilineComment.replace(/<self>/g, function () { return multilineComment; });\n\t}\n\tmultilineComment = multilineComment.replace(/<self>/g, function () { return /[^\\s\\S]/.source; });\n\n\n\tPrism.languages.rust = {\n\t\t'comment': [\n\t\t\t{\n\t\t\t\tpattern: RegExp(/(^|[^\\\\])/.source + multilineComment),\n\t\t\t\tlookbehind: true,\n\t\t\t\tgreedy: true\n\t\t\t},\n\t\t\t{\n\t\t\t\tpattern: /(^|[^\\\\:])\\/\\/.*/,\n\t\t\t\tlookbehind: true,\n\t\t\t\tgreedy: true\n\t\t\t}\n\t\t],\n\t\t'string': {\n\t\t\tpattern: /b?\"(?:\\\\[\\s\\S]|[^\\\\\"])*\"|b?r(#*)\"(?:[^\"]|\"(?!\\1))*\"\\1/,\n\t\t\tgreedy: true\n\t\t},\n\t\t'char': {\n\t\t\tpattern: /b?'(?:\\\\(?:x[0-7][\\da-fA-F]|u\\{(?:[\\da-fA-F]_*){1,6}\\}|.)|[^\\\\\\r\\n\\t'])'/,\n\t\t\tgreedy: true\n\t\t},\n\t\t'attribute': {\n\t\t\tpattern: /#!?\\[(?:[^\\[\\]\"]|\"(?:\\\\[\\s\\S]|[^\\\\\"])*\")*\\]/,\n\t\t\tgreedy: true,\n\t\t\talias: 'attr-name',\n\t\t\tinside: {\n\t\t\t\t'string': null // see below\n\t\t\t}\n\t\t},\n\n\t\t// Closure params should not be confused with bitwise OR |\n\t\t'closure-params': {\n\t\t\tpattern: /([=(,:]\\s*|\\bmove\\s*)\\|[^|]*\\||\\|[^|]*\\|(?=\\s*(?:\\{|->))/,\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\tinside: {\n\t\t\t\t'closure-punctuation': {\n\t\t\t\t\tpattern: /^\\||\\|$/,\n\t\t\t\t\talias: 'punctuation'\n\t\t\t\t},\n\t\t\t\trest: null // see below\n\t\t\t}\n\t\t},\n\n\t\t'lifetime-annotation': {\n\t\t\tpattern: /'\\w+/,\n\t\t\talias: 'symbol'\n\t\t},\n\n\t\t'fragment-specifier': {\n\t\t\tpattern: /(\\$\\w+:)[a-z]+/,\n\t\t\tlookbehind: true,\n\t\t\talias: 'punctuation'\n\t\t},\n\t\t'variable': /\\$\\w+/,\n\n\t\t'function-definition': {\n\t\t\tpattern: /(\\bfn\\s+)\\w+/,\n\t\t\tlookbehind: true,\n\t\t\talias: 'function'\n\t\t},\n\t\t'type-definition': {\n\t\t\tpattern: /(\\b(?:enum|struct|trait|type|union)\\s+)\\w+/,\n\t\t\tlookbehind: true,\n\t\t\talias: 'class-name'\n\t\t},\n\t\t'module-declaration': [\n\t\t\t{\n\t\t\t\tpattern: /(\\b(?:crate|mod)\\s+)[a-z][a-z_\\d]*/,\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'namespace'\n\t\t\t},\n\t\t\t{\n\t\t\t\tpattern: /(\\b(?:crate|self|super)\\s*)::\\s*[a-z][a-z_\\d]*\\b(?:\\s*::(?:\\s*[a-z][a-z_\\d]*\\s*::)*)?/,\n\t\t\t\tlookbehind: true,\n\t\t\t\talias: 'namespace',\n\t\t\t\tinside: {\n\t\t\t\t\t'punctuation': /::/\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t'keyword': [\n\t\t\t// https://github.com/rust-lang/reference/blob/master/src/keywords.md\n\t\t\t/\\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\\b/,\n\t\t\t// primitives and str\n\t\t\t// https://doc.rust-lang.org/stable/rust-by-example/primitives.html\n\t\t\t/\\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\\b/\n\t\t],\n\n\t\t// functions can technically start with an upper-case letter, but this will introduce a lot of false positives\n\t\t// and Rust's naming conventions recommend snake_case anyway.\n\t\t// https://doc.rust-lang.org/1.0.0/style/style/naming/README.html\n\t\t'function': /\\b[a-z_]\\w*(?=\\s*(?:::\\s*<|\\())/,\n\t\t'macro': {\n\t\t\tpattern: /\\b\\w+!/,\n\t\t\talias: 'property'\n\t\t},\n\t\t'constant': /\\b[A-Z_][A-Z_\\d]+\\b/,\n\t\t'class-name': /\\b[A-Z]\\w*\\b/,\n\n\t\t'namespace': {\n\t\t\tpattern: /(?:\\b[a-z][a-z_\\d]*\\s*::\\s*)*\\b[a-z][a-z_\\d]*\\s*::(?!\\s*<)/,\n\t\t\tinside: {\n\t\t\t\t'punctuation': /::/\n\t\t\t}\n\t\t},\n\n\t\t// Hex, oct, bin, dec numbers with visual separators and type suffix\n\t\t'number': /\\b(?:0x[\\dA-Fa-f](?:_?[\\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\\d(?:_?\\d)*)?\\.)?\\d(?:_?\\d)*(?:[Ee][+-]?\\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\\b/,\n\t\t'boolean': /\\b(?:false|true)\\b/,\n\t\t'punctuation': /->|\\.\\.=|\\.{1,3}|::|[{}[\\];(),:]/,\n\t\t'operator': /[-+*\\/%!^]=?|=[=>]?|&[&=]?|\\|[|=]?|<<?=?|>>?=?|[@?]/\n\t};\n\n\tPrism.languages.rust['closure-params'].inside.rest = Prism.languages.rust;\n\tPrism.languages.rust['attribute'].inside['string'] = Prism.languages.rust['string'];\n\n}(Prism));\n","Prism.languages.sql = {\n\t'comment': {\n\t\tpattern: /(^|[^\\\\])(?:\\/\\*[\\s\\S]*?\\*\\/|(?:--|\\/\\/|#).*)/,\n\t\tlookbehind: true\n\t},\n\t'variable': [\n\t\t{\n\t\t\tpattern: /@([\"'`])(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])+\\1/,\n\t\t\tgreedy: true\n\t\t},\n\t\t/@[\\w.$]+/\n\t],\n\t'string': {\n\t\tpattern: /(^|[^@\\\\])(\"|')(?:\\\\[\\s\\S]|(?!\\2)[^\\\\]|\\2\\2)*\\2/,\n\t\tgreedy: true,\n\t\tlookbehind: true\n\t},\n\t'identifier': {\n\t\tpattern: /(^|[^@\\\\])`(?:\\\\[\\s\\S]|[^`\\\\]|``)*`/,\n\t\tgreedy: true,\n\t\tlookbehind: true,\n\t\tinside: {\n\t\t\t'punctuation': /^`|`$/\n\t\t}\n\t},\n\t'function': /\\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\\s*\\()/i, // Should we highlight user defined functions too?\n\t'keyword': /\\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\\b/i,\n\t'boolean': /\\b(?:FALSE|NULL|TRUE)\\b/i,\n\t'number': /\\b0x[\\da-f]+\\b|\\b\\d+(?:\\.\\d*)?|\\B\\.\\d+\\b/i,\n\t'operator': /[-+*\\/=%^~]|&&?|\\|\\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\\b/i,\n\t'punctuation': /[;[\\]()`,.]/\n};\n","(function (Prism) {\n\n\t// https://yaml.org/spec/1.2/spec.html#c-ns-anchor-property\n\t// https://yaml.org/spec/1.2/spec.html#c-ns-alias-node\n\tvar anchorOrAlias = /[*&][^\\s[\\]{},]+/;\n\t// https://yaml.org/spec/1.2/spec.html#c-ns-tag-property\n\tvar tag = /!(?:<[\\w\\-%#;/?:@&=+$,.!~*'()[\\]]+>|(?:[a-zA-Z\\d-]*!)?[\\w\\-%#;/?:@&=+$.~*'()]+)?/;\n\t// https://yaml.org/spec/1.2/spec.html#c-ns-properties(n,c)\n\tvar properties = '(?:' + tag.source + '(?:[ \\t]+' + anchorOrAlias.source + ')?|'\n\t\t+ anchorOrAlias.source + '(?:[ \\t]+' + tag.source + ')?)';\n\t// https://yaml.org/spec/1.2/spec.html#ns-plain(n,c)\n\t// This is a simplified version that doesn't support \"#\" and multiline keys\n\t// All these long scarry character classes are simplified versions of YAML's characters\n\tvar plainKey = /(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-]<PLAIN>)(?:[ \\t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source\n\t\t.replace(/<PLAIN>/g, function () { return /[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]/.source; });\n\tvar string = /\"(?:[^\"\\\\\\r\\n]|\\\\.)*\"|'(?:[^'\\\\\\r\\n]|\\\\.)*'/.source;\n\n\t/**\n\t *\n\t * @param {string} value\n\t * @param {string} [flags]\n\t * @returns {RegExp}\n\t */\n\tfunction createValuePattern(value, flags) {\n\t\tflags = (flags || '').replace(/m/g, '') + 'm'; // add m flag\n\t\tvar pattern = /([:\\-,[{]\\s*(?:\\s<<prop>>[ \\t]+)?)(?:<<value>>)(?=[ \\t]*(?:$|,|\\]|\\}|(?:[\\r\\n]\\s*)?#))/.source\n\t\t\t.replace(/<<prop>>/g, function () { return properties; }).replace(/<<value>>/g, function () { return value; });\n\t\treturn RegExp(pattern, flags);\n\t}\n\n\tPrism.languages.yaml = {\n\t\t'scalar': {\n\t\t\tpattern: RegExp(/([\\-:]\\s*(?:\\s<<prop>>[ \\t]+)?[|>])[ \\t]*(?:((?:\\r?\\n|\\r)[ \\t]+)\\S[^\\r\\n]*(?:\\2[^\\r\\n]+)*)/.source\n\t\t\t\t.replace(/<<prop>>/g, function () { return properties; })),\n\t\t\tlookbehind: true,\n\t\t\talias: 'string'\n\t\t},\n\t\t'comment': /#.*/,\n\t\t'key': {\n\t\t\tpattern: RegExp(/((?:^|[:\\-,[{\\r\\n?])[ \\t]*(?:<<prop>>[ \\t]+)?)<<key>>(?=\\s*:\\s)/.source\n\t\t\t\t.replace(/<<prop>>/g, function () { return properties; })\n\t\t\t\t.replace(/<<key>>/g, function () { return '(?:' + plainKey + '|' + string + ')'; })),\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true,\n\t\t\talias: 'atrule'\n\t\t},\n\t\t'directive': {\n\t\t\tpattern: /(^[ \\t]*)%.+/m,\n\t\t\tlookbehind: true,\n\t\t\talias: 'important'\n\t\t},\n\t\t'datetime': {\n\t\t\tpattern: createValuePattern(/\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \\t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \\t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?/.source),\n\t\t\tlookbehind: true,\n\t\t\talias: 'number'\n\t\t},\n\t\t'boolean': {\n\t\t\tpattern: createValuePattern(/false|true/.source, 'i'),\n\t\t\tlookbehind: true,\n\t\t\talias: 'important'\n\t\t},\n\t\t'null': {\n\t\t\tpattern: createValuePattern(/null|~/.source, 'i'),\n\t\t\tlookbehind: true,\n\t\t\talias: 'important'\n\t\t},\n\t\t'string': {\n\t\t\tpattern: createValuePattern(string),\n\t\t\tlookbehind: true,\n\t\t\tgreedy: true\n\t\t},\n\t\t'number': {\n\t\t\tpattern: createValuePattern(/[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)/.source, 'i'),\n\t\t\tlookbehind: true\n\t\t},\n\t\t'tag': tag,\n\t\t'important': anchorOrAlias,\n\t\t'punctuation': /---|[:[\\]{}\\-,|>?]|\\.\\.\\./\n\t};\n\n\tPrism.languages.yml = Prism.languages.yaml;\n\n}(Prism));\n","// https://www.json.org/json-en.html\nPrism.languages.json = {\n\t'property': {\n\t\tpattern: /(^|[^\\\\])\"(?:\\\\.|[^\\\\\"\\r\\n])*\"(?=\\s*:)/,\n\t\tlookbehind: true,\n\t\tgreedy: true\n\t},\n\t'string': {\n\t\tpattern: /(^|[^\\\\])\"(?:\\\\.|[^\\\\\"\\r\\n])*\"(?!\\s*:)/,\n\t\tlookbehind: true,\n\t\tgreedy: true\n\t},\n\t'comment': {\n\t\tpattern: /\\/\\/.*|\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,\n\t\tgreedy: true\n\t},\n\t'number': /-?\\b\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?\\b/i,\n\t'punctuation': /[{}[\\],]/,\n\t'operator': /:/,\n\t'boolean': /\\b(?:false|true)\\b/,\n\t'null': {\n\t\tpattern: /\\bnull\\b/,\n\t\talias: 'keyword'\n\t}\n};\n\nPrism.languages.webmanifest = Prism.languages.json;\n","// Import Prism core and set manual mode before loading any grammars\nimport Prism from \"prismjs\";\n\nPrism.manual = true;\n\n// Import grammars in dependency order\n// markup, css, and clike are standalone\nimport \"prismjs/components/prism-markup\";\nimport \"prismjs/components/prism-css\";\nimport \"prismjs/components/prism-clike\";\n\n// javascript depends on clike\nimport \"prismjs/components/prism-javascript\";\n\n// typescript depends on javascript\nimport \"prismjs/components/prism-typescript\";\n\n// python is standalone\nimport \"prismjs/components/prism-python\";\n\n// java depends on clike\nimport \"prismjs/components/prism-java\";\n\n// c depends on clike\nimport \"prismjs/components/prism-c\";\n\n// cpp depends on c\nimport \"prismjs/components/prism-cpp\";\n\n// go depends on clike\nimport \"prismjs/components/prism-go\";\n\n// rust depends on clike\nimport \"prismjs/components/prism-rust\";\n\n// sql is standalone\nimport \"prismjs/components/prism-sql\";\n\n// Yaml \nimport \"prismjs/components/prism-yaml\";\n\n// JSON\nimport \"prismjs/components/prism-json\";\n\nexport { Prism };\n","/**\n * Dropdown widget — a select-like component composing ContextMenu.\n *\n * Features:\n * - Keyboard navigation (Enter/Space/ArrowDown opens; ArrowUp/Down navigates; Enter selects; Escape closes)\n * - Type-ahead filtering with 500ms buffer reset\n * - ARIA: role=\"listbox\" on menu, role=\"option\" on items, aria-haspopup/aria-expanded on trigger\n * - Programmatic value get/set\n * - dismissOnClickOutside for click-outside handling\n */\n\nimport { ContextMenu } from \"./context-menu\";\nimport type { MenuItem } from \"./context-menu\";\nimport { dismissOnClickOutside } from \"./dismiss\";\nimport type { DismissHandle } from \"./dismiss\";\nimport { Check, iconHtml } from \"../util/icons\";\n\n/** A single item in a {@link Dropdown}. */\nexport interface DropdownItem {\n /** Unique identifier for this item. */\n id: string;\n /** Human-readable display name shown in trigger and menu. */\n label: string;\n /** Optional secondary description shown below the label. */\n description?: string;\n /**\n * Optional icon: either an HTML string or a render function.\n * Render functions receive the icon container element.\n */\n icon?: string | ((container: HTMLElement) => void);\n /** Group key — separator inserted between different sections. */\n section?: string;\n /** When true, the item is rendered dimmed and cannot be selected. */\n disabled?: boolean;\n}\n\n/** Construction options for {@link Dropdown}. */\nexport interface DropdownOptions {\n /** Available items. */\n items: DropdownItem[];\n /** Called when an item is selected. */\n onSelect?: (item: DropdownItem) => void;\n /** Initially selected item id. */\n value?: string;\n /** Placeholder text when nothing selected (default: \"Select...\"). */\n placeholder?: string;\n /** Additional CSS class on the trigger button. */\n className?: string;\n}\n\nexport class Dropdown {\n private triggerEl: HTMLButtonElement;\n private menu: ContextMenu;\n private currentItems: DropdownItem[];\n private selectedId: string | null;\n private onSelectCallback: ((item: DropdownItem) => void) | undefined;\n private placeholder: string;\n private dismissHandle: DismissHandle | null = null;\n private docKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** Type-ahead state */\n private typeAheadBuffer = \"\";\n private typeAheadTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: DropdownOptions) {\n this.currentItems = options.items;\n this.selectedId = options.value ?? null;\n this.onSelectCallback = options.onSelect;\n this.placeholder = options.placeholder ?? \"Select...\";\n\n // Create trigger button\n this.triggerEl = document.createElement(\"button\");\n this.triggerEl.type = \"button\";\n this.triggerEl.classList.add(\"blx-dropdown-trigger\");\n if (options.className) {\n this.triggerEl.classList.add(options.className);\n }\n this.triggerEl.setAttribute(\"aria-haspopup\", \"listbox\");\n this.triggerEl.setAttribute(\"aria-expanded\", \"false\");\n this.updateTriggerLabel();\n\n // Create ContextMenu with listbox role\n this.menu = new ContextMenu({\n role: \"listbox\",\n className: \"blx-dropdown-menu\",\n });\n\n // Wire up ContextMenu callbacks\n this.menu.onSelect = (menuItem: MenuItem) => {\n const item = this.currentItems.find((it) => it.id === menuItem.id);\n if (!item) return;\n this.selectedId = item.id;\n this.updateTriggerLabel();\n this.close();\n this.onSelectCallback?.(item);\n };\n\n this.menu.onClose = () => {\n this.close();\n };\n }\n\n /**\n * Append trigger button and menu to the given container.\n * The menu element is appended to the nearest `.blx-editor` ancestor (for\n * CSS variable inheritance) or document.body as a fallback.\n * Call before interacting with the dropdown.\n */\n attachTo(container: HTMLElement): void {\n container.appendChild(this.triggerEl);\n // Append menu to the nearest .blx-editor ancestor so it can inherit\n // CSS custom properties (--blx-surface, --blx-text, etc.).\n // position:fixed in .blx-menu means placement is viewport-relative regardless.\n const editorRoot = container.closest(\".blx-editor\") as HTMLElement | null;\n (editorRoot ?? document.body).appendChild(this.menu.el);\n\n // Wire trigger event listeners\n this.triggerEl.addEventListener(\"click\", this.handleTriggerClick);\n this.triggerEl.addEventListener(\"keydown\", this.handleTriggerKeyDown);\n }\n\n /** Currently selected item id, or null if nothing is selected. */\n get value(): string | null {\n return this.selectedId;\n }\n\n /**\n * Programmatically set the selected item.\n * Updates trigger label. Does not call onSelect.\n */\n setValue(id: string): void {\n this.selectedId = id;\n this.updateTriggerLabel();\n }\n\n /** Open the dropdown menu. */\n open(): void {\n const rect = this.triggerEl.getBoundingClientRect();\n const checkIcon = iconHtml(Check, 14);\n const menuItems: MenuItem[] = this.currentItems.map((item) => ({\n id: item.id,\n label: item.label,\n description: item.description,\n icon: item.id === this.selectedId\n ? (container: HTMLElement) => {\n container.innerHTML = checkIcon;\n container.classList.add(\"blx-dropdown-check\");\n }\n : item.icon ?? (() => {}), // spacer preserves label alignment\n section: item.section,\n disabled: item.disabled,\n }));\n\n this.menu.show(rect, menuItems);\n this.triggerEl.setAttribute(\"aria-expanded\", \"true\");\n\n // Right-align menu with trigger when trigger is in the right half of viewport\n requestAnimationFrame(() => {\n const menuEl = this.menu.el;\n const menuWidth = menuEl.offsetWidth;\n const triggerRight = rect.right;\n if (rect.left > window.innerWidth / 2) {\n menuEl.style.left = `${triggerRight - menuWidth}px`;\n }\n });\n\n // Highlight currently selected item\n if (this.selectedId) {\n const idx = this.currentItems.findIndex((it) => it.id === this.selectedId);\n if (idx >= 0) {\n this.menu.selectIndex(idx);\n }\n }\n\n // Install keydown forwarder on document\n this.docKeyHandler = (e: KeyboardEvent) => {\n // First try ContextMenu navigation (ArrowUp/Down/Enter/Escape)\n const consumed = this.menu.handleKeyDown(e);\n if (!consumed) {\n // If not consumed, try type-ahead\n this.handleTypeAhead(e);\n }\n };\n document.addEventListener(\"keydown\", this.docKeyHandler, true);\n\n // Install dismiss-on-click-outside (ignore trigger)\n this.dismissHandle = dismissOnClickOutside(\n this.menu.el,\n () => this.close(),\n {\n escapeKey: false, // Escape is handled via docKeyHandler → ContextMenu.handleKeyDown\n defer: true,\n ignoreElements: [this.triggerEl],\n },\n );\n }\n\n /** Close the dropdown menu and return focus to trigger. */\n close(): void {\n if (!this.menu.visible) return;\n this.menu.hide();\n this.triggerEl.setAttribute(\"aria-expanded\", \"false\");\n\n // Remove document keydown forwarder\n if (this.docKeyHandler) {\n document.removeEventListener(\"keydown\", this.docKeyHandler, true);\n this.docKeyHandler = null;\n }\n\n // Remove dismiss handler\n if (this.dismissHandle) {\n this.dismissHandle.remove();\n this.dismissHandle = null;\n }\n\n // Clear type-ahead buffer\n if (this.typeAheadTimer) {\n clearTimeout(this.typeAheadTimer);\n this.typeAheadTimer = null;\n }\n this.typeAheadBuffer = \"\";\n }\n\n /**\n * Clean up the dropdown: remove trigger from DOM, destroy menu, remove all listeners.\n */\n destroy(): void {\n this.close();\n this.triggerEl.removeEventListener(\"click\", this.handleTriggerClick);\n this.triggerEl.removeEventListener(\"keydown\", this.handleTriggerKeyDown);\n this.triggerEl.remove();\n this.menu.destroy();\n }\n\n // ── Private ────────────────────────────────────────────────────\n\n private updateTriggerLabel(): void {\n const selected = this.currentItems.find((it) => it.id === this.selectedId);\n this.triggerEl.textContent = selected?.label ?? this.placeholder;\n }\n\n private readonly handleTriggerClick = (): void => {\n if (this.menu.visible) {\n this.close();\n } else {\n this.open();\n }\n };\n\n private readonly handleTriggerKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Enter\" || e.key === \" \" || e.key === \"ArrowDown\") {\n e.preventDefault();\n if (!this.menu.visible) {\n this.open();\n }\n }\n };\n\n private handleTypeAhead(e: KeyboardEvent): void {\n // Only single printable characters without modifier keys\n if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;\n\n this.typeAheadBuffer += e.key.toLowerCase();\n\n if (this.typeAheadTimer) clearTimeout(this.typeAheadTimer);\n this.typeAheadTimer = setTimeout(() => {\n this.typeAheadBuffer = \"\";\n this.typeAheadTimer = null;\n }, 500);\n\n // Find first non-disabled item whose label starts with buffer\n const match = this.currentItems.findIndex(\n (item) => !item.disabled && item.label.toLowerCase().startsWith(this.typeAheadBuffer),\n );\n\n if (match >= 0) {\n this.menu.selectIndex(match);\n }\n }\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { Prism } from \"./prism-loader\";\nimport { Dropdown } from \"../ui/dropdown\";\nimport type { DropdownItem } from \"../ui/dropdown\";\n\nexport interface CodeBlockMetadata {\n [key: string]: unknown;\n language: string;\n agendaDate?: string; // ISO 8601 date: \"YYYY-MM-DD\"\n}\n\nexport const CODE_LANGUAGES = [\n { id: \"plain\", label: \"Plain Text\" },\n { id: \"json\", label: \"JSON\"},\n { id: \"javascript\", label: \"JavaScript\" },\n { id: \"typescript\", label: \"TypeScript\" },\n { id: \"html\", label: \"HTML\" },\n { id: \"css\", label: \"CSS\" },\n { id: \"python\", label: \"Python\" },\n { id: \"java\", label: \"Java\" },\n { id: \"c\", label: \"C\" },\n { id: \"cpp\", label: \"C++\" },\n { id: \"go\", label: \"Go\" },\n { id: \"rust\", label: \"Rust\" },\n { id: \"sql\", label: \"SQL\" },\n { id: \"yaml\", label: \"YAML\"},\n] as const;\n\nconst VALID_LANGUAGE_IDS: Set<string> = new Set(CODE_LANGUAGES.map((l) => l.id));\n\n/** Map language IDs to Prism grammar names */\nfunction prismGrammarName(language: string): string {\n if (language === \"html\") return \"markup\";\n return language;\n}\n\n// ── Deferred Prism highlighting ──────────────────────────────────\n\nconst pendingHighlights = new WeakMap<HTMLElement, number>();\n\nfunction saveCursorOffset(el: HTMLElement): number | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const range = sel.getRangeAt(0);\n if (!el.contains(range.startContainer)) return null;\n const preRange = document.createRange();\n preRange.selectNodeContents(el);\n preRange.setEnd(range.startContainer, range.startOffset);\n return preRange.toString().length;\n}\n\nfunction restoreCursorOffset(el: HTMLElement, offset: number): void {\n const sel = window.getSelection();\n if (!sel) return;\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n let remaining = offset;\n let node = walker.nextNode();\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n const range = document.createRange();\n // Fix trailing newline: cursor at end of text node ending with \\n\n // should be positioned after the sibling <br> so the caret renders\n // on the new empty line, not at the end of the previous line.\n if (\n remaining === len &&\n node.textContent?.endsWith(\"\\n\") &&\n node.nextSibling?.nodeName === \"BR\"\n ) {\n range.setStartAfter(node.nextSibling);\n } else {\n range.setStart(node, remaining);\n }\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n remaining -= len;\n node = walker.nextNode();\n }\n}\n\n/**\n * Schedule Prism highlighting to run on the next animation frame.\n * This keeps the synchronous update() cursor-safe (uses textContent),\n * then applies syntax-highlighted innerHTML after the event handler\n * has finished positioning the cursor.\n */\nfunction scheduleHighlight(\n codeEl: HTMLElement,\n text: string,\n language: string,\n): void {\n const existing = pendingHighlights.get(codeEl);\n if (existing !== undefined) cancelAnimationFrame(existing);\n\n const grammarName = prismGrammarName(language);\n if (language === \"plain\" || !Prism.languages[grammarName]) {\n pendingHighlights.delete(codeEl);\n return;\n }\n\n const frame = requestAnimationFrame(() => {\n pendingHighlights.delete(codeEl);\n // Bail if content changed since we scheduled\n if (codeEl.textContent !== text) return;\n\n const offset = saveCursorOffset(codeEl);\n const hadFocus =\n document.activeElement === codeEl ||\n codeEl.contains(document.activeElement);\n\n codeEl.innerHTML = Prism.highlight(\n text,\n Prism.languages[grammarName],\n grammarName,\n );\n if (text.endsWith(\"\\n\")) {\n codeEl.appendChild(document.createElement(\"br\"));\n }\n\n if (offset !== null && hadFocus) {\n codeEl.focus();\n restoreCursorOffset(codeEl, offset);\n }\n });\n pendingHighlights.set(codeEl, frame);\n}\n\n// ── Immediate render (used for initial render / language change) ─\n\nfunction renderCodeContent(\n codeEl: HTMLElement,\n text: string,\n language: string,\n): void {\n codeEl.style.whiteSpace = \"pre\";\n\n const grammarName = prismGrammarName(language);\n if (language === \"plain\" || !Prism.languages[grammarName]) {\n codeEl.textContent = text;\n } else {\n codeEl.innerHTML = Prism.highlight(text, Prism.languages[grammarName], grammarName);\n }\n\n if (!text || text.endsWith(\"\\n\")) {\n codeEl.appendChild(document.createElement(\"br\"));\n }\n}\n\n// ── Dropdown WeakMap ─────────────────────────────────────────────\n// Maps container → Dropdown instance so update() can call setValue()\nconst codeLangDropdowns = new WeakMap<HTMLElement, Dropdown>();\n\n// ── Plugin ───────────────────────────────────────────────────────\n\nexport const codeBlockPlugin: BlockTypePlugin<CodeBlockMetadata> = {\n type: \"code\",\n label: \"Code Block\",\n hasTextContent: true,\n indentable: false,\n tabInsertsSpaces: true,\n allowedAttributes: [],\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): CodeBlockMetadata {\n return { language: \"plain\" };\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\", shortcutHint: \"Ctrl+Shift+0\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n ];\n },\n\n metadataFromConversion(_fromType: string, fromMetadata: BlockMetadata): CodeBlockMetadata {\n const result: CodeBlockMetadata = { language: \"plain\" };\n if (typeof fromMetadata.agendaDate === \"string\") {\n result.agendaDate = fromMetadata.agendaDate;\n }\n return result;\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n\n // Generic content wrapper (hover widgets will attach here)\n const contentWrapper = document.createElement(\"div\");\n contentWrapper.classList.add(\"blx-block-content\");\n\n const codeBlock = document.createElement(\"div\");\n codeBlock.classList.add(\"blx-code-block\");\n\n // Language picker using Dropdown widget\n const picker = document.createElement(\"div\");\n picker.classList.add(\"blx-code-lang-picker\");\n picker.setAttribute(\"contenteditable\", \"false\");\n\n const langItems: DropdownItem[] = CODE_LANGUAGES.map((lang) => ({\n id: lang.id,\n label: lang.label,\n }));\n\n // Destroy old dropdown before creating a new one (prevents orphaned menu elements)\n codeLangDropdowns.get(container)?.destroy();\n\n const langDropdown = new Dropdown({\n items: langItems,\n value: metadata.language,\n className: \"blx-code-lang-dropdown\",\n onSelect: (item) => {\n const event = new CustomEvent(\"blx:codeLanguageChange\", {\n bubbles: true,\n detail: { language: item.id },\n });\n container.dispatchEvent(event);\n },\n });\n\n const pre = document.createElement(\"pre\");\n pre.classList.add(\"blx-code-pre\");\n\n const code = document.createElement(\"code\");\n code.classList.add(\"blx-code-content\");\n code.setAttribute(\"contenteditable\", \"true\");\n code.setAttribute(\"spellcheck\", \"false\");\n code.setAttribute(\"dir\", \"ltr\");\n\n // Full Prism render on initial mount\n renderCodeContent(code, content.text, metadata.language);\n\n pre.appendChild(code);\n codeBlock.appendChild(pre);\n contentWrapper.appendChild(codeBlock);\n contentWrapper.appendChild(picker);\n container.appendChild(contentWrapper);\n\n // attachTo must be called after picker is in the DOM so that\n // closest(\".blx-editor\") succeeds and the menu inherits CSS variables.\n langDropdown.attachTo(picker);\n codeLangDropdowns.set(container, langDropdown);\n\n return code;\n },\n\n update(container, contentEditable, content, metadata) {\n if (!contentEditable) return;\n contentEditable.setAttribute(\"dir\", \"ltr\");\n\n // Sync language picker via Dropdown instance\n const dropdown = codeLangDropdowns.get(container);\n if (dropdown) {\n dropdown.setValue(metadata.language);\n }\n\n // Set text immediately via textContent (cursor-safe — no DOM destruction)\n contentEditable.textContent = content.text;\n contentEditable.style.whiteSpace = \"pre\";\n if (!content.text || content.text.endsWith(\"\\n\")) {\n contentEditable.appendChild(document.createElement(\"br\"));\n }\n\n // Defer Prism highlighting to next frame so cursor positioning\n // from the event handler isn't disrupted by innerHTML replacement\n scheduleHighlight(contentEditable, content.text, metadata.language);\n },\n\n serializeMetadata(m) {\n const out: Record<string, unknown> = { language: m.language };\n if (m.agendaDate) out.agendaDate = m.agendaDate;\n return out;\n },\n\n deserializeMetadata(raw) {\n const language = typeof raw.language === \"string\" && VALID_LANGUAGE_IDS.has(raw.language)\n ? raw.language\n : \"plain\";\n const result: CodeBlockMetadata = { language };\n if (typeof raw.agendaDate === \"string\") result.agendaDate = raw.agendaDate;\n return result;\n },\n};\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget } from \"../schema\";\n\nexport interface HorizontalRuleMetadata {\n [key: string]: unknown;\n}\n\nexport const horizontalRulePlugin: BlockTypePlugin<HorizontalRuleMetadata> = {\n type: \"horizontal-rule\",\n label: \"Horizontal Rule\",\n hasTextContent: false,\n indentable: false,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): HorizontalRuleMetadata {\n return {};\n },\n\n convertibleTo(): ConversionTarget[] {\n return []; // No text content — cannot convert\n },\n\n render(container) {\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-horizontal-rule\");\n wrapper.setAttribute(\"contenteditable\", \"false\");\n const hr = document.createElement(\"hr\");\n hr.classList.add(\"blx-hr\");\n wrapper.appendChild(hr);\n container.appendChild(wrapper);\n return null;\n },\n};\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { renderAttributedString, getBlockDir, isBlockReadOnly } from \"./render-utils\";\nimport { classifyAgendaDate, agendaStateClass } from \"../date-picker/agenda-utils\";\nimport { iconHtml, Repeat2 } from \"../util/icons\";\n\nexport interface ChecklistMetadata {\n [key: string]: unknown;\n checked: boolean;\n dueDate?: string; // ISO 8601 date — task deadline\n scheduledDate?: string; // ISO 8601 date — planned start/work date\n eventDate?: string; // ISO 8601 date — calendar event\n recurrence?: {\n interval: number;\n unit: \"day\" | \"week\" | \"month\" | \"year\";\n anchor?: string;\n fromCompletion?: boolean;\n };\n /** @deprecated — migrated to dueDate/scheduledDate/eventDate by deserializeMetadata */\n agendaDate?: string;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n}\n\nexport const checklistPlugin: BlockTypePlugin<ChecklistMetadata> = {\n type: \"checklist\",\n label: \"Checklist\",\n hasTextContent: true,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): ChecklistMetadata {\n return { checked: false };\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\", shortcutHint: \"Ctrl+Shift+0\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n { type: \"blockquote\", label: \"Quote\", description: \"Blockquote text\" },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n ];\n },\n\n metadataFromConversion(_fromType: string, fromMetadata: BlockMetadata): ChecklistMetadata {\n const result: ChecklistMetadata = { checked: false };\n // Preserve date role fields across type conversions\n if (fromMetadata.dueDate !== undefined) result.dueDate = fromMetadata.dueDate as string;\n if (fromMetadata.scheduledDate !== undefined) result.scheduledDate = fromMetadata.scheduledDate as string;\n if (fromMetadata.eventDate !== undefined) result.eventDate = fromMetadata.eventDate as string;\n if (fromMetadata.recurrence !== undefined) result.recurrence = fromMetadata.recurrence as ChecklistMetadata[\"recurrence\"];\n // Keep agendaDate in case conversion happens before migration\n if (fromMetadata.agendaDate !== undefined) result.agendaDate = fromMetadata.agendaDate as string;\n return result;\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n\n const list = document.createElement(\"ul\");\n list.classList.add(\"blx-checklist\");\n list.setAttribute(\"dir\", getBlockDir(metadata));\n\n const li = document.createElement(\"li\");\n li.classList.add(\"blx-checklist-item\");\n if (metadata.checked) {\n li.classList.add(\"blx-checklist-checked\");\n }\n\n // Create checkbox\n const readOnly = isBlockReadOnly(container);\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.classList.add(\"blx-checklist-checkbox\");\n checkbox.checked = metadata.checked;\n checkbox.setAttribute(\"contenteditable\", \"false\");\n if (readOnly) checkbox.disabled = true;\n\n if (!readOnly) {\n // Dispatch custom event when checkbox is clicked.\n // We use the click event and read checkbox.checked AFTER the browser's\n // native toggle so that the visual state and our model stay in sync.\n // (Using mousedown + preventDefault broke unchecking: the subsequent\n // click event would re-toggle the checkbox when the DOM node wasn't moved.)\n checkbox.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n const event = new CustomEvent(\"blx:checklistToggle\", {\n bubbles: true,\n detail: { checked: checkbox.checked },\n });\n container.dispatchEvent(event);\n });\n }\n\n // Create content span\n const contentSpan = document.createElement(\"span\");\n contentSpan.classList.add(\"blx-checklist-content\");\n contentSpan.setAttribute(\"contenteditable\", \"true\");\n renderAttributedString(contentSpan, content);\n\n li.appendChild(checkbox);\n li.appendChild(contentSpan);\n\n // Agenda badge (right-aligned, contenteditable=false)\n const dateInfo = resolveChecklistDisplayDate(metadata);\n if (dateInfo) {\n li.appendChild(renderAgendaBadge(dateInfo.date, dateInfo.role, metadata.checked, !!metadata.recurrence, container));\n }\n\n list.appendChild(li);\n container.appendChild(list);\n\n return contentSpan;\n },\n\n update(container, contentEditable, content, metadata) {\n if (!contentEditable) return;\n\n // Update checkbox state\n const checkbox = container.querySelector<HTMLInputElement>(\".blx-checklist-checkbox\");\n const li = container.querySelector(\".blx-checklist-item\");\n\n if (checkbox) {\n checkbox.checked = metadata.checked;\n }\n\n if (li) {\n if (metadata.checked) {\n li.classList.add(\"blx-checklist-checked\");\n } else {\n li.classList.remove(\"blx-checklist-checked\");\n }\n }\n\n const list = container.querySelector(\"ul\");\n if (list) {\n list.setAttribute(\"dir\", getBlockDir(metadata));\n }\n\n // Update agenda badge\n const existingBadge = container.querySelector(\".blx-agenda-badge\");\n const dateInfo = resolveChecklistDisplayDate(metadata);\n if (dateInfo) {\n const li2 = container.querySelector(\".blx-checklist-item\");\n if (existingBadge) {\n // Update existing badge\n const display = classifyAgendaDate(dateInfo.date, undefined, dateInfo.role);\n existingBadge.textContent = display.label;\n existingBadge.className = `blx-agenda-badge ${agendaStateClass(display.state)}`;\n if (metadata.checked) existingBadge.classList.add(\"blx-agenda-done\");\n if (metadata.recurrence) existingBadge.classList.add(\"blx-agenda-recurring\");\n (existingBadge as HTMLElement).dataset.agendaDate = dateInfo.date;\n (existingBadge as HTMLElement).dataset.agendaRole = dateInfo.role;\n // Update recurrence indicator\n const existingRecur = existingBadge.querySelector(\".blx-agenda-recurrence\");\n if (metadata.recurrence && !existingRecur) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n existingBadge.appendChild(recur);\n } else if (!metadata.recurrence && existingRecur) {\n existingRecur.remove();\n }\n } else if (li2) {\n // Add new badge\n li2.appendChild(renderAgendaBadge(dateInfo.date, dateInfo.role, metadata.checked, !!metadata.recurrence, container));\n }\n } else if (existingBadge) {\n existingBadge.remove();\n }\n\n renderAttributedString(contentEditable, content);\n },\n\n serializeMetadata(m) {\n const out: Record<string, unknown> = { checked: m.checked };\n if (m.dueDate) out.dueDate = m.dueDate;\n if (m.scheduledDate) out.scheduledDate = m.scheduledDate;\n if (m.eventDate) out.eventDate = m.eventDate;\n if (m.recurrence) out.recurrence = m.recurrence;\n if (m.agendaDate) out.agendaDate = m.agendaDate;\n return out;\n },\n\n deserializeMetadata(raw) {\n // Migrate legacy agendaDate → dueDate (checklists are tasks)\n if (raw.agendaDate && !raw.dueDate && !raw.scheduledDate && !raw.eventDate) {\n raw.dueDate = raw.agendaDate;\n delete raw.agendaDate;\n }\n\n const result: ChecklistMetadata = { checked: raw.checked === true };\n if (typeof raw.dueDate === \"string\") result.dueDate = raw.dueDate;\n if (typeof raw.scheduledDate === \"string\") result.scheduledDate = raw.scheduledDate;\n if (typeof raw.eventDate === \"string\") result.eventDate = raw.eventDate;\n if (raw.recurrence && typeof raw.recurrence === \"object\") {\n result.recurrence = raw.recurrence as ChecklistMetadata[\"recurrence\"];\n }\n // Keep agendaDate if it wasn't migrated (i.e., new fields already present)\n if (typeof raw.agendaDate === \"string\") result.agendaDate = raw.agendaDate;\n return result;\n },\n};\n\n/**\n * Resolve the most relevant date from metadata for display.\n * Priority: dueDate > scheduledDate > eventDate > (legacy) agendaDate.\n */\nfunction resolveChecklistDisplayDate(metadata: ChecklistMetadata): { date: string; role: \"due\" | \"scheduled\" | \"event\" } | null {\n if (metadata.dueDate) return { date: typeof metadata.dueDate === \"string\" ? metadata.dueDate : String(metadata.dueDate), role: \"due\" };\n if (metadata.scheduledDate) return { date: typeof metadata.scheduledDate === \"string\" ? metadata.scheduledDate : String(metadata.scheduledDate), role: \"scheduled\" };\n if (metadata.eventDate) return { date: typeof metadata.eventDate === \"string\" ? metadata.eventDate : String(metadata.eventDate), role: \"event\" };\n // Legacy fallback\n if (metadata.agendaDate) return { date: typeof metadata.agendaDate === \"string\" ? metadata.agendaDate : String(metadata.agendaDate), role: \"due\" };\n return null;\n}\n\n/** Create an agenda badge element for checklist items. */\nfunction renderAgendaBadge(\n dateStr: string,\n role: \"due\" | \"scheduled\" | \"event\",\n checked: boolean,\n recurring: boolean,\n container: HTMLElement,\n): HTMLElement {\n const display = classifyAgendaDate(dateStr, undefined, role);\n const badge = document.createElement(\"span\");\n badge.classList.add(\"blx-agenda-badge\", agendaStateClass(display.state));\n if (checked) badge.classList.add(\"blx-agenda-done\");\n if (recurring) badge.classList.add(\"blx-agenda-recurring\");\n badge.setAttribute(\"contenteditable\", \"false\");\n badge.dataset.agendaDate = dateStr;\n badge.dataset.agendaRole = role;\n badge.textContent = display.label;\n\n // Recurrence indicator\n if (recurring) {\n const recur = document.createElement(\"span\");\n recur.className = \"blx-agenda-recurrence\";\n recur.innerHTML = iconHtml(Repeat2, 14, { \"stroke-width\": \"2.5\" });\n badge.appendChild(recur);\n }\n\n // Click to edit agenda item (disabled in read-only mode)\n if (!isBlockReadOnly(container)) {\n badge.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n container.dispatchEvent(new CustomEvent(\"blx:agendaEdit\", {\n bubbles: true,\n detail: { role, date: dateStr },\n }));\n });\n }\n\n return badge;\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget } from \"../schema\";\n\nexport interface YouTubeMetadata {\n [key: string]: unknown;\n videoId: string;\n startTime?: number;\n}\n\n/**\n * Extract a YouTube video ID from various URL formats:\n * - https://www.youtube.com/watch?v=VIDEO_ID\n * - https://youtu.be/VIDEO_ID\n * - https://www.youtube.com/embed/VIDEO_ID\n * - https://youtube.com/shorts/VIDEO_ID\n * - https://www.youtube-nocookie.com/embed/VIDEO_ID\n *\n * Returns `{ videoId, startTime? }` or `null` if no match.\n */\nexport function parseYouTubeUrl(\n raw: string,\n): { videoId: string; startTime?: number } | null {\n const trimmed = raw.trim();\n\n // youtu.be/VIDEO_ID\n const shortMatch = trimmed.match(\n /(?:https?:\\/\\/)?youtu\\.be\\/([A-Za-z0-9_-]{11})/,\n );\n if (shortMatch) {\n return { videoId: shortMatch[1], startTime: parseStart(trimmed) };\n }\n\n // youtube.com variants\n const longMatch = trimmed.match(\n /(?:https?:\\/\\/)?(?:www\\.)?(?:youtube\\.com|youtube-nocookie\\.com)\\/(?:watch\\?.*v=|embed\\/|shorts\\/)([A-Za-z0-9_-]{11})/,\n );\n if (longMatch) {\n return { videoId: longMatch[1], startTime: parseStart(trimmed) };\n }\n\n // Bare video ID (exactly 11 chars, valid characters)\n if (/^[A-Za-z0-9_-]{11}$/.test(trimmed)) {\n return { videoId: trimmed };\n }\n\n return null;\n}\n\n/** Extract `t=` or `start=` seconds from a URL query string. */\nfunction parseStart(url: string): number | undefined {\n const tMatch = url.match(/[?&](?:t|start)=(\\d+)/);\n return tMatch ? Number(tMatch[1]) : undefined;\n}\n\nexport const youtubePlugin: BlockTypePlugin<YouTubeMetadata> = {\n type: \"youtube\",\n label: \"YouTube\",\n hasTextContent: false,\n indentable: false,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): YouTubeMetadata {\n return { videoId: \"\" };\n },\n\n convertibleTo(): ConversionTarget[] {\n return []; // No text content — cannot convert\n },\n\n serializeMetadata(m: YouTubeMetadata) {\n const out: Record<string, unknown> = { videoId: m.videoId };\n if (m.startTime !== undefined) out.startTime = m.startTime;\n return out;\n },\n\n deserializeMetadata(raw: Record<string, unknown>): YouTubeMetadata {\n return {\n videoId: typeof raw.videoId === \"string\" ? raw.videoId : \"\",\n startTime:\n typeof raw.startTime === \"number\" ? raw.startTime : undefined,\n };\n },\n\n render(container, _content, metadata) {\n container.innerHTML = \"\";\n\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-youtube\");\n wrapper.setAttribute(\"contenteditable\", \"false\");\n\n if (!metadata.videoId) {\n // Show URL input placeholder\n const placeholder = document.createElement(\"div\");\n placeholder.classList.add(\"blx-youtube-placeholder\");\n\n const icon = document.createElement(\"span\");\n icon.classList.add(\"blx-youtube-icon\");\n icon.textContent = \"\\u25B6\"; // ▶\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"blx-youtube-input\");\n input.placeholder = \"Paste a YouTube URL…\";\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n const parsed = parseYouTubeUrl(input.value);\n if (parsed) {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-youtube-commit\", {\n bubbles: true,\n detail: parsed,\n }),\n );\n } else {\n input.classList.add(\"blx-youtube-input-error\");\n setTimeout(() => input.classList.remove(\"blx-youtube-input-error\"), 600);\n }\n }\n });\n\n placeholder.appendChild(icon);\n placeholder.appendChild(input);\n wrapper.appendChild(placeholder);\n } else {\n // Render responsive iframe embed\n const aspect = document.createElement(\"div\");\n aspect.classList.add(\"blx-youtube-aspect\", \"blx-youtube-loading\");\n\n let src = `https://www.youtube-nocookie.com/embed/${metadata.videoId}`;\n if (metadata.startTime) src += `?start=${metadata.startTime}`;\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = src;\n iframe.setAttribute(\"frameborder\", \"0\");\n iframe.setAttribute(\n \"allow\",\n \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n );\n iframe.setAttribute(\"allowfullscreen\", \"\");\n iframe.setAttribute(\"loading\", \"lazy\");\n iframe.title = \"YouTube video\";\n\n iframe.addEventListener(\"load\", () => {\n aspect.classList.remove(\"blx-youtube-loading\");\n });\n\n aspect.appendChild(iframe);\n wrapper.appendChild(aspect);\n }\n\n container.appendChild(wrapper);\n return null;\n },\n\n update(container, _contentEditable, _content, metadata) {\n // Only re-render if videoId changed — compare with current iframe src\n const iframe = container.querySelector(\"iframe\");\n const hasVideo = !!metadata.videoId;\n const hasIframe = !!iframe;\n\n if (hasVideo === hasIframe && hasIframe) {\n // Both exist — check if src matches\n let expected = `https://www.youtube-nocookie.com/embed/${metadata.videoId}`;\n if (metadata.startTime) expected += `?start=${metadata.startTime}`;\n if (iframe.src === expected) return;\n }\n\n // Full re-render\n this.render(container, _content, metadata);\n },\n};\n","export type { BlobStore } from \"./types\";\n\nimport type { BlobStore } from \"./types\";\n\n// ── Module-level blob store (follows the setUrlResolver pattern) ────\n\nlet _blobStore: BlobStore | null = null;\n\n/** Register a blob store for the editor to use for image storage. */\nexport function setBlobStore(store: BlobStore | null): void {\n _blobStore = store;\n}\n\n/** Get the currently registered blob store (if any). */\nexport function getBlobStore(): BlobStore | null {\n return _blobStore;\n}\n\n// ── Blob reference helpers ──────────────────────────────────────────\n\n/** Prefix used for blob-store references in metadata.src. */\nconst BLOB_REF_PREFIX = \"blxblob:\";\n\n/** Check whether a `src` value is a blob-store reference. */\nexport function isBlobRef(src: unknown): boolean {\n return typeof src === \"string\" && src.startsWith(BLOB_REF_PREFIX);\n}\n\n/** Build a blob reference string from a SHA-256 hex digest. */\nexport function makeBlobRef(sha256Hex: string): string {\n return `${BLOB_REF_PREFIX}${sha256Hex}`;\n}\n\n/** Extract the hash portion from a blob reference string. */\nexport function blobRefHash(ref: string): string {\n return ref.slice(BLOB_REF_PREFIX.length);\n}\n\n/**\n * Resolve a `src` string to a displayable URL.\n *\n * - Regular URLs / data URIs are returned as-is.\n * - Blob references (`blxblob:…`) are resolved through the registered\n * blob store. Returns `null` if the store is missing or the key is\n * not found.\n */\nexport async function resolveBlobSrc(\n src: unknown,\n): Promise<string | null> {\n const srcStr = String(src);\n if (!isBlobRef(srcStr)) return srcStr;\n if (!_blobStore) return null;\n return _blobStore.getUrl(srcStr);\n}\n\n/**\n * Store a file's contents in the blob store (if one is registered) and\n * return the blob reference key. Falls back to a base64 data URI when\n * no blob store is available.\n */\nexport async function storeFileAsBlob(file: File): Promise<string> {\n if (_blobStore) {\n const buffer = await readFileAsArrayBuffer(file);\n return _blobStore.put(buffer);\n }\n // Fallback: convert to data URI (legacy behaviour)\n return new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n}\n\n/** Read a File as an ArrayBuffer (works in jsdom where File.arrayBuffer may be missing). */\nfunction readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {\n if (typeof file.arrayBuffer === \"function\") {\n return file.arrayBuffer();\n }\n return new Promise<ArrayBuffer>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as ArrayBuffer);\n reader.onerror = () => reject(reader.error);\n reader.readAsArrayBuffer(file);\n });\n}\n\n// ── SHA-256 hashing utility ─────────────────────────────────────────\n\n/**\n * Compute the SHA-256 hex digest of an ArrayBuffer.\n * Uses the Web Crypto API (available in browsers and Node 18+).\n */\nexport async function sha256Hex(data: ArrayBuffer): Promise<string> {\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const bytes = new Uint8Array(hashBuffer);\n let hex = \"\";\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i].toString(16).padStart(2, \"0\");\n }\n return hex;\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget } from \"../schema\";\nimport { isBlobRef, resolveBlobSrc, storeFileAsBlob } from \"../blob-store\";\nimport { iconHtml, Image as ImageIcon } from \"../util/icons\";\n\n/**\n * Extract a plain string from a raw metadata value.\n * Handles plain strings, Automerge ImmutableString (.val property),\n * and legacy map-encoded strings created by a previous ImmutableString\n * serialization bug where ImmutableString was spread into { val: \"...\" }.\n */\nfunction extractString(val: unknown): string | undefined {\n if (typeof val === \"string\") return val;\n if (val == null) return undefined;\n // ImmutableString / legacy map-encoded string both surface a .val string property\n if (typeof (val as Record<string, unknown>).val === \"string\") {\n return (val as Record<string, unknown>).val as string;\n }\n return undefined;\n}\n\nexport interface ImageMetadata {\n [key: string]: unknown;\n /** Image source URL, data: URI, or blob-store reference (`blxblob:…`) */\n src: string;\n /** Alt text for accessibility */\n alt?: string;\n /** Caption text */\n caption?: string;\n /** Display width in pixels (null = auto) */\n width?: number;\n /** Intrinsic image width, captured on first load. Used with naturalHeight\n * to set width/height attributes so the browser reserves correct aspect\n * ratio space before the image loads, preventing layout shift. */\n naturalWidth?: number;\n /** Intrinsic image height, captured on first load. */\n naturalHeight?: number;\n}\n\nexport const imagePlugin: BlockTypePlugin<ImageMetadata> = {\n type: \"image\",\n label: \"Image\",\n hasTextContent: false,\n indentable: false,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): ImageMetadata {\n return { src: \"\" };\n },\n\n convertibleTo(): ConversionTarget[] {\n return []; // No text content — cannot convert\n },\n\n serializeMetadata(m: ImageMetadata) {\n const out: Record<string, unknown> = { src: m.src };\n if (m.alt) out.alt = m.alt;\n if (m.caption) out.caption = m.caption;\n if (m.width !== undefined) out.width = m.width;\n if (m.naturalWidth !== undefined) out.naturalWidth = m.naturalWidth;\n if (m.naturalHeight !== undefined) out.naturalHeight = m.naturalHeight;\n return out;\n },\n\n deserializeMetadata(raw: Record<string, unknown>): ImageMetadata {\n return {\n src: extractString(raw.src) ?? \"\",\n alt: extractString(raw.alt),\n caption: extractString(raw.caption),\n width: typeof raw.width === \"number\" ? raw.width : undefined,\n naturalWidth: typeof raw.naturalWidth === \"number\" ? raw.naturalWidth : undefined,\n naturalHeight: typeof raw.naturalHeight === \"number\" ? raw.naturalHeight : undefined,\n };\n },\n\n render(container, _content, rawMetadata) {\n // Normalize raw metadata — Automerge proxy values (ImmutableString, legacy maps)\n // must be deserialized into plain primitives before use.\n const metadata = imagePlugin.deserializeMetadata!(rawMetadata as Record<string, unknown>);\n container.innerHTML = \"\";\n\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-image\");\n wrapper.setAttribute(\"contenteditable\", \"false\");\n\n if (!metadata.src) {\n // Empty state — show upload/URL input area\n const placeholder = document.createElement(\"div\");\n placeholder.classList.add(\"blx-image-placeholder\");\n\n const icon = document.createElement(\"span\");\n icon.classList.add(\"blx-image-icon\");\n icon.innerHTML = iconHtml(ImageIcon, 28);\n\n const label = document.createElement(\"span\");\n label.classList.add(\"blx-image-placeholder-label\");\n label.textContent = \"Add an image\";\n\n const actions = document.createElement(\"div\");\n actions.classList.add(\"blx-image-actions\");\n\n // Upload button\n const uploadBtn = document.createElement(\"button\");\n uploadBtn.type = \"button\";\n uploadBtn.classList.add(\"blx-image-upload-btn\");\n uploadBtn.textContent = \"Upload\";\n const fileInput = document.createElement(\"input\");\n fileInput.type = \"file\";\n fileInput.accept = \"image/*\";\n fileInput.style.display = \"none\";\n uploadBtn.addEventListener(\"click\", () => fileInput.click());\n fileInput.addEventListener(\"change\", () => {\n const file = fileInput.files?.[0];\n if (file) {\n storeFileAsBlob(file).then((src) => {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-commit\", {\n bubbles: true,\n detail: { src },\n }),\n );\n });\n }\n });\n\n // URL input\n const urlInput = document.createElement(\"input\");\n urlInput.type = \"text\";\n urlInput.classList.add(\"blx-image-url-input\");\n urlInput.placeholder = \"or paste an image URL…\";\n urlInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n const src = urlInput.value.trim();\n if (src) {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-commit\", {\n bubbles: true,\n detail: { src },\n }),\n );\n }\n }\n });\n\n actions.appendChild(uploadBtn);\n actions.appendChild(fileInput);\n actions.appendChild(urlInput);\n\n // Drag-drop support on placeholder\n placeholder.addEventListener(\"dragover\", (e) => {\n if (e.dataTransfer?.types.includes(\"Files\")) {\n e.preventDefault();\n e.dataTransfer.dropEffect = \"copy\";\n placeholder.classList.add(\"blx-image-placeholder-dragover\");\n }\n });\n placeholder.addEventListener(\"dragleave\", () => {\n placeholder.classList.remove(\"blx-image-placeholder-dragover\");\n });\n placeholder.addEventListener(\"drop\", (e) => {\n placeholder.classList.remove(\"blx-image-placeholder-dragover\");\n const file = e.dataTransfer?.files[0];\n if (file && file.type.startsWith(\"image/\")) {\n e.preventDefault();\n storeFileAsBlob(file).then((src) => {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-commit\", {\n bubbles: true,\n detail: { src },\n }),\n );\n });\n }\n });\n\n placeholder.appendChild(icon);\n placeholder.appendChild(label);\n placeholder.appendChild(actions);\n wrapper.appendChild(placeholder);\n } else {\n // Render image with optional resize handles and caption\n const figure = document.createElement(\"figure\");\n figure.classList.add(\"blx-image-figure\");\n\n const imgContainer = document.createElement(\"div\");\n imgContainer.classList.add(\"blx-image-container\", \"blx-image-loading\");\n if (metadata.width) {\n imgContainer.style.width = `${metadata.width}px`;\n }\n\n const img = document.createElement(\"img\");\n img.alt = metadata.alt ?? \"\";\n img.loading = \"lazy\"\n img.classList.add(\"blx-image-img\");\n img.draggable = false;\n img.loading = \"lazy\";\n\n // Set intrinsic dimensions as HTML attributes so the browser can\n // compute aspect-ratio before the image loads, preventing CLS.\n if (metadata.naturalWidth && metadata.naturalHeight) {\n img.width = metadata.naturalWidth;\n img.height = metadata.naturalHeight;\n }\n\n img.addEventListener(\"load\", () => {\n imgContainer.classList.remove(\"blx-image-loading\");\n // Capture intrinsic dimensions on first load so subsequent renders\n // can reserve the correct space before the image loads.\n const nw = img.naturalWidth;\n const nh = img.naturalHeight;\n if (nw > 0 && nh > 0 && (nw !== metadata.naturalWidth || nh !== metadata.naturalHeight)) {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-dimensions\", {\n bubbles: true,\n detail: { naturalWidth: nw, naturalHeight: nh },\n }),\n );\n }\n });\n img.addEventListener(\"error\", () => {\n imgContainer.classList.remove(\"blx-image-loading\");\n imgContainer.classList.add(\"blx-image-error\");\n });\n\n // Resolve blob-store references asynchronously; plain URLs set immediately.\n if (isBlobRef(metadata.src)) {\n resolveBlobSrc(metadata.src).then((url) => {\n if (url) {\n img.src = url;\n } else {\n imgContainer.classList.remove(\"blx-image-loading\");\n imgContainer.classList.add(\"blx-image-error\");\n }\n });\n } else {\n img.src = metadata.src;\n }\n\n // Resize handle\n const resizeHandle = document.createElement(\"div\");\n resizeHandle.classList.add(\"blx-image-resize-handle\");\n setupResizeHandle(resizeHandle, imgContainer, wrapper);\n\n imgContainer.appendChild(img);\n imgContainer.appendChild(resizeHandle);\n figure.appendChild(imgContainer);\n\n // Caption\n const caption = document.createElement(\"figcaption\");\n caption.classList.add(\"blx-image-caption\");\n caption.setAttribute(\"contenteditable\", \"true\");\n caption.setAttribute(\"data-placeholder\", \"Add a caption…\");\n caption.textContent = metadata.caption ?? \"\";\n caption.addEventListener(\"input\", () => {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-caption-change\", {\n bubbles: true,\n detail: { caption: caption.textContent ?? \"\" },\n }),\n );\n });\n // Prevent block-level keydown from interfering with caption editing\n caption.addEventListener(\"keydown\", (e) => {\n e.stopPropagation();\n });\n figure.appendChild(caption);\n\n wrapper.appendChild(figure);\n }\n\n container.appendChild(wrapper);\n return null;\n },\n};\n\nfunction setupResizeHandle(\n handle: HTMLElement,\n imgContainer: HTMLElement,\n wrapper: HTMLElement,\n): void {\n let startX = 0;\n let startWidth = 0;\n\n const onMouseMove = (e: MouseEvent) => {\n const delta = e.clientX - startX;\n const newWidth = Math.max(100, startWidth + delta);\n imgContainer.style.width = `${newWidth}px`;\n };\n\n const onMouseUp = () => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"mouseup\", onMouseUp);\n const width = imgContainer.offsetWidth;\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-image-resize\", {\n bubbles: true,\n detail: { width },\n }),\n );\n };\n\n handle.addEventListener(\"mousedown\", (e) => {\n e.preventDefault();\n startX = e.clientX;\n startWidth = imgContainer.offsetWidth;\n document.addEventListener(\"mousemove\", onMouseMove);\n document.addEventListener(\"mouseup\", onMouseUp);\n });\n}\n","import { AttributedString } from \"../attributed-string\";\nimport type { Span } from \"../attributed-string/types\";\nimport type { BlockTypePlugin, ConversionTarget } from \"../schema\";\nimport { ContextMenu, type MenuItem } from \"../ui/context-menu\";\nimport { dismissOnClickOutside, type DismissHandle } from \"../ui/dismiss\";\nimport { isBlockReadOnly, renderAttributedString } from \"./render-utils\";\n\nexport interface TableMetadata {\n [key: string]: unknown;\n /** Header row cells (one AttributedString per column) */\n header: AttributedString[];\n /** Body rows (each row is one AttributedString per column) */\n rows: AttributedString[][];\n /** Column alignments: \"left\" | \"center\" | \"right\" | \"none\" */\n columnAlignments?: string[];\n /** Column widths as percentages */\n columnWidths?: number[];\n}\n\n/** Unified selection state for the table */\nexport interface TableSelection {\n type: \"rect\" | \"row\" | \"col\";\n anchorRow: number;\n anchorCol: number;\n focusRow: number;\n focusCol: number;\n}\n\n/** Minimum table dimensions */\nconst MIN_ROWS = 1;\nconst MIN_COLS = 1;\n/** Default column count for a new table / Format B fallback */\nconst DEFAULT_COLS = 3;\n\n/**\n * Build the table DOM structure.\n *\n * Each cell is a contenteditable <td>. Keyboard and mouse events are\n * handled here and bubble via custom events that the editor listens for.\n */\nfunction buildTable(\n container: HTMLElement,\n metadata: TableMetadata,\n): void {\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-table-wrapper\");\n wrapper.setAttribute(\"contenteditable\", \"false\");\n\n const numCols = metadata.header.length;\n const totalRows = 1 + metadata.rows.length;\n const readOnly = isBlockReadOnly(container);\n\n function getCellContent(r: number, c: number): AttributedString {\n const raw = r === 0 ? metadata.header[c] : metadata.rows[r - 1][c];\n // After Automerge sync, cells may be raw Span[] instead of AttributedString\n if (raw instanceof AttributedString) return raw;\n if (Array.isArray(raw)) return AttributedString.fromSpans(raw as unknown as Span[]);\n return AttributedString.empty();\n }\n\n const table = document.createElement(\"table\");\n table.classList.add(\"blx-table\");\n\n const tbody = document.createElement(\"tbody\");\n\n // Create inner container early so overlay/handles can reference it\n const inner = document.createElement(\"div\");\n inner.classList.add(\"blx-table-inner\");\n\n // Track the currently focused cell for navigation\n let focusedRow = -1;\n let focusedCol = -1;\n\n // ── Selection state ────────────────────────────────────────\n let selection: TableSelection | null = null;\n /** mousedown started but hasn't crossed a cell boundary yet */\n let isDragPending = false;\n /** drag has crossed a cell boundary → rectangular cell selection active */\n let isCellSelecting = false;\n\n function getSelectionRect() {\n if (!selection) return null;\n let startRow = Math.min(selection.anchorRow, selection.focusRow);\n let endRow = Math.max(selection.anchorRow, selection.focusRow);\n let startCol = Math.min(selection.anchorCol, selection.focusCol);\n let endCol = Math.max(selection.anchorCol, selection.focusCol);\n\n if (selection.type === \"row\") {\n startCol = 0;\n endCol = numCols - 1;\n } else if (selection.type === \"col\") {\n startRow = 0;\n endRow = totalRows - 1;\n }\n return { startRow, endRow, startCol, endCol };\n }\n\n function hasMultiCellSelection(): boolean {\n if (!selection) return false;\n if (selection.type === \"row\" || selection.type === \"col\") return true;\n return (\n selection.anchorRow !== selection.focusRow ||\n selection.anchorCol !== selection.focusCol\n );\n }\n\n // ── Selection overlay ────────────────────────────────────\n const selectionOverlay = document.createElement(\"div\");\n selectionOverlay.classList.add(\"blx-table-selection-overlay\");\n\n function updateSelectionOverlay() {\n const rect = getSelectionRect();\n if (!rect || !hasMultiCellSelection()) {\n selectionOverlay.style.display = \"none\";\n return;\n }\n const topLeft = table.querySelector<HTMLElement>(\n `[data-row=\"${rect.startRow}\"][data-col=\"${rect.startCol}\"]`,\n );\n const bottomRight = table.querySelector<HTMLElement>(\n `[data-row=\"${rect.endRow}\"][data-col=\"${rect.endCol}\"]`,\n );\n if (!topLeft || !bottomRight) {\n selectionOverlay.style.display = \"none\";\n return;\n }\n const innerRect = inner.getBoundingClientRect();\n const tlRect = topLeft.getBoundingClientRect();\n const brRect = bottomRight.getBoundingClientRect();\n selectionOverlay.style.display = \"block\";\n selectionOverlay.style.left = `${tlRect.left - innerRect.left}px`;\n selectionOverlay.style.top = `${tlRect.top - innerRect.top}px`;\n selectionOverlay.style.width = `${brRect.right - tlRect.left}px`;\n selectionOverlay.style.height = `${brRect.bottom - tlRect.top}px`;\n }\n\n function clearSelection() {\n selection = null;\n isCellSelecting = false;\n selectionOverlay.style.display = \"none\";\n updateFocusHandles();\n // Deactivate row/col widgets\n rowWidget.classList.remove(\"blx-table-widget-active\");\n colWidget.classList.remove(\"blx-table-widget-active\");\n }\n\n function applySelection() {\n // If rect selection collapsed to a single cell, exit selection and refocus\n if (\n selection?.type === \"rect\" &&\n selection.anchorRow === selection.focusRow &&\n selection.anchorCol === selection.focusCol\n ) {\n const { anchorRow, anchorCol } = selection;\n clearSelection();\n focusCell(anchorRow, anchorCol);\n return;\n }\n updateSelectionOverlay();\n }\n\n /** Clear contents of all cells in the current selection rectangle.\n * Emits a single bulk event so the editor can update metadata in one\n * transaction (individual events would trigger re-renders mid-loop). */\n function clearSelectedCells() {\n const rect = getSelectionRect();\n if (!rect) return;\n const keys: string[] = [];\n for (let r = rect.startRow; r <= rect.endRow; r++) {\n for (let c = rect.startCol; c <= rect.endCol; c++) {\n const cell = table.querySelector<HTMLElement>(\n `[data-row=\"${r}\"][data-col=\"${c}\"]`,\n );\n if (cell) cell.textContent = \"\";\n keys.push(`${r},${c}`);\n }\n }\n emitTableEvent(\"blx:tableBulkClear\", { keys });\n }\n\n // ── Focus handles (edge/corner drag targets) ──────────────\n const focusHandles: HTMLElement[] = [];\n const handleNames = [\"top\", \"bottom\", \"left\", \"right\", \"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\"] as const;\n for (const name of handleNames) {\n const handle = document.createElement(\"div\");\n handle.classList.add(\"blx-table-focus-handle\", `blx-table-focus-handle-${name}`);\n handle.style.display = \"none\";\n focusHandles.push(handle);\n }\n\n function updateFocusHandles() {\n if (focusedRow < 0 || focusedCol < 0 || hasMultiCellSelection()) {\n for (const h of focusHandles) h.style.display = \"none\";\n return;\n }\n const cell = table.querySelector<HTMLElement>(\n `[data-row=\"${focusedRow}\"][data-col=\"${focusedCol}\"]`,\n );\n if (!cell) {\n for (const h of focusHandles) h.style.display = \"none\";\n return;\n }\n const innerRect = inner.getBoundingClientRect();\n const cr = cell.getBoundingClientRect();\n const l = cr.left - innerRect.left;\n const t = cr.top - innerRect.top;\n const w = cr.width;\n const h = cr.height;\n const edgeW = 4; // width of edge strips\n const cornerS = 6; // corner square size\n\n for (let i = 0; i < handleNames.length; i++) {\n const el = focusHandles[i];\n el.style.display = \"block\";\n switch (handleNames[i]) {\n case \"top\":\n el.style.left = `${l + cornerS}px`; el.style.top = `${t - edgeW / 2}px`;\n el.style.width = `${w - 2 * cornerS}px`; el.style.height = `${edgeW}px`;\n break;\n case \"bottom\":\n el.style.left = `${l + cornerS}px`; el.style.top = `${t + h - edgeW / 2}px`;\n el.style.width = `${w - 2 * cornerS}px`; el.style.height = `${edgeW}px`;\n break;\n case \"left\":\n el.style.left = `${l - edgeW / 2}px`; el.style.top = `${t + cornerS}px`;\n el.style.width = `${edgeW}px`; el.style.height = `${h - 2 * cornerS}px`;\n break;\n case \"right\":\n el.style.left = `${l + w - edgeW / 2}px`; el.style.top = `${t + cornerS}px`;\n el.style.width = `${edgeW}px`; el.style.height = `${h - 2 * cornerS}px`;\n break;\n case \"top-left\":\n el.style.left = `${l - cornerS / 2}px`; el.style.top = `${t - cornerS / 2}px`;\n el.style.width = `${cornerS}px`; el.style.height = `${cornerS}px`;\n break;\n case \"top-right\":\n el.style.left = `${l + w - cornerS / 2}px`; el.style.top = `${t - cornerS / 2}px`;\n el.style.width = `${cornerS}px`; el.style.height = `${cornerS}px`;\n break;\n case \"bottom-left\":\n el.style.left = `${l - cornerS / 2}px`; el.style.top = `${t + h - cornerS / 2}px`;\n el.style.width = `${cornerS}px`; el.style.height = `${cornerS}px`;\n break;\n case \"bottom-right\":\n el.style.left = `${l + w - cornerS / 2}px`; el.style.top = `${t + h - cornerS / 2}px`;\n el.style.width = `${cornerS}px`; el.style.height = `${cornerS}px`;\n break;\n }\n }\n }\n\n // Focus handle drag → expand selection\n for (const handle of focusHandles) {\n handle.addEventListener(\"mousedown\", (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (focusedRow < 0 || focusedCol < 0) return;\n selection = {\n type: \"rect\",\n anchorRow: focusedRow,\n anchorCol: focusedCol,\n focusRow: focusedRow,\n focusCol: focusedCol,\n };\n isDragPending = true;\n isCellSelecting = true; // skip pending phase\n window.getSelection()?.removeAllRanges();\n // Blur the focused cell so the focus ring doesn't persist during drag\n const focused = table.querySelector<HTMLElement>(\".blx-table-cell:focus\");\n if (focused) focused.blur();\n updateFocusHandles();\n });\n }\n\n // ── Row/Column pill widgets ──────────────────────────────\n function makeDots(count: number): DocumentFragment {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const dot = document.createElement(\"span\");\n dot.classList.add(\"blx-table-widget-dot\");\n frag.appendChild(dot);\n }\n return frag;\n }\n\n const rowWidget = document.createElement(\"button\");\n rowWidget.classList.add(\"blx-table-row-widget\");\n rowWidget.setAttribute(\"tabindex\", \"-1\");\n rowWidget.setAttribute(\"contenteditable\", \"false\");\n rowWidget.appendChild(makeDots(3));\n rowWidget.title = \"Select row\";\n\n const colWidget = document.createElement(\"button\");\n colWidget.classList.add(\"blx-table-col-widget\");\n colWidget.setAttribute(\"tabindex\", \"-1\");\n colWidget.setAttribute(\"contenteditable\", \"false\");\n colWidget.appendChild(makeDots(3));\n colWidget.title = \"Select column\";\n\n const addRowWidget = document.createElement(\"button\");\n addRowWidget.classList.add(\"blx-table-add-row-widget\");\n addRowWidget.setAttribute(\"tabindex\", \"-1\");\n addRowWidget.setAttribute(\"contenteditable\", \"false\");\n addRowWidget.textContent = \"+\";\n addRowWidget.title = \"Add row\";\n\n const addColWidget = document.createElement(\"button\");\n addColWidget.classList.add(\"blx-table-add-col-widget\");\n addColWidget.setAttribute(\"tabindex\", \"-1\");\n addColWidget.setAttribute(\"contenteditable\", \"false\");\n addColWidget.textContent = \"+\";\n addColWidget.title = \"Add column\";\n\n let hoveredRowIndex = -1;\n let hoveredColIndex = -1;\n\n // ── Cell dispatch helper ───────────────────────────────────\n function emitTableEvent(name: string, detail: Record<string, unknown>) {\n wrapper.dispatchEvent(\n new CustomEvent(name, { bubbles: true, detail }),\n );\n }\n\n function emitCellEdit(row: number, col: number, value: string) {\n emitTableEvent(\"blx:tableCellEdit\", { row, col, value });\n }\n\n // ── Focus a cell by row/col ────────────────────────────────\n function focusCell(row: number, col: number, cursorEnd = false) {\n const cell = table.querySelector<HTMLElement>(\n `[data-row=\"${row}\"][data-col=\"${col}\"]`,\n );\n if (cell) {\n cell.focus();\n // Position cursor at start or end of cell text\n const sel = window.getSelection();\n if (sel) {\n const range = document.createRange();\n if (cursorEnd && cell.childNodes.length > 0) {\n const lastNode = cell.lastChild!;\n if (lastNode.nodeType === Node.TEXT_NODE) {\n range.setStart(lastNode, lastNode.textContent?.length ?? 0);\n } else {\n range.setStartAfter(lastNode);\n }\n } else if (cell.childNodes.length > 0) {\n range.setStart(cell.childNodes[0], 0);\n } else {\n range.setStart(cell, 0);\n }\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n // ── Build cells ────────────────────────────────────────────\n for (let r = 0; r < totalRows; r++) {\n const tr = document.createElement(\"tr\");\n tr.classList.add(\"blx-table-row\");\n\n for (let c = 0; c < numCols; c++) {\n const td = document.createElement(\"td\");\n td.classList.add(\"blx-table-cell\");\n if (!readOnly) td.setAttribute(\"contenteditable\", \"true\");\n td.setAttribute(\"data-row\", String(r));\n td.setAttribute(\"data-col\", String(c));\n const cellContent = getCellContent(r, c);\n if (!cellContent.isEmpty()) {\n renderAttributedString(td, cellContent);\n }\n\n // ── Input handling ───────────────────────────────\n if (!readOnly) {\n td.addEventListener(\"input\", () => {\n emitCellEdit(r, c, td.textContent ?? \"\");\n });\n }\n\n td.addEventListener(\"focus\", () => {\n focusedRow = r;\n focusedCol = c;\n // If a multi-cell selection is active and the user focuses a cell\n // (e.g. via Tab or programmatic focus), clear the selection.\n // Don't clear during an active cell-drag — the mouseover handler\n // manages that.\n if (hasMultiCellSelection() && !isDragPending) {\n clearSelection();\n }\n updateFocusHandles();\n });\n\n td.addEventListener(\"blur\", () => {\n // Delay so that if focus moves to another cell the new focus\n // handler runs first.\n requestAnimationFrame(() => {\n if (focusedRow === r && focusedCol === c) {\n // Still us — likely blurred to non-cell element\n }\n updateFocusHandles();\n });\n });\n\n // ── Keyboard navigation within the table ────────\n if (!readOnly) td.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (e.isComposing) return;\n\n // Single-cell formatting shortcuts (Ctrl/Cmd+B/I/U)\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\n let attribute: string | null = null;\n switch (e.key.toLowerCase()) {\n case \"b\": attribute = \"bold\"; break;\n case \"i\": attribute = \"italic\"; break;\n case \"u\": attribute = \"underline\"; break;\n }\n if (attribute) {\n // If text is selected within the cell, let the editor handle it\n // for selection-aware formatting. Only use bulk format for whole cell.\n const sel = window.getSelection();\n if (sel && !sel.isCollapsed && sel.rangeCount > 0) {\n // Don't intercept — let it bubble to the editor's handleFormatKeyDown\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableBulkFormat\", {\n startRow: r, endRow: r,\n startCol: c, endCol: c,\n attribute,\n });\n return;\n }\n }\n\n const curOffset = getCellCursorOffset(td);\n const textLen = (td.textContent ?? \"\").length;\n\n // Ctrl/Cmd+Shift+ArrowRight → add column after current\n if (e.key === \"ArrowRight\" && (e.ctrlKey || e.metaKey) && e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableAddColumn\", { col: c + 1 });\n return;\n }\n\n // Ctrl/Cmd+Shift+ArrowLeft → add column before current\n if (e.key === \"ArrowLeft\" && (e.ctrlKey || e.metaKey) && e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableAddColumn\", { col: c });\n return;\n }\n\n // Tab → next cell (or new row)\n if (e.key === \"Tab\" && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n if (c < numCols - 1) {\n focusCell(r, c + 1);\n } else if (r < totalRows - 1) {\n focusCell(r + 1, 0);\n } else {\n // Last cell — create new row\n emitTableEvent(\"blx:tableCreateRowBelow\", { row: r });\n }\n return;\n }\n\n // Shift+Tab → previous cell\n if (e.key === \"Tab\" && e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n if (c > 0) {\n focusCell(r, c - 1, true);\n } else if (r > 0) {\n focusCell(r - 1, numCols - 1, true);\n }\n return;\n }\n\n // Shift+Enter → always insert a new row below current\n if (e.key === \"Enter\" && e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableCreateRowBelow\", { row: r });\n return;\n }\n\n // Enter → move to cell below, or add row on last non-empty\n // row, or exit table on last empty row\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n\n // If there's a row below, just move down (like a spreadsheet)\n if (r < totalRows - 1) {\n focusCell(r + 1, c);\n return;\n }\n\n // On the last row — check if it's empty\n let rowEmpty = true;\n for (let ci = 0; ci < numCols; ci++) {\n if (!getCellContent(r, ci).isEmpty()) {\n rowEmpty = false;\n break;\n }\n }\n // Also check DOM in case of uncommitted edits\n if (rowEmpty) {\n const rowCells = tr.querySelectorAll<HTMLElement>(\".blx-table-cell\");\n for (const cell of rowCells) {\n if ((cell.textContent ?? \"\").length > 0) {\n rowEmpty = false;\n break;\n }\n }\n }\n if (rowEmpty && totalRows > MIN_ROWS) {\n // Exit table: delete the empty row and create a new block below.\n emitTableEvent(\"blx:tableExit\", { deleteRow: r });\n } else {\n // Last row with content — add a new row\n emitTableEvent(\"blx:tableCreateRowBelow\", { row: r });\n }\n return;\n }\n\n // Shift+Arrow at cell boundary → start rectangular selection\n if (e.shiftKey && !e.ctrlKey && !e.metaKey) {\n // Get the selection focus offset (the moving end of a text selection)\n const selFocusOffset = getCellSelectionFocusOffset(td);\n const atStart = selFocusOffset === 0;\n const atEnd = selFocusOffset >= textLen;\n const onFirstLine = isCellCaretOnFirstLine(td);\n const onLastLine = isCellCaretOnLastLine(td);\n\n let focusRow = r;\n let focusCol = c;\n let shouldSelect = false;\n\n if (e.key === \"ArrowLeft\" && atStart && c > 0) {\n focusCol = c - 1;\n shouldSelect = true;\n } else if (e.key === \"ArrowRight\" && atEnd && c < numCols - 1) {\n focusCol = c + 1;\n shouldSelect = true;\n } else if (e.key === \"ArrowUp\" && onFirstLine && r > 0) {\n focusRow = r - 1;\n shouldSelect = true;\n } else if (e.key === \"ArrowDown\" && onLastLine && r < totalRows - 1) {\n focusRow = r + 1;\n shouldSelect = true;\n }\n\n if (shouldSelect) {\n e.preventDefault();\n e.stopPropagation();\n td.blur();\n selection = {\n type: \"rect\",\n anchorRow: r,\n anchorCol: c,\n focusRow,\n focusCol,\n };\n applySelection();\n wrapper.focus();\n return;\n }\n }\n\n // ArrowUp → move to cell above\n if (e.key === \"ArrowUp\" && !e.shiftKey) {\n if (r > 0) {\n e.preventDefault();\n e.stopPropagation();\n focusCell(r - 1, c, false);\n } else {\n // At top row — navigate out of table (up)\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableNavigateOut\", { direction: \"up\" });\n }\n return;\n }\n\n // ArrowDown → move to cell below\n if (e.key === \"ArrowDown\" && !e.shiftKey) {\n if (r < totalRows - 1) {\n e.preventDefault();\n e.stopPropagation();\n focusCell(r + 1, c, false);\n } else {\n // At bottom row — navigate out of table (down)\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableNavigateOut\", { direction: \"down\" });\n }\n return;\n }\n\n // ArrowLeft at start → previous cell\n if (e.key === \"ArrowLeft\" && !e.shiftKey && curOffset === 0) {\n e.preventDefault();\n e.stopPropagation();\n if (c > 0) {\n focusCell(r, c - 1, true);\n } else if (r > 0) {\n focusCell(r - 1, numCols - 1, true);\n } else {\n emitTableEvent(\"blx:tableNavigateOut\", { direction: \"up\" });\n }\n return;\n }\n\n // ArrowRight at end → next cell\n if (e.key === \"ArrowRight\" && !e.shiftKey && curOffset >= textLen) {\n e.preventDefault();\n e.stopPropagation();\n if (c < numCols - 1) {\n focusCell(r, c + 1);\n } else if (r < totalRows - 1) {\n focusCell(r + 1, 0);\n } else {\n emitTableEvent(\"blx:tableNavigateOut\", { direction: \"down\" });\n }\n return;\n }\n\n // Backspace at start of first cell of first row — navigate out\n if (e.key === \"Backspace\" && curOffset === 0 && textLen === 0 && r === 0 && c === 0) {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableNavigateOut\", { direction: \"up\" });\n return;\n }\n\n // Escape → exit table editing, let editor handle block focus\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n td.blur();\n emitTableEvent(\"blx:tableEscape\", {});\n return;\n }\n });\n\n // ── Mouse selection ────────────────────────────────\n if (!readOnly) {\n // mousedown: record anchor cell, but let the browser handle in-cell\n // text selection. Only convert to rectangular cell selection when\n // the mouse enters a *different* cell (see mouseover below).\n td.addEventListener(\"mousedown\", (e: MouseEvent) => {\n if (e.button !== 0) return;\n // If there's an active multi-cell selection and user clicks\n // without dragging to a new cell, clear it on mousedown.\n if (hasMultiCellSelection()) {\n clearSelection();\n }\n selection = {\n type: \"rect\",\n anchorRow: r,\n anchorCol: c,\n focusRow: r,\n focusCol: c,\n };\n isDragPending = true;\n isCellSelecting = false;\n });\n\n td.addEventListener(\"mouseover\", () => {\n if (!isDragPending || !selection) return;\n // Mouse entered a different cell → convert to cell selection\n if (selection.anchorRow !== r || selection.anchorCol !== c) {\n if (!isCellSelecting) {\n // First boundary crossing: clear the browser's text selection,\n // blur the focused cell (removes focus ring), and switch to\n // rectangular cell mode.\n isCellSelecting = true;\n window.getSelection()?.removeAllRanges();\n const focused = table.querySelector<HTMLElement>(\".blx-table-cell:focus\");\n if (focused) focused.blur();\n updateFocusHandles();\n }\n selection = { ...selection, focusRow: r, focusCol: c };\n applySelection();\n }\n });\n }\n\n tr.appendChild(td);\n }\n\n tbody.appendChild(tr);\n }\n\n // Prevent the browser from extending its own text selection while\n // we're doing rectangular cell selection.\n wrapper.addEventListener(\"selectstart\", (e) => {\n if (isCellSelecting) {\n e.preventDefault();\n }\n });\n\n // End drag on mouseup (use document to catch drags that leave the table)\n function onMouseUp() {\n if (isDragPending) {\n isDragPending = false;\n if (isCellSelecting) {\n applySelection();\n const rect = getSelectionRect();\n if (rect) {\n emitTableEvent(\"blx:tableSelectionChanged\", rect);\n }\n }\n }\n }\n wrapper.addEventListener(\"mouseup\", onMouseUp);\n // Also listen on document for drags that end outside the table.\n // Use capture so we reliably hear it even if something stops propagation.\n document.addEventListener(\"mouseup\", onMouseUp, true);\n\n // ── Bulk operations on multi-cell selection ──────────────────\n // Uses capture phase so it fires before the per-cell keydown handler.\n wrapper.addEventListener(\n \"keydown\",\n (e: KeyboardEvent) => {\n if (!hasMultiCellSelection()) return;\n\n if (e.key === \"Backspace\" || e.key === \"Delete\") {\n e.preventDefault();\n e.stopPropagation();\n clearSelectedCells();\n // Reposition overlay to match new cell sizes after content was removed\n applySelection();\n return;\n }\n\n // Escape clears the selection (returns to single-cell editing)\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n const anchor = selection;\n clearSelection();\n if (anchor) {\n focusCell(anchor.anchorRow, anchor.anchorCol);\n }\n return;\n }\n\n // Formatting shortcuts during multi-cell selection\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\n let attribute: string | null = null;\n switch (e.key.toLowerCase()) {\n case \"b\": attribute = \"bold\"; break;\n case \"i\": attribute = \"italic\"; break;\n case \"u\": attribute = \"underline\"; break;\n }\n if (attribute) {\n e.preventDefault();\n e.stopPropagation();\n const rect = getSelectionRect();\n if (rect) {\n emitTableEvent(\"blx:tableBulkFormat\", {\n startRow: rect.startRow, endRow: rect.endRow,\n startCol: rect.startCol, endCol: rect.endCol,\n attribute,\n });\n }\n return;\n }\n }\n\n // Row selection keyboard extension: Shift+Arrow to extend\n if (selection?.type === \"row\" && e.shiftKey) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusRow: Math.min(selection.focusRow + 1, totalRows - 1) };\n applySelection();\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusRow: Math.max(selection.focusRow - 1, 0) };\n applySelection();\n return;\n }\n }\n\n // Column selection keyboard extension: Shift+Arrow to extend\n if (selection?.type === \"col\" && e.shiftKey) {\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusCol: Math.min(selection.focusCol + 1, numCols - 1) };\n applySelection();\n return;\n }\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusCol: Math.max(selection.focusCol - 1, 0) };\n applySelection();\n return;\n }\n }\n\n // Rectangular selection keyboard extension: Shift+Arrow to extend\n if (selection?.type === \"rect\" && e.shiftKey) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusRow: Math.min(selection.focusRow + 1, totalRows - 1) };\n applySelection();\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusRow: Math.max(selection.focusRow - 1, 0) };\n applySelection();\n return;\n }\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusCol: Math.min(selection.focusCol + 1, numCols - 1) };\n applySelection();\n return;\n }\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n e.stopPropagation();\n selection = { ...selection, focusCol: Math.max(selection.focusCol - 1, 0) };\n applySelection();\n return;\n }\n }\n\n // Plain arrow (no shift) during multi-cell selection: collapse to anchor and focus\n if (!e.shiftKey && [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\"].includes(e.key)) {\n e.preventDefault();\n e.stopPropagation();\n const anchor = selection;\n clearSelection();\n if (anchor) {\n focusCell(anchor.anchorRow, anchor.anchorCol);\n }\n return;\n }\n\n // Any other printable key: clear selected cells, focus anchor,\n // and let the keystroke flow into the anchor cell.\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n clearSelectedCells();\n const anchor = selection;\n clearSelection();\n if (anchor) {\n focusCell(anchor.anchorRow, anchor.anchorCol);\n }\n // Don't prevent default — let the character be typed\n return;\n }\n },\n true, // capture phase\n );\n\n table.appendChild(tbody);\n\n // ── Column widths via colgroup ─────────────────────────────\n const colgroup = document.createElement(\"colgroup\");\n for (let c = 0; c < numCols; c++) {\n const col = document.createElement(\"col\");\n if (metadata.columnWidths?.[c]) {\n col.style.width = `${metadata.columnWidths[c]}%`;\n }\n colgroup.appendChild(col);\n }\n table.insertBefore(colgroup, tbody);\n\n // Assemble inner container: table + overlay + focus handles\n inner.appendChild(table);\n if (!readOnly) {\n inner.appendChild(selectionOverlay);\n for (const h of focusHandles) inner.appendChild(h);\n\n // ── Column resize handles ──────────────────────────────────\n // One per internal column boundary\n for (let c = 0; c < numCols - 1; c++) {\n const resizeHandle = document.createElement(\"div\");\n resizeHandle.classList.add(\"blx-table-col-resize\");\n resizeHandle.dataset.col = String(c);\n inner.appendChild(resizeHandle);\n }\n\n function positionResizeHandles() {\n const handles = inner.querySelectorAll<HTMLElement>(\".blx-table-col-resize\");\n const innerRect = inner.getBoundingClientRect();\n handles.forEach((handle) => {\n const ci = parseInt(handle.dataset.col!, 10);\n const cell = table.querySelector<HTMLElement>(`[data-row=\"0\"][data-col=\"${ci}\"]`);\n if (!cell) return;\n const cellRect = cell.getBoundingClientRect();\n handle.style.left = `${cellRect.right - innerRect.left - 3}px`;\n handle.style.top = \"0\";\n handle.style.width = \"6px\";\n handle.style.height = `${inner.scrollHeight}px`;\n });\n }\n\n requestAnimationFrame(positionResizeHandles);\n\n let resizingCol = -1;\n let resizeStartX = 0;\n let resizeStartWidths: number[] = [];\n\n inner.addEventListener(\"mousedown\", (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (!target.classList.contains(\"blx-table-col-resize\")) return;\n e.preventDefault();\n e.stopPropagation();\n resizingCol = parseInt(target.dataset.col!, 10);\n resizeStartX = e.clientX;\n const tableWidth = table.getBoundingClientRect().width;\n resizeStartWidths = [];\n for (let c = 0; c < numCols; c++) {\n const cell = table.querySelector<HTMLElement>(`[data-row=\"0\"][data-col=\"${c}\"]`);\n resizeStartWidths.push(cell ? (cell.getBoundingClientRect().width / tableWidth) * 100 : 100 / numCols);\n }\n\n const onMouseMove = (me: MouseEvent) => {\n const dx = me.clientX - resizeStartX;\n const tw = table.getBoundingClientRect().width;\n const dxPct = (dx / tw) * 100;\n const minPct = (60 / tw) * 100;\n const newWidths = [...resizeStartWidths];\n let leftW = resizeStartWidths[resizingCol] + dxPct;\n let rightW = resizeStartWidths[resizingCol + 1] - dxPct;\n if (leftW < minPct) { leftW = minPct; rightW = resizeStartWidths[resizingCol] + resizeStartWidths[resizingCol + 1] - minPct; }\n if (rightW < minPct) { rightW = minPct; leftW = resizeStartWidths[resizingCol] + resizeStartWidths[resizingCol + 1] - minPct; }\n newWidths[resizingCol] = leftW;\n newWidths[resizingCol + 1] = rightW;\n const cols = colgroup.querySelectorAll(\"col\");\n for (let c = 0; c < cols.length; c++) cols[c].style.width = `${newWidths[c]}%`;\n positionResizeHandles();\n };\n\n const onMouseUp = () => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"mouseup\", onMouseUp);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n const tw = table.getBoundingClientRect().width;\n const finalWidths: number[] = [];\n for (let c = 0; c < numCols; c++) {\n const cell = table.querySelector<HTMLElement>(`[data-row=\"0\"][data-col=\"${c}\"]`);\n finalWidths.push(cell ? (cell.getBoundingClientRect().width / tw) * 100 : 100 / numCols);\n }\n emitTableEvent(\"blx:tableColumnWidths\", { widths: finalWidths });\n resizingCol = -1;\n };\n\n document.addEventListener(\"mousemove\", onMouseMove);\n document.addEventListener(\"mouseup\", onMouseUp);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n });\n }\n wrapper.appendChild(inner);\n wrapper.setAttribute(\"tabindex\", \"-1\");\n\n // ── Row/column widget click handlers ─────────────────────\n const tableContextMenu = new ContextMenu({ className: \"blx-action-menu\" });\n let tableContextDismiss: DismissHandle | null = null;\n let tableContextKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n function dismissTableContextMenu() {\n tableContextMenu.hide();\n tableContextMenu.el.remove();\n tableContextDismiss?.remove();\n tableContextDismiss = null;\n if (tableContextKeyHandler) {\n document.removeEventListener(\"keydown\", tableContextKeyHandler, true);\n tableContextKeyHandler = null;\n }\n }\n\n tableContextMenu.onClose = () => dismissTableContextMenu();\n\n function showContextMenu(\n anchorEl: HTMLElement,\n items: Array<{ label: string; action: () => void; danger?: boolean }>,\n ) {\n dismissTableContextMenu();\n\n const menuItems: MenuItem[] = items.map((item, i) => ({\n id: `table-ctx-${i}`,\n label: item.label,\n danger: item.danger,\n data: item,\n }));\n\n tableContextMenu.onSelect = (mi: MenuItem) => {\n const entry = mi.data as { action: () => void };\n dismissTableContextMenu();\n entry.action();\n };\n\n const editorRoot = wrapper.closest(\".blx-editor\") || document.body;\n editorRoot.appendChild(tableContextMenu.el);\n\n const anchorRect = anchorEl.getBoundingClientRect();\n tableContextMenu.show(anchorRect, menuItems);\n\n // Keyboard handler (capture phase)\n tableContextKeyHandler = (e: KeyboardEvent) => {\n const consumed = tableContextMenu.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", tableContextKeyHandler, true);\n\n // Outside click dismiss\n tableContextDismiss = dismissOnClickOutside(\n tableContextMenu.el,\n () => dismissTableContextMenu(),\n );\n }\n\n function showRowContextMenu() {\n const rect = getSelectionRect();\n if (!rect) return;\n const startRow = rect.startRow;\n const endRow = rect.endRow;\n showContextMenu(rowWidget, [\n { label: \"Insert row above\", action: () => emitTableEvent(\"blx:tableInsertRowAbove\", { row: startRow }) },\n { label: \"Insert row below\", action: () => emitTableEvent(\"blx:tableCreateRowBelow\", { row: endRow }) },\n { label: \"Duplicate\", action: () => emitTableEvent(\"blx:tableDuplicateRow\", { startRow, endRow }) },\n { label: \"Clear contents\", action: () => emitTableEvent(\"blx:tableClearRow\", { startRow, endRow }) },\n { label: \"Delete\", danger: true, action: () => {\n for (let r = endRow; r >= startRow; r--) {\n emitTableEvent(\"blx:tableDeleteRow\", { row: r });\n }\n }},\n ]);\n }\n\n function showColContextMenu() {\n const rect = getSelectionRect();\n if (!rect) return;\n const startCol = rect.startCol;\n const endCol = rect.endCol;\n showContextMenu(colWidget, [\n { label: \"Insert column left\", action: () => emitTableEvent(\"blx:tableAddColumn\", { col: startCol }) },\n { label: \"Insert column right\", action: () => emitTableEvent(\"blx:tableAddColumn\", { col: endCol + 1 }) },\n { label: \"Duplicate\", action: () => emitTableEvent(\"blx:tableDuplicateColumn\", { startCol, endCol }) },\n { label: \"Clear contents\", action: () => emitTableEvent(\"blx:tableClearColumn\", { startCol, endCol }) },\n { label: \"Delete\", danger: true, action: () => {\n for (let c = endCol; c >= startCol; c--) {\n emitTableEvent(\"blx:tableDeleteColumn\", { col: c });\n }\n }},\n ]);\n }\n\n rowWidget.addEventListener(\"mousedown\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (hoveredRowIndex < 0) return;\n if (selection?.type === \"row\" && rowWidget.classList.contains(\"blx-table-widget-active\")) {\n // Second click → context menu\n showRowContextMenu();\n return;\n }\n // First click → enter row selection\n selection = {\n type: \"row\",\n anchorRow: hoveredRowIndex,\n anchorCol: 0,\n focusRow: hoveredRowIndex,\n focusCol: numCols - 1,\n };\n rowWidget.classList.add(\"blx-table-widget-active\");\n colWidget.classList.remove(\"blx-table-widget-active\");\n applySelection();\n // Focus wrapper for keyboard events\n wrapper.focus();\n });\n\n colWidget.addEventListener(\"mousedown\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (hoveredColIndex < 0) return;\n if (selection?.type === \"col\" && colWidget.classList.contains(\"blx-table-widget-active\")) {\n // Second click → context menu\n showColContextMenu();\n return;\n }\n // First click → enter column selection\n selection = {\n type: \"col\",\n anchorRow: 0,\n anchorCol: hoveredColIndex,\n focusRow: totalRows - 1,\n focusCol: hoveredColIndex,\n };\n colWidget.classList.add(\"blx-table-widget-active\");\n rowWidget.classList.remove(\"blx-table-widget-active\");\n applySelection();\n // Focus wrapper for keyboard events\n wrapper.focus();\n });\n\n addRowWidget.addEventListener(\"mousedown\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableCreateRowBelow\", { row: totalRows - 1 });\n });\n\n addColWidget.addEventListener(\"mousedown\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n emitTableEvent(\"blx:tableAddColumn\", { col: numCols });\n });\n\n // ── Track mouse position to show row/col widgets ───────────\n function positionWidgets(e: MouseEvent) {\n const tableRect = table.getBoundingClientRect();\n const mouseX = e.clientX;\n const mouseY = e.clientY;\n\n // Row widget: lock position when selection is active, otherwise track mouse\n if (!rowWidget.classList.contains(\"blx-table-widget-active\")) {\n const rows = table.querySelectorAll<HTMLElement>(\".blx-table-row\");\n let foundRow = false;\n if (mouseX >= tableRect.left - 8 && mouseX <= tableRect.left + 8 &&\n mouseY >= tableRect.top && mouseY <= tableRect.bottom) {\n for (let i = 0; i < rows.length; i++) {\n const rect = rows[i].getBoundingClientRect();\n if (mouseY >= rect.top && mouseY <= rect.bottom) {\n hoveredRowIndex = i;\n rowWidget.classList.add(\"blx-table-widget-visible\");\n rowWidget.style.top = `${rect.top - tableRect.top + rect.height / 2}px`;\n foundRow = true;\n break;\n }\n }\n }\n if (!foundRow) {\n rowWidget.classList.remove(\"blx-table-widget-visible\");\n hoveredRowIndex = -1;\n }\n }\n\n // Column widget: lock position when selection is active, otherwise track mouse\n if (!colWidget.classList.contains(\"blx-table-widget-active\")) {\n const firstRowCells = table.querySelectorAll<HTMLElement>(\n '.blx-table-cell[data-row=\"0\"]',\n );\n let foundCol = false;\n if (mouseY >= tableRect.top - 8 && mouseY <= tableRect.top + 8 &&\n mouseX >= tableRect.left && mouseX <= tableRect.right) {\n for (let i = 0; i < firstRowCells.length; i++) {\n const rect = firstRowCells[i].getBoundingClientRect();\n if (mouseX >= rect.left && mouseX <= rect.right) {\n hoveredColIndex = i;\n colWidget.classList.add(\"blx-table-widget-visible\");\n colWidget.style.left = `${rect.left - tableRect.left + rect.width / 2}px`;\n foundCol = true;\n break;\n }\n }\n }\n if (!foundCol) {\n colWidget.classList.remove(\"blx-table-widget-visible\");\n hoveredColIndex = -1;\n }\n }\n\n // Add-row widget: show on the bottom border\n if (mouseY >= tableRect.bottom - 8 && mouseY <= tableRect.bottom + 8 &&\n mouseX >= tableRect.left && mouseX <= tableRect.right) {\n addRowWidget.classList.add(\"blx-table-widget-visible\");\n } else {\n addRowWidget.classList.remove(\"blx-table-widget-visible\");\n }\n\n // Add-col widget: show on the right border\n if (mouseX >= tableRect.right - 8 && mouseX <= tableRect.right + 8 &&\n mouseY >= tableRect.top && mouseY <= tableRect.bottom) {\n addColWidget.classList.add(\"blx-table-widget-visible\");\n } else {\n addColWidget.classList.remove(\"blx-table-widget-visible\");\n }\n }\n\n if (!readOnly) {\n wrapper.addEventListener(\"mousemove\", positionWidgets);\n wrapper.addEventListener(\"mouseleave\", () => {\n if (!rowWidget.classList.contains(\"blx-table-widget-active\")) {\n rowWidget.classList.remove(\"blx-table-widget-visible\");\n hoveredRowIndex = -1;\n }\n addRowWidget.classList.remove(\"blx-table-widget-visible\");\n addColWidget.classList.remove(\"blx-table-widget-visible\");\n if (!colWidget.classList.contains(\"blx-table-widget-active\")) {\n colWidget.classList.remove(\"blx-table-widget-visible\");\n hoveredColIndex = -1;\n }\n });\n\n wrapper.appendChild(rowWidget);\n wrapper.appendChild(colWidget);\n wrapper.appendChild(addRowWidget);\n wrapper.appendChild(addColWidget);\n }\n\n container.appendChild(wrapper);\n}\n\n/**\n * Get cursor offset within a cell element (range start).\n */\nfunction getCellCursorOffset(cell: HTMLElement): number {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return 0;\n const range = sel.getRangeAt(0);\n if (!cell.contains(range.startContainer)) return 0;\n const preRange = document.createRange();\n preRange.selectNodeContents(cell);\n preRange.setEnd(range.startContainer, range.startOffset);\n return preRange.toString().length;\n}\n\n/**\n * Get the selection's focus offset within a cell (the moving end of an\n * extended text selection). Uses Selection.focusNode/focusOffset which\n * track the user's extending endpoint, unlike Range which is always\n * start-to-end ordered.\n */\nfunction getCellSelectionFocusOffset(cell: HTMLElement): number {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || !sel.focusNode) return 0;\n if (!cell.contains(sel.focusNode)) return 0;\n const preRange = document.createRange();\n preRange.selectNodeContents(cell);\n preRange.setEnd(sel.focusNode, sel.focusOffset);\n return preRange.toString().length;\n}\n\n/** Is the caret on the first visual line of a cell? */\nfunction isCellCaretOnFirstLine(cell: HTMLElement): boolean {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return true;\n try {\n const caretRange = sel.getRangeAt(0).cloneRange();\n caretRange.collapse(true);\n const caretRect = caretRange.getBoundingClientRect();\n const walker = document.createTreeWalker(cell, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode();\n if (!firstTextNode) return true;\n const startRange = document.createRange();\n startRange.setStart(firstTextNode, 0);\n startRange.collapse(true);\n const startRect = startRange.getBoundingClientRect();\n if (caretRect.height === 0 && startRect.height === 0) return true;\n return Math.abs(caretRect.top - startRect.top) < 2;\n } catch {\n return true;\n }\n}\n\n/** Is the caret on the last visual line of a cell? */\nfunction isCellCaretOnLastLine(cell: HTMLElement): boolean {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return true;\n try {\n const caretRange = sel.getRangeAt(0).cloneRange();\n caretRange.collapse(false);\n const caretRect = caretRange.getBoundingClientRect();\n const walker = document.createTreeWalker(cell, NodeFilter.SHOW_TEXT);\n let lastTextNode: Node | null = null;\n let node: Node | null;\n while ((node = walker.nextNode())) lastTextNode = node;\n if (!lastTextNode) return true;\n const endRange = document.createRange();\n endRange.setStart(lastTextNode, lastTextNode.textContent?.length ?? 0);\n endRange.collapse(true);\n const endRect = endRange.getBoundingClientRect();\n if (caretRect.height === 0 && endRect.height === 0) return true;\n return Math.abs(caretRect.top - endRect.top) < 2;\n } catch {\n return true;\n }\n}\n\n// ── Plugin ───────────────────────────────────────────────────────\n\nexport const tablePlugin: BlockTypePlugin<TableMetadata> = {\n type: \"table\",\n label: \"Table\",\n hasTextContent: false,\n indentable: false,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): TableMetadata {\n const e = () => AttributedString.empty();\n return {\n header: [e(), e(), e()],\n rows: [[e(), e(), e()]],\n };\n },\n\n convertibleTo(): ConversionTarget[] {\n return []; // No text content — cannot convert\n },\n\n render(container, _content, rawMeta) {\n container.innerHTML = \"\";\n buildTable(container, tablePlugin.deserializeMetadata!(rawMeta as Record<string, unknown>));\n return null; // Non-text block\n },\n\n serializeMetadata(m: TableMetadata) {\n const toSpans = (cell: AttributedString | Span[]): Span[] => {\n if (cell instanceof AttributedString) return cell.isEmpty() ? [] : [...cell.spans];\n if (Array.isArray(cell)) return cell as Span[];\n return [];\n };\n const result: Record<string, unknown> = {\n header: m.header.map(toSpans),\n rows: m.rows.map((row) => row.map(toSpans)),\n };\n if (m.columnAlignments) result.columnAlignments = [...m.columnAlignments];\n if (m.columnWidths) result.columnWidths = [...m.columnWidths];\n return result;\n },\n\n deserializeMetadata(raw: Record<string, unknown>): TableMetadata {\n const fromSpans = (spans: unknown): AttributedString => {\n if (spans instanceof AttributedString) return spans;\n if (Array.isArray(spans) && spans.length > 0) {\n return AttributedString.fromSpans(spans as Span[]);\n }\n return AttributedString.empty();\n };\n\n // Format B detection: rows is a number\n if (typeof raw.rows === \"number\") {\n const numRows = Math.max(MIN_ROWS, raw.rows as number);\n const numCols = Math.max(MIN_COLS, (raw.columns as number) || DEFAULT_COLS);\n const cells = (raw.cells && typeof raw.cells === \"object\" && !Array.isArray(raw.cells))\n ? raw.cells as Record<string, unknown>\n : {};\n\n const toAS = (val: unknown): AttributedString => {\n if (typeof val === \"string\" && val) return AttributedString.fromPlain(val);\n if (Array.isArray(val)) return fromSpans(val);\n return AttributedString.empty();\n };\n\n const header: AttributedString[] = [];\n for (let c = 0; c < numCols; c++) {\n header.push(toAS(cells[`0,${c}`]));\n }\n const rows: AttributedString[][] = [];\n for (let r = 1; r < numRows; r++) {\n const row: AttributedString[] = [];\n for (let c = 0; c < numCols; c++) {\n row.push(toAS(cells[`${r},${c}`]));\n }\n rows.push(row);\n }\n return { header, rows };\n }\n\n // Format A: header/rows arrays\n const rawHeader = Array.isArray(raw.header) ? raw.header : [];\n const rawRows = Array.isArray(raw.rows) ? raw.rows : [];\n\n const header: AttributedString[] = rawHeader.map((cell: unknown) => fromSpans(cell));\n const rows: AttributedString[][] = rawRows.map((row: unknown) =>\n Array.isArray(row) ? row.map((cell: unknown) => fromSpans(cell)) : [],\n );\n\n if (header.length === 0) {\n header.push(AttributedString.empty());\n for (const row of rows) row.push(AttributedString.empty());\n }\n\n const result: TableMetadata = { header, rows };\n if (Array.isArray(raw.columnAlignments)) {\n result.columnAlignments = raw.columnAlignments as string[];\n }\n if (Array.isArray(raw.columnWidths)) {\n result.columnWidths = raw.columnWidths as number[];\n }\n return result;\n },\n};\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { renderAttributedString, getBlockDir } from \"./render-utils\";\n\nexport interface BlockquoteMetadata {\n [key: string]: unknown;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n}\n\nexport const blockquotePlugin: BlockTypePlugin<BlockquoteMetadata> = {\n type: \"blockquote\",\n label: \"Quote\",\n hasTextContent: true,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): BlockquoteMetadata {\n return {};\n },\n\n render(container, content, metadata) {\n container.innerHTML = \"\";\n const bq = document.createElement(\"blockquote\");\n bq.classList.add(\"blx-blockquote\");\n const p = document.createElement(\"p\");\n p.setAttribute(\"contenteditable\", \"true\");\n p.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(p, content);\n bq.appendChild(p);\n container.appendChild(bq);\n return p;\n },\n\n update(_container, contentEditable, content, metadata) {\n if (!contentEditable) return;\n contentEditable.setAttribute(\"dir\", getBlockDir(metadata));\n renderAttributedString(contentEditable, content);\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\", shortcutHint: \"Ctrl+Shift+0\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 }, shortcutHint: \"Ctrl+Shift+1\" },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 }, shortcutHint: \"Ctrl+Shift+2\" },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 }, shortcutHint: \"Ctrl+Shift+3\" },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 }, shortcutHint: \"Ctrl+Shift+4\" },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false }, shortcutHint: \"Ctrl+Shift+5\" },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true }, shortcutHint: \"Ctrl+Shift+6\" },\n { type: \"checklist\", label: \"Checklist\", description: \"Checklist with checkboxes\", metadata: { checked: false } },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n ];\n },\n\n metadataFromConversion(_fromType: string, _fromMetadata: BlockMetadata): BlockquoteMetadata {\n return {};\n },\n\n serializeMetadata(_m) {\n return {};\n },\n\n deserializeMetadata(_raw) {\n return {};\n },\n};\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget, BlockMetadata } from \"../schema\";\nimport { isBlockReadOnly } from \"./render-utils\";\n\nexport interface MermaidMetadata {\n [key: string]: unknown;\n // The mermaid source code is stored as the block's AttributedString content\n}\n\n// ── Lazy mermaid loading ─────────────────────────────────────────\n\nlet mermaidMod: { default: { initialize: Function; render: Function } } | null =\n null;\nlet mermaidInitialized = false;\nlet mermaidLoadPromise: Promise<\n { default: { initialize: Function; render: Function } } | null\n> | null = null;\n\nasync function ensureMermaid(\n theme: \"default\" | \"dark\" | \"neutral\" = \"neutral\",\n): Promise<typeof mermaidMod> {\n if (!mermaidMod) {\n // Single-flight: reuse the same promise for concurrent callers\n if (!mermaidLoadPromise) {\n mermaidLoadPromise = import(\"mermaid\")\n .then((mod) => {\n mermaidMod = mod;\n return mermaidMod;\n })\n .catch(() => {\n mermaidLoadPromise = null; // allow retry on next call\n return null;\n });\n }\n const result = await mermaidLoadPromise;\n if (!result) return null;\n }\n if (!mermaidInitialized) {\n mermaidMod!.default.initialize({\n startOnLoad: false,\n theme,\n suppressErrors: true,\n });\n mermaidInitialized = true;\n }\n return mermaidMod;\n}\n\n// ── Serialized mermaid rendering ─────────────────────────────────\n// mermaid.render() uses global DOM state internally and cannot handle\n// concurrent calls — the first succeeds but the rest fail/corrupt.\n// We serialize all render calls through a simple queue.\n\nconst pendingRenders = new WeakMap<HTMLElement, ReturnType<typeof setTimeout>>();\nlet renderCounter = 0;\nlet renderQueue: Promise<void> = Promise.resolve();\n\nfunction scheduleMermaidRender(\n previewEl: HTMLElement,\n source: string,\n container: HTMLElement,\n): void {\n const existing = pendingRenders.get(previewEl);\n if (existing !== undefined) clearTimeout(existing);\n\n const timer = setTimeout(() => {\n pendingRenders.delete(previewEl);\n // Chain onto the queue so renders execute one at a time\n renderQueue = renderQueue.then(() =>\n renderMermaidDiagram(previewEl, source, container),\n );\n }, 400);\n pendingRenders.set(previewEl, timer);\n}\n\nasync function renderMermaidDiagram(\n previewEl: HTMLElement,\n source: string,\n container: HTMLElement,\n): Promise<void> {\n const diagramEl = previewEl.querySelector(\n \".blx-mermaid-diagram\",\n ) as HTMLElement | null;\n const errorEl = previewEl.querySelector(\n \".blx-mermaid-error\",\n ) as HTMLElement | null;\n if (!diagramEl || !errorEl) return;\n\n if (!source.trim()) {\n diagramEl.innerHTML = \"\";\n errorEl.textContent = \"\";\n previewEl.classList.add(\"blx-mermaid-empty\");\n return;\n }\n previewEl.classList.remove(\"blx-mermaid-empty\");\n\n // Detect dark mode\n const editorEl = container.closest(\"[data-blx-theme]\");\n const theme =\n editorEl?.getAttribute(\"data-blx-theme\") === \"dark\" ? \"dark\" : \"neutral\";\n\n const mod = await ensureMermaid(theme);\n if (!mod) {\n errorEl.textContent =\n \"Install the mermaid package to render diagrams: npm install mermaid\";\n diagramEl.innerHTML = \"\";\n return;\n }\n\n const id = `blx-mermaid-${renderCounter++}`;\n try {\n const { svg } = await mod.default.render(id, source);\n diagramEl.innerHTML = svg;\n errorEl.textContent = \"\";\n } catch (err: unknown) {\n // mermaid injects a temp element on error — clean it up\n const tempEl = document.getElementById(id);\n if (tempEl) tempEl.remove();\n\n const message =\n err instanceof Error ? err.message : \"Invalid diagram syntax\";\n errorEl.textContent = message;\n diagramEl.innerHTML = \"\";\n }\n}\n\n// ── Export helper ────────────────────────────────────────────────\n\n/**\n * Render mermaid source to an SVG string with a specific theme.\n * Returns null if mermaid is not available or the source has invalid syntax.\n * Serialized through the render queue to avoid mermaid concurrency issues.\n */\nexport async function renderMermaidSvg(\n source: string,\n theme: \"light\" | \"dark\" = \"light\",\n): Promise<string | null> {\n const mermaidTheme = theme === \"dark\" ? \"dark\" : \"neutral\";\n const mod = await ensureMermaid(mermaidTheme);\n if (!mod) return null;\n\n return new Promise((resolve) => {\n renderQueue = renderQueue.then(async () => {\n // Re-initialize with the requested theme before each render\n mod!.default.initialize({ startOnLoad: false, theme: mermaidTheme });\n const id = `blx-mermaid-export-${renderCounter++}`;\n try {\n const { svg } = await mod!.default.render(id, source);\n resolve(svg);\n } catch {\n const tempEl = document.getElementById(id);\n if (tempEl) tempEl.remove();\n resolve(null);\n }\n });\n });\n}\n\n// ── Plugin ───────────────────────────────────────────────────────\n\nexport const mermaidPlugin: BlockTypePlugin<MermaidMetadata> = {\n type: \"mermaid\",\n label: \"Mermaid Diagram\",\n hasTextContent: true,\n indentable: false,\n tabInsertsSpaces: true,\n allowedAttributes: [],\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): MermaidMetadata {\n return {};\n },\n\n convertibleTo(): ConversionTarget[] {\n return [\n {\n type: \"code\",\n label: \"Code Block\",\n description: \"Convert to code block\",\n },\n {\n type: \"paragraph\",\n label: \"Paragraph\",\n description: \"Plain text block\",\n shortcutHint: \"Ctrl+Shift+0\",\n },\n {\n type: \"heading\",\n label: \"Heading 1\",\n description: \"Large heading\",\n metadata: { level: 1 },\n shortcutHint: \"Ctrl+Shift+1\",\n },\n {\n type: \"heading\",\n label: \"Heading 2\",\n description: \"Medium heading\",\n metadata: { level: 2 },\n shortcutHint: \"Ctrl+Shift+2\",\n },\n {\n type: \"heading\",\n label: \"Heading 3\",\n description: \"Small heading\",\n metadata: { level: 3 },\n shortcutHint: \"Ctrl+Shift+3\",\n },\n ];\n },\n\n metadataFromConversion(\n _fromType: string,\n _fromMetadata: BlockMetadata,\n ): MermaidMetadata {\n return {};\n },\n\n render(container, content, _metadata) {\n container.innerHTML = \"\";\n const readOnly = isBlockReadOnly(container);\n\n const contentWrapper = document.createElement(\"div\");\n contentWrapper.classList.add(\"blx-block-content\");\n\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-mermaid\");\n\n // In read-only mode, show only the rendered diagram (no source editor)\n if (readOnly) {\n const preview = document.createElement(\"div\");\n preview.classList.add(\"blx-mermaid-preview\");\n\n const diagram = document.createElement(\"div\");\n diagram.classList.add(\"blx-mermaid-diagram\");\n\n const errorEl = document.createElement(\"div\");\n errorEl.classList.add(\"blx-mermaid-error\");\n\n preview.appendChild(diagram);\n preview.appendChild(errorEl);\n\n wrapper.appendChild(preview);\n contentWrapper.appendChild(wrapper);\n container.appendChild(contentWrapper);\n\n scheduleMermaidRender(preview, content.text, container);\n return null;\n }\n\n // Code area (hidden when not editing)\n const codeArea = document.createElement(\"div\");\n codeArea.classList.add(\"blx-mermaid-code\");\n\n const label = document.createElement(\"div\");\n label.classList.add(\"blx-mermaid-label\");\n label.setAttribute(\"contenteditable\", \"false\");\n label.textContent = \"Mermaid\";\n\n const pre = document.createElement(\"pre\");\n pre.classList.add(\"blx-mermaid-pre\");\n\n const code = document.createElement(\"code\");\n code.classList.add(\"blx-mermaid-content\");\n code.setAttribute(\"contenteditable\", \"true\");\n code.setAttribute(\"spellcheck\", \"false\");\n code.setAttribute(\"dir\", \"ltr\");\n code.style.whiteSpace = \"pre\";\n code.textContent = content.text;\n if (!content.text || content.text.endsWith(\"\\n\")) {\n code.appendChild(document.createElement(\"br\"));\n }\n\n pre.appendChild(code);\n codeArea.appendChild(label);\n codeArea.appendChild(pre);\n\n // Preview area\n const preview = document.createElement(\"div\");\n preview.classList.add(\"blx-mermaid-preview\");\n\n const diagram = document.createElement(\"div\");\n diagram.classList.add(\"blx-mermaid-diagram\");\n\n const errorEl = document.createElement(\"div\");\n errorEl.classList.add(\"blx-mermaid-error\");\n\n preview.appendChild(diagram);\n preview.appendChild(errorEl);\n\n // Click on preview → enter edit mode\n preview.addEventListener(\"click\", (e) => {\n // Don't capture clicks when already editing\n if (wrapper.classList.contains(\"blx-mermaid--editing\")) return;\n e.preventDefault();\n e.stopPropagation();\n wrapper.classList.add(\"blx-mermaid--editing\");\n requestAnimationFrame(() => {\n code.focus();\n // Place cursor at end\n const sel = window.getSelection();\n if (sel) {\n const range = document.createRange();\n range.selectNodeContents(code);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n });\n });\n\n // Focus/blur on code element toggles editing mode\n code.addEventListener(\"focus\", () => {\n wrapper.classList.add(\"blx-mermaid--editing\");\n });\n\n code.addEventListener(\"blur\", (e) => {\n const fe = e as FocusEvent;\n // Don't collapse if focus moves within the mermaid wrapper\n if (\n fe.relatedTarget instanceof Node &&\n wrapper.contains(fe.relatedTarget)\n ) {\n return;\n }\n // Small delay to avoid flicker\n setTimeout(() => {\n if (!code.contains(document.activeElement)) {\n wrapper.classList.remove(\"blx-mermaid--editing\");\n // Layout shifted — nudge the custom caret to reposition\n document.dispatchEvent(new Event(\"selectionchange\"));\n }\n }, 100);\n });\n\n // Start in editing mode when content is empty (newly created block)\n if (!content.text) {\n wrapper.classList.add(\"blx-mermaid--editing\");\n }\n\n wrapper.appendChild(codeArea);\n wrapper.appendChild(preview);\n contentWrapper.appendChild(wrapper);\n container.appendChild(contentWrapper);\n\n // Initial render of diagram\n scheduleMermaidRender(preview, content.text, container);\n\n return code;\n },\n\n update(container, contentEditable, content, _metadata) {\n if (!contentEditable) return;\n contentEditable.setAttribute(\"dir\", \"ltr\");\n\n // Set text immediately (cursor-safe)\n contentEditable.textContent = content.text;\n contentEditable.style.whiteSpace = \"pre\";\n if (!content.text || content.text.endsWith(\"\\n\")) {\n contentEditable.appendChild(document.createElement(\"br\"));\n }\n\n // Schedule debounced mermaid re-render\n const preview = container.querySelector(\n \".blx-mermaid-preview\",\n ) as HTMLElement | null;\n if (preview) {\n scheduleMermaidRender(preview, content.text, container);\n }\n },\n\n serializeMetadata(m) {\n return { ...m };\n },\n\n deserializeMetadata(raw) {\n const result: MermaidMetadata = {};\n if (typeof raw.agendaDate === \"string\") {\n result.agendaDate = raw.agendaDate;\n }\n return result;\n },\n};\n","import { AttributedString } from \"../attributed-string\";\nimport type { BlockTypePlugin, ConversionTarget } from \"../schema\";\nimport { iconHtml, Pencil, X } from \"../util/icons\";\nimport { isBlockReadOnly } from \"./render-utils\";\n\nexport interface ExcalidrawMetadata {\n [key: string]: unknown;\n /** Serialized Excalidraw scene data (JSON string of { elements, appState }) */\n sceneData: string;\n /** Cached SVG string for preview rendering without loading Excalidraw */\n previewSvg?: string;\n /** Display width in pixels (null = auto) */\n width?: number;\n}\n\nexport const excalidrawPlugin: BlockTypePlugin<ExcalidrawMetadata> = {\n type: \"excalidraw\",\n label: \"Excalidraw\",\n hasTextContent: false,\n indentable: false,\n\n defaultContent() {\n return AttributedString.empty();\n },\n\n defaultMetadata(): ExcalidrawMetadata {\n return { sceneData: \"\" };\n },\n\n convertibleTo(): ConversionTarget[] {\n return [];\n },\n\n serializeMetadata(m: ExcalidrawMetadata) {\n const out: Record<string, unknown> = { sceneData: m.sceneData };\n if (m.previewSvg) out.previewSvg = m.previewSvg;\n if (m.width !== undefined) out.width = m.width;\n return out;\n },\n\n deserializeMetadata(raw: Record<string, unknown>): ExcalidrawMetadata {\n return {\n sceneData: typeof raw.sceneData === \"string\" ? raw.sceneData : \"\",\n previewSvg:\n typeof raw.previewSvg === \"string\" ? raw.previewSvg : undefined,\n width: typeof raw.width === \"number\" ? raw.width : undefined,\n };\n },\n\n render(container, _content, metadata) {\n container.innerHTML = \"\";\n const readOnly = isBlockReadOnly(container);\n\n const wrapper = document.createElement(\"div\");\n wrapper.classList.add(\"blx-excalidraw\");\n wrapper.setAttribute(\"contenteditable\", \"false\");\n\n if (!metadata.sceneData) {\n if (readOnly) {\n // Read-only empty state — nothing to display\n container.appendChild(wrapper);\n return null;\n }\n\n // Empty state — show placeholder\n const placeholder = document.createElement(\"div\");\n placeholder.classList.add(\"blx-excalidraw-placeholder\");\n\n const icon = document.createElement(\"span\");\n icon.classList.add(\"blx-excalidraw-icon\");\n icon.innerHTML = iconHtml(Pencil, 28);\n\n const label = document.createElement(\"span\");\n label.classList.add(\"blx-excalidraw-placeholder-label\");\n label.textContent = \"Click to create a drawing\";\n\n const createBtn = document.createElement(\"button\");\n createBtn.type = \"button\";\n createBtn.classList.add(\"blx-excalidraw-create-btn\");\n createBtn.textContent = \"Create\";\n createBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n });\n\n placeholder.addEventListener(\"click\", () => {\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n });\n\n placeholder.appendChild(icon);\n placeholder.appendChild(label);\n placeholder.appendChild(createBtn);\n wrapper.appendChild(placeholder);\n } else {\n // Render preview\n const figure = document.createElement(\"div\");\n figure.classList.add(\"blx-excalidraw-figure\");\n\n const preview = document.createElement(\"div\");\n preview.classList.add(\"blx-excalidraw-preview\");\n if (metadata.width) {\n preview.style.maxWidth = `${metadata.width}px`;\n }\n\n if (metadata.previewSvg) {\n preview.innerHTML = metadata.previewSvg;\n } else {\n // No cached preview — show a placeholder indicating the drawing exists\n const noPreview = document.createElement(\"div\");\n noPreview.classList.add(\"blx-excalidraw-no-preview\");\n noPreview.innerHTML = iconHtml(Pencil, 48);\n const noPreviewLabel = document.createElement(\"span\");\n noPreviewLabel.textContent = readOnly ? \"Drawing\" : \"Drawing (click to edit)\";\n noPreview.appendChild(noPreviewLabel);\n preview.appendChild(noPreview);\n }\n\n if (!readOnly) {\n // Edit overlay on hover\n const editOverlay = document.createElement(\"div\");\n editOverlay.classList.add(\"blx-excalidraw-edit-overlay\");\n const editBtn = document.createElement(\"button\");\n editBtn.type = \"button\";\n editBtn.classList.add(\"blx-excalidraw-edit-btn\");\n editBtn.innerHTML = iconHtml(Pencil, 16);\n editBtn.appendChild(document.createTextNode(\" Edit\"));\n editOverlay.appendChild(editBtn);\n\n editOverlay.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n wrapper.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n });\n\n figure.appendChild(preview);\n figure.appendChild(editOverlay);\n } else {\n figure.appendChild(preview);\n }\n\n wrapper.appendChild(figure);\n }\n\n container.appendChild(wrapper);\n\n return null;\n },\n};\n\n// ── Export helper ────────────────────────────────────────────────\n\n/**\n * Re-render an Excalidraw scene to SVG with a specific theme.\n * Returns null if excalidraw is not available or the scene is invalid.\n */\nexport async function renderExcalidrawSvg(\n sceneData: string,\n theme: \"light\" | \"dark\" = \"light\",\n): Promise<string | null> {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n let ExcalidrawMod: any;\n try {\n ExcalidrawMod = await import(\n /* webpackIgnore: true */ \"@excalidraw/excalidraw\"\n );\n } catch {\n return null;\n }\n\n try {\n const scene = JSON.parse(sceneData);\n const svgElement = await ExcalidrawMod.exportToSvg({\n elements: scene.elements || [],\n appState: {\n ...(scene.appState || {}),\n theme,\n exportBackground: false,\n },\n files: null,\n });\n if (svgElement instanceof SVGSVGElement) {\n return svgElement.outerHTML;\n }\n if (typeof svgElement === \"string\") {\n return svgElement;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// ── Modal helper for editor integration ──────────────────────────\n\n/**\n * Opens the Excalidraw editor in a fullscreen modal overlay.\n * Dynamically imports react, react-dom, and @excalidraw/excalidraw.\n *\n * Returns a cleanup function. Calls `onSave` with the scene data and SVG\n * preview when the user closes the modal.\n */\nexport async function openExcalidrawModal(\n sceneData: string | null,\n onSave: (sceneData: string, previewSvg: string) => void,\n onClose: () => void,\n options?: { theme?: \"light\" | \"dark\" },\n): Promise<void> {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n let React: any;\n let ReactDOM: any;\n let ExcalidrawMod: any;\n\n try {\n React = await import(/* webpackIgnore: true */ \"react\");\n ReactDOM = await import(/* webpackIgnore: true */ \"react-dom/client\");\n ExcalidrawMod = await import(\n /* webpackIgnore: true */ \"@excalidraw/excalidraw\"\n );\n } catch {\n alert(\n \"Excalidraw requires the following packages:\\n\" +\n \" npm install react react-dom @excalidraw/excalidraw\\n\\n\" +\n \"Please install them and try again.\",\n );\n onClose();\n return;\n }\n\n // Inject Excalidraw CSS if not already loaded.\n // We inject a <link> stylesheet rather than import() because import() expects\n // a JS module and CDN servers return text/css which fails MIME type checking.\n // import.meta.resolve() uses the import map to resolve the bare specifier to\n // the actual CDN URL.\n if (!document.querySelector(\"[data-blx-excalidraw-css]\")) {\n try {\n const specifier = \"@excalidraw/excalidraw\" + \"/index.css\";\n const resolvedUrl = import.meta.resolve(specifier);\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = resolvedUrl;\n link.setAttribute(\"data-blx-excalidraw-css\", \"loaded\");\n document.head.appendChild(link);\n // Wait briefly for stylesheet to load before rendering\n await new Promise<void>((resolve) => {\n link.onload = () => resolve();\n link.onerror = () => resolve(); // continue even if CSS fails\n setTimeout(resolve, 2000); // timeout fallback\n });\n } catch {\n // CSS not available — Excalidraw will render with limited styling\n }\n }\n\n // Parse initial scene\n let initialData: Record<string, unknown> | undefined;\n if (sceneData) {\n try {\n initialData = JSON.parse(sceneData);\n } catch {\n initialData = undefined;\n }\n }\n\n // Create modal overlay\n const overlay = document.createElement(\"div\");\n overlay.classList.add(\"blx-excalidraw-modal\");\n\n const backdrop = document.createElement(\"div\");\n backdrop.classList.add(\"blx-excalidraw-modal-backdrop\");\n\n const modalContent = document.createElement(\"div\");\n modalContent.classList.add(\"blx-excalidraw-modal-content\");\n\n // Header\n const header = document.createElement(\"div\");\n header.classList.add(\"blx-excalidraw-modal-header\");\n\n const title = document.createElement(\"span\");\n title.classList.add(\"blx-excalidraw-modal-title\");\n title.textContent = \"Excalidraw\";\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.type = \"button\";\n closeBtn.classList.add(\"blx-excalidraw-modal-close\");\n closeBtn.innerHTML = iconHtml(X, 14);\n\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n // Body (React mount point)\n const body = document.createElement(\"div\");\n body.classList.add(\"blx-excalidraw-modal-body\");\n\n modalContent.appendChild(header);\n modalContent.appendChild(body);\n overlay.appendChild(backdrop);\n overlay.appendChild(modalContent);\n document.body.appendChild(overlay);\n\n // Track latest scene data\n let latestElements: unknown[] = [];\n let latestAppState: Record<string, unknown> = {};\n\n // Mount React\n const root = ReactDOM.createRoot(body);\n const excalidrawEl = React.createElement(ExcalidrawMod.Excalidraw as any, {\n initialData,\n theme: options?.theme ?? \"light\",\n UIOptions: {\n canvasActions: {\n loadScene: false,\n saveToActiveFile: false,\n clearCanvas: false,\n toggleTheme: false,\n },\n tools: { image: false },\n },\n onChange: (elements: unknown[], appState: Record<string, unknown>) => {\n latestElements = elements;\n // Only keep rendering-relevant appState fields\n latestAppState = {\n viewBackgroundColor: appState.viewBackgroundColor,\n currentItemStrokeColor: appState.currentItemStrokeColor,\n currentItemBackgroundColor: appState.currentItemBackgroundColor,\n };\n },\n });\n root.render(excalidrawEl);\n\n // Nudge Excalidraw to recalculate canvas size once layout settles\n requestAnimationFrame(() => window.dispatchEvent(new Event(\"resize\")));\n\n // Close handler\n const cleanup = async () => {\n // Export SVG preview\n let previewSvg = \"\";\n try {\n const svgElement = await ExcalidrawMod.exportToSvg({\n elements: latestElements,\n appState: { ...latestAppState, exportBackground: false },\n files: null,\n });\n if (svgElement instanceof SVGSVGElement) {\n previewSvg = svgElement.outerHTML;\n } else if (typeof svgElement === \"string\") {\n previewSvg = svgElement;\n }\n } catch {\n // Preview export failed — save without preview\n }\n\n const sceneJSON = JSON.stringify({\n elements: latestElements,\n appState: latestAppState,\n });\n\n root.unmount();\n overlay.remove();\n\n if (latestElements.length > 0) {\n onSave(sceneJSON, previewSvg);\n }\n onClose();\n };\n\n closeBtn.addEventListener(\"click\", cleanup);\n backdrop.addEventListener(\"click\", cleanup);\n\n // Escape key closes modal — but only if no Excalidraw sub-dialog is open\n const keyHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n // Check for open Excalidraw dialogs (help, export, etc.)\n const hasSubDialog = document.querySelector(\n \".excalidraw-modal-container, .excalidraw .Modal\",\n );\n if (hasSubDialog) return; // let Excalidraw handle it\n\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", keyHandler, true);\n cleanup();\n }\n };\n document.addEventListener(\"keydown\", keyHandler, true);\n}\n","import type { SchemaRegistry } from \"../schema\";\nimport { paragraphPlugin } from \"./paragraph\";\nimport { headingPlugin } from \"./heading\";\nimport { listPlugin } from \"./list\";\nimport { codeBlockPlugin } from \"./code\";\nimport { horizontalRulePlugin } from \"./horizontal-rule\";\nimport { checklistPlugin } from \"./checklist\";\nimport { youtubePlugin } from \"./youtube\";\nimport { imagePlugin } from \"./image\";\nimport { tablePlugin } from \"./table\";\nimport { blockquotePlugin } from \"./blockquote\";\nimport { mermaidPlugin } from \"./mermaid\";\nimport { excalidrawPlugin } from \"./excalidraw\";\n\nexport { paragraphPlugin } from \"./paragraph\";\nexport { headingPlugin } from \"./heading\";\nexport { listPlugin } from \"./list\";\nexport { codeBlockPlugin, CODE_LANGUAGES } from \"./code\";\nexport { horizontalRulePlugin } from \"./horizontal-rule\";\nexport { checklistPlugin } from \"./checklist\";\nexport { youtubePlugin, parseYouTubeUrl } from \"./youtube\";\nexport { imagePlugin } from \"./image\";\nexport { tablePlugin } from \"./table\";\nexport { blockquotePlugin } from \"./blockquote\";\nexport { mermaidPlugin, renderMermaidSvg } from \"./mermaid\";\nexport { excalidrawPlugin, openExcalidrawModal, renderExcalidrawSvg } from \"./excalidraw\";\nexport { renderAttributedString, setUrlResolver, resolveUrl, getBlockDir, setBlockRefRenderCallback } from \"./render-utils\";\nexport type { ParagraphMetadata } from \"./paragraph\";\nexport type { HeadingMetadata, TaskStatus } from \"./heading\";\nexport type { ListMetadata } from \"./list\";\nexport type { CodeBlockMetadata } from \"./code\";\nexport type { HorizontalRuleMetadata } from \"./horizontal-rule\";\nexport type { ChecklistMetadata } from \"./checklist\";\nexport type { YouTubeMetadata } from \"./youtube\";\nexport type { ImageMetadata } from \"./image\";\nexport type { TableMetadata } from \"./table\";\nexport type { BlockquoteMetadata } from \"./blockquote\";\nexport type { MermaidMetadata } from \"./mermaid\";\nexport type { ExcalidrawMetadata } from \"./excalidraw\";\n\n/** Register the default set of block type plugins */\nexport function registerDefaultPlugins(registry: SchemaRegistry): void {\n registry.register(paragraphPlugin);\n registry.register(headingPlugin);\n registry.register(listPlugin);\n registry.register(codeBlockPlugin);\n registry.register(horizontalRulePlugin);\n registry.register(checklistPlugin);\n registry.register(youtubePlugin);\n registry.register(imagePlugin);\n registry.register(tablePlugin);\n registry.register(blockquotePlugin);\n registry.register(mermaidPlugin);\n registry.register(excalidrawPlugin);\n\n // Aliases for renamed block types (backwards compatibility)\n registry.registerAlias(\"task-list\", \"checklist\");\n}\n","import type { Span } from \"../attributed-string\";\nimport type { BlockJSON } from \"../types\";\n\n/** 4-space indent per nesting level — maximally compatible across CommonMark parsers. */\nconst INDENT = \" \";\n\n/**\n * Convert an array of editor blocks to a Markdown string.\n */\nexport function blocksToMarkdown(blocks: BlockJSON[]): string {\n const lines: string[] = [];\n let orderedCounter = 0;\n let prevWasList = false;\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const isList = block.type === \"list\" || block.type === \"checklist\";\n const isOrdered = block.type === \"list\" &&\n (block.metadata.listType === \"ordered\" || block.metadata.ordered === true);\n\n // Reset ordered counter when switching away from ordered list\n if (!isOrdered) {\n orderedCounter = 0;\n }\n\n // Add blank line when transitioning from list to non-list\n if (prevWasList && !isList) {\n lines.push(\"\");\n }\n prevWasList = isList;\n\n switch (block.type) {\n case \"title\": {\n const text = spansToMarkdown(block.content.spans);\n if (text) {\n lines.push(\"# \" + text);\n lines.push(\"\");\n }\n break;\n }\n\n case \"paragraph\": {\n const text = spansToMarkdown(block.content.spans);\n lines.push(text);\n lines.push(\"\");\n break;\n }\n\n case \"heading\": {\n const level = Math.min(Math.max((block.metadata.level as number) || 1, 1), 4);\n const prefix = \"#\".repeat(level) + \" \";\n const text = spansToMarkdown(block.content.spans);\n lines.push(prefix + text);\n lines.push(\"\");\n break;\n }\n\n case \"checklist\": {\n const indentLevel = (block.metadata.indentLevel as number) || (block.metadata.indent as number) || 0;\n const indent = INDENT.repeat(indentLevel);\n const text = spansToMarkdown(block.content.spans);\n const checked = block.metadata.checked ? \"x\" : \" \";\n lines.push(`${indent}- [${checked}] ${text}`);\n break;\n }\n\n case \"list\": {\n const indentLevel = (block.metadata.indentLevel as number) || (block.metadata.indent as number) || 0;\n const indent = INDENT.repeat(indentLevel);\n const text = spansToMarkdown(block.content.spans);\n\n if (block.metadata.listType === \"task\") {\n const checked = block.metadata.checked ? \"x\" : \" \";\n lines.push(`${indent}- [${checked}] ${text}`);\n } else if (block.metadata.listType === \"ordered\" || block.metadata.ordered === true) {\n orderedCounter++;\n lines.push(`${indent}${orderedCounter}. ${text}`);\n } else {\n lines.push(`${indent}- ${text}`);\n }\n break;\n }\n\n case \"code\": {\n const lang = (block.metadata.language as string) || \"\";\n const text = block.content.spans.map((s) => s.text).join(\"\");\n lines.push(\"```\" + lang);\n lines.push(text);\n lines.push(\"```\");\n lines.push(\"\");\n break;\n }\n\n case \"horizontal-rule\": {\n lines.push(\"---\");\n lines.push(\"\");\n break;\n }\n\n case \"image\": {\n const src = (block.metadata.src as string) || \"\";\n const alt = (block.metadata.alt as string) || \"\";\n const caption = (block.metadata.caption as string) || \"\";\n lines.push(``);\n if (caption) {\n lines.push(`_${caption}_`);\n }\n lines.push(\"\");\n break;\n }\n\n case \"youtube\": {\n const videoId = (block.metadata.videoId as string) || \"\";\n lines.push(`[YouTube](https://youtube.com/watch?v=${videoId})`);\n lines.push(\"\");\n break;\n }\n\n case \"table\": {\n exportTable(block.metadata, lines);\n break;\n }\n\n default: {\n // Unknown block type — output plain text\n const text = spansToMarkdown(block.content.spans);\n if (text) {\n lines.push(text);\n lines.push(\"\");\n }\n break;\n }\n }\n }\n\n // Trim trailing blank lines\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Extract plain text from a table cell (Span[] or AttributedString with .spans) */\nfunction cellToText(cell: unknown): string {\n if (!cell) return \"\";\n if (typeof cell === \"string\") return cell;\n // AttributedString instance or object with .spans\n if (typeof cell === \"object\" && \"spans\" in (cell as Record<string, unknown>)) {\n const spans = (cell as { spans: ReadonlyArray<Span> }).spans;\n return spansToMarkdown(spans);\n }\n // Raw Span[]\n if (Array.isArray(cell)) {\n return spansToMarkdown(cell as Span[]);\n }\n return \"\";\n}\n\n/** Export a table block to Markdown lines */\nfunction exportTable(metadata: Record<string, unknown>, lines: string[]): void {\n // Format A: header (Span[][]) + rows (Span[][][])\n if (Array.isArray(metadata.header)) {\n const header = metadata.header as unknown[];\n const rows = Array.isArray(metadata.rows) ? metadata.rows as unknown[][] : [];\n const numCols = header.length;\n if (numCols === 0) return;\n\n // Header row\n const headerCells = header.map((cell) => escapePipe(cellToText(cell)));\n lines.push(\"| \" + headerCells.join(\" | \") + \" |\");\n\n // Separator row\n const sep = Array(numCols).fill(\"---\");\n lines.push(\"| \" + sep.join(\" | \") + \" |\");\n\n // Data rows\n for (const row of rows) {\n const rowCells: string[] = [];\n for (let c = 0; c < numCols; c++) {\n rowCells.push(escapePipe(cellToText(Array.isArray(row) ? row[c] : \"\")));\n }\n lines.push(\"| \" + rowCells.join(\" | \") + \" |\");\n }\n lines.push(\"\");\n return;\n }\n\n // Format B: rows (number), columns (number), cells (Record<string, string>)\n const numRows = (metadata.rows as number) || 0;\n const numCols = (metadata.columns as number) || 0;\n const cells = (metadata.cells && typeof metadata.cells === \"object\" && !Array.isArray(metadata.cells))\n ? metadata.cells as Record<string, string>\n : {};\n\n if (numRows > 0 && numCols > 0) {\n // Header row\n const headerCells: string[] = [];\n for (let c = 0; c < numCols; c++) {\n headerCells.push(escapePipe(cells[`0,${c}`] || \"\"));\n }\n lines.push(\"| \" + headerCells.join(\" | \") + \" |\");\n\n // Separator row\n const sep = Array(numCols).fill(\"---\");\n lines.push(\"| \" + sep.join(\" | \") + \" |\");\n\n // Data rows\n for (let r = 1; r < numRows; r++) {\n const rowCells: string[] = [];\n for (let c = 0; c < numCols; c++) {\n rowCells.push(escapePipe(cells[`${r},${c}`] || \"\"));\n }\n lines.push(\"| \" + rowCells.join(\" | \") + \" |\");\n }\n lines.push(\"\");\n }\n}\n\n/**\n * Convert attributed spans to inline Markdown.\n */\n/** Escape pipe characters in table cell text for Markdown export */\nfunction escapePipe(text: string): string {\n return text.replace(/\\|/g, \"\\\\|\");\n}\n\nfunction spansToMarkdown(spans: ReadonlyArray<Span>): string {\n let result = \"\";\n\n for (const span of spans) {\n let text = span.text;\n const attrs = span.attributes;\n\n // Apply inline formatting (inner to outer)\n if (attrs.code) {\n text = \"`\" + text + \"`\";\n } else {\n if (attrs.bold) {\n text = \"**\" + text + \"**\";\n }\n if (attrs.italic) {\n text = \"_\" + text + \"_\";\n }\n if (attrs.strikethrough) {\n text = \"~~\" + text + \"~~\";\n }\n }\n\n if (attrs.href) {\n text = `[${text}](${attrs.href})`;\n }\n\n result += text;\n }\n\n return result;\n}\n","/**\n * Generate a unique block ID using UUID v4.\n *\n * Uses `crypto.randomUUID()` when available (all modern browsers and\n * Node 19+). Falls back to a manual implementation for older runtimes\n * (e.g. jsdom in tests).\n */\nexport function generateId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n // Fallback: manual UUID v4 for environments without crypto.randomUUID\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/** Validate whether a string is a valid UUID v4 */\nexport function isUUID(id: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);\n}\n","import { ContextMenu, type MenuItem } from \"../ui/context-menu\";\n\nexport interface SlashMenuItem {\n type: string;\n label: string;\n description: string;\n metadata?: Record<string, unknown>;\n}\n\nexport const SLASH_MENU_ITEMS: SlashMenuItem[] = [\n { type: \"paragraph\", label: \"Paragraph\", description: \"Plain text block\" },\n { type: \"heading\", label: \"Heading 1\", description: \"Large heading\", metadata: { level: 1 } },\n { type: \"heading\", label: \"Heading 2\", description: \"Medium heading\", metadata: { level: 2 } },\n { type: \"heading\", label: \"Heading 3\", description: \"Small heading\", metadata: { level: 3 } },\n { type: \"heading\", label: \"Heading 4\", description: \"Smallest heading\", metadata: { level: 4 } },\n { type: \"list\", label: \"Bullet List\", description: \"Unordered list\", metadata: { ordered: false } },\n { type: \"list\", label: \"Numbered List\", description: \"Ordered list\", metadata: { ordered: true } },\n { type: \"checklist\", label: \"Checklist\", description: \"Checklist with checkboxes\", metadata: { checked: false } },\n { type: \"blockquote\", label: \"Quote\", description: \"Blockquote text\", metadata: {} },\n { type: \"code\", label: \"Code Block\", description: \"Syntax-highlighted code\", metadata: { language: \"plain\" } },\n { type: \"horizontal-rule\", label: \"Horizontal Rule\", description: \"Visual divider\", metadata: {} },\n { type: \"image\", label: \"Image\", description: \"Upload or embed an image\", metadata: { src: \"\" } },\n { type: \"youtube\", label: \"YouTube\", description: \"Embed a YouTube video\", metadata: { videoId: \"\" } },\n { type: \"table\", label: \"Table\", description: \"Insert a table\" },\n { type: \"mermaid\", label: \"Mermaid Diagram\", description: \"Create a diagram with Mermaid syntax\", metadata: {} },\n { type: \"excalidraw\", label: \"Excalidraw\", description: \"Draw with Excalidraw\", metadata: {} },\n];\n\nexport class SlashMenu {\n private menu: ContextMenu;\n private allItems: SlashMenuItem[];\n private filteredItems: SlashMenuItem[];\n private onSelectCb: (item: SlashMenuItem) => void;\n\n constructor(\n items: SlashMenuItem[],\n onSelect: (item: SlashMenuItem) => void,\n onClose: () => void,\n ) {\n this.allItems = items;\n this.filteredItems = items;\n this.onSelectCb = onSelect;\n\n this.menu = new ContextMenu({ className: \"blx-slash-menu\" });\n this.menu.onSelect = (mi: MenuItem) => {\n this.onSelectCb(mi.data as SlashMenuItem);\n };\n this.menu.onClose = onClose;\n }\n\n get element(): HTMLElement {\n return this.menu.el;\n }\n\n get hasItems(): boolean {\n return this.menu.hasItems;\n }\n\n show(anchorRect: DOMRect): void {\n this.filteredItems = this.allItems;\n this.menu.show(anchorRect, this.toMenuItems(this.filteredItems));\n }\n\n /** Reposition the menu relative to a new anchor rect (e.g. on scroll) */\n reposition(anchorRect: DOMRect): void {\n this.menu.reposition(anchorRect);\n }\n\n hide(): void {\n this.menu.hide();\n }\n\n get visible(): boolean {\n return this.menu.visible;\n }\n\n /** Update the filter query. Filters allItems, resets selection, re-renders. */\n updateFilter(query: string): void {\n if (query === \"\") {\n this.filteredItems = this.allItems;\n } else {\n const q = query.toLowerCase();\n this.filteredItems = this.allItems.filter(\n (item) =>\n item.label.toLowerCase().includes(q) ||\n item.type.toLowerCase().includes(q),\n );\n }\n this.menu.setItems(this.toMenuItems(this.filteredItems));\n }\n\n /** Handle keyboard events. Returns true if the event was consumed. */\n handleKeyDown(e: KeyboardEvent): boolean {\n return this.menu.handleKeyDown(e);\n }\n\n destroy(): void {\n this.menu.destroy();\n }\n\n private toMenuItems(items: SlashMenuItem[]): MenuItem[] {\n return items.map((item, i) => ({\n id: `${item.type}-${i}`,\n label: item.label,\n description: item.description,\n data: item,\n }));\n }\n}\n","import type { AutoCompleteEntry } from \"./types\";\nimport { ContextMenu, type MenuItem } from \"../ui/context-menu\";\n\n/**\n * Floating menu showing autocomplete results.\n * Triggered by `[[` in the editor; wraps ContextMenu.\n */\nexport class AutoCompleteMenu {\n private menu: ContextMenu;\n private items: AutoCompleteEntry[] = [];\n private onSelectCb: (entry: AutoCompleteEntry) => void;\n\n constructor(\n onSelect: (entry: AutoCompleteEntry) => void,\n onClose: () => void,\n ) {\n this.onSelectCb = onSelect;\n\n this.menu = new ContextMenu({\n className: \"blx-autocomplete-menu\",\n emptyText: \"No results\",\n });\n this.menu.onSelect = (mi: MenuItem) => {\n this.onSelectCb(mi.data as AutoCompleteEntry);\n };\n this.menu.onClose = onClose;\n }\n\n get element(): HTMLElement {\n return this.menu.el;\n }\n\n get visible(): boolean {\n return this.menu.visible;\n }\n\n get hasItems(): boolean {\n return this.menu.hasItems;\n }\n\n show(anchorRect: DOMRect): void {\n this.menu.show(anchorRect, this.toMenuItems(this.items));\n }\n\n /** Reposition the menu relative to a new anchor rect (e.g. caret moved). */\n reposition(anchorRect: DOMRect): void {\n this.menu.reposition(anchorRect);\n }\n\n hide(): void {\n this.menu.hide();\n }\n\n /** Update displayed results. Resets selection to first item. */\n updateResults(entries: AutoCompleteEntry[]): void {\n this.items = entries;\n this.menu.setItems(this.toMenuItems(entries));\n }\n\n /** Handle keyboard events. Returns true if the event was consumed. */\n handleKeyDown(e: KeyboardEvent): boolean {\n return this.menu.handleKeyDown(e);\n }\n\n destroy(): void {\n this.menu.destroy();\n }\n\n private toMenuItems(entries: AutoCompleteEntry[]): MenuItem[] {\n return entries.map((entry) => ({\n id: entry.id,\n label: entry.label,\n description: entry.description,\n icon: entry.icon,\n data: entry,\n }));\n }\n}\n","/**\n * Date picker for task agenda items with role selection, explicit confirmation,\n * and recurrence configuration.\n *\n * Features:\n * - Role tabs: Due | Scheduled | Event (context-sensitive defaults)\n * - Natural language date suggestions (type \"tomorrow\", \"next friday\", etc.)\n * - Mini calendar grid (month view) with keyboard navigation\n * - Explicit confirm/cancel (tick/cross) in footer bar\n * - Repeat configuration (interval + unit + fromCompletion flag)\n * - Remove agenda item button (when editing an existing agenda date)\n *\n * Follows the same lifecycle pattern as EmojiPicker:\n * - `show(anchorRect, options?)` positions and displays the picker\n * - `reposition(anchorRect)` follows the caret on scroll\n * - `hide()` / `visible` / `destroy()` for cleanup\n * - `handleKeyDown(e)` returns true if the event was consumed\n */\n\nimport { formatAgendaDateISO, MONTH_NAMES_FULL } from \"./agenda-utils\";\nimport type { DateSuggestion } from \"./date-parser\";\n\nexport type DateRole = \"due\" | \"scheduled\" | \"event\";\n\nexport interface Recurrence {\n interval: number;\n unit: \"day\" | \"week\" | \"month\" | \"year\";\n anchor?: string;\n fromCompletion?: boolean;\n}\n\nconst DAY_NAMES_SHORT = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\nconst MONTH_NAMES_SHORT = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n\nexport class DatePicker {\n private el: HTMLElement;\n private onSelect: (isoDate: string, role: DateRole, recurrence?: Recurrence) => void;\n private onRemove: () => void;\n private onClose: () => void;\n private pendingInteraction = false;\n\n private currentMonth: Date;\n private selectedDate: string | null = null;\n private pendingDate: string | null = null;\n private selectedRole: DateRole = \"due\";\n private blockType: string | null = null;\n\n // Repeat state\n private repeatEnabled = false;\n private repeatInterval = 1;\n private repeatUnit: Recurrence[\"unit\"] = \"day\";\n private fromCompletion = false;\n private showingRepeatConfig = false;\n\n // DOM refs\n private roleTabBar: HTMLElement;\n private calendarGrid: HTMLElement;\n private monthLabel: HTMLElement;\n private removeBtn: HTMLButtonElement;\n private footerBar: HTMLElement;\n private tickBtn: HTMLButtonElement;\n private repeatToggleBtn: HTMLButtonElement;\n private repeatConfigEl: HTMLElement;\n\n // Calendar section (for collapsing when repeat config is shown)\n private calendarSection: HTMLElement;\n\n // Suggestion mode state\n private suggestionList: HTMLElement;\n private headerEl: HTMLElement;\n private dowRow: HTMLElement;\n private inSuggestionMode = false;\n private suggestions: DateSuggestion[] = [];\n private suggestionIndex = 0;\n\n constructor(\n onSelect: (isoDate: string, role: DateRole, recurrence?: Recurrence) => void,\n onRemove: () => void,\n onClose: () => void,\n ) {\n this.onSelect = onSelect;\n this.onRemove = onRemove;\n this.onClose = onClose;\n this.currentMonth = new Date();\n this.currentMonth.setDate(1);\n\n this.el = document.createElement(\"div\");\n this.el.classList.add(\"blx-date-picker\");\n this.el.style.display = \"none\";\n\n // Prevent clicks inside picker from blurring the block.\n // Allow native behavior for form controls (inputs, selects, checkboxes)\n // so the repeat config section remains interactive.\n this.el.addEventListener(\"mousedown\", (e) => {\n this.pendingInteraction = true;\n const target = e.target as HTMLElement;\n if (\n target instanceof HTMLInputElement ||\n target instanceof HTMLSelectElement ||\n target.closest(\"label\")\n ) {\n e.stopPropagation();\n return;\n }\n e.preventDefault();\n });\n this.el.addEventListener(\"mouseup\", () => {\n queueMicrotask(() => {\n this.pendingInteraction = false;\n });\n });\n\n // ── Role tabs ──\n this.roleTabBar = document.createElement(\"div\");\n this.roleTabBar.classList.add(\"blx-date-picker-roles\");\n this.renderRoleTabs();\n this.el.appendChild(this.roleTabBar);\n\n // Suggestion list (hidden by default, shown during text search)\n this.suggestionList = document.createElement(\"div\");\n this.suggestionList.classList.add(\"blx-date-picker-suggestions\");\n this.suggestionList.style.display = \"none\";\n this.el.appendChild(this.suggestionList);\n\n // Calendar section wrapper (collapsible for repeat config)\n this.calendarSection = document.createElement(\"div\");\n this.calendarSection.classList.add(\"blx-date-picker-calendar-section\");\n\n // Calendar header (< Month Year >)\n this.headerEl = document.createElement(\"div\");\n this.headerEl.classList.add(\"blx-date-picker-header\");\n\n const prevBtn = document.createElement(\"button\");\n prevBtn.type = \"button\";\n prevBtn.classList.add(\"blx-date-picker-nav\");\n prevBtn.textContent = \"\\u2039\"; // ‹\n prevBtn.addEventListener(\"click\", () => this.navigateMonth(-1));\n\n this.monthLabel = document.createElement(\"span\");\n this.monthLabel.classList.add(\"blx-date-picker-month\");\n\n const nextBtn = document.createElement(\"button\");\n nextBtn.type = \"button\";\n nextBtn.classList.add(\"blx-date-picker-nav\");\n nextBtn.textContent = \"\\u203A\"; // ›\n nextBtn.addEventListener(\"click\", () => this.navigateMonth(1));\n\n this.headerEl.appendChild(prevBtn);\n this.headerEl.appendChild(this.monthLabel);\n this.headerEl.appendChild(nextBtn);\n this.calendarSection.appendChild(this.headerEl);\n\n // Day-of-week header row\n this.dowRow = document.createElement(\"div\");\n this.dowRow.classList.add(\"blx-date-picker-dow\");\n for (const d of [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]) {\n const cell = document.createElement(\"span\");\n cell.textContent = d;\n this.dowRow.appendChild(cell);\n }\n this.calendarSection.appendChild(this.dowRow);\n\n // Calendar grid\n this.calendarGrid = document.createElement(\"div\");\n this.calendarGrid.classList.add(\"blx-date-picker-grid\");\n this.calendarSection.appendChild(this.calendarGrid);\n\n this.el.appendChild(this.calendarSection);\n\n // ── Repeat config (hidden by default, replaces calendar) ──\n this.repeatConfigEl = document.createElement(\"div\");\n this.repeatConfigEl.classList.add(\"blx-date-picker-repeat-config\");\n this.repeatConfigEl.style.display = \"none\";\n this.el.appendChild(this.repeatConfigEl);\n\n // ── Footer bar: [Repeat toggle] ... [× cancel] [✓ confirm] ──\n this.footerBar = document.createElement(\"div\");\n this.footerBar.classList.add(\"blx-date-picker-footer\");\n\n this.repeatToggleBtn = document.createElement(\"button\");\n this.repeatToggleBtn.type = \"button\";\n this.repeatToggleBtn.classList.add(\"blx-date-picker-repeat-toggle\");\n this.repeatToggleBtn.innerHTML = `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"17 1 21 5 17 9\"></polyline><path d=\"M3 11V9a4 4 0 0 1 4-4h14\"></path><polyline points=\"7 23 3 19 7 15\"></polyline><path d=\"M21 13v2a4 4 0 0 1-4 4H3\"></path></svg><span>Repeat</span>`;\n this.repeatToggleBtn.disabled = true;\n this.repeatToggleBtn.addEventListener(\"click\", () => this.toggleRepeatConfig());\n this.footerBar.appendChild(this.repeatToggleBtn);\n\n const footerSpacer = document.createElement(\"div\");\n footerSpacer.classList.add(\"blx-date-picker-footer-spacer\");\n this.footerBar.appendChild(footerSpacer);\n\n const crossBtn = document.createElement(\"button\");\n crossBtn.type = \"button\";\n crossBtn.classList.add(\"blx-date-picker-confirm-btn\", \"blx-date-picker-cross\");\n crossBtn.innerHTML = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>`;\n crossBtn.title = \"Cancel\";\n crossBtn.addEventListener(\"click\", () => this.onClose());\n this.footerBar.appendChild(crossBtn);\n\n this.tickBtn = document.createElement(\"button\");\n this.tickBtn.type = \"button\";\n this.tickBtn.classList.add(\"blx-date-picker-confirm-btn\", \"blx-date-picker-tick\");\n this.tickBtn.innerHTML = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg>`;\n this.tickBtn.title = \"Confirm\";\n this.tickBtn.disabled = true;\n this.tickBtn.addEventListener(\"click\", () => this.confirmDate());\n this.footerBar.appendChild(this.tickBtn);\n\n this.el.appendChild(this.footerBar);\n\n // Remove button (hidden when no existing agenda item)\n this.removeBtn = document.createElement(\"button\");\n this.removeBtn.type = \"button\";\n this.removeBtn.classList.add(\"blx-date-picker-remove\");\n this.removeBtn.textContent = \"Remove agenda item\";\n this.removeBtn.addEventListener(\"click\", () => {\n this.onRemove();\n });\n this.el.appendChild(this.removeBtn);\n }\n\n get element(): HTMLElement {\n return this.el;\n }\n\n /**\n * Show the picker anchored to the given rect.\n * @param anchorRect - Caret or block bounding rect\n * @param options - Optional initial state for role, date, recurrence, blockType\n */\n show(anchorRect: DOMRect, options?: {\n initialRole?: DateRole;\n initialDate?: string;\n initialRecurrence?: Recurrence;\n blockType?: string;\n } | string | null): void {\n // Support legacy signature: show(rect, existingDate?)\n let existingDate: string | undefined;\n let initialRole: DateRole | undefined;\n let initialRecurrence: Recurrence | undefined;\n let blockType: string | undefined;\n\n if (typeof options === \"string\") {\n existingDate = options;\n } else if (options && typeof options === \"object\" && !(options instanceof DOMRect)) {\n existingDate = options.initialDate;\n initialRole = options.initialRole;\n initialRecurrence = options.initialRecurrence;\n blockType = options.blockType;\n }\n\n this.blockType = blockType ?? null;\n this.selectedDate = existingDate ?? null;\n this.pendingDate = existingDate ?? null;\n\n // Set role (for paragraphs, force \"event\")\n if (this.blockType === \"paragraph\") {\n this.selectedRole = \"event\";\n } else {\n this.selectedRole = initialRole ?? \"due\";\n }\n\n // Set recurrence state\n if (initialRecurrence) {\n this.repeatEnabled = true;\n this.repeatInterval = initialRecurrence.interval;\n this.repeatUnit = initialRecurrence.unit;\n this.fromCompletion = initialRecurrence.fromCompletion ?? false;\n this.showingRepeatConfig = true;\n } else {\n this.repeatEnabled = false;\n this.repeatInterval = 1;\n this.repeatUnit = \"day\";\n this.fromCompletion = false;\n this.showingRepeatConfig = false;\n }\n\n // If editing an existing agenda date, show calendar at that month\n if (existingDate) {\n const [y, m] = existingDate.split(\"-\").map(Number);\n this.currentMonth = new Date(y, m - 1, 1);\n } else {\n this.currentMonth = new Date();\n this.currentMonth.setDate(1);\n }\n\n this.removeBtn.style.display = existingDate ? \"\" : \"none\";\n\n // Reset suggestion mode\n this.exitSuggestionMode();\n this.renderRoleTabs();\n this.renderCalendar();\n this.updateConfirmState();\n this.updateRepeatSection();\n this.el.style.display = \"\";\n this.el.style.position = \"fixed\";\n this.el.style.left = `${anchorRect.left + 16}px`;\n this.el.style.top = \"auto\";\n this.el.style.bottom = `${window.innerHeight - anchorRect.top + 4}px`;\n\n // Viewport check\n requestAnimationFrame(() => {\n this.clampToViewport(anchorRect);\n });\n }\n\n reposition(anchorRect: DOMRect): void {\n this.el.style.left = `${anchorRect.left + 16}px`;\n this.el.style.top = \"auto\";\n this.el.style.bottom = `${window.innerHeight - anchorRect.top + 4}px`;\n this.clampToViewport(anchorRect);\n }\n\n /** Clamp the picker within the viewport, flipping or pinning as needed. */\n private clampToViewport(anchorRect: DOMRect): void {\n const rect = this.el.getBoundingClientRect();\n const vh = window.innerHeight;\n const vw = window.innerWidth;\n\n // Vertical: if above-anchor placement bleeds past top, try below\n if (rect.top < 0) {\n this.el.style.bottom = \"auto\";\n this.el.style.top = `${anchorRect.bottom + 4}px`;\n }\n\n // Re-check after potential flip — if still overflowing, pin to viewport edge\n const adjusted = this.el.getBoundingClientRect();\n if (adjusted.bottom > vh) {\n this.el.style.bottom = \"8px\";\n this.el.style.top = \"auto\";\n }\n if (adjusted.top < 0) {\n this.el.style.top = \"8px\";\n this.el.style.bottom = \"auto\";\n }\n\n // Horizontal\n if (rect.right > vw) {\n this.el.style.left = `${vw - rect.width - 8}px`;\n }\n if (rect.left < 0) {\n this.el.style.left = \"8px\";\n }\n }\n\n hide(): void {\n this.el.style.display = \"none\";\n this.exitSuggestionMode();\n }\n\n get visible(): boolean {\n return this.el.style.display !== \"none\";\n }\n\n isInteracting(): boolean {\n return this.pendingInteraction || this.el.contains(document.activeElement);\n }\n\n /**\n * Update displayed date suggestions.\n * Called by the editor on each keystroke while @ search is active.\n * Pass an empty array or null to exit suggestion mode.\n */\n updateSuggestions(suggestions: DateSuggestion[] | null): void {\n if (!suggestions || suggestions.length === 0) {\n this.exitSuggestionMode();\n return;\n }\n\n this.enterSuggestionMode(suggestions);\n }\n\n /**\n * Programmatically set the role (due/scheduled/event).\n * Used by inline syntax detection (e.g., @due(...) sets role to \"due\").\n */\n setRole(role: DateRole): void {\n if (this.blockType === \"paragraph\" && (role === \"due\" || role === \"scheduled\")) {\n return; // Paragraphs only support \"event\" role\n }\n this.selectedRole = role;\n this.renderRoleTabs();\n }\n\n /**\n * Programmatically confirm the current suggestion (like pressing Enter).\n * Used by inline syntax auto-confirm (typing the closing paren).\n * If in suggestion mode with suggestions, selects the highlighted one.\n * If a pending date is set, confirms it.\n */\n confirmSelection(): void {\n if (this.inSuggestionMode && this.suggestions.length > 0) {\n this.setPendingDate(this.suggestions[this.suggestionIndex].isoDate);\n this.confirmDate();\n } else if (this.pendingDate) {\n this.confirmDate();\n }\n }\n\n /** Handle keyboard events. Returns true if the event was consumed. */\n handleKeyDown(e: KeyboardEvent): boolean {\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.onClose();\n return true;\n }\n\n if (e.key === \"Enter\" && !this.inSuggestionMode && this.pendingDate) {\n e.preventDefault();\n this.confirmDate();\n return true;\n }\n\n if (this.inSuggestionMode && this.suggestions.length > 0) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n this.suggestionIndex = (this.suggestionIndex + 1) % this.suggestions.length;\n this.updateSuggestionSelection();\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n this.suggestionIndex = (this.suggestionIndex - 1 + this.suggestions.length) % this.suggestions.length;\n this.updateSuggestionSelection();\n return true;\n }\n if (e.key === \"Enter\" || e.key === \"Tab\") {\n e.preventDefault();\n // Set as pending, then confirm\n this.setPendingDate(this.suggestions[this.suggestionIndex].isoDate);\n this.confirmDate();\n return true;\n }\n }\n\n // Let other keys pass through to BlockController for text input\n return false;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n // ── Role tabs ──\n\n private renderRoleTabs(): void {\n this.roleTabBar.innerHTML = \"\";\n\n // For paragraphs, only \"event\" is valid — hide the tab bar entirely\n if (this.blockType === \"paragraph\") {\n this.roleTabBar.style.display = \"none\";\n return;\n }\n this.roleTabBar.style.display = \"\";\n\n const roles: Array<{ key: DateRole; label: string }> = [\n { key: \"due\", label: \"Due\" },\n { key: \"scheduled\", label: \"Scheduled\" },\n { key: \"event\", label: \"Event\" },\n ];\n\n for (const { key, label } of roles) {\n const tab = document.createElement(\"button\");\n tab.type = \"button\";\n tab.classList.add(\"blx-date-picker-role-tab\");\n if (key === this.selectedRole) {\n tab.classList.add(\"blx-date-picker-role-active\");\n }\n tab.textContent = label;\n tab.addEventListener(\"click\", () => {\n this.selectedRole = key;\n this.renderRoleTabs();\n });\n this.roleTabBar.appendChild(tab);\n }\n }\n\n // ── Confirm / Cancel ──\n\n private confirmDate(): void {\n if (!this.pendingDate) return;\n\n const recurrence: Recurrence | undefined = this.repeatEnabled ? {\n interval: this.repeatInterval,\n unit: this.repeatUnit,\n fromCompletion: this.fromCompletion || undefined,\n } : undefined;\n\n this.onSelect(this.pendingDate, this.selectedRole, recurrence);\n }\n\n private updateConfirmState(): void {\n this.tickBtn.disabled = !this.pendingDate;\n this.repeatToggleBtn.disabled = !this.pendingDate;\n this.updateRepeatLabel();\n }\n\n private formatRecurrenceLabel(): string {\n if (!this.repeatEnabled) return \"Repeat\";\n const unit = this.repeatInterval === 1\n ? this.repeatUnit\n : this.repeatUnit + \"s\";\n return this.repeatInterval === 1\n ? `Every ${unit}`\n : `Every ${this.repeatInterval} ${unit}`;\n }\n\n private updateRepeatLabel(): void {\n const span = this.repeatToggleBtn.querySelector(\"span\");\n if (span) span.textContent = this.formatRecurrenceLabel();\n }\n\n private setPendingDate(iso: string): void {\n this.pendingDate = iso;\n this.updateConfirmState();\n this.renderCalendar();\n\n // Navigate calendar to show the pending date's month\n const [y, m] = iso.split(\"-\").map(Number);\n const pendingMonth = new Date(y, m - 1, 1);\n if (pendingMonth.getFullYear() !== this.currentMonth.getFullYear() ||\n pendingMonth.getMonth() !== this.currentMonth.getMonth()) {\n this.currentMonth = pendingMonth;\n this.renderCalendar();\n }\n\n // Update repeat config date chip if visible\n if (this.showingRepeatConfig) {\n this.buildRepeatConfig();\n }\n }\n\n // ── Repeat config ──\n\n private toggleRepeatConfig(): void {\n this.showingRepeatConfig = !this.showingRepeatConfig;\n this.repeatEnabled = this.showingRepeatConfig;\n this.updateRepeatSection();\n }\n\n private updateRepeatSection(): void {\n if (this.showingRepeatConfig) {\n this.buildRepeatConfig();\n this.repeatConfigEl.style.display = \"\";\n this.calendarSection.style.display = \"none\";\n this.repeatToggleBtn.classList.add(\"blx-date-picker-repeat-active\");\n } else {\n this.repeatConfigEl.style.display = \"none\";\n this.calendarSection.style.display = \"\";\n this.repeatToggleBtn.classList.remove(\"blx-date-picker-repeat-active\");\n }\n this.updateRepeatLabel();\n }\n\n /** Format pending date as \"Wed, Mar 25\" for the repeat config chip. */\n private formatDateChip(iso: string): string {\n const [y, m, d] = iso.split(\"-\").map(Number);\n const dt = new Date(y, m - 1, d);\n return `${DAY_NAMES_SHORT[dt.getDay()]}, ${MONTH_NAMES_SHORT[dt.getMonth()]} ${d}`;\n }\n\n private buildRepeatConfig(): void {\n this.repeatConfigEl.innerHTML = \"\";\n\n // Date chip — shows selected date, click to return to calendar\n if (this.pendingDate) {\n const dateChip = document.createElement(\"button\");\n dateChip.type = \"button\";\n dateChip.classList.add(\"blx-date-picker-date-chip\");\n dateChip.innerHTML = `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect><line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"></line><line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\"></line><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\"></line></svg><span>${this.formatDateChip(this.pendingDate)}</span><svg class=\"blx-date-picker-date-chip-edit\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"></path><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"></path></svg>`;\n dateChip.title = \"Change date\";\n dateChip.addEventListener(\"click\", () => {\n this.showingRepeatConfig = false;\n this.updateRepeatSection();\n });\n this.repeatConfigEl.appendChild(dateChip);\n }\n\n // \"Every [N] [unit]\" row\n const row = document.createElement(\"div\");\n row.classList.add(\"blx-date-picker-repeat-row\");\n\n const everyLabel = document.createElement(\"span\");\n everyLabel.classList.add(\"blx-date-picker-repeat-label\");\n everyLabel.textContent = \"Every\";\n row.appendChild(everyLabel);\n\n const numInput = document.createElement(\"input\");\n numInput.type = \"number\";\n numInput.min = \"1\";\n numInput.max = \"365\";\n numInput.value = String(this.repeatInterval);\n numInput.classList.add(\"blx-date-picker-repeat-num\");\n numInput.addEventListener(\"change\", () => {\n const val = parseInt(numInput.value, 10);\n if (!isNaN(val) && val >= 1) {\n this.repeatInterval = val;\n } else {\n numInput.value = String(this.repeatInterval);\n }\n this.updateRepeatLabel();\n });\n numInput.addEventListener(\"input\", () => {\n const val = parseInt(numInput.value, 10);\n if (!isNaN(val) && val >= 1) {\n this.repeatInterval = val;\n this.updateRepeatLabel();\n }\n });\n row.appendChild(numInput);\n\n const unitSelect = document.createElement(\"select\");\n unitSelect.classList.add(\"blx-date-picker-repeat-unit\");\n const units: Array<{ value: Recurrence[\"unit\"]; label: string; labelPlural: string }> = [\n { value: \"day\", label: \"day\", labelPlural: \"days\" },\n { value: \"week\", label: \"week\", labelPlural: \"weeks\" },\n { value: \"month\", label: \"month\", labelPlural: \"months\" },\n { value: \"year\", label: \"year\", labelPlural: \"years\" },\n ];\n for (const u of units) {\n const opt = document.createElement(\"option\");\n opt.value = u.value;\n opt.textContent = this.repeatInterval === 1 ? u.label : u.labelPlural;\n if (u.value === this.repeatUnit) opt.selected = true;\n unitSelect.appendChild(opt);\n }\n unitSelect.addEventListener(\"change\", () => {\n this.repeatUnit = unitSelect.value as Recurrence[\"unit\"];\n this.updateRepeatLabel();\n });\n row.appendChild(unitSelect);\n\n this.repeatConfigEl.appendChild(row);\n\n // \"Start counting from completion\" checkbox\n const checkRow = document.createElement(\"label\");\n checkRow.classList.add(\"blx-date-picker-repeat-check\");\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.checked = this.fromCompletion;\n checkbox.addEventListener(\"change\", () => {\n this.fromCompletion = checkbox.checked;\n });\n checkRow.appendChild(checkbox);\n\n const checkLabel = document.createElement(\"span\");\n checkLabel.textContent = \"From completion date\";\n checkRow.appendChild(checkLabel);\n\n this.repeatConfigEl.appendChild(checkRow);\n }\n\n // ── Suggestion mode ──\n\n private enterSuggestionMode(suggestions: DateSuggestion[]): void {\n this.inSuggestionMode = true;\n this.suggestions = suggestions;\n this.suggestionIndex = 0;\n\n // Hide calendar UI\n this.calendarSection.style.display = \"none\";\n this.footerBar.style.display = \"none\";\n this.repeatConfigEl.style.display = \"none\";\n this.removeBtn.style.display = \"none\";\n\n // Show and render suggestion list\n this.suggestionList.style.display = \"\";\n this.renderSuggestions();\n }\n\n private exitSuggestionMode(): void {\n this.inSuggestionMode = false;\n this.suggestions = [];\n this.suggestionIndex = 0;\n this.suggestionList.style.display = \"none\";\n\n // Show calendar UI\n this.calendarSection.style.display = \"\";\n this.footerBar.style.display = \"\";\n // removeBtn visibility is controlled by show()\n }\n\n private renderSuggestions(): void {\n this.suggestionList.innerHTML = \"\";\n\n if (this.suggestions.length === 0) {\n const empty = document.createElement(\"div\");\n empty.classList.add(\"blx-date-picker-suggestion-empty\");\n empty.textContent = \"No matching dates\";\n this.suggestionList.appendChild(empty);\n return;\n }\n\n for (let i = 0; i < this.suggestions.length; i++) {\n const s = this.suggestions[i];\n const item = document.createElement(\"button\");\n item.type = \"button\";\n item.classList.add(\"blx-date-picker-suggestion-item\");\n if (i === this.suggestionIndex) {\n item.classList.add(\"blx-date-picker-suggestion-selected\");\n }\n\n const label = document.createElement(\"span\");\n label.classList.add(\"blx-date-picker-suggestion-label\");\n label.textContent = s.label;\n\n const desc = document.createElement(\"span\");\n desc.classList.add(\"blx-date-picker-suggestion-date\");\n desc.textContent = s.description;\n\n item.appendChild(label);\n item.appendChild(desc);\n\n item.addEventListener(\"click\", () => {\n this.setPendingDate(s.isoDate);\n this.confirmDate();\n });\n\n this.suggestionList.appendChild(item);\n }\n }\n\n private updateSuggestionSelection(): void {\n const items = this.suggestionList.querySelectorAll(\".blx-date-picker-suggestion-item\");\n items.forEach((el, i) => {\n el.classList.toggle(\"blx-date-picker-suggestion-selected\", i === this.suggestionIndex);\n });\n }\n\n // ── Calendar ──\n\n private navigateMonth(delta: number): void {\n this.currentMonth.setMonth(this.currentMonth.getMonth() + delta);\n this.renderCalendar();\n }\n\n private renderCalendar(): void {\n const year = this.currentMonth.getFullYear();\n const month = this.currentMonth.getMonth();\n\n this.monthLabel.textContent = `${MONTH_NAMES_FULL[month]} ${year}`;\n\n this.calendarGrid.innerHTML = \"\";\n\n const firstDay = new Date(year, month, 1).getDay(); // 0=Sun\n const daysInMonth = new Date(year, month + 1, 0).getDate();\n\n const today = formatAgendaDateISO(new Date());\n\n // Padding for days before the 1st\n for (let i = 0; i < firstDay; i++) {\n const pad = document.createElement(\"span\");\n pad.classList.add(\"blx-date-picker-pad\");\n this.calendarGrid.appendChild(pad);\n }\n\n for (let d = 1; d <= daysInMonth; d++) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.classList.add(\"blx-date-picker-day\");\n btn.textContent = String(d);\n\n const iso = formatAgendaDateISO(new Date(year, month, d));\n btn.dataset.date = iso;\n\n if (iso === today) {\n btn.classList.add(\"blx-date-picker-today\");\n }\n if (iso === this.pendingDate) {\n btn.classList.add(\"blx-date-picker-selected\");\n }\n\n btn.addEventListener(\"click\", () => {\n this.setPendingDate(iso);\n });\n\n this.calendarGrid.appendChild(btn);\n }\n }\n}\n","/**\n * Natural language date parser for the @ agenda trigger.\n *\n * Parses common date phrases (\"tomorrow\", \"next friday\", \"march 15\") into\n * date suggestions. Designed to be lightweight (no external dependencies)\n * and handle the most common patterns users type.\n */\n\nimport { formatAgendaDateISO, MONTH_NAMES_FULL } from \"./agenda-utils\";\n\n/** A parsed date suggestion shown in the picker. */\nexport interface DateSuggestion {\n /** Human-readable label (e.g. \"Tomorrow\", \"Next Friday\") */\n label: string;\n /** Formatted date description (e.g. \"Wed, Mar 11\") */\n description: string;\n /** The resolved Date object */\n date: Date;\n /** ISO date string (\"YYYY-MM-DD\") */\n isoDate: string;\n}\n\nconst DAY_NAMES = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nconst DAY_ABBREVS = [\"sun\", \"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\"];\nconst MONTH_ABBREVS = [\"jan\", \"feb\", \"mar\", \"apr\", \"may\", \"jun\", \"jul\", \"aug\", \"sep\", \"oct\", \"nov\", \"dec\"];\nconst MONTH_NAMES_LOWER = MONTH_NAMES_FULL.map(m => m.toLowerCase());\n\n/** Short month names for description formatting. */\nconst MONTH_SHORT = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n\n/** Format a date as \"Wed, Mar 11\" for the description field. */\nfunction formatDescription(d: Date, ref: Date): string {\n const dayName = DAY_NAMES[d.getDay()].slice(0, 3);\n const month = MONTH_SHORT[d.getMonth()];\n const day = d.getDate();\n if (d.getFullYear() !== ref.getFullYear()) {\n return `${dayName}, ${month} ${day}, ${d.getFullYear()}`;\n }\n return `${dayName}, ${month} ${day}`;\n}\n\n/** Get the next occurrence of a given day-of-week (0=Sun, 6=Sat), never today. */\nfunction nextDayOfWeek(ref: Date, targetDay: number): Date {\n const d = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n const currentDay = d.getDay();\n let daysAhead = targetDay - currentDay;\n if (daysAhead <= 0) daysAhead += 7;\n d.setDate(d.getDate() + daysAhead);\n return d;\n}\n\n/** Get the occurrence of a day-of-week that's at least 7 days away (\"next\" modifier). */\nfunction nextWeekDayOfWeek(ref: Date, targetDay: number): Date {\n const d = nextDayOfWeek(ref, targetDay);\n // If the nearest occurrence is less than 7 days away, skip to the one after\n const refMidnight = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n const diff = Math.round((d.getTime() - refMidnight.getTime()) / (1000 * 60 * 60 * 24));\n if (diff < 7) {\n d.setDate(d.getDate() + 7);\n }\n return d;\n}\n\nfunction makeSuggestion(label: string, date: Date, ref: Date): DateSuggestion {\n return {\n label,\n description: formatDescription(date, ref),\n date,\n isoDate: formatAgendaDateISO(date),\n };\n}\n\n/**\n * Parse a natural language date query into suggestions.\n *\n * Returns up to 5 suggestions sorted by relevance. Empty query returns\n * empty array (the caller should show the default calendar UI).\n */\nexport function parseDateQuery(query: string, now?: Date): DateSuggestion[] {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n\n const ref = now ?? new Date();\n const results: DateSuggestion[] = [];\n const seen = new Set<string>(); // Deduplicate by isoDate\n\n function add(label: string, date: Date): void {\n const iso = formatAgendaDateISO(date);\n if (seen.has(iso)) return;\n seen.add(iso);\n results.push(makeSuggestion(label, date, ref));\n }\n\n // 1. Relative words\n const relatives: Array<{ names: string[]; offset: number }> = [\n { names: [\"today\"], offset: 0 },\n { names: [\"tomorrow\"], offset: 1 },\n { names: [\"yesterday\"], offset: -1 },\n ];\n for (const rel of relatives) {\n for (const name of rel.names) {\n if (name.startsWith(q) || q.startsWith(name)) {\n const d = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n d.setDate(d.getDate() + rel.offset);\n add(name.charAt(0).toUpperCase() + name.slice(1), d);\n break;\n }\n }\n }\n\n // 2. Day-of-week names (next occurrence, never today)\n for (let i = 0; i < 7; i++) {\n const fullName = DAY_NAMES[i].toLowerCase();\n const abbrev = DAY_ABBREVS[i];\n if (fullName.startsWith(q) || abbrev.startsWith(q)) {\n add(DAY_NAMES[i], nextDayOfWeek(ref, i));\n }\n }\n\n // 3. \"next X\" patterns\n if (q.startsWith(\"next\") || \"next\".startsWith(q)) {\n const rest = q.length > 4 ? q.slice(4).trim() : \"\";\n\n if (q.length <= 4) {\n // Just \"n\", \"ne\", \"nex\", \"next\" — show common next options\n const d7 = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n d7.setDate(d7.getDate() + 7);\n add(\"Next week\", d7);\n const dm = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n dm.setMonth(dm.getMonth() + 1);\n add(\"Next month\", dm);\n } else {\n // \"next week\"\n if (\"week\".startsWith(rest)) {\n const d = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n d.setDate(d.getDate() + 7);\n add(\"Next week\", d);\n }\n // \"next month\"\n if (\"month\".startsWith(rest)) {\n const d = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n d.setMonth(d.getMonth() + 1);\n add(\"Next month\", d);\n }\n // \"next {dayname}\"\n for (let i = 0; i < 7; i++) {\n const fullName = DAY_NAMES[i].toLowerCase();\n const abbrev = DAY_ABBREVS[i];\n if (fullName.startsWith(rest) || abbrev.startsWith(rest)) {\n add(`Next ${DAY_NAMES[i]}`, nextWeekDayOfWeek(ref, i));\n }\n }\n }\n }\n\n // 4. Month names with optional day\n for (let m = 0; m < 12; m++) {\n const fullMonth = MONTH_NAMES_LOWER[m];\n const abbrev = MONTH_ABBREVS[m];\n\n // Check if query starts with month name or abbreviation\n let monthMatched = false;\n let restAfterMonth = \"\";\n\n if (q.length <= fullMonth.length && fullMonth.startsWith(q)) {\n monthMatched = true;\n } else if (q.startsWith(fullMonth)) {\n monthMatched = true;\n restAfterMonth = q.slice(fullMonth.length).trim();\n } else if (q.length <= 3 && abbrev.startsWith(q)) {\n monthMatched = true;\n } else if (q.startsWith(abbrev) && q.length > 3) {\n // \"mar15\" or \"mar 15\"\n monthMatched = true;\n restAfterMonth = q.slice(3).trim();\n }\n\n if (!monthMatched) continue;\n\n if (restAfterMonth) {\n // Parse day number\n const dayNum = parseInt(restAfterMonth, 10);\n if (dayNum >= 1 && dayNum <= 31) {\n // Try current year first, then next year\n let d = new Date(ref.getFullYear(), m, dayNum);\n if (d.getMonth() !== m) continue; // Invalid date (e.g., Feb 30)\n const refMidnight = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n if (d < refMidnight) {\n // Date is in the past this year, try next year\n d = new Date(ref.getFullYear() + 1, m, dayNum);\n if (d.getMonth() !== m) continue;\n }\n add(`${MONTH_NAMES_FULL[m]} ${dayNum}`, d);\n }\n } else {\n // Just the month name — show the 1st of that month (nearest future)\n let d = new Date(ref.getFullYear(), m, 1);\n const refMidnight = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n if (d < refMidnight) {\n d = new Date(ref.getFullYear() + 1, m, 1);\n }\n add(`${MONTH_NAMES_FULL[m]} 1`, d);\n }\n }\n\n // 5. Numeric slash dates: \"3/15\", \"03/15\"\n const slashMatch = /^(\\d{1,2})\\/(\\d{1,2})$/.exec(q);\n if (slashMatch) {\n const month = parseInt(slashMatch[1], 10) - 1;\n const day = parseInt(slashMatch[2], 10);\n if (month >= 0 && month < 12 && day >= 1 && day <= 31) {\n let d = new Date(ref.getFullYear(), month, day);\n if (d.getMonth() === month) {\n const refMidnight = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n if (d < refMidnight) {\n d = new Date(ref.getFullYear() + 1, month, day);\n }\n if (d.getMonth() === month) {\n add(`${MONTH_NAMES_FULL[month]} ${day}`, d);\n }\n }\n }\n }\n\n // 6. Relative offset shorthand: \"+3d\", \"+2w\", \"+1m\"\n const offsetMatch = /^\\+(\\d+)\\s*([dwm])/.exec(q);\n if (offsetMatch) {\n const n = parseInt(offsetMatch[1], 10);\n const unit = offsetMatch[2];\n const d = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());\n if (unit === \"d\") {\n d.setDate(d.getDate() + n);\n add(`+${n} day${n === 1 ? \"\" : \"s\"}`, d);\n } else if (unit === \"w\") {\n d.setDate(d.getDate() + n * 7);\n add(`+${n} week${n === 1 ? \"\" : \"s\"}`, d);\n } else if (unit === \"m\") {\n d.setMonth(d.getMonth() + n);\n add(`+${n} month${n === 1 ? \"\" : \"s\"}`, d);\n }\n }\n\n return results.slice(0, 5);\n}\n","/**\n * Single floating drag handle that repositions on hover.\n * Uses pointer-based drag (mousedown/mousemove/mouseup) for reordering\n * with animated gap and a ghost element.\n *\n * Supports multi-block drag when a block selection is active.\n * On touch devices, the handle appears on tap and supports touch-based dragging.\n */\nimport { iconHtml, GripVertical } from \"../util/icons\";\n\n/**\n * Return the vertical center of a block's first line for gutter widget alignment.\n * Non-text blocks (image, youtube, hr) have contenteditable=\"false\" on their\n * direct child — for those we use the editor's computed line-height so the\n * widgets sit near the top, matching paragraph positioning.\n */\nexport function firstLineCenterY(blockEl: HTMLElement, editorRoot: HTMLElement): number {\n const firstChild = blockEl.firstElementChild as HTMLElement | null;\n const isNonTextBlock = firstChild?.getAttribute(\"contenteditable\") === \"false\";\n\n if (isNonTextBlock) {\n // Tables: center on the heading row (first <tr>)\n const headingRow = firstChild!.querySelector(\".blx-table-row\") as HTMLElement | null;\n if (headingRow) {\n const rowRect = headingRow.getBoundingClientRect();\n return rowRect.top + rowRect.height / 2;\n }\n\n // HR: center vertically\n if (firstChild!.classList.contains(\"blx-horizontal-rule\")) {\n const rect = firstChild!.getBoundingClientRect();\n return rect.top + rect.height / 2;\n }\n\n const rect = firstChild!.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(editorRoot).lineHeight) || 24;\n return rect.top + lineHeight;\n }\n\n // Text block — original logic: align to first line of contenteditable\n const contentEl = blockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement | null\n ?? firstChild;\n const contentRect = contentEl ? contentEl.getBoundingClientRect() : blockEl.getBoundingClientRect();\n const style = contentEl ? getComputedStyle(contentEl) : null;\n const lineHeight = style ? parseFloat(style.lineHeight) || contentRect.height : contentRect.height;\n const paddingTop = style ? parseFloat(style.paddingTop) || 0 : 0;\n return contentRect.top + paddingTop + Math.min(lineHeight, contentRect.height - paddingTop) / 2;\n}\n\nexport class DragHandle {\n private editorRoot: HTMLElement;\n private gutterEl: HTMLElement;\n private handle: HTMLElement;\n private onMoveBlock: (blockId: string, toIndex: number) => void;\n private onMoveBlocks: ((blockIds: string[], toIndex: number) => void) | null;\n private getSelectedBlockIds: (() => string[] | null) | null;\n private onDragStart: (() => void) | null;\n private onDragEnd: (() => void) | null;\n private onDoubleTap: ((blockId: string) => void) | null;\n private isBlockDraggable: ((blockId: string) => boolean) | null;\n\n /** The block element the handle is currently positioned next to */\n private hoveredBlockEl: HTMLElement | null = null;\n private _menuActive = false;\n\n /** Drag state — single or multi block */\n private dragBlockIds: string[] = [];\n private dragFromIndices: number[] = [];\n private ghost: HTMLElement | null = null;\n private ghostOffsetY: number = 0;\n private currentDropSlot: number = -1;\n private sourceHeight: number = 0;\n /** Original midpoints cached at drag start (immune to CSS transition drift) */\n private cachedMidpoints: number[] = [];\n\n /** Bound handlers for document-level listeners (so we can remove them) */\n private boundDocMouseMove: ((e: MouseEvent) => void) | null = null;\n private boundDocMouseUp: ((e: MouseEvent) => void) | null = null;\n\n /** Bound handlers for touch-based document-level listeners */\n private boundDocTouchMove: ((e: TouchEvent) => void) | null = null;\n private boundDocTouchEnd: ((e: TouchEvent) => void) | null = null;\n\n /** Touch drag state: timer for long-press detection */\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\n private longPressTriggered = false;\n private touchStartY = 0;\n private touchStartX = 0;\n\n /** Delay in ms before a touch becomes a drag (long-press) */\n private static LONG_PRESS_DELAY = 300;\n /** Max movement in px during long-press before it's cancelled */\n private static LONG_PRESS_TOLERANCE = 8;\n /** Max interval in ms between two taps to count as double-tap */\n private static DOUBLE_TAP_DELAY = 300;\n /** Timestamp of the last quick tap on the handle (for double-tap detection) */\n private lastHandleTapTime = 0;\n\n /** Pending mouse drag: mousedown recorded but drag not started until mousemove */\n private pendingMouseDrag = false;\n private mouseDownX = 0;\n private mouseDownY = 0;\n\n constructor(\n editorRoot: HTMLElement,\n gutterEl: HTMLElement,\n onMoveBlock: (blockId: string, toIndex: number) => void,\n options?: {\n getSelectedBlockIds?: () => string[] | null;\n onMoveBlocks?: (blockIds: string[], toIndex: number) => void;\n onDragStart?: () => void;\n onDragEnd?: () => void;\n onDoubleTap?: (blockId: string) => void;\n isBlockDraggable?: (blockId: string) => boolean;\n },\n ) {\n this.editorRoot = editorRoot;\n this.gutterEl = gutterEl;\n this.onMoveBlock = onMoveBlock;\n this.getSelectedBlockIds = options?.getSelectedBlockIds ?? null;\n this.onMoveBlocks = options?.onMoveBlocks ?? null;\n this.onDragStart = options?.onDragStart ?? null;\n this.onDragEnd = options?.onDragEnd ?? null;\n this.onDoubleTap = options?.onDoubleTap ?? null;\n this.isBlockDraggable = options?.isBlockDraggable ?? null;\n\n // Create handle element\n this.handle = document.createElement(\"div\");\n this.handle.classList.add(\"blx-drag-handle\");\n this.handle.setAttribute(\"contenteditable\", \"false\");\n this.handle.innerHTML = iconHtml(GripVertical, 14);\n this.gutterEl.appendChild(this.handle);\n\n this.attachListeners();\n }\n\n /** Hide the handle and clear hover state (e.g. when user starts typing) */\n hide(): void {\n if (this.dragBlockIds.length > 0) return; // don't interfere with active drag\n this.hideHandle();\n this.hoveredBlockEl = null;\n }\n\n /** Called by the editor when the block action menu opens — suppresses the drag handle */\n notifyMenuOpen(): void {\n this._menuActive = true;\n this.hide();\n }\n\n /** Called by the editor when the block action menu closes */\n notifyMenuClosed(): void {\n this._menuActive = false;\n }\n\n destroy(): void {\n this.editorRoot.removeEventListener(\"mousemove\", this.handleMouseMove);\n this.editorRoot.removeEventListener(\"mouseleave\", this.handleMouseLeave);\n this.handle.removeEventListener(\"mousedown\", this.handleMouseDown);\n this.handle.removeEventListener(\"mouseleave\", this.handleHandleLeave);\n this.handle.removeEventListener(\"dblclick\", this.handleDblClick);\n // Touch listeners\n this.editorRoot.removeEventListener(\"touchstart\", this.handleEditorTouchStart);\n this.handle.removeEventListener(\"touchstart\", this.handleHandleTouchStart);\n this.cancelLongPress();\n this.cleanupDrag();\n this.handle.remove();\n }\n\n private attachListeners(): void {\n // Mouse listeners (desktop)\n this.editorRoot.addEventListener(\"mousemove\", this.handleMouseMove);\n this.editorRoot.addEventListener(\"mouseleave\", this.handleMouseLeave);\n this.handle.addEventListener(\"mousedown\", this.handleMouseDown);\n this.handle.addEventListener(\"mouseleave\", this.handleHandleLeave);\n this.handle.addEventListener(\"dblclick\", this.handleDblClick);\n\n // Touch listeners (mobile)\n this.editorRoot.addEventListener(\"touchstart\", this.handleEditorTouchStart, { passive: true });\n this.handle.addEventListener(\"touchstart\", this.handleHandleTouchStart, { passive: false });\n }\n\n // ── Hover positioning ────────────────────────────────────────\n\n private handleMouseMove = (e: MouseEvent): void => {\n // Don't reposition during drag, pending drag, or while action menu is open\n if (this.dragBlockIds.length > 0 || this.pendingMouseDrag || this._menuActive) return;\n\n const target = e.target as HTMLElement;\n\n // If hovering over the handle itself, keep it visible at current position\n if (this.handle.contains(target)) {\n this.showHandle();\n return;\n }\n\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl || !this.editorRoot.contains(blockEl)) {\n // Cursor not directly over a block (gap, left/right whitespace, etc.)\n // Fast path: already tracking a block and cursor is within its vertical range\n if (this.hoveredBlockEl) {\n const rect = this.hoveredBlockEl.getBoundingClientRect();\n if (e.clientY >= rect.top && e.clientY <= rect.bottom) return;\n }\n // Slow path: find the block at this Y position (handles whitespace approach)\n const blockAtY = this.findBlockAtY(e.clientY, e.clientX);\n if (blockAtY) {\n this.hoveredBlockEl = blockAtY;\n this.positionHandle(blockAtY);\n return;\n }\n this.hideHandle();\n this.hoveredBlockEl = null;\n return;\n }\n\n this.hoveredBlockEl = blockEl;\n this.positionHandle(blockEl);\n };\n\n private showHandle(): void {\n this.handle.style.opacity = \"1\";\n this.handle.style.transform = \"translateX(0)\";\n }\n\n private hideHandle(): void {\n this.handle.style.opacity = \"0\";\n this.handle.style.transform = \"translateX(-4px)\";\n }\n\n private findBlockAtY(clientY: number, clientX: number): HTMLElement | null {\n const blocks = this.editorRoot.querySelectorAll<HTMLElement>(\".blx-block\");\n for (const block of blocks) {\n const r = block.getBoundingClientRect();\n if (clientY >= r.top && clientY <= r.bottom && clientX <= r.right) return block;\n }\n return null;\n }\n\n private handleMouseLeave = (_e: MouseEvent): void => {\n if (this.dragBlockIds.length === 0) {\n this.hideHandle();\n this.hoveredBlockEl = null;\n }\n };\n\n /** Hide handle when mouse leaves it away from the editor */\n private handleHandleLeave = (e: MouseEvent): void => {\n if (this.dragBlockIds.length > 0) return;\n // If cursor is still within the editor's horizontal extent (including left\n // whitespace), let handleMouseMove take over instead of hiding immediately.\n const editorRect = this.editorRoot.getBoundingClientRect();\n if (e.clientX >= editorRect.left && e.clientX <= editorRect.right) return;\n this.hideHandle();\n this.hoveredBlockEl = null;\n };\n\n private positionHandle(blockEl: HTMLElement): void {\n const blockId = blockEl.dataset.blockId;\n if (blockId && this.isBlockDraggable && !this.isBlockDraggable(blockId)) {\n this.hideHandle();\n return;\n }\n\n const gutterRect = this.gutterEl.getBoundingClientRect();\n const firstLineCenter = firstLineCenterY(blockEl, this.editorRoot);\n\n this.showHandle();\n this.handle.style.top = `${firstLineCenter - gutterRect.top - this.handle.offsetHeight / 2}px`;\n this.handle.dataset.blockId = blockEl.dataset.blockId ?? \"\";\n }\n\n // ── Double-click / double-tap ────────────────────────────────\n\n private handleDblClick = (e: MouseEvent): void => {\n e.preventDefault();\n e.stopPropagation();\n const blockId = this.handle.dataset.blockId;\n if (blockId) this.onDoubleTap?.(blockId);\n };\n\n // ── Touch: show handle on block tap ─────────────────────────\n\n private handleEditorTouchStart = (e: TouchEvent): void => {\n // Don't reposition during drag\n if (this.dragBlockIds.length > 0) return;\n\n const touch = e.touches[0];\n if (!touch) return;\n\n const target = touch.target as HTMLElement;\n\n // If touching the handle itself, keep it visible\n if (this.handle.contains(target)) return;\n\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl || !this.editorRoot.contains(blockEl)) {\n this.hideHandle();\n this.hoveredBlockEl = null;\n return;\n }\n\n this.hoveredBlockEl = blockEl;\n this.positionHandle(blockEl);\n };\n\n // ── Touch: drag via long-press on handle ──────────────────\n\n private handleHandleTouchStart = (e: TouchEvent): void => {\n const touch = e.touches[0];\n if (!touch) return;\n\n // Detect double-tap: if second tap arrives within DOUBLE_TAP_DELAY, fire callback\n const now = Date.now();\n if (now - this.lastHandleTapTime < DragHandle.DOUBLE_TAP_DELAY) {\n e.preventDefault();\n this.lastHandleTapTime = 0;\n const blockId = this.handle.dataset.blockId;\n if (blockId) this.onDoubleTap?.(blockId);\n return;\n }\n\n // Prevent default to avoid scrolling and text selection while on handle\n e.preventDefault();\n\n this.touchStartX = touch.clientX;\n this.touchStartY = touch.clientY;\n this.longPressTriggered = false;\n\n // Start long-press timer\n this.longPressTimer = setTimeout(() => {\n this.longPressTriggered = true;\n this.startDrag(this.touchStartX, this.touchStartY);\n\n // Haptic feedback if available\n if (navigator.vibrate) {\n navigator.vibrate(30);\n }\n }, DragHandle.LONG_PRESS_DELAY);\n\n // Listen for move/end to potentially cancel the long-press\n this.boundDocTouchMove = this.handleDocTouchMoveDuringLongPress.bind(this);\n this.boundDocTouchEnd = this.handleDocTouchEndDuringLongPress.bind(this);\n document.addEventListener(\"touchmove\", this.boundDocTouchMove, { passive: false });\n document.addEventListener(\"touchend\", this.boundDocTouchEnd, true);\n document.addEventListener(\"touchcancel\", this.boundDocTouchEnd, true);\n };\n\n private handleDocTouchMoveDuringLongPress(e: TouchEvent): void {\n const touch = e.touches[0];\n if (!touch) return;\n\n if (!this.longPressTriggered) {\n // Long-press hasn't fired yet — check if movement exceeds tolerance\n const dx = touch.clientX - this.touchStartX;\n const dy = touch.clientY - this.touchStartY;\n if (Math.abs(dx) > DragHandle.LONG_PRESS_TOLERANCE ||\n Math.abs(dy) > DragHandle.LONG_PRESS_TOLERANCE) {\n this.cancelLongPress();\n this.cleanupLongPressListeners();\n return;\n }\n // Prevent scrolling during long-press wait\n e.preventDefault();\n return;\n }\n\n // Long-press was triggered — we're in drag mode\n e.preventDefault();\n this.handleDragMove(touch.clientX, touch.clientY);\n }\n\n private handleDocTouchEndDuringLongPress(e: TouchEvent): void {\n if (!this.longPressTriggered) {\n // Long-press didn't fire — record tap time for double-tap detection\n this.lastHandleTapTime = Date.now();\n this.cancelLongPress();\n this.cleanupLongPressListeners();\n return;\n }\n\n // Long-press drag completed — finalize\n this.cleanupLongPressListeners();\n this.handleDragEnd();\n }\n\n private cancelLongPress(): void {\n if (this.longPressTimer) {\n clearTimeout(this.longPressTimer);\n this.longPressTimer = null;\n }\n this.longPressTriggered = false;\n }\n\n private cleanupLongPressListeners(): void {\n if (this.boundDocTouchMove) {\n document.removeEventListener(\"touchmove\", this.boundDocTouchMove);\n this.boundDocTouchMove = null;\n }\n if (this.boundDocTouchEnd) {\n document.removeEventListener(\"touchend\", this.boundDocTouchEnd, true);\n document.removeEventListener(\"touchcancel\", this.boundDocTouchEnd, true);\n this.boundDocTouchEnd = null;\n }\n }\n\n // ── Pointer-based drag ───────────────────────────────────────\n\n private handleMouseDown = (e: MouseEvent): void => {\n // Only left button\n if (e.button !== 0) return;\n e.preventDefault();\n\n // Record position but don't start drag yet — wait for mousemove.\n // This lets dblclick fire on clicks without movement.\n this.pendingMouseDrag = true;\n this.mouseDownX = e.clientX;\n this.mouseDownY = e.clientY;\n\n // Attach document-level mouse listeners (capture phase)\n this.boundDocMouseMove = this.handleDocMouseMove.bind(this);\n this.boundDocMouseUp = this.handleDocMouseUp.bind(this);\n document.addEventListener(\"mousemove\", this.boundDocMouseMove, true);\n document.addEventListener(\"mouseup\", this.boundDocMouseUp, true);\n };\n\n private handleDocMouseMove(e: MouseEvent): void {\n if (this.pendingMouseDrag) {\n // First movement after mousedown — initiate drag now\n const dx = e.clientX - this.mouseDownX;\n const dy = e.clientY - this.mouseDownY;\n if (Math.abs(dx) < 3 && Math.abs(dy) < 3) return; // ignore micro-jitter\n this.pendingMouseDrag = false;\n this.startDrag(this.mouseDownX, this.mouseDownY);\n }\n this.handleDragMove(e.clientX, e.clientY);\n }\n\n private handleDocMouseUp(_e: MouseEvent): void {\n if (this.pendingMouseDrag) {\n // Mouseup without movement — no drag. Clean up listeners.\n this.pendingMouseDrag = false;\n if (this.boundDocMouseMove) {\n document.removeEventListener(\"mousemove\", this.boundDocMouseMove, true);\n this.boundDocMouseMove = null;\n }\n if (this.boundDocMouseUp) {\n document.removeEventListener(\"mouseup\", this.boundDocMouseUp, true);\n this.boundDocMouseUp = null;\n }\n return;\n }\n this.handleDragEnd();\n }\n\n // ── Unified drag logic (shared by mouse and touch) ─────────\n\n /**\n * Begin a drag operation from the given screen coordinates.\n * Called by both mousedown and touch long-press.\n */\n private startDrag(clientX: number, clientY: number): void {\n const blockId = this.handle.dataset.blockId;\n if (!blockId) return;\n\n const blockEl = this.editorRoot.querySelector<HTMLElement>(\n `.blx-block[data-block-id=\"${blockId}\"]`,\n );\n if (!blockEl) return;\n\n const blocks = Array.from(this.editorRoot.querySelectorAll<HTMLElement>(\".blx-block\"));\n\n // Determine which blocks to drag: if block selection is active and the\n // hovered block is part of it, drag the entire selection\n const selectedIds = this.getSelectedBlockIds?.() ?? null;\n const isPartOfSelection = selectedIds && selectedIds.includes(blockId);\n\n if (isPartOfSelection && selectedIds!.length > 1) {\n this.dragBlockIds = selectedIds!;\n } else {\n this.dragBlockIds = [blockId];\n }\n\n // Find indices of all dragged blocks\n this.dragFromIndices = this.dragBlockIds.map((id) => {\n const el = this.editorRoot.querySelector<HTMLElement>(\n `.blx-block[data-block-id=\"${id}\"]`,\n );\n return el ? blocks.indexOf(el) : -1;\n }).filter((i) => i >= 0);\n\n // Use the first dragged index as the \"from\" anchor\n this.dragFromIndices.sort((a, b) => a - b);\n const firstDragIndex = this.dragFromIndices[0];\n this.currentDropSlot = firstDragIndex;\n\n // Compute combined source height from all dragged blocks\n const firstBlockRect = blocks[firstDragIndex].getBoundingClientRect();\n const lastDragIndex = this.dragFromIndices[this.dragFromIndices.length - 1];\n const lastBlockRect = blocks[lastDragIndex].getBoundingClientRect();\n this.sourceHeight = lastBlockRect.bottom - firstBlockRect.top;\n this.ghostOffsetY = clientY - firstBlockRect.top;\n\n // Cache original midpoints before any transforms are applied\n this.cachedMidpoints = [];\n for (let i = 0; i < blocks.length; i++) {\n const rect = blocks[i].getBoundingClientRect();\n this.cachedMidpoints.push(rect.top + rect.height / 2);\n }\n\n // Create ghost — for multi-block, create a container with all selected blocks\n this.ghost = document.createElement(\"div\");\n this.ghost.classList.add(\"blx-drag-ghost\", \"blx-editor\");\n // Inherit --blx-* CSS custom properties via the blx-editor class,\n // but override layout properties that would conflict with the ghost.\n this.ghost.style.padding = \"0\";\n this.ghost.style.minWidth = \"0\";\n // Copy theme attribute so dark-mode variables resolve\n const theme = this.editorRoot.getAttribute(\"data-blx-theme\");\n if (theme) {\n this.ghost.setAttribute(\"data-blx-theme\", theme);\n }\n this.ghost.style.width = `${firstBlockRect.width}px`;\n this.ghost.style.top = `${firstBlockRect.top}px`;\n this.ghost.style.left = `${firstBlockRect.left}px`;\n\n for (const dragIdx of this.dragFromIndices) {\n const clone = blocks[dragIdx].cloneNode(true) as HTMLElement;\n clone.style.transform = \"\";\n this.ghost.appendChild(clone);\n }\n\n // Add handle icon to ghost\n const ghostHandle = this.handle.cloneNode(true) as HTMLElement;\n const handleRect = this.handle.getBoundingClientRect();\n ghostHandle.style.opacity = \"1\";\n ghostHandle.style.left = `${handleRect.left - firstBlockRect.left}px`;\n ghostHandle.style.top = `${handleRect.top - firstBlockRect.top}px`;\n this.ghost.appendChild(ghostHandle);\n document.body.appendChild(this.ghost);\n\n // Hide originals (keep layout space)\n for (const dragIdx of this.dragFromIndices) {\n blocks[dragIdx].classList.add(\"blx-block-dragging\");\n }\n\n // Enable transitions on all blocks\n for (const b of blocks) {\n b.classList.add(\"blx-block-shift\");\n }\n\n // Hide handle during drag\n this.hideHandle();\n\n // Notify listeners (e.g. to hide action menu button)\n this.onDragStart?.();\n\n // Set grabbing cursor globally (no effect on touch, but harmless)\n document.body.style.cursor = \"grabbing\";\n }\n\n /** Update drag position from screen coordinates. */\n private handleDragMove(clientX: number, clientY: number): void {\n if (!this.ghost || this.dragBlockIds.length === 0) return;\n\n // Reposition ghost\n const ghostTop = clientY - this.ghostOffsetY;\n this.ghost.style.top = `${ghostTop}px`;\n\n // Use ghost center for predictable landing based on block bounds\n const ghostCenter = ghostTop + this.sourceHeight / 2;\n\n // Compute drop slot (with hysteresis to prevent jitter)\n const dropSlot = this.computeDropSlot(ghostCenter);\n if (dropSlot === this.currentDropSlot) return;\n this.currentDropSlot = dropSlot;\n\n // Apply transforms for animated gap\n const blocks = this.editorRoot.querySelectorAll<HTMLElement>(\".blx-block\");\n const isDragged = new Set(this.dragFromIndices);\n\n for (let i = 0; i < blocks.length; i++) {\n if (isDragged.has(i)) continue; // source blocks are hidden\n\n // Count how many dragged blocks are before this block's position\n const draggedBefore = this.dragFromIndices.filter((d) => d < i).length;\n // The block's \"effective\" position after removing dragged blocks\n const effectivePos = i - draggedBefore;\n\n // Where the group will land (0-based among non-dragged blocks)\n const effectiveDropSlot = dropSlot - this.dragFromIndices.filter((d) => d < dropSlot).length;\n\n if (effectivePos < effectiveDropSlot) {\n // Block is above the drop position — shift up by source height if needed\n const shiftUp = this.dragFromIndices.filter((d) => d < i).length;\n if (shiftUp > 0) {\n // These blocks fill the gap left by removed blocks above them\n const gapHeight = this.dragFromIndices\n .filter((d) => d < i)\n .reduce((sum, d) => {\n const rect = blocks[d].getBoundingClientRect();\n return sum + rect.height;\n }, 0);\n blocks[i].style.transform = `translateY(${-gapHeight}px)`;\n } else {\n blocks[i].style.transform = \"translateY(0)\";\n }\n } else {\n // Block is at or below the drop position — shift down to make room\n const gapHeight = this.sourceHeight;\n const compensation = this.dragFromIndices\n .filter((d) => d < i)\n .reduce((sum, d) => {\n const rect = blocks[d].getBoundingClientRect();\n return sum + rect.height;\n }, 0);\n blocks[i].style.transform = `translateY(${gapHeight - compensation}px)`;\n }\n }\n }\n\n /** Finalize the drag and apply the move. */\n private handleDragEnd(): void {\n if (this.dragBlockIds.length === 0) return;\n\n const dropSlot = this.currentDropSlot;\n const movedBlockIds = [...this.dragBlockIds];\n const firstFromIndex = this.dragFromIndices[0];\n\n // Compute effective target: account for dragged blocks being removed\n const draggedBeforeDrop = this.dragFromIndices.filter((d) => d < dropSlot).length;\n const effectiveIndex = dropSlot - draggedBeforeDrop;\n\n const firstEffectiveFrom = firstFromIndex - this.dragFromIndices.filter((d) => d < firstFromIndex).length;\n\n if (effectiveIndex !== firstEffectiveFrom) {\n if (movedBlockIds.length === 1) {\n const fromIndex = this.dragFromIndices[0];\n const singleEffective = dropSlot > fromIndex ? dropSlot - 1 : dropSlot;\n this.onMoveBlock(movedBlockIds[0], singleEffective);\n } else if (this.onMoveBlocks) {\n this.onMoveBlocks(movedBlockIds, effectiveIndex);\n }\n }\n\n this.cleanupDrag();\n\n // Keep handle visible on the first (possibly moved) block\n const blockEl = this.editorRoot.querySelector<HTMLElement>(\n `.blx-block[data-block-id=\"${movedBlockIds[0]}\"]`,\n );\n if (blockEl) {\n this.hoveredBlockEl = blockEl;\n this.positionHandle(blockEl);\n }\n }\n\n /**\n * Compute drop slot (0..N) from ghost center Y using cached midpoints.\n * Hysteresis biases midpoints by THRESHOLD relative to the current slot\n * so the ghost must cross a midpoint by extra pixels before changing,\n * preventing jitter near boundaries.\n */\n private computeDropSlot(ghostCenter: number): number {\n const THRESHOLD = 8;\n let slot = this.cachedMidpoints.length;\n const isDragged = new Set(this.dragFromIndices);\n\n for (let i = 0; i < this.cachedMidpoints.length; i++) {\n if (isDragged.has(i)) continue;\n\n const midY = this.cachedMidpoints[i];\n\n // Hysteresis: bias midpoints to resist changes from current slot.\n const effectiveMidY = this.currentDropSlot >= 0\n ? midY + (i < this.currentDropSlot ? -THRESHOLD : THRESHOLD)\n : midY;\n\n if (ghostCenter < effectiveMidY) {\n slot = i;\n break;\n }\n }\n\n return slot;\n }\n\n private cleanupDrag(): void {\n // Remove ghost\n if (this.ghost) {\n this.ghost.remove();\n this.ghost = null;\n }\n\n // Remove dragging class from source blocks\n for (const id of this.dragBlockIds) {\n const blockEl = this.editorRoot.querySelector<HTMLElement>(\n `.blx-block[data-block-id=\"${id}\"]`,\n );\n if (blockEl) {\n blockEl.classList.remove(\"blx-block-dragging\");\n }\n }\n\n // Remove shift class and reset transforms on all blocks\n const blocks = this.editorRoot.querySelectorAll<HTMLElement>(\".blx-block\");\n for (const b of blocks) {\n b.classList.remove(\"blx-block-shift\");\n b.style.transform = \"\";\n }\n\n // Remove document mouse listeners\n if (this.boundDocMouseMove) {\n document.removeEventListener(\"mousemove\", this.boundDocMouseMove, true);\n this.boundDocMouseMove = null;\n }\n if (this.boundDocMouseUp) {\n document.removeEventListener(\"mouseup\", this.boundDocMouseUp, true);\n this.boundDocMouseUp = null;\n }\n\n // Remove document touch listeners\n this.cleanupLongPressListeners();\n this.cancelLongPress();\n\n // Reset pending state\n this.pendingMouseDrag = false;\n\n // Reset cursor\n document.body.style.cursor = \"\";\n\n // Reset state\n this.dragBlockIds = [];\n this.dragFromIndices = [];\n this.currentDropSlot = -1;\n this.sourceHeight = 0;\n this.cachedMidpoints = [];\n this.hideHandle();\n\n // Notify listeners\n this.onDragEnd?.();\n }\n}\n","/**\n * Reusable floating container with positioning and dismiss logic.\n * Content is appended by the consumer via `popover.el`.\n *\n * Used internally by LinkPopover, HighlightPicker, and InlineToolbar.\n */\n\nimport { positionFixed } from \"./position-fixed\";\nimport { dismissOnClickOutside, type DismissHandle } from \"./dismiss\";\n\n/** Construction options for {@link Popover}. */\nexport interface PopoverOptions {\n /** Additional CSS class (e.g. \"blx-link-popover\") */\n className?: string;\n /** CSS display value when shown (default: \"flex\") */\n displayMode?: string;\n /** Pixel gap between anchor and popover (default: 6) */\n gap?: number;\n /** Horizontal alignment (default: \"center\") */\n align?: \"start\" | \"center\";\n /** Preferred vertical placement (default: \"below\") */\n placement?: \"above\" | \"below\";\n /** Dismiss on click outside (default: true) */\n dismissOnClickOutside?: boolean;\n /** Dismiss on Escape key (default: true) */\n dismissOnEscape?: boolean;\n}\n\nexport class Popover {\n /** The root DOM element of the popover. Append to document before calling {@link show}. */\n readonly el: HTMLElement;\n\n private _visible = false;\n private opts: PopoverOptions;\n private dismissHandle: DismissHandle | null = null;\n\n /** Called after the popover is hidden (by any means). */\n onHide: (() => void) | null = null;\n\n /**\n * Create a new Popover.\n * @param options - Optional configuration overrides.\n */\n constructor(options?: PopoverOptions) {\n this.opts = { ...options };\n\n this.el = document.createElement(\"div\");\n this.el.classList.add(\"blx-popover\");\n if (this.opts.className) {\n this.el.classList.add(this.opts.className);\n }\n this.el.style.display = \"none\";\n }\n\n /** Whether the popover is currently visible. */\n get visible(): boolean {\n return this._visible;\n }\n\n /**\n * Show the popover anchored to `anchorRect`.\n * Installs click-outside and/or Escape-key dismiss handlers as configured.\n * @param anchorRect - Bounding rect of the element to anchor to.\n */\n show(anchorRect: DOMRect): void {\n this.el.style.display = this.opts.displayMode ?? \"flex\";\n this._visible = true;\n\n this.positionTo(anchorRect);\n\n // Install dismiss handlers\n if (this.opts.dismissOnClickOutside !== false) {\n this.dismissHandle = dismissOnClickOutside(\n this.el,\n () => this.hide(),\n { escapeKey: this.opts.dismissOnEscape !== false },\n );\n } else if (this.opts.dismissOnEscape !== false) {\n // Escape-only dismiss (no click-outside)\n this.dismissHandle = dismissOnClickOutside(\n this.el,\n () => this.hide(),\n { escapeKey: true, defer: false },\n );\n // Override: we only want escape, not click-outside. The dismiss\n // utility installs both, so we need a different approach.\n // Actually, let's just install the escape handler directly.\n this.dismissHandle.remove();\n const keyHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n this.hide();\n }\n };\n document.addEventListener(\"keydown\", keyHandler, true);\n this.dismissHandle = {\n remove: () => document.removeEventListener(\"keydown\", keyHandler, true),\n };\n }\n }\n\n /**\n * Reposition to a new anchor rect without toggling visibility or dismiss handlers.\n * No-op if the popover is not currently visible.\n * @param anchorRect - New bounding rect to anchor to.\n */\n reposition(anchorRect: DOMRect): void {\n if (!this._visible) return;\n this.positionTo(anchorRect);\n }\n\n private positionTo(anchorRect: DOMRect): void {\n positionFixed(this.el, anchorRect, {\n gap: this.opts.gap ?? 6,\n align: this.opts.align ?? \"center\",\n placement: this.opts.placement ?? \"below\",\n });\n }\n\n /**\n * Hide the popover and remove all dismiss handlers.\n * Fires {@link onHide} if it was previously visible.\n */\n hide(): void {\n if (!this._visible) return;\n this.el.style.display = \"none\";\n this._visible = false;\n this.dismissHandle?.remove();\n this.dismissHandle = null;\n this.onHide?.();\n }\n\n /** Hide the popover and remove its element from the DOM. */\n destroy(): void {\n this.hide();\n this.el.remove();\n }\n}\n","import type { Attributes } from \"../attributed-string/types\";\nimport { Popover } from \"../ui/popover\";\n\n/** Context passed to custom toolbar button handlers */\nexport interface ToolbarActionContext {\n /** ID of the block containing the selection */\n blockId: string;\n /** Start offset of the selection within the block */\n start: number;\n /** End offset of the selection within the block */\n end: number;\n /** Attributes that are active across the entire selection */\n activeAttributes: Attributes;\n /** Convenience: apply or remove a single attribute on the selection */\n applyAttribute: (attribute: string, active: boolean) => void;\n}\n\n/** Toolbar button configuration */\nexport interface ToolbarButton {\n /** Unique key identifying this button */\n key: string;\n /** Accessible label / tooltip text */\n label: string;\n /**\n * Button icon — either a text string or a render function.\n * When a string, displayed as text with a CSS class `blx-inline-toolbar-icon-{key}`.\n * When a function, called with the container element to render custom HTML.\n */\n icon: string | ((container: HTMLElement) => void);\n /**\n * Attribute to toggle (e.g. \"bold\", \"italic\").\n * When set, clicking the button toggles this attribute via the standard\n * applyAttributes/removeAttributes transaction flow.\n * Mutually exclusive with `onAction`.\n */\n attribute?: string;\n /**\n * Custom action handler. Called when the button is clicked.\n * Use this for buttons that need non-standard behavior (e.g. link input,\n * color picker). Mutually exclusive with `attribute`.\n */\n onAction?: (context: ToolbarActionContext) => void;\n /**\n * Custom active-state check. When provided, this function determines\n * whether the button appears pressed/active. When omitted, buttons\n * with `attribute` use the standard attribute intersection check.\n */\n isActive?: (context: ToolbarActionContext) => boolean;\n}\n\n/** Standard inline formatting buttons */\nexport const TOOLBAR_BUTTONS: ToolbarButton[] = [\n { key: \"bold\", label: \"Bold\", icon: \"B\", attribute: \"bold\" },\n { key: \"italic\", label: \"Italic\", icon: \"I\", attribute: \"italic\" },\n { key: \"underline\", label: \"Underline\", icon: \"U\", attribute: \"underline\" },\n { key: \"strikethrough\", label: \"Strikethrough\", icon: \"S\", attribute: \"strikethrough\" },\n { key: \"code\", label: \"Code\", icon: \"<>\", attribute: \"code\" },\n];\n\n/**\n * Floating inline toolbar that appears on text selection.\n *\n * Provides buttons for formatting and is extensible via `addButton()`.\n * Positioned above (or below) the selection bounding rect. Dismissed on\n * selection collapse, click outside, or Escape key.\n */\nexport class InlineToolbar {\n private popover: Popover;\n private onFormat: (attribute: string, active: boolean) => void;\n private onCustomAction: ((key: string, context: ToolbarActionContext) => void) | null = null;\n private activeAttributes: Set<string> = new Set();\n\n /** Built-in buttons (left group) */\n private builtinButtons: ToolbarButton[];\n /** Plugin-added buttons (right group, after separator) */\n private pluginButtons: ToolbarButton[] = [];\n /** Current action context (set on show/update, used by click handlers) */\n private actionContext: ToolbarActionContext | null = null;\n\n constructor(\n onFormat: (attribute: string, active: boolean) => void,\n builtinButtons?: ToolbarButton[],\n ) {\n this.onFormat = onFormat;\n this.builtinButtons = builtinButtons ?? [...TOOLBAR_BUTTONS];\n\n this.popover = new Popover({\n className: \"blx-inline-toolbar\",\n displayMode: \"flex\",\n gap: 6,\n align: \"center\",\n placement: \"above\",\n dismissOnClickOutside: false,\n dismissOnEscape: true,\n });\n this.popover.onHide = () => {\n this.actionContext = null;\n };\n\n this.popover.el.setAttribute(\"role\", \"toolbar\");\n this.popover.el.setAttribute(\"aria-label\", \"Text formatting\");\n this.renderButtons();\n }\n\n get element(): HTMLElement {\n return this.popover.el;\n }\n\n get visible(): boolean {\n return this.popover.visible;\n }\n\n /** Set the handler for custom (non-attribute) button actions */\n setCustomActionHandler(handler: (key: string, context: ToolbarActionContext) => void): void {\n this.onCustomAction = handler;\n }\n\n /**\n * Add a button to the toolbar. Plugin buttons appear after a separator.\n * If a button with the same key already exists, it is replaced.\n */\n addButton(button: ToolbarButton): void {\n this.removeButton(button.key);\n this.pluginButtons.push(button);\n this.renderButtons();\n }\n\n /** Remove a plugin-added button by key. Returns true if found. */\n removeButton(key: string): boolean {\n const idx = this.pluginButtons.findIndex((b) => b.key === key);\n if (idx !== -1) {\n this.pluginButtons.splice(idx, 1);\n this.renderButtons();\n return true;\n }\n return false;\n }\n\n /** Get all currently registered buttons (built-in + plugin) */\n getButtons(): ReadonlyArray<ToolbarButton> {\n return [...this.builtinButtons, ...this.pluginButtons];\n }\n\n /**\n * Show the toolbar positioned relative to the given selection rect.\n * Positions above the selection by default; flips below if near viewport top.\n */\n show(selectionRect: DOMRect, activeAttrs: Attributes, context?: ToolbarActionContext): void {\n this.actionContext = context ?? null;\n this.syncActiveState(activeAttrs);\n\n this.popover.show(selectionRect);\n }\n\n /** Reposition the toolbar to follow a new anchor rect (e.g. on scroll) */\n reposition(selectionRect: DOMRect): void {\n this.popover.reposition(selectionRect);\n }\n\n /** Update the active state of buttons without repositioning */\n updateActiveAttributes(activeAttrs: Attributes, context?: ToolbarActionContext): void {\n if (context) this.actionContext = context;\n this.syncActiveState(activeAttrs);\n }\n\n hide(): void {\n this.popover.hide();\n }\n\n destroy(): void {\n this.popover.destroy();\n }\n\n /** Sync the active set from standard attributes + custom isActive checks */\n private syncActiveState(activeAttrs: Attributes): void {\n this.activeAttributes.clear();\n for (const [key, value] of Object.entries(activeAttrs)) {\n if (value) this.activeAttributes.add(key);\n }\n\n // Evaluate custom isActive for buttons that provide it\n if (this.actionContext) {\n for (const btn of [...this.builtinButtons, ...this.pluginButtons]) {\n if (btn.isActive) {\n if (btn.isActive(this.actionContext)) {\n this.activeAttributes.add(btn.attribute ?? btn.key);\n } else {\n this.activeAttributes.delete(btn.attribute ?? btn.key);\n }\n }\n }\n }\n\n this.updateButtonStates();\n }\n\n private renderButtons(): void {\n this.popover.el.innerHTML = \"\";\n\n const renderGroup = (buttons: ToolbarButton[]) => {\n for (const btn of buttons) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.classList.add(\"blx-inline-toolbar-btn\");\n button.dataset.buttonKey = btn.key;\n if (btn.attribute) button.dataset.attribute = btn.attribute;\n button.setAttribute(\"aria-label\", btn.label);\n button.title = btn.label;\n\n if (typeof btn.icon === \"string\") {\n const span = document.createElement(\"span\");\n span.classList.add(`blx-inline-toolbar-icon-${btn.key}`);\n span.textContent = btn.icon;\n button.appendChild(span);\n } else {\n btn.icon(button);\n }\n\n // Prevent the button tap/click from stealing focus/selection.\n // mousedown (desktop): preventDefault keeps the editor focused.\n // touchstart (mobile): preventDefault keeps the text selection alive,\n // but also suppresses the subsequent click event — so on touch we\n // fire the action on touchend instead.\n button.addEventListener(\"mousedown\", (e) => { e.preventDefault(); });\n button.addEventListener(\"touchstart\", (e) => { e.preventDefault(); }, { passive: false });\n\n // touchend: fire the action here on mobile (click won't fire after\n // touchstart preventDefault). Also preventDefault to suppress the\n // delayed mousedown/click the browser would otherwise synthesize.\n button.addEventListener(\"touchend\", (e) => {\n e.preventDefault();\n this.handleButtonClick(btn);\n });\n\n // click: fire the action on desktop (mousedown preventDefault does\n // NOT suppress click, unlike touchstart).\n button.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.handleButtonClick(btn);\n });\n\n this.popover.el.appendChild(button);\n }\n };\n\n renderGroup(this.builtinButtons);\n\n // Add separator + plugin buttons when present\n if (this.pluginButtons.length > 0) {\n const sep = document.createElement(\"div\");\n sep.classList.add(\"blx-inline-toolbar-sep\");\n this.popover.el.appendChild(sep);\n\n renderGroup(this.pluginButtons);\n }\n }\n\n private handleButtonClick(btn: ToolbarButton): void {\n if (btn.onAction && this.actionContext) {\n // Custom action — delegate to the plugin's handler\n btn.onAction(this.actionContext);\n return;\n }\n\n if (btn.onAction && !this.actionContext) {\n // Custom action but no context yet — fire through the editor's handler\n if (this.onCustomAction) {\n // Build a minimal context — the editor handler will fill in the rest\n this.onCustomAction(btn.key, this.actionContext!);\n }\n return;\n }\n\n // Standard attribute toggle\n const attr = btn.attribute ?? btn.key;\n const isActive = this.activeAttributes.has(attr);\n if (isActive) {\n this.activeAttributes.delete(attr);\n } else {\n this.activeAttributes.add(attr);\n }\n this.updateButtonStates();\n this.onFormat(attr, !isActive);\n }\n\n private updateButtonStates(): void {\n const buttons = this.popover.el.querySelectorAll<HTMLElement>(\".blx-inline-toolbar-btn\");\n for (const button of buttons) {\n const attr = button.dataset.attribute ?? button.dataset.buttonKey;\n if (attr) {\n button.classList.toggle(\"blx-inline-toolbar-btn-active\", this.activeAttributes.has(attr));\n }\n }\n }\n}\n","/**\n * Small floating input for entering/editing link URLs.\n * Displayed below the inline toolbar or selection.\n */\n\nimport { Popover } from \"../ui/popover\";\n\nexport class LinkPopover {\n private popover: Popover;\n private input: HTMLInputElement;\n private applyBtn: HTMLButtonElement;\n private removeBtn: HTMLButtonElement;\n private onApply: (url: string) => void;\n private onRemove: () => void;\n private onClose: () => void;\n\n constructor(\n onApply: (url: string) => void,\n onRemove: () => void,\n onClose: () => void,\n ) {\n this.onApply = onApply;\n this.onRemove = onRemove;\n this.onClose = onClose;\n\n this.popover = new Popover({ className: \"blx-link-popover\" });\n this.popover.onHide = () => this.onClose();\n\n this.input = document.createElement(\"input\");\n this.input.type = \"url\";\n this.input.classList.add(\"blx-link-popover-input\");\n this.input.placeholder = \"Paste or type a URL...\";\n this.input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.hide();\n }\n // Stop propagation to prevent the editor from intercepting these keys\n e.stopPropagation();\n });\n\n this.applyBtn = document.createElement(\"button\");\n this.applyBtn.type = \"button\";\n this.applyBtn.classList.add(\"blx-link-popover-btn\", \"blx-link-popover-apply\");\n this.applyBtn.textContent = \"Apply\";\n this.applyBtn.addEventListener(\"mousedown\", (e) => e.preventDefault());\n this.applyBtn.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.submit();\n });\n\n this.removeBtn = document.createElement(\"button\");\n this.removeBtn.type = \"button\";\n this.removeBtn.classList.add(\"blx-link-popover-btn\", \"blx-link-popover-remove\");\n this.removeBtn.textContent = \"Remove\";\n this.removeBtn.addEventListener(\"mousedown\", (e) => e.preventDefault());\n this.removeBtn.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.onRemove();\n this.hide();\n });\n\n const row = document.createElement(\"div\");\n row.classList.add(\"blx-link-popover-row\");\n row.appendChild(this.input);\n row.appendChild(this.applyBtn);\n row.appendChild(this.removeBtn);\n this.popover.el.appendChild(row);\n }\n\n get element(): HTMLElement {\n return this.popover.el;\n }\n\n get visible(): boolean {\n return this.popover.visible;\n }\n\n /**\n * Show the popover at a position relative to a given rect.\n * Pre-fills the URL if editing an existing link.\n */\n show(anchorRect: DOMRect, existingUrl?: string): void {\n this.input.value = existingUrl ?? \"\";\n this.removeBtn.style.display = existingUrl ? \"\" : \"none\";\n\n this.popover.show(anchorRect);\n\n // Focus input after positioning (rAF to wait for positionFixed)\n requestAnimationFrame(() => {\n this.input.focus();\n });\n }\n\n hide(): void {\n this.popover.hide();\n }\n\n destroy(): void {\n this.popover.destroy();\n }\n\n private submit(): void {\n const url = this.input.value.trim();\n if (url) {\n this.onApply(url);\n }\n this.hide();\n }\n}\n","/**\n * Small floating popover showing color swatches for text highlighting.\n * Displayed below the inline toolbar or selection rect.\n */\n\nimport { Popover } from \"../ui/popover\";\nimport { iconHtml, X } from \"../util/icons\";\n\n/** Predefined highlight colors available in the picker. */\nexport const HIGHLIGHT_COLORS = [\n { name: \"yellow\", label: \"Yellow\" },\n { name: \"green\", label: \"Green\" },\n { name: \"blue\", label: \"Blue\" },\n { name: \"pink\", label: \"Pink\" },\n { name: \"orange\", label: \"Orange\" },\n { name: \"purple\", label: \"Purple\" },\n] as const;\n\nexport type HighlightColorName = (typeof HIGHLIGHT_COLORS)[number][\"name\"];\n\nexport class HighlightPicker {\n private popover: Popover;\n private onApply: (color: string) => void;\n private onRemove: () => void;\n private onClose: () => void;\n\n constructor(\n onApply: (color: string) => void,\n onRemove: () => void,\n onClose: () => void,\n ) {\n this.onApply = onApply;\n this.onRemove = onRemove;\n this.onClose = onClose;\n\n this.popover = new Popover({ className: \"blx-highlight-picker\" });\n this.popover.onHide = () => this.onClose();\n\n const row = document.createElement(\"div\");\n row.classList.add(\"blx-highlight-picker-row\");\n\n for (const color of HIGHLIGHT_COLORS) {\n const swatch = document.createElement(\"button\");\n swatch.type = \"button\";\n swatch.classList.add(\"blx-highlight-swatch\", `blx-highlight-swatch-${color.name}`);\n swatch.dataset.color = color.name;\n swatch.setAttribute(\"aria-label\", color.label);\n swatch.title = color.label;\n swatch.addEventListener(\"mousedown\", (e) => e.preventDefault());\n swatch.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.onApply(color.name);\n this.hide();\n });\n row.appendChild(swatch);\n }\n\n // Remove highlight button\n const removeBtn = document.createElement(\"button\");\n removeBtn.type = \"button\";\n removeBtn.classList.add(\"blx-highlight-swatch\", \"blx-highlight-swatch-remove\");\n removeBtn.setAttribute(\"aria-label\", \"Remove highlight\");\n removeBtn.title = \"Remove highlight\";\n removeBtn.innerHTML = iconHtml(X, 10);\n removeBtn.addEventListener(\"mousedown\", (e) => e.preventDefault());\n removeBtn.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.onRemove();\n this.hide();\n });\n row.appendChild(removeBtn);\n\n this.popover.el.appendChild(row);\n }\n\n get element(): HTMLElement {\n return this.popover.el;\n }\n\n get visible(): boolean {\n return this.popover.visible;\n }\n\n /**\n * Show the picker positioned relative to the given anchor rect.\n * Highlights the currently active color (if any).\n */\n show(anchorRect: DOMRect, activeColor?: string): void {\n // Update active state on swatches\n for (const swatch of this.popover.el.querySelectorAll<HTMLElement>(\".blx-highlight-swatch\")) {\n swatch.classList.toggle(\n \"blx-highlight-swatch-active\",\n !!activeColor && swatch.dataset.color === activeColor,\n );\n }\n\n this.popover.show(anchorRect);\n }\n\n hide(): void {\n this.popover.hide();\n }\n\n destroy(): void {\n this.popover.destroy();\n }\n}\n","/**\n * Block action menu: a ⊞ trigger button that appears on hover and opens\n * a context menu of block-level actions (convert, delete, copy link, etc.).\n */\n\nimport { ContextMenu, type MenuItem } from \"../ui/context-menu\";\nimport { dismissOnClickOutside, type DismissHandle } from \"../ui/dismiss\";\nimport { firstLineCenterY } from \"../drag-handle/drag-handle\";\nimport { iconHtml, Plus } from \"../util/icons\";\n\nexport interface BlockActionMenuEntry {\n key: string;\n label: string;\n icon?: string | ((container: HTMLElement) => void);\n danger?: boolean;\n section?: \"convert\" | \"action\" | \"task\" | \"danger\";\n disabled?: boolean;\n /** Dynamic disabled check — called when menu opens with the target block IDs. */\n isDisabled?: (blockIds: string[]) => boolean;\n hint?: string; // pre-computed display hint (e.g. \"⌫\") passed to ContextMenu\n commandName?: string; // informational: editor command this action triggers\n onAction: (blockIds: string[]) => void;\n}\n\nexport class BlockActionMenu {\n private editorRoot: HTMLElement;\n private gutterEl: HTMLElement;\n private btn: HTMLElement;\n private menu: ContextMenu;\n private getTargetBlockIds: () => string[];\n private getMenuItems: () => BlockActionMenuEntry[];\n\n private hoveredBlockEl: HTMLElement | null = null;\n private menuOpen = false;\n private _dragActive = false;\n\n /** Called when the action menu opens/closes — used by editor to hide drag handle */\n onOpen: (() => void) | null = null;\n onClose: (() => void) | null = null;\n\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private dismissHandle: DismissHandle | null = null;\n private scrollHandler: ((e: Event) => void) | null = null;\n private shouldShowForBlock: ((blockId: string) => boolean) | null = null;\n\n constructor(\n editorRoot: HTMLElement,\n gutterEl: HTMLElement,\n getTargetBlockIds: () => string[],\n getMenuItems: () => BlockActionMenuEntry[],\n options?: {\n shouldShowForBlock?: (blockId: string) => boolean;\n },\n ) {\n this.editorRoot = editorRoot;\n this.gutterEl = gutterEl;\n this.getTargetBlockIds = getTargetBlockIds;\n this.getMenuItems = getMenuItems;\n this.shouldShowForBlock = options?.shouldShowForBlock ?? null;\n\n // Create trigger button\n this.btn = document.createElement(\"div\");\n this.btn.classList.add(\"blx-action-btn\");\n this.btn.setAttribute(\"contenteditable\", \"false\");\n this.btn.innerHTML = iconHtml(Plus, 14);\n this.gutterEl.appendChild(this.btn);\n\n // Create ContextMenu for the dropdown\n this.menu = new ContextMenu({ className: \"blx-action-menu\" });\n this.menu.onSelect = (mi: MenuItem) => {\n const entry = mi.data as BlockActionMenuEntry;\n const blockIds = this.getTargetBlockIds();\n this.closeMenu();\n entry.onAction(blockIds);\n };\n this.menu.onClose = () => this.closeMenu();\n\n this.attachListeners();\n }\n\n /** The block ID the trigger button is currently associated with */\n get hoveredBlockId(): string | null {\n return this.btn.dataset.blockId ?? null;\n }\n\n /** Hide the button and close menu if open (e.g. when user starts typing or dragging) */\n hide(): void {\n if (this.menuOpen) {\n this.closeMenu();\n }\n this.hideBtn();\n this.hoveredBlockEl = null;\n }\n\n /** Called by the editor when a block drag starts — suppresses the action button */\n notifyDragStart(): void {\n this._dragActive = true;\n this.hide();\n }\n\n /** Called by the editor when a block drag ends */\n notifyDragEnd(): void {\n this._dragActive = false;\n }\n\n destroy(): void {\n this.closeMenu();\n this.editorRoot.removeEventListener(\"mousemove\", this.handleMouseMove);\n this.editorRoot.removeEventListener(\"mouseleave\", this.handleMouseLeave);\n this.btn.removeEventListener(\"click\", this.handleBtnClick);\n this.btn.removeEventListener(\"mouseleave\", this.handleBtnLeave);\n // Touch listeners\n this.editorRoot.removeEventListener(\"touchstart\", this.handleTouchStart);\n this.btn.removeEventListener(\"touchend\", this.handleBtnTouchEnd);\n this.btn.remove();\n this.menu.destroy();\n }\n\n private attachListeners(): void {\n // Mouse (desktop)\n this.editorRoot.addEventListener(\"mousemove\", this.handleMouseMove);\n this.editorRoot.addEventListener(\"mouseleave\", this.handleMouseLeave);\n this.btn.addEventListener(\"click\", this.handleBtnClick);\n this.btn.addEventListener(\"mouseleave\", this.handleBtnLeave);\n\n // Touch (mobile): show the button when tapping a block\n this.editorRoot.addEventListener(\"touchstart\", this.handleTouchStart, { passive: true });\n this.btn.addEventListener(\"touchend\", this.handleBtnTouchEnd);\n }\n\n // ── Touch: show button on block tap ─────────────────────────\n\n private handleTouchStart = (e: TouchEvent): void => {\n if (this.menuOpen) return;\n\n const touch = e.touches[0];\n if (!touch) return;\n\n const target = touch.target as HTMLElement;\n\n // If touching the button itself, keep it visible\n if (this.btn.contains(target)) return;\n\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl || !this.editorRoot.contains(blockEl)) {\n this.hideBtn();\n this.hoveredBlockEl = null;\n return;\n }\n\n this.hoveredBlockEl = blockEl;\n this.positionBtn(blockEl);\n };\n\n // ── Hover positioning ────────────────────────────────────────\n\n private handleMouseMove = (e: MouseEvent): void => {\n // Don't reposition while menu is open or a drag is in progress\n if (this.menuOpen || this._dragActive) return;\n\n const target = e.target as HTMLElement;\n\n // If hovering over the button itself, keep it visible\n if (this.btn.contains(target)) {\n this.showBtn();\n return;\n }\n\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl || !this.editorRoot.contains(blockEl)) {\n // Cursor not directly over a block (gap, left/right whitespace, etc.)\n // Fast path: already tracking a block and cursor is within its vertical range\n if (this.hoveredBlockEl) {\n const rect = this.hoveredBlockEl.getBoundingClientRect();\n if (e.clientY >= rect.top && e.clientY <= rect.bottom) return;\n }\n // Slow path: find the block at this Y position (handles whitespace approach)\n const blockAtY = this.findBlockAtY(e.clientY, e.clientX);\n if (blockAtY) {\n this.hoveredBlockEl = blockAtY;\n this.positionBtn(blockAtY);\n return;\n }\n this.hideBtn();\n this.hoveredBlockEl = null;\n return;\n }\n\n this.hoveredBlockEl = blockEl;\n this.positionBtn(blockEl);\n };\n\n private showBtn(): void {\n this.btn.style.opacity = \"1\";\n this.btn.style.transform = \"translateX(0)\";\n }\n\n private hideBtn(): void {\n this.btn.style.opacity = \"0\";\n this.btn.style.transform = \"translateX(-4px)\";\n }\n\n private findBlockAtY(clientY: number, clientX: number): HTMLElement | null {\n const blocks = this.editorRoot.querySelectorAll<HTMLElement>(\".blx-block\");\n for (const block of blocks) {\n const r = block.getBoundingClientRect();\n if (clientY >= r.top && clientY <= r.bottom && clientX <= r.right) return block;\n }\n return null;\n }\n\n private handleMouseLeave = (_e: MouseEvent): void => {\n if (this.menuOpen) return;\n this.hideBtn();\n this.hoveredBlockEl = null;\n };\n\n private handleBtnLeave = (e: MouseEvent): void => {\n if (this.menuOpen) return;\n // If cursor is still within the editor's horizontal extent (including left\n // whitespace outside .blx-content), let handleMouseMove take over instead\n // of hiding immediately. This supports full-width .blx-editor layouts.\n const editorRect = this.editorRoot.getBoundingClientRect();\n if (e.clientX >= editorRect.left && e.clientX <= editorRect.right) return;\n this.hideBtn();\n this.hoveredBlockEl = null;\n };\n\n private positionBtn(blockEl: HTMLElement): void {\n const blockId = blockEl.dataset.blockId;\n if (blockId && this.shouldShowForBlock && !this.shouldShowForBlock(blockId)) {\n this.hideBtn();\n return;\n }\n\n const gutterRect = this.gutterEl.getBoundingClientRect();\n const firstLineCenter = firstLineCenterY(blockEl, this.editorRoot);\n\n this.showBtn();\n this.btn.style.top = `${firstLineCenter - gutterRect.top - this.btn.offsetHeight / 2}px`;\n this.btn.dataset.blockId = blockEl.dataset.blockId ?? \"\";\n }\n\n // ── Menu open / close ────────────────────────────────────────\n\n private handleBtnClick = (e: MouseEvent): void => {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.menuOpen) {\n this.closeMenu();\n return;\n }\n\n this.openMenu();\n };\n\n /** Touch equivalent of click for the action button */\n private handleBtnTouchEnd = (e: TouchEvent): void => {\n e.preventDefault();\n\n if (this.menuOpen) {\n this.closeMenu();\n return;\n }\n\n this.openMenu();\n };\n\n private openMenu(): void {\n const entries = this.getMenuItems();\n if (entries.length === 0) return;\n\n const menuItems = this.toMenuItems(entries);\n\n // Append menu el to editor root so CSS custom properties are inherited\n this.editorRoot.appendChild(this.menu.el);\n\n const btnRect = this.btn.getBoundingClientRect();\n this.menu.show(btnRect, menuItems);\n this.menuOpen = true;\n this.onOpen?.();\n\n // Close on external scroll (but not scrolling within the menu itself)\n this.scrollHandler = (e: Event) => {\n if (this.menu.el.contains(e.target as Node)) return;\n this.closeMenu();\n };\n window.addEventListener(\"scroll\", this.scrollHandler, true);\n\n // Keyboard handler (capture phase)\n this.keyHandler = (e: KeyboardEvent) => {\n if (!this.menuOpen) return;\n const consumed = this.menu.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", this.keyHandler, true);\n\n // Close on outside click/touch (defer to avoid instant dismiss)\n this.dismissHandle = dismissOnClickOutside(\n this.menu.el,\n () => this.closeMenu(),\n { ignoreElements: [this.btn] },\n );\n }\n\n closeMenu(): void {\n this.menu.hide();\n this.menu.el.remove();\n this.menuOpen = false;\n this.onClose?.();\n\n if (this.scrollHandler) {\n window.removeEventListener(\"scroll\", this.scrollHandler, true);\n this.scrollHandler = null;\n }\n if (this.keyHandler) {\n document.removeEventListener(\"keydown\", this.keyHandler, true);\n this.keyHandler = null;\n }\n this.dismissHandle?.remove();\n this.dismissHandle = null;\n }\n\n private toMenuItems(entries: BlockActionMenuEntry[]): MenuItem[] {\n const blockIds = this.getTargetBlockIds();\n return entries.map((entry) => ({\n id: entry.key,\n label: entry.label,\n icon: entry.icon,\n danger: entry.danger,\n section: entry.section,\n disabled: entry.disabled ?? entry.isDisabled?.(blockIds) ?? false,\n hint: entry.hint,\n data: entry,\n }));\n }\n}\n","/**\n * Convert a KeyboardEvent into a canonical descriptor string.\n *\n * Modifiers are prepended in order: ctrl+meta+alt+shift+key\n *\n * For single-char keys (e.key.length === 1): shift is implicit in the\n * character casing (\"G\" not \"shift+G\"), so shift is not prepended.\n *\n * For non-char keys (ArrowDown, Home, Tab, etc.): shift is included\n * when held.\n */\nexport function eventToDescriptor(e: KeyboardEvent): string {\n const parts: string[] = [];\n const isSingleChar = e.key.length === 1;\n\n if (e.ctrlKey) parts.push(\"ctrl\");\n if (e.metaKey) parts.push(\"meta\");\n if (e.altKey) parts.push(\"alt\");\n // Only include shift for non-character keys\n if (e.shiftKey && !isSingleChar) parts.push(\"shift\");\n\n parts.push(e.key);\n return parts.join(\"+\");\n}\n\n/**\n * Handles multi-key sequences of arbitrary length (e.g. \"g,g\", \"d,d\",\n * \" ,g,a\") and single-key lookups against a keybinding map.\n *\n * `resolve()` returns:\n * - An action name string when matched\n * - `\"pending\"` when waiting for the next key in a sequence\n * - `null` when no match is found\n *\n * When an accumulated buffer has both an exact match AND is the prefix of\n * a longer sequence, the sequencer returns \"pending\" and waits. If the\n * timeout fires before the next key, the `onFallback` callback is invoked\n * with the shorter match's action name.\n */\nexport class KeySequencer {\n private buffer: string | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private sequenceTimeout = 500; // ms\n\n /**\n * Resolve a key descriptor against a binding map.\n *\n * @param onFallback — called when a pending sequence times out and had\n * a shorter exact action. The caller should execute the action.\n */\n resolve(\n descriptor: string,\n bindings: Record<string, string>,\n onFallback?: (action: string) => void,\n ): string | \"pending\" | null {\n this.clearTimer();\n\n // Build the candidate sequence\n const candidate = this.buffer !== null\n ? `${this.buffer},${descriptor}`\n : descriptor;\n\n // Check for exact match\n const exactAction = bindings[candidate];\n\n // Check if candidate is the prefix of any longer sequence\n const isPrefix = Object.keys(bindings).some(\n (key) => key.startsWith(candidate + \",\"),\n );\n\n if (exactAction && !isPrefix) {\n // Exact match, no longer sequences possible — execute immediately\n this.buffer = null;\n return exactAction;\n }\n\n if (isPrefix) {\n // Could be the start of a longer sequence — go pending\n this.buffer = candidate;\n const fallbackAction = exactAction; // may be undefined\n this.timer = setTimeout(() => {\n this.buffer = null;\n this.timer = null;\n if (fallbackAction && onFallback) {\n onFallback(fallbackAction);\n }\n }, this.sequenceTimeout);\n return \"pending\";\n }\n\n if (exactAction) {\n // Exact match (isPrefix was false)\n this.buffer = null;\n return exactAction;\n }\n\n // No match for the accumulated sequence.\n // If we had a buffer, the sequence is broken — reset and try\n // the current descriptor alone as a fresh start.\n if (this.buffer !== null) {\n this.buffer = null;\n return this.resolve(descriptor, bindings, onFallback);\n }\n\n return null;\n }\n\n private clearTimer(): void {\n if (this.timer !== null) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n private clearPending(): void {\n this.buffer = null;\n this.clearTimer();\n }\n\n destroy(): void {\n this.clearPending();\n }\n}\n","import type { KeybindingMap } from \"./types\";\n\nexport const DEFAULT_KEYBINDINGS: KeybindingMap = {\n normal: {\n ArrowDown: \"moveDown\",\n ArrowUp: \"moveUp\",\n Home: \"jumpToFirst\",\n End: \"jumpToLast\",\n \"shift+ArrowDown\": \"extendDown\",\n \"shift+ArrowUp\": \"extendUp\",\n \"shift+Home\": \"extendToFirst\",\n \"shift+End\": \"extendToLast\",\n Escape: \"exitToEditing\",\n Enter: \"enterEditingAtStart\",\n Delete: \"deleteBlock\",\n Backspace: \"deleteBlock\",\n \"alt+ArrowUp\": \"moveBlockUp\",\n \"alt+ArrowDown\": \"moveBlockDown\",\n Tab: \"indentSelection\",\n \"shift+Tab\": \"outdentSelection\",\n PageUp: \"pageUp\",\n PageDown: \"pageDown\",\n // Cross-platform Mod shortcuts (ctrl = Linux/Win, meta = macOS)\n \"ctrl+a\": \"selectAllBlocks\",\n \"meta+a\": \"selectAllBlocks\",\n \"ctrl+o\": \"jumpBack\",\n \"meta+o\": \"jumpBack\",\n \"ctrl+shift+I\": \"jumpForward\",\n \"meta+shift+I\": \"jumpForward\",\n // Vim-style navigation\n j: \"moveDown\",\n k: \"moveUp\",\n \"g,g\": \"jumpToFirst\",\n G: \"jumpToLast\",\n i: \"enterEditingAtStart\",\n a: \"enterEditingAtEnd\",\n o: \"newBlockBelow\",\n O: \"newBlockAbove\",\n \"g,.\": \"jumpToLastEdit\",\n \"d,d\": \"deleteBlock\",\n \"c,c\": \"changeBlock\",\n x: \"deleteBlock\",\n J: \"joinWithNext\",\n v: \"enterVisualBlock\",\n y: \"yankBlock\",\n p: \"pasteAfter\",\n P: \"pasteBefore\",\n \" \": \"toggleChecklist\",\n \" , \": \"openDocumentSwitcher\",\n \"/\": \"openSearch\",\n n: \"searchNext\",\n N: \"searchPrev\",\n u: \"undo\",\n \"ctrl+R\": \"redo\",\n \">\": \"indentSelection\",\n \"<\": \"outdentSelection\",\n \".\": \"dotRepeat\",\n \":\": \"openCommandMode\",\n \"ctrl+/\": \"openSlashMenu\",\n \"meta+/\": \"openSlashMenu\",\n },\n visualBlock: {\n ArrowDown: \"moveOrExtendDown\",\n ArrowUp: \"moveOrExtendUp\",\n \"shift+ArrowDown\": \"extendDown\",\n \"shift+ArrowUp\": \"extendUp\",\n \"shift+Home\": \"extendToFirst\",\n \"shift+End\": \"extendToLast\",\n Delete: \"deleteSelection\",\n Backspace: \"deleteSelection\",\n \"alt+ArrowUp\": \"moveBlockUp\",\n \"alt+ArrowDown\": \"moveBlockDown\",\n Tab: \"indentSelection\",\n \"shift+Tab\": \"outdentSelection\",\n Escape: \"exitToNormal\",\n Enter: \"enterEditingAtStart\",\n // Cross-platform Mod shortcuts\n \"ctrl+a\": \"selectAllBlocks\",\n \"meta+a\": \"selectAllBlocks\",\n \"ctrl+o\": \"jumpBack\",\n \"meta+o\": \"jumpBack\",\n \"ctrl+shift+I\": \"jumpForward\",\n \"meta+shift+I\": \"jumpForward\",\n // Vim-style\n v: \"exitToNormal\",\n j: \"extendDown\",\n k: \"extendUp\",\n d: \"deleteSelection\",\n c: \"changeSelection\",\n x: \"deleteSelection\",\n y: \"yankSelection\",\n p: \"pasteAfter\",\n P: \"pasteBefore\",\n i: \"enterEditingAtStart\",\n a: \"enterEditingAtEnd\",\n \" \": \"toggleChecklist\",\n \" , \": \"openDocumentSwitcher\",\n \"/\": \"openSearch\",\n u: \"undo\",\n \"ctrl+R\": \"redo\",\n \">\": \"indentSelection\",\n \"<\": \"outdentSelection\",\n \".\": \"dotRepeat\",\n \":\": \"openCommandMode\",\n \"ctrl+/\": \"openSlashMenu\",\n \"meta+/\": \"openSlashMenu\",\n },\n};\n","import type { KeybindingMap } from \"./types\";\nimport { DEFAULT_KEYBINDINGS } from \"./defaults\";\n\nexport const VIM_KEYBINDINGS: KeybindingMap = {\n normal: {\n ...DEFAULT_KEYBINDINGS.normal,\n j: \"moveDown\",\n k: \"moveUp\",\n \"g,g\": \"jumpToFirst\",\n G: \"jumpToLast\",\n i: \"enterEditingAtStart\",\n a: \"enterEditingAtEnd\",\n o: \"newBlockBelow\",\n O: \"newBlockAbove\",\n \"d,d\": \"deleteBlock\",\n \"c,c\": \"changeBlock\",\n x: \"deleteBlock\",\n J: \"joinWithNext\",\n v: \"enterVisualBlock\",\n y: \"yankBlock\", // clipboard\n p: \"pasteAfter\", // clipboard\n P: \"pasteBefore\", // clipboard\n \"/\": \"openSearch\",\n n: \"searchNext\",\n N: \"searchPrev\",\n u: \"undo\",\n \"ctrl+R\": \"redo\",\n \">\": \"indentSelection\",\n \"<\": \"outdentSelection\",\n \".\": \"dotRepeat\",\n \" ,t\": \"cycleTaskStatus\",\n \" ,T\": \"openTaskStatusMenu\",\n \" ,a\": \"openAgendaPickerFromNormal\",\n \" ,x\": \"removeTaskStatus\",\n \"z,c\": \"foldBlock\",\n \"z,o\": \"unfoldBlock\",\n \"z,a\": \"toggleFold\",\n \"z,M\": \"foldAll\",\n \"z,R\": \"unfoldAll\",\n \":\": \"openCommandMode\",\n \"ctrl+/\": \"openSlashMenu\",\n \"meta+/\": \"openSlashMenu\",\n },\n visualBlock: {\n ...DEFAULT_KEYBINDINGS.visualBlock,\n j: \"extendDown\",\n k: \"extendUp\",\n d: \"deleteSelection\",\n c: \"changeSelection\",\n x: \"deleteSelection\",\n i: \"enterEditingAtStart\",\n a: \"enterEditingAtEnd\",\n v: \"exitToNormal\",\n y: \"yankSelection\", // clipboard\n p: \"pasteAfter\", // clipboard\n P: \"pasteBefore\", // clipboard\n \"/\": \"openSearch\",\n u: \"undo\",\n \"ctrl+R\": \"redo\",\n \">\": \"indentSelection\",\n \"<\": \"outdentSelection\",\n \".\": \"dotRepeat\",\n \":\": \"openCommandMode\",\n \"ctrl+/\": \"openSlashMenu\",\n \"meta+/\": \"openSlashMenu\",\n },\n};\n","import type { Block } from \"../types\";\n\nexport interface SearchOptions {\n caseSensitive?: boolean;\n regex?: boolean;\n blockTypes?: string[];\n}\n\nexport interface SearchMatch {\n blockId: string;\n blockType: string;\n /** Character offset within the block's text content */\n start: number;\n /** Character offset (exclusive) within the block's text content */\n end: number;\n /** The matched text */\n matchText: string;\n /** Surrounding context text */\n context: string;\n}\n\nexport interface ReplaceResult {\n blockId: string;\n /** Number of replacements made in this block */\n count: number;\n}\n\n/**\n * Search engine that operates on the block model (not the DOM).\n * Stateless — takes blocks as input and returns matches.\n */\nexport class SearchEngine {\n /**\n * Search all blocks for a query string or regex pattern.\n */\n search(blocks: ReadonlyArray<Block>, query: string, options: SearchOptions = {}): SearchMatch[] {\n if (!query) return [];\n\n const matches: SearchMatch[] = [];\n const pattern = this.buildPattern(query, options);\n if (!pattern) return [];\n\n for (const block of blocks) {\n // Filter by block type if specified\n if (options.blockTypes && options.blockTypes.length > 0) {\n if (!options.blockTypes.includes(block.type)) continue;\n }\n\n const text = block.content.text;\n if (!text) continue;\n\n let match: RegExpExecArray | null;\n // Reset lastIndex for global regex\n pattern.lastIndex = 0;\n\n while ((match = pattern.exec(text)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n\n matches.push({\n blockId: block.id,\n blockType: block.type,\n start,\n end,\n matchText: match[0],\n context: this.extractContext(text, start, end),\n });\n\n // Prevent infinite loop on zero-length matches\n if (match[0].length === 0) {\n pattern.lastIndex++;\n }\n }\n }\n\n return matches;\n }\n\n /**\n * Count total matches across all blocks.\n */\n count(blocks: ReadonlyArray<Block>, query: string, options: SearchOptions = {}): number {\n return this.search(blocks, query, options).length;\n }\n\n private buildPattern(query: string, options: SearchOptions): RegExp | null {\n const flags = options.caseSensitive ? \"g\" : \"gi\";\n\n if (options.regex) {\n try {\n return new RegExp(query, flags);\n } catch {\n return null; // Invalid regex\n }\n }\n\n // Escape special regex characters for literal search\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(escaped, flags);\n }\n\n private extractContext(text: string, start: number, end: number, contextChars = 40): string {\n const ctxStart = Math.max(0, start - contextChars);\n const ctxEnd = Math.min(text.length, end + contextChars);\n let context = text.slice(ctxStart, ctxEnd);\n if (ctxStart > 0) context = \"\\u2026\" + context;\n if (ctxEnd < text.length) context = context + \"\\u2026\";\n return context;\n }\n}\n","import type { SearchMatch, SearchOptions } from \"./search-engine\";\nimport { iconHtml, ChevronDown } from \"../util/icons\";\n\nexport interface SearchUICallbacks {\n /** Called when the query, options, or navigation changes. */\n onSearch: (query: string, options: SearchOptions) => SearchMatch[];\n /** Called to navigate to (highlight & scroll to) a specific match. */\n onNavigate: (match: SearchMatch) => void;\n /** Called to replace a single match with replacement text. */\n onReplace: (match: SearchMatch, replacement: string) => void;\n /** Called to replace all matches. */\n onReplaceAll: (matches: SearchMatch[], replacement: string) => void;\n /** Called when the panel is closed. */\n onClose: () => void;\n}\n\n/**\n * Search & Replace panel UI.\n * Renders a fixed panel at the top-right of the editor.\n * Replace row is collapsed by default with a toggle button.\n */\nexport class SearchUI {\n readonly element: HTMLElement;\n private searchInput: HTMLInputElement;\n private replaceInput: HTMLInputElement;\n private countLabel: HTMLElement;\n private caseSensitiveBtn: HTMLButtonElement;\n private regexBtn: HTMLButtonElement;\n private replaceRow: HTMLElement;\n private expandBtn: HTMLButtonElement;\n private replaceExpanded = false;\n\n private callbacks: SearchUICallbacks;\n private matches: SearchMatch[] = [];\n private currentIndex = 0;\n private caseSensitive = false;\n private useRegex = false;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(callbacks: SearchUICallbacks) {\n this.callbacks = callbacks;\n this.element = this.build();\n this.searchInput = this.element.querySelector(\".blx-search-input\") as HTMLInputElement;\n this.replaceInput = this.element.querySelector(\".blx-search-replace-input\") as HTMLInputElement;\n this.countLabel = this.element.querySelector(\".blx-search-count\") as HTMLElement;\n this.caseSensitiveBtn = this.element.querySelector(\".blx-search-btn-case\") as HTMLButtonElement;\n this.regexBtn = this.element.querySelector(\".blx-search-btn-regex\") as HTMLButtonElement;\n this.replaceRow = this.element.querySelector(\".blx-search-replace-row\") as HTMLElement;\n this.expandBtn = this.element.querySelector(\".blx-search-expand-btn\") as HTMLButtonElement;\n }\n\n show(): void {\n this.element.style.display = \"flex\";\n this.positionPanel();\n this.searchInput.focus();\n this.searchInput.select();\n }\n\n hide(): void {\n this.element.style.display = \"none\";\n this.matches = [];\n this.currentIndex = 0;\n this.updateCount();\n }\n\n get visible(): boolean {\n return this.element.style.display !== \"none\";\n }\n\n /** Focus the search input (e.g. when re-opening). */\n focus(): void {\n this.searchInput.focus();\n this.searchInput.select();\n }\n\n /** Navigate to the next search match. */\n next(): void {\n this.navigateNext();\n }\n\n /** Navigate to the previous search match. */\n prev(): void {\n this.navigatePrev();\n }\n\n /** Handle keydown events. Returns true if consumed. */\n handleKeyDown(e: KeyboardEvent): boolean {\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.callbacks.onClose();\n return true;\n }\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n this.navigateNext();\n return true;\n }\n if (e.key === \"Enter\" && e.shiftKey) {\n e.preventDefault();\n this.navigatePrev();\n return true;\n }\n return false;\n }\n\n destroy(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.element.remove();\n }\n\n // ── Private ─────────────────────────────────────────────────────\n\n /** Position the panel at the top-right of the nearest scrollable ancestor. */\n private positionPanel(): void {\n const parent = this.element.parentElement;\n if (!parent) return;\n\n // Walk up to find the scroll container (or use the editor root's parent)\n let scrollParent: HTMLElement | null = parent.parentElement;\n while (scrollParent && scrollParent !== document.body) {\n const overflow = getComputedStyle(scrollParent).overflowY;\n if (overflow === \"auto\" || overflow === \"scroll\") break;\n scrollParent = scrollParent.parentElement;\n }\n\n const ref = scrollParent ?? parent;\n const rect = ref.getBoundingClientRect();\n this.element.style.top = `${rect.top + 8}px`;\n this.element.style.right = `${window.innerWidth - rect.right + 8}px`;\n }\n\n private toggleReplace(): void {\n this.replaceExpanded = !this.replaceExpanded;\n this.replaceRow.classList.toggle(\"blx-search-replace-row-visible\", this.replaceExpanded);\n this.expandBtn.classList.toggle(\"blx-search-expand-btn-active\", this.replaceExpanded);\n if (this.replaceExpanded) {\n this.replaceInput.focus();\n }\n }\n\n private build(): HTMLElement {\n const panel = document.createElement(\"div\");\n panel.classList.add(\"blx-search-panel\");\n panel.style.display = \"none\";\n\n // Expand/collapse button for replace row\n const expandBtn = document.createElement(\"button\");\n expandBtn.type = \"button\";\n expandBtn.classList.add(\"blx-search-expand-btn\");\n expandBtn.innerHTML = iconHtml(ChevronDown, 12);\n expandBtn.title = \"Toggle Replace\";\n expandBtn.addEventListener(\"click\", () => this.toggleReplace());\n\n // Search row\n const searchRow = document.createElement(\"div\");\n searchRow.classList.add(\"blx-search-row\");\n\n const inputWrap = document.createElement(\"div\");\n inputWrap.classList.add(\"blx-search-input-wrap\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"blx-search-input\");\n input.placeholder = \"Find\\u2026\";\n input.addEventListener(\"input\", () => this.onQueryChange());\n input.addEventListener(\"keydown\", (e) => this.handleKeyDown(e));\n\n const caseSensitiveBtn = document.createElement(\"button\");\n caseSensitiveBtn.type = \"button\";\n caseSensitiveBtn.classList.add(\"blx-search-option-btn\", \"blx-search-btn-case\");\n caseSensitiveBtn.textContent = \"Aa\";\n caseSensitiveBtn.title = \"Case sensitive\";\n caseSensitiveBtn.addEventListener(\"click\", () => {\n this.caseSensitive = !this.caseSensitive;\n caseSensitiveBtn.classList.toggle(\"blx-search-option-btn-active\", this.caseSensitive);\n this.runSearch();\n });\n\n const regexBtn = document.createElement(\"button\");\n regexBtn.type = \"button\";\n regexBtn.classList.add(\"blx-search-option-btn\", \"blx-search-btn-regex\");\n regexBtn.textContent = \".*\";\n regexBtn.title = \"Use regex\";\n regexBtn.addEventListener(\"click\", () => {\n this.useRegex = !this.useRegex;\n regexBtn.classList.toggle(\"blx-search-option-btn-active\", this.useRegex);\n this.runSearch();\n });\n\n inputWrap.appendChild(input);\n inputWrap.appendChild(caseSensitiveBtn);\n inputWrap.appendChild(regexBtn);\n\n // Count + nav buttons\n const count = document.createElement(\"span\");\n count.classList.add(\"blx-search-count\");\n count.textContent = \"0 results\";\n\n const prevBtn = document.createElement(\"button\");\n prevBtn.type = \"button\";\n prevBtn.classList.add(\"blx-search-nav-btn\");\n prevBtn.textContent = \"\\u2191\"; // ↑\n prevBtn.title = \"Previous match (Shift+Enter)\";\n prevBtn.addEventListener(\"click\", () => this.navigatePrev());\n\n const nextBtn = document.createElement(\"button\");\n nextBtn.type = \"button\";\n nextBtn.classList.add(\"blx-search-nav-btn\");\n nextBtn.textContent = \"\\u2193\"; // ↓\n nextBtn.title = \"Next match (Enter)\";\n nextBtn.addEventListener(\"click\", () => this.navigateNext());\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.type = \"button\";\n closeBtn.classList.add(\"blx-search-close-btn\");\n closeBtn.textContent = \"\\u00D7\"; // ×\n closeBtn.title = \"Close (Escape)\";\n closeBtn.addEventListener(\"click\", () => this.callbacks.onClose());\n\n searchRow.appendChild(inputWrap);\n searchRow.appendChild(count);\n searchRow.appendChild(prevBtn);\n searchRow.appendChild(nextBtn);\n searchRow.appendChild(closeBtn);\n\n // Replace row (hidden by default)\n const replaceRow = document.createElement(\"div\");\n replaceRow.classList.add(\"blx-search-replace-row\");\n\n const replaceInputWrap = document.createElement(\"div\");\n replaceInputWrap.classList.add(\"blx-search-input-wrap\");\n\n const replaceInput = document.createElement(\"input\");\n replaceInput.type = \"text\";\n replaceInput.classList.add(\"blx-search-replace-input\");\n replaceInput.placeholder = \"Replace\\u2026\";\n replaceInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.callbacks.onClose();\n }\n });\n\n replaceInputWrap.appendChild(replaceInput);\n\n const replaceBtn = document.createElement(\"button\");\n replaceBtn.type = \"button\";\n replaceBtn.classList.add(\"blx-search-replace-btn\");\n replaceBtn.textContent = \"Replace\";\n replaceBtn.addEventListener(\"click\", () => this.replaceCurrent());\n\n const replaceAllBtn = document.createElement(\"button\");\n replaceAllBtn.type = \"button\";\n replaceAllBtn.classList.add(\"blx-search-replace-btn\");\n replaceAllBtn.textContent = \"All\";\n replaceAllBtn.addEventListener(\"click\", () => this.replaceAll());\n\n replaceRow.appendChild(replaceInputWrap);\n replaceRow.appendChild(replaceBtn);\n replaceRow.appendChild(replaceAllBtn);\n\n // Layout: expand button on left, rows stacked on right\n const body = document.createElement(\"div\");\n body.classList.add(\"blx-search-body\");\n body.appendChild(searchRow);\n body.appendChild(replaceRow);\n\n panel.appendChild(expandBtn);\n panel.appendChild(body);\n\n // Prevent click/focus from stealing editor focus\n panel.addEventListener(\"mousedown\", (e) => {\n // Allow input focus but prevent blur\n if (\n e.target instanceof HTMLInputElement ||\n e.target instanceof HTMLButtonElement\n ) {\n return;\n }\n e.preventDefault();\n });\n\n return panel;\n }\n\n private onQueryChange(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => this.runSearch(), 80);\n }\n\n private runSearch(): void {\n const query = this.searchInput.value;\n this.matches = this.callbacks.onSearch(query, {\n caseSensitive: this.caseSensitive,\n regex: this.useRegex,\n });\n this.currentIndex = 0;\n this.updateCount();\n if (this.matches.length > 0) {\n this.callbacks.onNavigate(this.matches[0]);\n }\n }\n\n private navigateNext(): void {\n if (this.matches.length === 0) return;\n this.currentIndex = (this.currentIndex + 1) % this.matches.length;\n this.updateCount();\n this.callbacks.onNavigate(this.matches[this.currentIndex]);\n }\n\n private navigatePrev(): void {\n if (this.matches.length === 0) return;\n this.currentIndex =\n (this.currentIndex - 1 + this.matches.length) % this.matches.length;\n this.updateCount();\n this.callbacks.onNavigate(this.matches[this.currentIndex]);\n }\n\n private replaceCurrent(): void {\n if (this.matches.length === 0) return;\n const match = this.matches[this.currentIndex];\n this.callbacks.onReplace(match, this.replaceInput.value);\n // Re-search to update matches\n this.runSearch();\n }\n\n private replaceAll(): void {\n if (this.matches.length === 0) return;\n this.callbacks.onReplaceAll(this.matches, this.replaceInput.value);\n this.runSearch();\n }\n\n private updateCount(): void {\n if (this.matches.length === 0) {\n this.countLabel.textContent = this.searchInput.value\n ? \"No results\"\n : \"0 results\";\n } else {\n this.countLabel.textContent = `${this.currentIndex + 1} of ${this.matches.length}`;\n }\n }\n}\n","import type { UndoAction, UndoEntry, CursorState } from \"./types\";\n\nexport interface UndoManagerOptions {\n /** Maximum entries in the undo stack (default 200) */\n maxEntries?: number;\n /** Max ms between content changes on the same block to merge them (default 500) */\n mergeWindow?: number;\n}\n\n/**\n * Transaction-aware undo/redo history manager.\n *\n * Records individual actions or compound groups (e.g., block split = content\n * change + block add). Consecutive content changes on the same block within\n * `mergeWindow` ms are automatically coalesced into a single entry.\n */\nexport class UndoManager {\n private undoStack: UndoEntry[] = [];\n private redoStack: UndoEntry[] = [];\n private readonly maxEntries: number;\n private readonly mergeWindow: number;\n\n // Compound grouping state\n private compoundActions: UndoAction[] | null = null;\n private compoundBeforeCursor: CursorState | null = null;\n\n constructor(options?: UndoManagerOptions) {\n this.maxEntries = options?.maxEntries ?? 200;\n this.mergeWindow = options?.mergeWindow ?? 500;\n }\n\n /** Start grouping actions into a single compound entry */\n beginGroup(beforeCursor: CursorState | null): void {\n this.compoundActions = [];\n this.compoundBeforeCursor = beforeCursor;\n }\n\n /** Whether a compound group is currently active */\n get isGrouping(): boolean {\n return this.compoundActions !== null;\n }\n\n /**\n * Record an undoable action.\n *\n * If a compound group is active, the action is appended to the group.\n * Otherwise, consecutive content changes on the same block within\n * `mergeWindow` are merged into the last entry.\n */\n record(\n action: UndoAction,\n beforeCursor: CursorState | null,\n afterCursor: CursorState | null,\n ): void {\n if (this.compoundActions !== null) {\n this.compoundActions.push(action);\n return;\n }\n\n // Try to merge consecutive content changes on the same block\n if (action.type === \"contentChange\" && this.undoStack.length > 0) {\n const last = this.undoStack[this.undoStack.length - 1];\n if (\n last.actions.length === 1 &&\n last.actions[0].type === \"contentChange\" &&\n last.actions[0].blockId === action.blockId &&\n Date.now() - last.timestamp < this.mergeWindow\n ) {\n // Merge: keep the original `before`, update the `after`\n last.actions[0] = {\n ...last.actions[0],\n after: action.after,\n };\n last.afterCursor = afterCursor;\n last.timestamp = Date.now();\n this.redoStack = [];\n return;\n }\n }\n\n this.pushEntry({\n actions: [action],\n beforeCursor,\n afterCursor,\n timestamp: Date.now(),\n });\n }\n\n /** End compound group and push as a single entry */\n endGroup(afterCursor: CursorState | null): void {\n if (this.compoundActions === null) return;\n const actions = this.compoundActions;\n this.compoundActions = null;\n if (actions.length > 0) {\n this.pushEntry({\n actions,\n beforeCursor: this.compoundBeforeCursor,\n afterCursor,\n timestamp: Date.now(),\n });\n }\n this.compoundBeforeCursor = null;\n }\n\n private pushEntry(entry: UndoEntry): void {\n this.undoStack.push(entry);\n if (this.undoStack.length > this.maxEntries) {\n this.undoStack.shift();\n }\n this.redoStack = [];\n }\n\n /** Pop the last undo entry. Returns null if nothing to undo. */\n popUndo(): UndoEntry | null {\n const entry = this.undoStack.pop() ?? null;\n if (entry) {\n this.redoStack.push(entry);\n }\n return entry;\n }\n\n /** Pop the last redo entry. Returns null if nothing to redo. */\n popRedo(): UndoEntry | null {\n const entry = this.redoStack.pop() ?? null;\n if (entry) {\n this.undoStack.push(entry);\n }\n return entry;\n }\n\n canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.compoundActions = null;\n this.compoundBeforeCursor = null;\n }\n\n get undoSize(): number {\n return this.undoStack.length;\n }\n\n get redoSize(): number {\n return this.redoStack.length;\n }\n}\n","/** A position in the editor (block + cursor offset) */\nexport interface JumpEntry {\n blockId: string;\n offset: number;\n}\n\nexport interface JumpListOptions {\n /** Maximum number of entries (default 100) */\n maxSize?: number;\n}\n\n/**\n * Vim-style navigation history (jumplist).\n *\n * Records cursor positions before \"jumps\" — significant position changes\n * such as search navigation, internal link clicks, or scrollToBlock calls.\n * Navigate with Ctrl-O (back) and Ctrl-I (forward).\n */\nexport class JumpList {\n private entries: JumpEntry[] = [];\n private index: number = -1;\n private readonly maxSize: number;\n\n constructor(options?: JumpListOptions) {\n this.maxSize = options?.maxSize ?? 100;\n }\n\n /**\n * Record the current position before jumping away.\n * Discards forward history (like vim's jumplist).\n */\n push(entry: JumpEntry): void {\n // Don't push duplicate of current position\n if (this.index >= 0) {\n const current = this.entries[this.index];\n if (current.blockId === entry.blockId) return;\n }\n\n // Discard entries after current index (forward history)\n this.entries = this.entries.slice(0, this.index + 1);\n this.entries.push(entry);\n if (this.entries.length > this.maxSize) {\n this.entries.shift();\n }\n this.index = this.entries.length - 1;\n }\n\n /** Go back (Ctrl-O). Returns the position to jump to, or null. */\n back(): JumpEntry | null {\n if (this.index <= 0) return null;\n this.index--;\n return { ...this.entries[this.index] };\n }\n\n /** Go forward (Ctrl-I). Returns the position to jump to, or null. */\n forward(): JumpEntry | null {\n if (this.index >= this.entries.length - 1) return null;\n this.index++;\n return { ...this.entries[this.index] };\n }\n\n /** Current position in the jump list */\n current(): JumpEntry | null {\n if (this.index < 0 || this.index >= this.entries.length) return null;\n return { ...this.entries[this.index] };\n }\n\n canGoBack(): boolean {\n return this.index > 0;\n }\n\n canGoForward(): boolean {\n return this.index < this.entries.length - 1;\n }\n\n clear(): void {\n this.entries = [];\n this.index = -1;\n }\n\n get size(): number {\n return this.entries.length;\n }\n}\n","import type { BlockController } from \"../block\";\n\nexport interface BlockViewportOptions {\n /**\n * Number of pixels above/below the viewport to keep blocks fully active\n * (listeners attached, content visible). Defaults to 1x viewport height,\n * giving a total active zone of ~3x the viewport (1 above + visible + 1 below).\n *\n * Blocks outside this zone are *ejected*: listeners detached and the\n * browser skips painting via `content-visibility: hidden`. The DOM stays\n * intact so the container height is perfectly preserved — zero layout shift.\n */\n bufferPx?: number;\n\n /**\n * Estimated height in px for blocks whose content has not yet been\n * rendered. Used as `minHeight` on the container to maintain scroll\n * position stability. Default: 32\n */\n estimatedBlockHeight?: number;\n}\n\n/**\n * Manages virtual rendering of blocks using IntersectionObserver.\n *\n * Two-tier lifecycle:\n *\n * 1. **First mount** — Block has never been rendered. When it enters the\n * buffer zone, `mountContent()` is called to run the plugin's `render()`\n * and attach listeners. This is the only transition that may cause a\n * layout shift (estimated height → real height); it is compensated\n * with a scroll anchor.\n *\n * 2. **Eject / Restore** — Once rendered, blocks are never unmounted.\n * When they leave the buffer, `ejectContent()` detaches listeners and\n * sets `content-visibility: hidden` (browser skips painting but\n * remembers the size). When they re-enter, `restoreContent()` reverses\n * this. Because the DOM is untouched, there is zero layout shift.\n *\n * When IntersectionObserver is unavailable (e.g. jsdom in tests), all blocks\n * are mounted immediately, preserving existing behavior.\n */\nexport class BlockViewport {\n private observer: IntersectionObserver | null = null;\n private controllers = new Map<string, BlockController>();\n private forceMounted = new Set<string>();\n /** Measured content heights — used as `minHeight` for blocks that have\n * never been rendered, so first-mount layout shifts are minimized. */\n private heightCache = new Map<string, number>();\n private readonly blocksContainer: HTMLElement;\n private readonly estimatedHeight: number;\n private readonly hasIO: boolean;\n /** Guard against re-entrant intersection callbacks caused by scrollBy */\n private handlingIntersection = false;\n\n /** Callback invoked after a batch of blocks is mounted by the viewport */\n onContentMounted: ((blockId: string) => void) | null = null;\n\n constructor(\n container: HTMLElement,\n options?: BlockViewportOptions,\n ) {\n this.blocksContainer = container;\n // Default buffer: 1x viewport height ≈ 3x total active zone.\n // Fall back to 800px for environments without window (tests).\n const bufferPx = options?.bufferPx ??\n (typeof window !== \"undefined\" ? window.innerHeight : 800);\n this.estimatedHeight = options?.estimatedBlockHeight ?? 32;\n this.hasIO = typeof IntersectionObserver !== \"undefined\";\n\n if (this.hasIO) {\n this.observer = new IntersectionObserver(\n this.handleIntersection,\n {\n // null root = browser viewport\n root: null,\n rootMargin: `${bufferPx}px 0px ${bufferPx}px 0px`,\n },\n );\n }\n }\n\n /**\n * Register a block controller with the viewport manager.\n * If IntersectionObserver is available, the block is observed and content\n * is mounted lazily. Otherwise, content is mounted immediately.\n */\n register(controller: BlockController): void {\n this.controllers.set(controller.blockId, controller);\n\n if (this.observer) {\n if (!controller.contentRendered) {\n const h = this.heightCache.get(controller.blockId) ?? this.estimatedHeight;\n controller.container.style.minHeight = `${h}px`;\n }\n this.observer.observe(controller.container);\n } else {\n // No IntersectionObserver (jsdom) → mount immediately\n if (!controller.contentRendered) {\n controller.mountContent();\n }\n }\n }\n\n /**\n * Register multiple block controllers in a single batch.\n * More efficient than individual register() calls during initial load.\n */\n registerBatch(controllers: BlockController[]): void {\n for (const ctrl of controllers) {\n this.controllers.set(ctrl.blockId, ctrl);\n }\n\n if (this.observer) {\n for (const ctrl of controllers) {\n if (!ctrl.contentRendered) {\n const h = this.heightCache.get(ctrl.blockId) ?? this.estimatedHeight;\n ctrl.container.style.minHeight = `${h}px`;\n }\n this.observer.observe(ctrl.container);\n }\n } else {\n for (const ctrl of controllers) {\n if (!ctrl.contentRendered) {\n ctrl.mountContent();\n }\n }\n }\n }\n\n /** Unregister a block and stop observing it */\n unregister(blockId: string): void {\n const ctrl = this.controllers.get(blockId);\n if (ctrl && this.observer) {\n this.observer.unobserve(ctrl.container);\n }\n this.controllers.delete(blockId);\n this.forceMounted.delete(blockId);\n }\n\n /**\n * Ensure a block's content is mounted and active (e.g., before focusing\n * or searching). The block is also marked as force-mounted so it won't\n * be ejected when scrolling away.\n */\n ensureMounted(blockId: string): void {\n const ctrl = this.controllers.get(blockId);\n if (!ctrl) { this.forceMounted.add(blockId); return; }\n\n if (!ctrl.contentRendered) {\n // First mount\n ctrl.mountContent();\n const h = ctrl.container.offsetHeight;\n if (h > 0) this.heightCache.set(blockId, h);\n ctrl.container.style.minHeight = \"\";\n this.onContentMounted?.(blockId);\n } else {\n // Might be ejected — restore\n ctrl.restoreContent();\n }\n this.forceMounted.add(blockId);\n }\n\n /**\n * Remove the force-mount flag from a block. If the block is outside the\n * viewport buffer, it may be ejected on the next intersection check.\n */\n releaseForceMounted(blockId: string): void {\n this.forceMounted.delete(blockId);\n }\n\n /** Whether a block is currently content-mounted */\n isContentMounted(blockId: string): boolean {\n return this.controllers.get(blockId)?.contentRendered ?? false;\n }\n\n /** Whether a block is force-mounted (won't be ejected by intersection) */\n isForceMounted(blockId: string): boolean {\n return this.forceMounted.has(blockId);\n }\n\n /**\n * Synchronously mount content for all blocks currently visible in the\n * viewport. Call this after the initial block load to avoid a flash of\n * empty containers.\n */\n mountInitialViewport(): void {\n if (!this.hasIO) return; // Already mounted everything\n\n for (const ctrl of this.controllers.values()) {\n if (ctrl.contentRendered) continue;\n if (this.isInViewport(ctrl.container)) {\n ctrl.mountContent();\n const h = ctrl.container.offsetHeight;\n if (h > 0) this.heightCache.set(ctrl.blockId, h);\n ctrl.container.style.minHeight = \"\";\n this.onContentMounted?.(ctrl.blockId);\n }\n }\n\n // Update placeholder heights for unmounted blocks using measured average\n this.updateEstimatedHeights();\n }\n\n /**\n * Ensure a block is mounted, then scroll its container into view.\n */\n scrollIntoView(blockId: string, behavior: ScrollBehavior = \"smooth\"): void {\n this.ensureMounted(blockId);\n const ctrl = this.controllers.get(blockId);\n if (!ctrl) return;\n const el = ctrl.container;\n if (typeof el.scrollIntoView !== \"function\") return;\n el.scrollIntoView({ behavior: \"instant\", block: \"nearest\" });\n if (behavior === \"smooth\") {\n requestAnimationFrame(() => {\n el.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n });\n }\n }\n\n /**\n * Recalculate the average height from measured blocks and apply it to\n * all never-rendered block placeholders.\n */\n private updateEstimatedHeights(): void {\n if (this.heightCache.size === 0) return;\n let sum = 0;\n for (const h of this.heightCache.values()) sum += h;\n const avg = Math.round(sum / this.heightCache.size);\n if (avg <= this.estimatedHeight) return;\n\n for (const ctrl of this.controllers.values()) {\n if (!ctrl.contentRendered && !this.heightCache.has(ctrl.blockId)) {\n ctrl.container.style.minHeight = `${avg}px`;\n }\n }\n }\n\n destroy(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n this.controllers.clear();\n this.forceMounted.clear();\n this.heightCache.clear();\n this.onContentMounted = null;\n }\n\n /** Check if an element is within the viewport (synchronous fallback) */\n private isInViewport(el: HTMLElement): boolean {\n try {\n const rect = el.getBoundingClientRect();\n if (rect.height === 0 && rect.width === 0 && rect.top === 0) return true;\n const viewHeight = window.innerHeight || document.documentElement.clientHeight;\n return rect.bottom >= 0 && rect.top <= viewHeight;\n } catch {\n return true;\n }\n }\n\n private handleIntersection = (entries: IntersectionObserverEntry[]): void => {\n // Guard: scrollBy compensation can trigger new intersection callbacks\n // on the next frame. Skip those to prevent a feedback loop.\n if (this.handlingIntersection) return;\n\n const toFirstMount: BlockController[] = [];\n const toRestore: BlockController[] = [];\n const toEject: BlockController[] = [];\n\n for (const entry of entries) {\n const blockId = (entry.target as HTMLElement).dataset?.blockId;\n if (!blockId) continue;\n\n const ctrl = this.controllers.get(blockId);\n if (!ctrl) continue;\n\n if (entry.isIntersecting) {\n if (!ctrl.contentRendered) {\n // Never rendered — needs first mount\n toFirstMount.push(ctrl);\n } else {\n // Was ejected — just restore listeners + visibility\n toRestore.push(ctrl);\n }\n } else {\n // Exiting the buffer zone — eject (detach listeners, hide paint)\n if (ctrl.contentRendered && !this.forceMounted.has(blockId)) {\n toEject.push(ctrl);\n }\n }\n }\n\n if (toFirstMount.length === 0 && toRestore.length === 0 && toEject.length === 0) return;\n\n this.handlingIntersection = true;\n\n // ── First mounts (may cause layout shift — use scroll anchor) ────\n if (toFirstMount.length > 0) {\n const anchorEl = this.pickScrollAnchor();\n const anchorTop = anchorEl ? anchorEl.getBoundingClientRect().top : 0;\n\n for (const ctrl of toFirstMount) {\n ctrl.mountContent();\n }\n\n // Cache real heights and clear placeholder minHeight now that\n // content is rendered and we're about to compensate the scroll.\n for (const ctrl of toFirstMount) {\n const h = ctrl.container.offsetHeight;\n if (h > 0) this.heightCache.set(ctrl.blockId, h);\n ctrl.container.style.minHeight = \"\";\n }\n\n // Compensate scroll position for layout shift from first mounts\n if (anchorEl) {\n const delta = anchorEl.getBoundingClientRect().top - anchorTop;\n if (Math.abs(delta) > 0.5) {\n window.scrollBy(0, delta);\n }\n }\n\n this.updateEstimatedHeights();\n this.onContentMounted?.(toFirstMount[toFirstMount.length - 1].blockId);\n }\n\n // ── Restores (zero layout shift — no compensation needed) ────────\n for (const ctrl of toRestore) {\n ctrl.restoreContent();\n }\n\n // ── Ejects — batch height reads then writes to avoid layout thrash ─\n if (toEject.length > 0) {\n // Read phase: capture heights before any DOM changes\n const heights = toEject.map(ctrl => ctrl.container.offsetHeight);\n // Write phase: eject with pre-read heights\n for (let i = 0; i < toEject.length; i++) {\n toEject[i].ejectContent(heights[i]);\n }\n }\n\n // Release the guard after a frame so intersection callbacks triggered\n // by our scrollBy are suppressed, but subsequent real scrolls work.\n requestAnimationFrame(() => {\n this.handlingIntersection = false;\n });\n };\n\n /**\n * Find a block container visible in the viewport to use as a scroll anchor.\n */\n private pickScrollAnchor(): HTMLElement | null {\n try {\n const rect = this.blocksContainer.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = window.innerHeight / 2;\n const el = document.elementFromPoint(x, y);\n return (el?.closest?.(\"[data-block-id]\") as HTMLElement) ?? null;\n } catch {\n return null;\n }\n }\n}\n","import type { UndoAction, CursorState } from \"../undo/types\";\nimport type { BlockJSON } from \"../types\";\nimport type { CrdtOperation, CrdtLogSnapshot } from \"./types\";\n\n/**\n * Append-only operation log for CRDT-style change tracking.\n *\n * Captures an initial editor snapshot and every subsequent edit as an\n * immutable operation entry. Supports compound grouping (e.g., block split\n * = content change + block add) so multi-action edits replay atomically.\n *\n * Each operation is tagged with a `peerId` to identify which collaborating\n * peer authored the change.\n */\nexport class CrdtLog {\n private initialState: BlockJSON[] = [];\n private operations: CrdtOperation[] = [];\n private nextId = 0;\n\n /** The local peer ID attached to new operations */\n private _localPeerId: string | null = null;\n\n // Compound grouping state\n private _grouping = false;\n private _groupActions: UndoAction[] = [];\n private _groupBeforeCursor: CursorState | null = null;\n\n /** Set the local peer ID for subsequent operations */\n setLocalPeerId(peerId: string): void {\n this._localPeerId = peerId;\n }\n\n /** Get the current local peer ID */\n getLocalPeerId(): string | null {\n return this._localPeerId;\n }\n\n /** Capture the initial editor state */\n setInitialState(blocks: BlockJSON[]): void {\n this.initialState = blocks.map((b) => ({\n ...b,\n content: { ...b.content },\n metadata: { ...b.metadata },\n }));\n }\n\n /** Start grouping actions into a single atomic operation */\n beginGroup(beforeCursor: CursorState | null): void {\n this._grouping = true;\n this._groupActions = [];\n this._groupBeforeCursor = beforeCursor;\n }\n\n /** Whether a compound group is currently active */\n get isGrouping(): boolean {\n return this._grouping;\n }\n\n /**\n * Record an action. If a compound group is active, the action is\n * buffered until `endGroup()` is called.\n */\n record(\n action: UndoAction,\n beforeCursor: CursorState | null,\n afterCursor: CursorState | null,\n ): void {\n if (this._grouping) {\n this._groupActions.push(action);\n return;\n }\n\n this.operations.push({\n id: this.nextId++,\n timestamp: Date.now(),\n peerId: this._localPeerId,\n actions: [action],\n beforeCursor,\n afterCursor,\n });\n }\n\n /**\n * Append an externally-built operation (e.g. from a remote peer).\n * Assigns a new sequential ID but preserves the original peerId.\n */\n appendRemote(op: Omit<CrdtOperation, \"id\">): void {\n this.operations.push({\n ...op,\n id: this.nextId++,\n });\n }\n\n /** End compound group and push as a single atomic operation */\n endGroup(afterCursor: CursorState | null): void {\n if (!this._grouping) return;\n const actions = this._groupActions;\n this._grouping = false;\n this._groupActions = [];\n\n if (actions.length > 0) {\n this.operations.push({\n id: this.nextId++,\n timestamp: Date.now(),\n peerId: this._localPeerId,\n actions,\n beforeCursor: this._groupBeforeCursor,\n afterCursor,\n });\n }\n this._groupBeforeCursor = null;\n }\n\n /** Total number of operations in the log */\n getOperationCount(): number {\n return this.operations.length;\n }\n\n /** Get a specific operation by index */\n getOperation(index: number): CrdtOperation | undefined {\n return this.operations[index];\n }\n\n /** Get the initial editor state */\n getInitialState(): BlockJSON[] {\n return this.initialState;\n }\n\n /** Get all operations */\n getOperations(): readonly CrdtOperation[] {\n return this.operations;\n }\n\n /** Clear all recorded operations (keeps initial state) */\n clear(): void {\n this.operations = [];\n this.nextId = 0;\n this._grouping = false;\n this._groupActions = [];\n this._groupBeforeCursor = null;\n }\n\n /** Serialize the log */\n toJSON(): CrdtLogSnapshot {\n return {\n initialState: this.initialState,\n operations: [...this.operations],\n };\n }\n}\n","/**\n * Replay UI — slider + transport controls anchored below the editor.\n *\n * Shows a timeline slider and play/pause/step controls that let the user\n * scrub through the CRDT operation log to see how the document was built.\n */\n\nimport { iconHtml, X, ChevronsLeft, ChevronsRight, Pause, Play } from \"../util/icons\";\n\nexport interface ReplayUICallbacks {\n onSeek(position: number): void;\n onPlay(): void;\n onPause(): void;\n onStepForward(): void;\n onStepBackward(): void;\n onExit(): void;\n getIsPlaying(): boolean;\n getCurrentPosition(): number;\n getTotalOperations(): number;\n}\n\nexport class ReplayUI {\n private container: HTMLElement;\n private slider: HTMLInputElement;\n private playBtn: HTMLButtonElement;\n private stepBackBtn: HTMLButtonElement;\n private stepFwdBtn: HTMLButtonElement;\n private exitBtn: HTMLButtonElement;\n private posLabel: HTMLSpanElement;\n private callbacks: ReplayUICallbacks;\n\n constructor(editorRoot: HTMLElement, callbacks: ReplayUICallbacks) {\n this.callbacks = callbacks;\n this.container = document.createElement(\"div\");\n this.container.className = \"blx-replay-bar\";\n\n // ── Transport buttons ──\n this.exitBtn = this.createButton(\"blx-replay-exit-btn\", \"Exit\", () => {\n this.callbacks.onExit();\n });\n this.exitBtn.title = \"Exit replay mode\";\n this.exitBtn.innerHTML = iconHtml(X, 14);\n\n this.stepBackBtn = this.createButton(\"blx-replay-btn\", \"Step back\", () => {\n this.callbacks.onStepBackward();\n this.update();\n });\n this.stepBackBtn.title = \"Step backward\";\n this.stepBackBtn.innerHTML = iconHtml(ChevronsLeft, 14);\n\n this.playBtn = this.createButton(\"blx-replay-btn blx-replay-play-btn\", \"Play\", () => {\n if (this.callbacks.getIsPlaying()) {\n this.callbacks.onPause();\n } else {\n this.callbacks.onPlay();\n }\n this.update();\n });\n this.playBtn.title = \"Play / Pause\";\n\n this.stepFwdBtn = this.createButton(\"blx-replay-btn\", \"Step forward\", () => {\n this.callbacks.onStepForward();\n this.update();\n });\n this.stepFwdBtn.title = \"Step forward\";\n this.stepFwdBtn.innerHTML = iconHtml(ChevronsRight, 14);\n\n // ── Slider ──\n this.slider = document.createElement(\"input\");\n this.slider.type = \"range\";\n this.slider.className = \"blx-replay-slider\";\n this.slider.min = \"0\";\n this.slider.max = \"0\";\n this.slider.value = \"0\";\n this.slider.addEventListener(\"input\", () => {\n this.callbacks.onSeek(parseInt(this.slider.value, 10));\n this.updateLabel();\n });\n\n // ── Position label ──\n this.posLabel = document.createElement(\"span\");\n this.posLabel.className = \"blx-replay-pos\";\n\n // ── Title ──\n const title = document.createElement(\"span\");\n title.className = \"blx-replay-title\";\n title.textContent = \"Replay\";\n\n // ── Assemble ──\n const controls = document.createElement(\"div\");\n controls.className = \"blx-replay-controls\";\n controls.appendChild(this.exitBtn);\n controls.appendChild(title);\n controls.appendChild(this.stepBackBtn);\n controls.appendChild(this.playBtn);\n controls.appendChild(this.stepFwdBtn);\n\n const sliderWrap = document.createElement(\"div\");\n sliderWrap.className = \"blx-replay-slider-wrap\";\n sliderWrap.appendChild(this.slider);\n sliderWrap.appendChild(this.posLabel);\n\n this.container.appendChild(controls);\n this.container.appendChild(sliderWrap);\n\n editorRoot.appendChild(this.container);\n this.update();\n }\n\n /** Refresh slider range, position, and play/pause icon */\n update(): void {\n const total = this.callbacks.getTotalOperations();\n const pos = this.callbacks.getCurrentPosition();\n this.slider.max = String(total);\n this.slider.value = String(pos);\n this.updateLabel();\n this.updatePlayIcon();\n this.stepBackBtn.disabled = pos <= 0;\n this.stepFwdBtn.disabled = pos >= total;\n }\n\n private updateLabel(): void {\n const total = this.callbacks.getTotalOperations();\n const pos = parseInt(this.slider.value, 10);\n this.posLabel.textContent = `${pos} / ${total}`;\n }\n\n private updatePlayIcon(): void {\n if (this.callbacks.getIsPlaying()) {\n // Pause icon\n this.playBtn.innerHTML = iconHtml(Pause, 14);\n } else {\n // Play icon\n this.playBtn.innerHTML = iconHtml(Play, 14, { fill: \"currentColor\", stroke: \"none\" });\n }\n }\n\n destroy(): void {\n this.container.remove();\n }\n\n private createButton(\n className: string,\n label: string,\n handler: () => void,\n ): HTMLButtonElement {\n const btn = document.createElement(\"button\");\n btn.className = className;\n btn.setAttribute(\"aria-label\", label);\n btn.addEventListener(\"click\", handler);\n return btn;\n }\n}\n","/**\n * Remote cursor renderer — positions colored caret indicators and selection\n * highlights as absolute overlays above the editor, using getBoundingClientRect\n * to compute positions.\n *\n * Cursors are rendered into a dedicated overlay container that sits outside\n * the contenteditable DOM. This avoids contaminating textContent,\n * Range.toString(), and TreeWalker traversals that the editor relies on\n * for offset calculations.\n */\n\nimport type { RemoteCursor } from \"./types\";\n\n/** CSS class prefix for remote cursor elements */\nconst CURSOR_CLASS = \"blx-remote-cursor\";\nconst LABEL_CLASS = \"blx-remote-cursor-label\";\nconst SELECTION_CLASS = \"blx-remote-cursor-selection\";\nconst OVERLAY_CLASS = \"blx-remote-cursor-overlay\";\nconst BLOCK_BORDER_CLASS = \"blx-remote-block-border\";\n\n/**\n * Render remote cursors (and optional selection highlights) as absolutely\n * positioned overlays.\n *\n * @param contentEditable - The block's contenteditable element (used for position measurement)\n * @param cursors - Array of remote cursors targeting this block\n */\nexport function renderRemoteCursors(\n contentEditable: HTMLElement,\n cursors: RemoteCursor[],\n): void {\n // Find the editor root (closest .blx-editor ancestor)\n const editorRoot = contentEditable.closest(\".blx-editor\");\n if (!editorRoot) return;\n\n // Get or create the overlay container\n let overlay = editorRoot.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) {\n overlay = document.createElement(\"div\");\n overlay.className = OVERLAY_CLASS;\n editorRoot.appendChild(overlay);\n }\n\n // Get the block's ID from the closest [data-block-id] ancestor\n const blockContainer = contentEditable.closest(\"[data-block-id]\");\n const blockId = blockContainer?.getAttribute(\"data-block-id\") ?? \"\";\n\n // Remove existing cursors for this block\n for (const el of overlay.querySelectorAll(`[data-cursor-block=\"${blockId}\"]`)) {\n el.remove();\n }\n\n if (cursors.length === 0) return;\n\n const rootRect = editorRoot.getBoundingClientRect();\n\n for (const cursor of cursors) {\n // Render selection highlight if the cursor has a range\n if (cursor.endOffset != null && cursor.endOffset !== cursor.offset) {\n const selRects = getSelectionRects(contentEditable, cursor.offset, cursor.endOffset);\n for (const sr of selRects) {\n const sel = document.createElement(\"div\");\n sel.className = SELECTION_CLASS;\n sel.dataset.peerId = cursor.peerId;\n sel.dataset.cursorBlock = blockId;\n sel.style.left = `${sr.x - rootRect.x}px`;\n sel.style.top = `${sr.y - rootRect.y}px`;\n sel.style.width = `${sr.width}px`;\n sel.style.height = `${sr.height}px`;\n sel.style.backgroundColor = cursor.color;\n overlay.appendChild(sel);\n }\n }\n\n // Render the caret at the selection head (endOffset) or at the cursor position\n const caretOffset = cursor.endOffset != null ? cursor.endOffset : cursor.offset;\n const rect = getCaretRect(contentEditable, caretOffset);\n if (!rect) continue;\n\n // Determine if the cursor is active (updated within last 3s) or idle\n const isActive =\n cursor.lastUpdated != null && Date.now() - cursor.lastUpdated < 3000;\n\n const el = document.createElement(\"div\");\n el.className = isActive\n ? `${CURSOR_CLASS} ${CURSOR_CLASS}--active`\n : CURSOR_CLASS;\n el.dataset.peerId = cursor.peerId;\n el.dataset.cursorBlock = blockId;\n\n // Position relative to editor root\n el.style.left = `${rect.x - rootRect.x}px`;\n el.style.top = `${rect.y - rootRect.y}px`;\n el.style.height = `${rect.height}px`;\n el.style.borderLeftColor = cursor.color;\n\n // Name label — only shown for active cursors\n if (isActive) {\n const label = document.createElement(\"span\");\n label.className = LABEL_CLASS;\n label.textContent = cursor.displayName;\n label.style.backgroundColor = cursor.color;\n el.appendChild(label);\n }\n\n overlay.appendChild(el);\n }\n}\n\n/** Remove all remote cursor elements for a specific block (or all blocks) */\nexport function clearRemoteCursors(contentEditable: HTMLElement): void {\n const editorRoot = contentEditable.closest(\".blx-editor\");\n if (!editorRoot) return;\n const overlay = editorRoot.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) return;\n\n const blockContainer = contentEditable.closest(\"[data-block-id]\");\n const blockId = blockContainer?.getAttribute(\"data-block-id\");\n\n if (blockId) {\n for (const el of overlay.querySelectorAll(`[data-cursor-block=\"${blockId}\"], [data-border-block=\"${blockId}\"]`)) {\n el.remove();\n }\n } else {\n overlay.innerHTML = \"\";\n }\n}\n\n/** Remove cursor overlays for a non-text block (uses the block container directly) */\nexport function clearRemoteCursorsFromContainer(container: HTMLElement): void {\n const editorRoot = container.closest(\".blx-editor\");\n if (!editorRoot) return;\n const overlay = editorRoot.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) return;\n\n const blockId = container.getAttribute(\"data-block-id\")\n ?? container.closest(\"[data-block-id]\")?.getAttribute(\"data-block-id\");\n if (blockId) {\n for (const el of overlay.querySelectorAll(`[data-cursor-block=\"${blockId}\"], [data-border-block=\"${blockId}\"]`)) {\n el.remove();\n }\n }\n}\n\n/**\n * Render a colored left-border indicator on a block to show it's part of\n * a remote peer's multi-block selection.\n */\nexport function renderBlockSelectionBorder(\n container: HTMLElement,\n cursors: RemoteCursor[],\n): void {\n const editorRoot = container.closest(\".blx-editor\");\n if (!editorRoot) return;\n\n let overlay = editorRoot.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) {\n overlay = document.createElement(\"div\");\n overlay.className = OVERLAY_CLASS;\n editorRoot.appendChild(overlay);\n }\n\n const blockId = container.getAttribute(\"data-block-id\")\n ?? container.closest(\"[data-block-id]\")?.getAttribute(\"data-block-id\") ?? \"\";\n\n // Remove existing border indicators for this block\n for (const el of overlay.querySelectorAll(`[data-border-block=\"${blockId}\"]`)) {\n el.remove();\n }\n\n if (cursors.length === 0) return;\n\n const rootRect = editorRoot.getBoundingClientRect();\n const blockRect = container.getBoundingClientRect();\n\n for (const cursor of cursors) {\n const bar = document.createElement(\"div\");\n bar.className = BLOCK_BORDER_CLASS;\n bar.dataset.peerId = cursor.peerId;\n bar.dataset.borderBlock = blockId;\n bar.style.left = `${blockRect.x - rootRect.x - 2}px`;\n bar.style.top = `${blockRect.y - rootRect.y}px`;\n bar.style.height = `${blockRect.height}px`;\n bar.style.backgroundColor = cursor.color;\n overlay.appendChild(bar);\n }\n}\n\n/**\n * Get an array of DOMRects covering a character range within a contenteditable.\n * Multi-line selections produce multiple rects (one per line fragment).\n */\nfunction getSelectionRects(\n container: HTMLElement,\n startOffset: number,\n endOffset: number,\n): DOMRect[] {\n const start = findTextPosition(container, Math.min(startOffset, endOffset));\n const end = findTextPosition(container, Math.max(startOffset, endOffset));\n if (!start.node || !end.node) return [];\n\n const range = document.createRange();\n try {\n range.setStart(start.node, start.offset);\n range.setEnd(end.node, end.offset);\n } catch {\n return [];\n }\n\n // Guard for environments where getClientRects is unavailable (e.g. jsdom)\n if (typeof range.getClientRects !== \"function\") return [];\n const rects = range.getClientRects();\n return Array.from(rects);\n}\n\n/**\n * Get a DOMRect for a character offset within a contenteditable.\n * Creates a zero-width range at the offset and measures it.\n */\nfunction getCaretRect(\n container: HTMLElement,\n offset: number,\n): DOMRect | null {\n const pos = findTextPosition(container, offset);\n if (!pos.node) return null;\n\n const range = document.createRange();\n try {\n range.setStart(pos.node, pos.offset);\n range.collapse(true);\n } catch {\n return null;\n }\n\n if (typeof range.getClientRects === \"function\") {\n const rects = range.getClientRects();\n if (rects.length > 0) return rects[0];\n }\n const containerRect = container.getBoundingClientRect();\n return new DOMRect(containerRect.x, containerRect.y, 0, containerRect.height);\n}\n\n/**\n * Walk text nodes to find the DOM position for a character offset.\n */\nfunction findTextPosition(\n container: HTMLElement,\n offset: number,\n): { node: Node | null; offset: number } {\n const walker = document.createTreeWalker(\n container,\n NodeFilter.SHOW_TEXT,\n );\n let remaining = offset;\n let node = walker.nextNode();\n\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n return { node, offset: remaining };\n }\n remaining -= len;\n node = walker.nextNode();\n }\n\n // Past end — position at end of last text node\n const lastChild = container.lastChild;\n if (lastChild && lastChild.nodeType === Node.TEXT_NODE) {\n return { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n }\n\n return { node: container, offset: 0 };\n}\n","/**\n * AutomergeSync — bridges an Automerge CRDT document with a BLX Editor.\n *\n * Maintains a parallel Automerge document that mirrors the editor's block\n * model. Local edits are translated into Automerge mutations (splice for\n * text, mark/unmark for rich-text attributes, object changes for metadata).\n * Remote Automerge changes are applied back to the editor.\n *\n * ## Automerge document schema\n *\n * ```\n * {\n * blockOrder: string[], // ordered block IDs\n * blocks: {\n * [blockId]: {\n * type: string,\n * text: string, // Automerge collaborative text\n * metadata: Record<string, any>,\n * }\n * }\n * }\n * ```\n *\n * Rich-text attributes (bold, italic, etc.) are stored as Automerge marks\n * on the `text` field of each block.\n */\n\nimport * as Automerge from \"@automerge/automerge\";\nimport type { EventBus } from \"../event-bus\";\nimport type { EditorEventMap } from \"../event-bus\";\nimport type { Block } from \"../types\";\nimport { AttributedString } from \"../attributed-string\";\nimport type { Attributes, Span } from \"../attributed-string\";\n\n// ── Automerge document schema ──────────────────────────────────────\n\nexport interface AutomergeBlockData {\n type: string;\n text: string;\n metadata: Record<string, unknown>;\n}\n\nexport interface AutomergeDocSchema {\n /** Ordered list of block IDs (determines document order) */\n blockOrder: string[];\n /** Map of blockId → block data */\n blocks: Record<string, AutomergeBlockData>;\n}\n\n// ── Attribute keys we track as Automerge marks ─────────────────────\n\n/**\n * Attribute keys that are stored as Automerge marks on the text.\n * These correspond to inline formatting in AttributedString.\n */\nconst MARK_ATTRIBUTES = new Set([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strikethrough\",\n \"code\",\n \"link\",\n \"backgroundColor\",\n \"blockRef\",\n]);\n\n// ── AutomergeSync class ────────────────────────────────────────────\n\nexport interface AutomergeSyncOptions {\n /** Optional hex actor ID for this peer (auto-generated if omitted) */\n actorId?: string;\n}\n\nexport class AutomergeSync {\n private doc: Automerge.Doc<AutomergeDocSchema>;\n /** When true, editor events are ignored (we're applying remote changes) */\n private _applying = false;\n /**\n * Cache of per-block span attribute signatures. Used to detect whether\n * formatting changed on a keystroke so we can skip the expensive\n * unmark-all / re-mark-all cycle when only text was inserted/deleted.\n */\n private _spanSigCache = new Map<string, string>();\n\n // Editor access\n private _getBlocks: () => ReadonlyArray<Block>;\n private _getBlock: (id: string) => Block | undefined;\n private _addBlock: (block: Block, index?: number) => Block;\n private _removeBlock: (id: string) => boolean;\n private _moveBlock: (id: string, toIndex: number) => boolean;\n private _updateBlockContent: (\n blockId: string,\n content: AttributedString,\n metadata?: Record<string, unknown>,\n blockType?: string,\n ) => void;\n private _replaceAllBlocks: ((blocks: Block[]) => void) | null;\n private _bus: EventBus<EditorEventMap>;\n\n // Event unsubscribe functions\n private _unsubs: Array<() => void> = [];\n\n constructor(\n editorApi: {\n getBlocks: () => ReadonlyArray<Block>;\n getBlock: (id: string) => Block | undefined;\n addBlock: (block: Block, index?: number) => Block;\n removeBlock: (id: string) => boolean;\n moveBlock: (id: string, toIndex: number) => boolean;\n updateBlockContent: (\n blockId: string,\n content: AttributedString,\n metadata?: Record<string, unknown>,\n blockType?: string,\n ) => void;\n replaceAllBlocks?: (blocks: Block[]) => void;\n bus: EventBus<EditorEventMap>;\n },\n options?: AutomergeSyncOptions,\n ) {\n this._getBlocks = editorApi.getBlocks;\n this._getBlock = editorApi.getBlock;\n this._addBlock = editorApi.addBlock;\n this._removeBlock = editorApi.removeBlock;\n this._moveBlock = editorApi.moveBlock;\n this._updateBlockContent = editorApi.updateBlockContent;\n this._replaceAllBlocks = editorApi.replaceAllBlocks ?? null;\n this._bus = editorApi.bus;\n\n // Initialize Automerge document\n this.doc = options?.actorId\n ? Automerge.init<AutomergeDocSchema>(options.actorId)\n : Automerge.init<AutomergeDocSchema>();\n\n // Populate from current editor state\n this.initFromEditor();\n\n // Listen for local editor changes\n this.setupListeners();\n }\n\n // ── Public API ────────────────────────────────────────────────────\n\n /** Get the underlying Automerge document (read-only view) */\n getDoc(): Automerge.Doc<AutomergeDocSchema> {\n return this.doc;\n }\n\n /** Get the actor ID of this Automerge instance */\n getActorId(): string {\n return Automerge.getActorId(this.doc);\n }\n\n /** Save the document to a binary blob for persistence */\n save(): Uint8Array {\n return Automerge.save(this.doc);\n }\n\n /** Load a document from a previously saved binary blob */\n load(data: Uint8Array, actorId?: string): void {\n this.doc = actorId\n ? Automerge.load<AutomergeDocSchema>(data, actorId)\n : Automerge.load<AutomergeDocSchema>(data);\n this.applyDocToEditor();\n }\n\n /**\n * Merge another Automerge document into this one. Useful for\n * initial sync when peers exchange full document state.\n */\n merge(otherDoc: Automerge.Doc<AutomergeDocSchema>): void {\n const oldDoc = this.doc;\n this.doc = Automerge.merge(this.doc, otherDoc);\n this.diffAndApply(oldDoc, this.doc);\n }\n\n /**\n * Generate a sync message to send to a remote peer.\n * Returns [updatedSyncState, message] where message may be null\n * if there's nothing new to send.\n */\n generateSyncMessage(\n syncState: Automerge.SyncState,\n ): [Automerge.SyncState, Uint8Array | null] {\n const [newState, msg] = Automerge.generateSyncMessage(this.doc, syncState);\n return [newState, msg ?? null];\n }\n\n /**\n * Receive a sync message from a remote peer.\n * Applies remote changes to both the Automerge doc and the editor.\n * Returns the updated sync state.\n */\n receiveSyncMessage(\n syncState: Automerge.SyncState,\n message: Uint8Array,\n ): Automerge.SyncState {\n const oldDoc = this.doc;\n const [newDoc, newState] = Automerge.receiveSyncMessage(\n this.doc,\n syncState,\n message,\n );\n\n this.doc = newDoc;\n this.diffAndApply(oldDoc, newDoc);\n return newState;\n }\n\n /**\n * Apply raw Automerge changes (from `getChanges` / `getAllChanges`).\n * Useful for replaying history or applying batched changes.\n */\n applyChanges(changes: Uint8Array[]): void {\n const oldDoc = this.doc;\n const [newDoc] = Automerge.applyChanges(this.doc, changes);\n this.doc = newDoc;\n this.diffAndApply(oldDoc, newDoc);\n }\n\n /** Get all changes since the document was created */\n getAllChanges(): Uint8Array[] {\n return Automerge.getAllChanges(this.doc);\n }\n\n /** Get changes since a set of heads */\n getChanges(heads: Automerge.Heads): Uint8Array[] {\n const sinceDoc = Automerge.view(this.doc, heads);\n return Automerge.getChanges(sinceDoc, this.doc);\n }\n\n /** Get the current document heads (for change tracking) */\n getHeads(): Automerge.Heads {\n return Automerge.getHeads(this.doc);\n }\n\n /** Create a new sync state for a peer connection */\n static initSyncState(): Automerge.SyncState {\n return Automerge.initSyncState();\n }\n\n /** Fork a copy of the document (for testing / branching) */\n fork(): Automerge.Doc<AutomergeDocSchema> {\n return Automerge.clone(this.doc);\n }\n\n /** Clean up event listeners */\n destroy(): void {\n for (const unsub of this._unsubs) unsub();\n this._unsubs = [];\n this._spanSigCache.clear();\n }\n\n /** Whether we are currently applying remote changes (suppressing local events) */\n get isApplying(): boolean {\n return this._applying;\n }\n\n // ── Initialization ────────────────────────────────────────────────\n\n /** Populate the Automerge doc from the current editor state */\n private initFromEditor(): void {\n const blocks = this._getBlocks();\n // Skip initialization for empty editors so that applying remote changes\n // doesn't conflict with an independent root-level assignment.\n if (blocks.length === 0) return;\n\n this.doc = Automerge.change(this.doc, (d) => {\n d.blockOrder = [];\n d.blocks = {};\n for (const block of blocks) {\n d.blockOrder.push(block.id);\n d.blocks[block.id] = {\n type: block.type,\n text: \"\",\n metadata: stripUndefined(block.metadata),\n };\n // Use splice to insert text as collaborative text\n const text = block.content.text;\n if (text.length > 0) {\n Automerge.splice(d, [\"blocks\", block.id, \"text\"], 0, 0, text);\n }\n // Apply marks for rich-text attributes\n this.applyMarksFromSpans(d, block.id, block.content.spans);\n // Cache span signature for formatting-change detection\n this._spanSigCache.set(block.id, spanSignature(block.content.spans));\n }\n });\n }\n\n // ── Local change listeners ────────────────────────────────────────\n\n /** Listen to editor events and mirror changes to the Automerge doc */\n private setupListeners(): void {\n const onContentChanged = ({\n blockId,\n content,\n metadata,\n }: {\n blockId: string;\n content: AttributedString;\n metadata?: Record<string, unknown>;\n }) => {\n if (this._applying) return;\n this.handleContentChanged(blockId, content, metadata);\n };\n\n const onBlockAdded = ({\n blockId,\n index,\n }: {\n blockId: string;\n index: number;\n }) => {\n if (this._applying) return;\n const block = this._getBlock(blockId);\n if (!block) return;\n this.handleBlockAdded(block, index);\n };\n\n const onBlockRemoved = ({ blockId }: { blockId: string }) => {\n if (this._applying) return;\n this.handleBlockRemoved(blockId);\n };\n\n const onBlockMoved = ({\n blockId,\n toIndex,\n }: {\n blockId: string;\n fromIndex: number;\n toIndex: number;\n }) => {\n if (this._applying) return;\n this.handleBlockMoved(blockId, toIndex);\n };\n\n const onBlockTypeChanged = ({\n blockId,\n newType,\n }: {\n blockId: string;\n oldType: string;\n newType: string;\n }) => {\n if (this._applying) return;\n this.handleBlockTypeChanged(blockId, newType);\n };\n\n this._bus.on(\"block:contentChanged\", onContentChanged);\n this._bus.on(\"block:added\", onBlockAdded);\n this._bus.on(\"block:removed\", onBlockRemoved);\n this._bus.on(\"block:moved\", onBlockMoved);\n this._bus.on(\"block:typeChanged\", onBlockTypeChanged);\n\n this._unsubs.push(\n () => this._bus.off(\"block:contentChanged\", onContentChanged),\n () => this._bus.off(\"block:added\", onBlockAdded),\n () => this._bus.off(\"block:removed\", onBlockRemoved),\n () => this._bus.off(\"block:moved\", onBlockMoved),\n () => this._bus.off(\"block:typeChanged\", onBlockTypeChanged),\n );\n }\n\n // ── Local change → Automerge mutation ─────────────────────────────\n\n private handleContentChanged(\n blockId: string,\n content: AttributedString,\n metadata?: Record<string, unknown>,\n ): void {\n const oldText = this.doc.blocks?.[blockId]?.text ?? \"\";\n const newText = content.text;\n\n // Detect whether formatting changed by comparing span attribute\n // signatures. For plain text edits (typing, deleting) within an\n // existing formatting span, Automerge's splice already handles mark\n // expansion/contraction — we can skip the expensive clear-all /\n // re-apply-all mark cycle entirely.\n const newSig = spanSignature(content.spans);\n const oldSig = this._spanSigCache.get(blockId);\n const formattingChanged = newSig !== oldSig;\n this._spanSigCache.set(blockId, newSig);\n\n this.doc = Automerge.change(this.doc, (d) => {\n if (!d.blocks[blockId]) return;\n\n // Diff the text and apply minimal splice operations\n const diff = diffText(oldText, newText);\n if (diff.del > 0 || diff.ins.length > 0) {\n Automerge.splice(\n d,\n [\"blocks\", blockId, \"text\"],\n diff.pos,\n diff.del,\n diff.ins,\n );\n }\n\n // Only re-apply marks when formatting actually changed.\n // This eliminates 4-10 WASM boundary crossings per keystroke\n // for the common case of typing within a span.\n if (formattingChanged) {\n const currentMarks = Automerge.marks(this.doc, [\"blocks\", blockId, \"text\"]);\n for (const mark of currentMarks) {\n try {\n Automerge.unmark(\n d,\n [\"blocks\", blockId, \"text\"],\n { start: mark.start, end: mark.end, expand: \"none\" },\n mark.name,\n );\n } catch {\n // Ignore errors from unmark on ranges that no longer exist\n }\n }\n this.applyMarksFromSpans(d, blockId, content.spans);\n }\n\n // Update metadata — incremental key-by-key updates on the existing\n // Automerge map. Full replacement (`d.blocks[blockId].metadata = x`)\n // creates a NEW map object, which means any concurrent modifications\n // by another peer (e.g. kura's setTaskStatus hint) target the OLD map\n // and are silently lost when the sync merges. Incremental updates\n // keep the same map identity so CRDT merge works correctly.\n if (metadata) {\n const stripped = stripUndefined(metadata);\n const existing = d.blocks[blockId].metadata as Record<string, unknown> | undefined;\n\n if (!existing) {\n // No metadata map yet — create from scratch\n d.blocks[blockId].metadata = stripped;\n } else {\n // Add / update keys\n for (const key of Object.keys(stripped)) {\n existing[key] = stripped[key];\n }\n // Remove keys no longer present\n for (const key of Object.keys(existing)) {\n if (!(key in stripped)) {\n delete existing[key];\n }\n }\n }\n }\n });\n }\n\n private handleBlockAdded(block: Block, index: number): void {\n this.doc = Automerge.change(this.doc, (d) => {\n // Lazily create base structure (may be absent if editor was empty at init)\n if (!d.blockOrder) d.blockOrder = [];\n if (!d.blocks) d.blocks = {};\n // Insert block ID at the correct position (use proxied splice for arrays)\n d.blockOrder.splice(index, 0, block.id);\n\n // Create block data\n d.blocks[block.id] = {\n type: block.type,\n text: \"\",\n metadata: stripUndefined(block.metadata),\n };\n\n // Insert text using Automerge.splice (for collaborative text)\n const text = block.content.text;\n if (text.length > 0) {\n Automerge.splice(d, [\"blocks\", block.id, \"text\"], 0, 0, text);\n }\n\n // Apply marks\n this.applyMarksFromSpans(d, block.id, block.content.spans);\n });\n // Cache span signature for formatting-change detection\n this._spanSigCache.set(block.id, spanSignature(block.content.spans));\n }\n\n private handleBlockRemoved(blockId: string): void {\n this.doc = Automerge.change(this.doc, (d) => {\n // Remove from blockOrder (use proxied splice for arrays)\n const idx = d.blockOrder.indexOf(blockId);\n if (idx >= 0) {\n d.blockOrder.splice(idx, 1);\n }\n // Remove block data\n delete d.blocks[blockId];\n });\n this._spanSigCache.delete(blockId);\n }\n\n private handleBlockMoved(blockId: string, toIndex: number): void {\n this.doc = Automerge.change(this.doc, (d) => {\n const fromIdx = d.blockOrder.indexOf(blockId);\n if (fromIdx < 0) return;\n // Use proxied splice for array operations\n d.blockOrder.splice(fromIdx, 1);\n d.blockOrder.splice(toIndex, 0, blockId);\n });\n }\n\n private handleBlockTypeChanged(blockId: string, newType: string): void {\n this.doc = Automerge.change(this.doc, (d) => {\n if (d.blocks[blockId]) {\n d.blocks[blockId].type = newType;\n }\n });\n // Invalidate cached span signature — the new block type may render\n // the same spans differently, so the next content change must\n // re-evaluate whether marks need updating.\n this._spanSigCache.delete(blockId);\n }\n\n // ── Remote change → Editor update ─────────────────────────────────\n\n /**\n * Diff two Automerge document versions and apply the differences\n * to the editor. This is called after receiving remote changes.\n */\n private diffAndApply(\n oldDoc: Automerge.Doc<AutomergeDocSchema>,\n newDoc: Automerge.Doc<AutomergeDocSchema>,\n ): void {\n this._applying = true;\n try {\n // Coerce blockOrder entries to plain strings — Automerge Rust writes\n // Scalar strings that JS 3.x surfaces as ImmutableString proxy objects\n // which fail === comparison and Map key lookups.\n const oldOrder = (oldDoc.blockOrder ?? []).map(String);\n const newOrder = (newDoc.blockOrder ?? []).map(String);\n const oldBlocks = oldDoc.blocks ?? {};\n const newBlocks = newDoc.blocks ?? {};\n\n // Find removed blocks\n const newOrderSet = new Set(newOrder);\n for (const id of oldOrder) {\n if (!newOrderSet.has(id)) {\n this._removeBlock(id);\n }\n }\n\n // Find added blocks and update existing ones\n const oldOrderSet = new Set(oldOrder);\n for (let i = 0; i < newOrder.length; i++) {\n const blockId = newOrder[i];\n const newData = newBlocks[blockId];\n if (!newData) continue;\n\n // Coerce type to plain string (see blockOrder comment above)\n const blockType = String(newData.type);\n\n if (!oldOrderSet.has(blockId)) {\n // New block — add it\n const content = this.blockDataToAttributedString(newDoc, blockId);\n this._addBlock(\n {\n id: blockId,\n type: blockType,\n content,\n metadata: { ...(newData.metadata as Record<string, unknown>) },\n },\n i,\n );\n } else {\n // Existing block — check for content/metadata/type changes\n const oldData = oldBlocks[blockId];\n if (!oldData) continue;\n\n const textChanged = oldData.text !== newData.text;\n const typeChanged = String(oldData.type) !== blockType;\n const oldMeta = oldData.metadata as Record<string, unknown>;\n const newMeta = newData.metadata as Record<string, unknown>;\n const metadataChanged = !metadataEqual(oldMeta, newMeta);\n\n // Check if marks changed (only when text didn't change,\n // since text changes already require a content rebuild).\n // Fetch marks once and reuse for blockDataToAttributedString.\n let marksChanged = false;\n let newMarks: Array<{ name: string; value: unknown; start: number; end: number }> | undefined;\n if (!textChanged) {\n const oldMarks = Automerge.marks(oldDoc, [\"blocks\", blockId, \"text\"]);\n newMarks = Automerge.marks(newDoc, [\"blocks\", blockId, \"text\"]);\n marksChanged = oldMarks.length !== newMarks.length ||\n oldMarks.some((m, i) =>\n m.name !== newMarks![i].name ||\n m.start !== newMarks![i].start ||\n m.end !== newMarks![i].end ||\n m.value !== newMarks![i].value,\n );\n }\n\n if (textChanged || marksChanged || metadataChanged || typeChanged) {\n // Fetch new marks once (reuse if already fetched above)\n if (!newMarks) {\n try {\n newMarks = Automerge.marks(newDoc, [\"blocks\", blockId, \"text\"]);\n } catch {\n newMarks = [];\n }\n }\n // Pass cached marks to avoid a redundant WASM call\n const content = this.blockDataToAttributedString(newDoc, blockId, newMarks);\n this._updateBlockContent(\n blockId,\n content,\n { ...(newData.metadata as Record<string, unknown>) },\n typeChanged ? blockType : undefined,\n );\n // Update span signature cache\n this._spanSigCache.set(blockId, spanSignature(content.spans));\n }\n }\n }\n\n // Handle block reordering\n // Check if block order changed (after adds/removes).\n // IMPORTANT: refresh the current order after each move because\n // _moveBlock() mutates the editor's block list in place.\n for (let i = 0; i < newOrder.length; i++) {\n const currentOrder = this._getBlocks().map((b) => b.id);\n if (currentOrder[i] !== newOrder[i]) {\n this._moveBlock(newOrder[i], i);\n }\n }\n } finally {\n this._applying = false;\n }\n }\n\n /**\n * Full replace: apply the entire Automerge doc to the editor.\n * Used after `load()`.\n */\n private applyDocToEditor(): void {\n this._applying = true;\n try {\n // Build block array from Automerge doc\n // Coerce IDs and types to plain strings (Rust Scalar → JS ImmutableString)\n const order = this.doc.blockOrder ?? [];\n const blocks: Block[] = [];\n for (const rawId of order) {\n const blockId = String(rawId);\n const data = this.doc.blocks?.[blockId];\n if (!data) continue;\n const content = this.blockDataToAttributedString(this.doc, blockId);\n blocks.push({\n id: blockId,\n type: String(data.type),\n content,\n metadata: { ...(data.metadata as Record<string, unknown>) },\n });\n }\n\n if (this._replaceAllBlocks) {\n // Fast path: bulk replace avoids per-block event/DOM overhead\n this._replaceAllBlocks(blocks);\n } else {\n // Fallback: remove-then-add one by one\n const existing = this._getBlocks();\n for (const block of existing) {\n this._removeBlock(block.id);\n }\n for (let i = 0; i < blocks.length; i++) {\n this._addBlock(blocks[i], i);\n }\n }\n } finally {\n this._applying = false;\n }\n }\n\n // ── AttributedString ↔ Automerge marks conversion ────────────────\n\n /**\n * Apply Automerge marks from AttributedString spans.\n * Must be called inside an `Automerge.change()` callback.\n */\n private applyMarksFromSpans(\n d: Automerge.Doc<AutomergeDocSchema>,\n blockId: string,\n spans: ReadonlyArray<Span>,\n ): void {\n let offset = 0;\n for (const span of spans) {\n const end = offset + span.text.length;\n for (const [key, value] of Object.entries(span.attributes)) {\n if (MARK_ATTRIBUTES.has(key)) {\n try {\n Automerge.mark(\n d,\n [\"blocks\", blockId, \"text\"],\n { start: offset, end, expand: \"after\" },\n key,\n value,\n );\n } catch {\n // Ignore mark errors on empty/invalid ranges\n }\n }\n }\n offset = end;\n }\n }\n\n /**\n * Convert an Automerge block's text + marks back to an AttributedString.\n *\n * Uses an efficient O(M log M) interval sweep (M = mark count) rather\n * than the previous O(M × N) per-character approach (N = text length).\n */\n private blockDataToAttributedString(\n doc: Automerge.Doc<AutomergeDocSchema>,\n blockId: string,\n cachedMarks?: ReadonlyArray<{ name: string; value: unknown; start: number; end: number }>,\n ): AttributedString {\n const data = doc.blocks?.[blockId];\n if (!data) return AttributedString.empty();\n\n const text = data.text ?? \"\";\n if (text.length === 0) return AttributedString.empty();\n\n // Reuse cached marks if provided (avoids redundant WASM call)\n let marks: ReadonlyArray<{\n name: string;\n value: unknown;\n start: number;\n end: number;\n }>;\n if (cachedMarks) {\n marks = cachedMarks;\n } else {\n try {\n marks = Automerge.marks(doc, [\"blocks\", blockId, \"text\"]);\n } catch {\n marks = [];\n }\n }\n\n if (marks.length === 0) {\n return AttributedString.fromPlain(text);\n }\n\n // Collect all unique boundary positions from marks, then sweep\n // through them to build spans. This is O(M log M) instead of O(M × N).\n const boundarySet = new Set<number>();\n boundarySet.add(0);\n boundarySet.add(text.length);\n for (const mark of marks) {\n if (mark.start > 0 && mark.start < text.length) boundarySet.add(mark.start);\n if (mark.end > 0 && mark.end < text.length) boundarySet.add(mark.end);\n }\n const boundaries = Array.from(boundarySet).sort((a, b) => a - b);\n\n // For each interval between boundaries, collect active marks\n const spans: Span[] = [];\n for (let i = 0; i < boundaries.length - 1; i++) {\n const start = boundaries[i];\n const end = boundaries[i + 1];\n const attrs: Attributes = {};\n for (const mark of marks) {\n if (mark.start <= start && mark.end >= end) {\n attrs[mark.name] = mark.value as string | number | boolean;\n }\n }\n spans.push({ text: text.slice(start, end), attributes: attrs });\n }\n\n // Merge adjacent spans with identical attributes\n const merged: Span[] = [];\n for (const span of spans) {\n const last = merged[merged.length - 1];\n if (last && attrsEqual(last.attributes, span.attributes)) {\n merged[merged.length - 1] = {\n text: last.text + span.text,\n attributes: last.attributes,\n };\n } else {\n merged.push(span);\n }\n }\n\n return AttributedString.fromSpans(merged);\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\n/** Simple text diff: find minimal insert/delete to go from `before` to `after` */\nexport function diffText(\n before: string,\n after: string,\n): { pos: number; del: number; ins: string } {\n // Find common prefix\n let prefixLen = 0;\n const minLen = Math.min(before.length, after.length);\n while (prefixLen < minLen && before[prefixLen] === after[prefixLen]) {\n prefixLen++;\n }\n\n // Find common suffix (from the remaining parts)\n let suffixLen = 0;\n const maxSuffix = Math.min(\n before.length - prefixLen,\n after.length - prefixLen,\n );\n while (\n suffixLen < maxSuffix &&\n before[before.length - 1 - suffixLen] === after[after.length - 1 - suffixLen]\n ) {\n suffixLen++;\n }\n\n return {\n pos: prefixLen,\n del: before.length - prefixLen - suffixLen,\n ins: after.slice(prefixLen, after.length - suffixLen),\n };\n}\n\nfunction attrsEqual(a: Attributes, b: Attributes): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if (a[k] !== b[k]) return false;\n }\n return true;\n}\n\n/**\n * Compute a signature string that represents the *formatting structure* of\n * the spans (the attribute keys/values per span, in order) but NOT the text.\n * Two spans lists with the same formatting structure but different text\n * produce the same signature, which lets us detect formatting-only changes.\n */\nfunction spanSignature(spans: ReadonlyArray<Span>): string {\n // Fast path: no formatting at all\n if (spans.length <= 1 && (spans.length === 0 || Object.keys(spans[0].attributes).length === 0)) {\n return \"\";\n }\n let sig = \"\";\n for (const span of spans) {\n const keys = Object.keys(span.attributes);\n if (keys.length === 0) {\n sig += `${span.text.length};`;\n } else {\n keys.sort();\n sig += `${span.text.length}:`;\n for (const k of keys) {\n sig += `${k}=${span.attributes[k]},`;\n }\n sig += \";\";\n }\n }\n return sig;\n}\n\n/**\n * Strip `undefined` values from a metadata object. Automerge rejects\n * `undefined` — editors signal property removal by setting the value to\n * `undefined`, but we must omit those keys entirely when writing to the CRDT.\n *\n * Also flattens `AttributedString` instances to plain `Span[]` arrays,\n * since Automerge can only store plain data (not class instances).\n */\nfunction stripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key in obj) {\n const val = obj[key];\n if (val !== undefined) {\n result[key] = flattenValue(val);\n }\n }\n return result;\n}\n\n/**\n * Recursively deep-clone metadata values for Automerge storage.\n * - Converts AttributedString instances to plain Span[] arrays\n * - Deep-clones objects to break Automerge proxy references\n * (proxies from previous reads can't be assigned back)\n */\nfunction flattenValue(val: unknown): unknown {\n if (val == null || typeof val === \"string\" || typeof val === \"number\" || typeof val === \"boolean\") {\n return val;\n }\n // Automerge ImmutableString — extract the plain string before the generic object handler.\n // ImmutableString has a .val string property; treating it as a plain object would serialize it\n // as { val: \"...\" } which creates a nested map in Automerge instead of a scalar string.\n if (Automerge.isImmutableString(val as object)) {\n return String(val);\n }\n if (val instanceof AttributedString) {\n return val.isEmpty() ? [] : val.spans.map(s => ({\n text: s.text,\n attributes: { ...s.attributes },\n }));\n }\n if (Array.isArray(val)) {\n return val.map(flattenValue);\n }\n if (typeof val === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(val as Record<string, unknown>)) {\n result[k] = flattenValue(v);\n }\n return result;\n }\n return val;\n}\n\n/**\n * Deep equality check for metadata objects. Handles nested objects and arrays\n * (e.g., table `cells` metadata) that shallow `!==` would always flag as changed.\n */\nfunction metadataEqual(\n a: Record<string, unknown> | null | undefined,\n b: Record<string, unknown> | null | undefined,\n): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if (!deepEqual(a[k], b[k])) return false;\n }\n return true;\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (Array.isArray(a)) {\n const arrB = b as unknown[];\n if (a.length !== arrB.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], arrB[i])) return false;\n }\n return true;\n }\n const objA = a as Record<string, unknown>;\n const objB = b as Record<string, unknown>;\n const keysA = Object.keys(objA);\n const keysB = Object.keys(objB);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if (!deepEqual(objA[k], objB[k])) return false;\n }\n return true;\n}\n","import type { Block } from \"../types\";\n\n/**\n * Extract a leading emoji from a string, if present.\n * Matches extended pictographic characters including ZWJ sequences.\n */\nfunction leadingEmoji(text: string): string | null {\n if (!text) return null;\n const match = text.match(\n /^(\\p{Extended_Pictographic}(\\u{FE0F}|\\u{200D}\\p{Extended_Pictographic})*)/u,\n );\n return match?.[0] || null;\n}\n\ninterface TocEntry {\n blockId: string;\n level: number;\n title: string;\n emoji: string | null;\n}\n\n// ── Size tables ─────────────────────────────────────────────\n// Three tiers per level: REST → ACTIVE → BROWSE\n// REST: not hovered, compact minimap\n// ACTIVE: hovered over TOC container, all entries grow uniformly\n// BROWSE: mouse over a specific entry, that entry pops dramatically\n\n/** Widths at rest (not hovered) */\nconst REST_W: Record<number, number> = { 1: 16, 2: 12, 3: 9, 4: 6 };\n/** Widths when widget is active (hovered) */\nconst ACTIVE_W: Record<number, number> = { 1: 24, 2: 18, 3: 13, 4: 9 };\n/** Widths when browsing directly over an entry */\nconst BROWSE_W: Record<number, number> = { 1: 48, 2: 38, 3: 28, 4: 18 };\n\n/** Heights at rest */\nconst REST_H: Record<number, number> = { 1: 2.5, 2: 2, 3: 1.5, 4: 1.25 };\n/** Heights when widget is active */\nconst ACTIVE_H: Record<number, number> = { 1: 3, 2: 2.5, 3: 2, 4: 1.5 };\n/** Heights when browsing directly over an entry */\nconst BROWSE_H: Record<number, number> = { 1: 5, 2: 4, 3: 3.5, 4: 2.5 };\n\n/** Radius in pixels around the cursor that triggers browse magnification */\nconst MAGNIFY_RADIUS = 100;\n/** Half-gap at rest */\nconst REST_HALF_GAP = 1.5;\n/** Half-gap when widget is active */\nconst ACTIVE_HALF_GAP = 4;\n/** Half-gap when browsing directly over an entry */\nconst BROWSE_HALF_GAP = 10;\n\n/**\n * Table of Contents widget — a minimap-style navigation rail on the right\n * side of the editor. Shows tiny right-aligned lines at rest. On hover,\n * entries expand into labeled pills with genie magnification that pops\n * the entry nearest to the cursor.\n */\nexport class TableOfContents {\n private readonly container: HTMLElement;\n private readonly track: HTMLElement;\n private readonly editorRoot: HTMLElement;\n private readonly getBlocks: () => ReadonlyArray<Block>;\n private readonly onNavigate: (blockId: string) => void;\n private activeBlockId: string | null = null;\n private entries: TocEntry[] = [];\n private entryEls: HTMLElement[] = [];\n private updateTimer: ReturnType<typeof setTimeout> | null = null;\n private scrollRaf: number | null = null;\n private scrollParent: HTMLElement | Window | null = null;\n private scrollHandler: (() => void) | null = null;\n private moveRaf: number | null = null;\n private lastMouseY = -9999;\n /** Timestamp until which scroll-based active tracking is suppressed (after click nav) */\n private scrollLockUntil = 0;\n /** Whether the mouse is currently over the TOC container */\n private isHovered = false;\n\n constructor(\n editorRoot: HTMLElement,\n getBlocks: () => ReadonlyArray<Block>,\n onNavigate: (blockId: string) => void,\n ) {\n this.editorRoot = editorRoot;\n this.getBlocks = getBlocks;\n this.onNavigate = onNavigate;\n\n // Build outer container\n this.container = document.createElement(\"div\");\n this.container.className = \"blx-toc\";\n this.container.setAttribute(\"role\", \"navigation\");\n this.container.setAttribute(\"aria-label\", \"Table of contents\");\n\n // Build sticky track\n this.track = document.createElement(\"div\");\n this.track.className = \"blx-toc-track\";\n this.container.appendChild(this.track);\n\n // Append as child of editorRoot (sibling of .blx-gutter and .blx-blocks)\n this.editorRoot.appendChild(this.container);\n\n // Handle clicks on entries via event delegation\n this.track.addEventListener(\"click\", this.handleClick);\n\n // Set up scroll-based active heading tracking\n this.setupScrollTracking();\n\n // Set up hover-based magnification\n this.container.addEventListener(\"mouseenter\", this.handleMouseEnter);\n this.container.addEventListener(\"mouseleave\", this.handleMouseLeave);\n this.container.addEventListener(\"mousemove\", this.handleMouseMove, {\n passive: true,\n });\n\n // Initial render\n this.update();\n }\n\n /**\n * Scan blocks for headings and rebuild the ToC entries.\n * Debounced when called repeatedly (e.g. rapid typing).\n */\n update(): void {\n if (this.updateTimer !== null) {\n clearTimeout(this.updateTimer);\n }\n this.updateTimer = setTimeout(() => {\n this.updateTimer = null;\n this.rebuild();\n }, 80);\n }\n\n /**\n * Highlight a specific entry as the active heading.\n */\n setActiveHeading(blockId: string | null): void {\n if (blockId === this.activeBlockId) return;\n this.activeBlockId = blockId;\n this.applyActiveClass();\n }\n\n /**\n * Hide the widget.\n */\n hide(): void {\n this.container.style.display = \"none\";\n }\n\n /**\n * Show the widget.\n */\n show(): void {\n this.container.style.display = \"\";\n }\n\n /**\n * Clean up DOM and listeners.\n */\n destroy(): void {\n if (this.updateTimer !== null) {\n clearTimeout(this.updateTimer);\n this.updateTimer = null;\n }\n if (this.scrollRaf !== null) {\n cancelAnimationFrame(this.scrollRaf);\n this.scrollRaf = null;\n }\n if (this.moveRaf !== null) {\n cancelAnimationFrame(this.moveRaf);\n this.moveRaf = null;\n }\n if (this.scrollHandler && this.scrollParent) {\n this.scrollParent.removeEventListener(\"scroll\", this.scrollHandler);\n this.scrollHandler = null;\n this.scrollParent = null;\n }\n this.container.removeEventListener(\"mouseenter\", this.handleMouseEnter);\n this.container.removeEventListener(\"mouseleave\", this.handleMouseLeave);\n this.container.removeEventListener(\"mousemove\", this.handleMouseMove);\n this.track.removeEventListener(\"click\", this.handleClick);\n this.container.remove();\n }\n\n // ── Private ─────────────────────────────────────────────────────\n\n private rebuild(): void {\n const blocks = this.getBlocks();\n this.entries = [];\n\n for (const block of blocks) {\n if (block.type !== \"heading\") continue;\n const level = (block.metadata as { level?: number }).level ?? 1;\n const text = block.content.text;\n const emoji = leadingEmoji(text);\n this.entries.push({\n blockId: block.id,\n level,\n title: text,\n emoji,\n });\n }\n\n // Toggle visibility: hide when no headings\n if (this.entries.length === 0) {\n this.container.classList.add(\"blx-toc-empty\");\n } else {\n this.container.classList.remove(\"blx-toc-empty\");\n }\n\n // Rebuild DOM\n this.track.innerHTML = \"\";\n this.entryEls = [];\n for (const entry of this.entries) {\n const btn = document.createElement(\"button\");\n btn.className = `blx-toc-entry blx-toc-entry-${entry.level}`;\n btn.dataset.blockId = entry.blockId;\n btn.type = \"button\";\n\n // Label comes first in DOM (left side), but is invisible by default\n const label = document.createElement(\"span\");\n label.className = \"blx-toc-label\";\n label.textContent = entry.title;\n btn.appendChild(label);\n\n if (entry.emoji) {\n const emojiEl = document.createElement(\"span\");\n emojiEl.className = \"blx-toc-emoji\";\n emojiEl.textContent = entry.emoji;\n btn.appendChild(emojiEl);\n }\n\n // Line is last in DOM (right side, flush to edge)\n const line = document.createElement(\"span\");\n line.className = \"blx-toc-line\";\n btn.appendChild(line);\n\n this.track.appendChild(btn);\n this.entryEls.push(btn);\n }\n\n this.applyActiveClass();\n // Re-apply magnification at current mouse pos\n this.applyMagnification();\n }\n\n private applyActiveClass(): void {\n for (const el of this.entryEls) {\n if (el.dataset.blockId === this.activeBlockId) {\n el.classList.add(\"blx-toc-entry-active\");\n } else {\n el.classList.remove(\"blx-toc-entry-active\");\n }\n }\n }\n\n private handleClick = (e: Event): void => {\n // The fisheye magnification shifts entry positions as the cursor moves,\n // so e.target may not be the entry the user intended. Instead, find\n // the entry whose vertical center is closest to the click Y coordinate.\n const me = e as MouseEvent;\n const cy = me.clientY;\n let bestEl: HTMLElement | null = null;\n let bestDist = Infinity;\n for (const el of this.entryEls) {\n const rect = el.getBoundingClientRect();\n const mid = rect.top + rect.height / 2;\n const dist = Math.abs(cy - mid);\n if (dist < bestDist) {\n bestDist = dist;\n bestEl = el;\n }\n }\n if (!bestEl?.dataset.blockId) return;\n this.setActiveHeading(bestEl.dataset.blockId);\n // Suppress scroll-based tracking while the scroll animation settles\n this.scrollLockUntil = Date.now() + 800;\n this.onNavigate(bestEl.dataset.blockId);\n this.pulseBlock(bestEl.dataset.blockId);\n };\n\n /**\n * Briefly pulse the background of a heading block to confirm navigation.\n */\n private pulseBlock(blockId: string): void {\n const blocksContainer =\n this.editorRoot.querySelector(\".blx-blocks\") as HTMLElement | null;\n if (!blocksContainer) return;\n const blockEl = blocksContainer.querySelector(\n `[data-block-id=\"${blockId}\"]`,\n );\n if (!blockEl) return;\n // Pulse the contentEditable child (the heading element) rather than the\n // full-width block container, so the highlight hugs the text area.\n const target = blockEl.querySelector(\"[contenteditable]\") ?? blockEl;\n target.classList.remove(\"blx-toc-pulse\");\n // Force reflow so re-adding the class restarts the animation\n void (target as HTMLElement).offsetWidth;\n target.classList.add(\"blx-toc-pulse\");\n target.addEventListener(\n \"animationend\",\n () => target.classList.remove(\"blx-toc-pulse\"),\n { once: true },\n );\n }\n\n // ── Hover magnification ─────────────────────────────────────\n\n private handleMouseEnter = (): void => {\n this.isHovered = true;\n this.container.classList.add(\"blx-toc-hovered\");\n this.applyMagnification();\n };\n\n private handleMouseLeave = (): void => {\n this.isHovered = false;\n this.container.classList.remove(\"blx-toc-hovered\");\n this.applyMagnification();\n };\n\n private handleMouseMove = (e: MouseEvent): void => {\n this.lastMouseY = e.clientY;\n\n if (this.moveRaf !== null) return;\n this.moveRaf = requestAnimationFrame(() => {\n this.moveRaf = null;\n this.applyMagnification();\n });\n };\n\n private applyMagnification(): void {\n const n = this.entryEls.length;\n if (n === 0) return;\n\n const my = this.lastMouseY;\n // p = 1 when hovered, 0 when not\n const p = this.isHovered ? 1 : 0;\n const sigma = MAGNIFY_RADIUS * 0.4;\n\n // Track which entry is closest to cursor (for label reveal)\n let bestBrowseIdx = -1;\n let bestBrowseVal = 0;\n\n for (let i = 0; i < n; i++) {\n const el = this.entryEls[i];\n const line = el.querySelector(\".blx-toc-line\") as HTMLElement;\n if (!line) continue;\n\n const entry = this.entries[i];\n const level = entry.level;\n\n // Browse factor: Gaussian bell curve per entry (only when hovered)\n let browse = 0;\n if (this.isHovered) {\n const entryRect = el.getBoundingClientRect();\n const entryCenterY = entryRect.top + entryRect.height / 2;\n const dy = Math.abs(my - entryCenterY);\n browse = Math.exp(-(dy * dy) / (2 * sigma * sigma));\n if (browse > bestBrowseVal) {\n bestBrowseVal = browse;\n bestBrowseIdx = i;\n }\n }\n\n // Sizes: REST → ACTIVE (driven by hover) → BROWSE (driven by gaussian)\n const rw = REST_W[level] ?? 16;\n const aw = ACTIVE_W[level] ?? 24;\n const bw = BROWSE_W[level] ?? 48;\n const w = rw + (aw - rw) * p + (bw - aw) * browse;\n\n const rh = REST_H[level] ?? 2.5;\n const ah = ACTIVE_H[level] ?? 3;\n const bh = BROWSE_H[level] ?? 5;\n const h = rh + (ah - rh) * p + (bh - ah) * browse;\n\n line.style.width = `${w}px`;\n line.style.height = `${h}px`;\n\n // Opacity\n const restOp = level === 1 ? 0.45 : level === 2 ? 0.35 : level === 3 ? 0.25 : 0.18;\n const activeOp = level === 1 ? 0.5 : level === 2 ? 0.4 : level === 3 ? 0.3 : 0.22;\n const browseOp = level === 1 ? 0.9 : level === 2 ? 0.8 : level === 3 ? 0.65 : 0.5;\n const isActive = el.dataset.blockId === this.activeBlockId;\n let opacity = restOp + (activeOp - restOp) * p + (browseOp - activeOp) * browse;\n if (isActive) opacity = Math.max(opacity, activeOp + (1 - activeOp) * p);\n line.style.opacity = String(opacity);\n\n // Gap\n const halfGap =\n REST_HALF_GAP +\n (ACTIVE_HALF_GAP - REST_HALF_GAP) * p +\n (BROWSE_HALF_GAP - ACTIVE_HALF_GAP) * browse;\n el.style.paddingTop = `${halfGap}px`;\n el.style.paddingBottom = `${halfGap}px`;\n }\n\n // Show label only on the entry nearest to cursor (matches click behavior)\n for (let i = 0; i < n; i++) {\n if (i === bestBrowseIdx) {\n this.entryEls[i].classList.add(\"blx-toc-entry-browsed\");\n } else {\n this.entryEls[i].classList.remove(\"blx-toc-entry-browsed\");\n }\n }\n }\n\n // ── Scroll tracking ─────────────────────────────────────────────\n\n /**\n * Set up scroll-based active heading tracking.\n * Find the scroll parent and listen for scroll events.\n */\n private setupScrollTracking(): void {\n // Find the scrollable ancestor\n this.scrollParent = this.findScrollParent(this.editorRoot);\n\n this.scrollHandler = () => {\n if (this.scrollRaf !== null) return;\n this.scrollRaf = requestAnimationFrame(() => {\n this.scrollRaf = null;\n this.computeActiveHeading();\n });\n };\n\n this.scrollParent.addEventListener(\"scroll\", this.scrollHandler, {\n passive: true,\n });\n }\n\n /**\n * Find the nearest scrollable ancestor, or fall back to window.\n */\n private findScrollParent(el: HTMLElement): HTMLElement | Window {\n let current: HTMLElement | null = el.parentElement;\n while (current) {\n const overflow = getComputedStyle(current).overflowY;\n if (overflow === \"auto\" || overflow === \"scroll\") {\n return current;\n }\n current = current.parentElement;\n }\n return window;\n }\n\n /**\n * Determine which heading is currently \"active\" based on scroll position.\n * Skipped briefly after click-navigation so the clicked heading stays active.\n */\n private computeActiveHeading(): void {\n // After click-navigation, suppress scroll tracking so the clicked\n // heading stays active while the scroll animation settles.\n if (Date.now() < this.scrollLockUntil) return;\n\n if (this.entries.length === 0) {\n this.setActiveHeading(null);\n return;\n }\n\n const blocksContainer =\n this.editorRoot.querySelector(\".blx-blocks\") as HTMLElement | null;\n if (!blocksContainer) return;\n\n const sp = this.scrollParent!;\n const isWindow = sp instanceof Window;\n const scrollTop = isWindow ? window.scrollY : (sp as HTMLElement).scrollTop;\n const clientH = isWindow\n ? window.innerHeight\n : (sp as HTMLElement).clientHeight;\n const scrollH = isWindow\n ? document.documentElement.scrollHeight\n : (sp as HTMLElement).scrollHeight;\n const spTop = isWindow\n ? 0\n : (sp as HTMLElement).getBoundingClientRect().top;\n\n // At the very top → pick the first heading\n if (scrollTop <= 2) {\n this.setActiveHeading(this.entries[0].blockId);\n return;\n }\n\n // At the very bottom → pick the last heading\n if (scrollTop + clientH >= scrollH - 2) {\n this.setActiveHeading(this.entries[this.entries.length - 1].blockId);\n return;\n }\n\n // Reference line: 1/4 down the viewport (tighter than 1/3)\n const viewportRef = isWindow\n ? scrollTop + clientH * 0.25\n : scrollTop + spTop + clientH * 0.25;\n\n let activeId: string | null = null;\n\n for (const entry of this.entries) {\n const blockEl = blocksContainer.querySelector(\n `[data-block-id=\"${entry.blockId}\"]`,\n ) as HTMLElement | null;\n if (!blockEl) continue;\n\n const rect = blockEl.getBoundingClientRect();\n const absoluteTop = isWindow\n ? rect.top + scrollTop\n : rect.top + scrollTop - spTop;\n\n if (absoluteTop <= viewportRef) {\n activeId = entry.blockId;\n }\n }\n\n if (activeId === null && this.entries.length > 0) {\n activeId = this.entries[0].blockId;\n }\n\n this.setActiveHeading(activeId);\n }\n}\n","import type { Block } from \"../types\";\n\nexport interface FoldState {\n foldedIds: string[];\n}\n\nexport interface FoldCallbacks {\n onFoldChanged?: (state: FoldState) => void;\n}\n\nexport class FoldManager {\n private foldedHeadingIds = new Set<string>();\n private hiddenBlockIds = new Set<string>();\n private callbacks: FoldCallbacks = {};\n\n setCallbacks(cb: FoldCallbacks): void {\n this.callbacks = cb;\n }\n\n loadState(state: FoldState | null): void {\n this.foldedHeadingIds.clear();\n if (state) {\n for (const id of state.foldedIds) this.foldedHeadingIds.add(id);\n }\n }\n\n getState(): FoldState {\n return { foldedIds: [...this.foldedHeadingIds] };\n }\n\n toggle(headingBlockId: string, allBlocks: ReadonlyArray<Block>): Set<string> {\n if (this.foldedHeadingIds.has(headingBlockId)) {\n this.foldedHeadingIds.delete(headingBlockId);\n } else {\n this.foldedHeadingIds.add(headingBlockId);\n }\n return this.recompute(allBlocks);\n }\n\n fold(headingBlockId: string, allBlocks: ReadonlyArray<Block>): Set<string> {\n if (this.foldedHeadingIds.has(headingBlockId)) return this.hiddenBlockIds;\n this.foldedHeadingIds.add(headingBlockId);\n return this.recompute(allBlocks);\n }\n\n unfold(headingBlockId: string, allBlocks: ReadonlyArray<Block>): Set<string> {\n if (!this.foldedHeadingIds.has(headingBlockId)) return this.hiddenBlockIds;\n this.foldedHeadingIds.delete(headingBlockId);\n return this.recompute(allBlocks);\n }\n\n foldAll(allBlocks: ReadonlyArray<Block>): Set<string> {\n for (const block of allBlocks) {\n if (block.type === \"heading\") this.foldedHeadingIds.add(block.id);\n }\n return this.recompute(allBlocks);\n }\n\n unfoldAll(allBlocks: ReadonlyArray<Block>): Set<string> {\n this.foldedHeadingIds.clear();\n return this.recompute(allBlocks);\n }\n\n isFolded(headingBlockId: string): boolean {\n return this.foldedHeadingIds.has(headingBlockId);\n }\n\n isHidden(blockId: string): boolean {\n return this.hiddenBlockIds.has(blockId);\n }\n\n recompute(allBlocks: ReadonlyArray<Block>): Set<string> {\n this.hiddenBlockIds = computeHiddenBlocks(this.foldedHeadingIds, allBlocks);\n for (const id of this.foldedHeadingIds) {\n if (!allBlocks.some((b) => b.id === id && b.type === \"heading\")) {\n this.foldedHeadingIds.delete(id);\n }\n }\n this.callbacks.onFoldChanged?.(this.getState());\n return this.hiddenBlockIds;\n }\n\n getHiddenBlockIds(): ReadonlySet<string> {\n return this.hiddenBlockIds;\n }\n\n findOwningHeading(\n blockId: string,\n allBlocks: ReadonlyArray<Block>,\n ): string | null {\n const idx = allBlocks.findIndex((b) => b.id === blockId);\n if (idx < 0) return null;\n if (allBlocks[idx].type === \"heading\") return blockId;\n for (let i = idx - 1; i >= 0; i--) {\n if (allBlocks[i].type === \"heading\") return allBlocks[i].id;\n }\n return null;\n }\n}\n\nexport function getHeadingScope(\n headingBlock: Block,\n allBlocks: ReadonlyArray<Block>,\n): string[] {\n const idx = allBlocks.findIndex((b) => b.id === headingBlock.id);\n if (idx < 0) return [];\n const level = (headingBlock.metadata?.level as number) ?? 1;\n const scope: string[] = [];\n for (let i = idx + 1; i < allBlocks.length; i++) {\n const block = allBlocks[i];\n if (block.type === \"heading\") {\n const blockLevel = (block.metadata?.level as number) ?? 1;\n if (blockLevel <= level) break;\n }\n scope.push(block.id);\n }\n return scope;\n}\n\nexport function computeHiddenBlocks(\n foldedHeadingIds: Set<string>,\n allBlocks: ReadonlyArray<Block>,\n): Set<string> {\n const hidden = new Set<string>();\n for (const block of allBlocks) {\n if (block.type !== \"heading\") continue;\n if (!foldedHeadingIds.has(block.id)) continue;\n if (hidden.has(block.id)) continue;\n const scope = getHeadingScope(block, allBlocks);\n for (const id of scope) hidden.add(id);\n }\n return hidden;\n}\n","export interface CommandEntry {\n description: string;\n handler: (args?: string) => void;\n}\n\nexport interface ExternalCommandEntry {\n id: string;\n label: string;\n description: string;\n execute: (args?: string) => void;\n}\n\nexport class CommandRegistry {\n private commands = new Map<string, CommandEntry>();\n\n register(name: string, entry: CommandEntry): void {\n this.commands.set(name, entry);\n }\n\n unregister(name: string): void {\n this.commands.delete(name);\n }\n\n execute(name: string, args?: string): void {\n const entry = this.commands.get(name);\n if (entry) entry.handler(args);\n }\n\n list(): Array<{ name: string; description: string }> {\n return Array.from(this.commands.entries()).map(([name, entry]) => ({\n name,\n description: entry.description,\n }));\n }\n\n has(name: string): boolean {\n return this.commands.has(name);\n }\n\n filter(prefix: string): Array<{ name: string; description: string }> {\n return this.list().filter((cmd) => cmd.name.startsWith(prefix));\n }\n\n listFull(): ExternalCommandEntry[] {\n return Array.from(this.commands.entries()).map(([name, entry]) => ({\n id: `editor:${name}`,\n label: name.charAt(0).toUpperCase() + name.slice(1),\n description: entry.description,\n execute: (args?: string) => entry.handler(args),\n }));\n }\n}\n","/**\n * Manages scroll-aware positioning for all floating UI elements.\n *\n * Each floating UI registers when it opens and unregisters when it\n * closes. A single capture-phase scroll listener handles repositioning,\n * hiding when the anchor scrolls off-screen, and re-showing when it\n * scrolls back.\n */\n\n/**\n * Registration record for a floating element managed by {@link FloatingScrollManager}.\n *\n * Register when the floating element becomes visible; unregister when it hides.\n */\nexport interface FloatingRegistration {\n /** Unique key (e.g. \"inline-toolbar\", \"slash-menu\") */\n key: string;\n /** Element whose viewport visibility determines show/hide */\n anchorEl: HTMLElement;\n /** Called on scroll when anchor is in viewport — receives fresh anchor rect */\n onReposition: (anchorRect: DOMRect) => void;\n /** Called when anchor scrolls out of viewport */\n onScrollOut: () => void;\n /** Called when anchor scrolls back into viewport */\n onScrollIn: () => void;\n}\n\ninterface RegistrationState {\n reg: FloatingRegistration;\n wasVisible: boolean;\n}\n\nexport class FloatingScrollManager {\n private registrations = new Map<string, RegistrationState>();\n private scrollHandler: (() => void) | null = null;\n\n /**\n * Register a floating element for scroll-aware management.\n * The element's visibility state is captured immediately; callbacks will fire\n * on subsequent scroll events.\n * @param reg - The registration record describing the floating element and its callbacks.\n */\n register(reg: FloatingRegistration): void {\n const wasVisible = isInViewport(reg.anchorEl);\n this.registrations.set(reg.key, { reg, wasVisible });\n this.ensureScrollListener();\n }\n\n /**\n * Unregister a floating element by key.\n * Removes the global scroll listener when no registrations remain.\n * @param key - The key used when calling {@link register}.\n */\n unregister(key: string): void {\n this.registrations.delete(key);\n if (this.registrations.size === 0) {\n this.removeScrollListener();\n }\n }\n\n /**\n * Unregister all floating elements and remove the scroll listener.\n * Call when the editor or owning component is destroyed.\n */\n destroy(): void {\n this.registrations.clear();\n this.removeScrollListener();\n }\n\n private ensureScrollListener(): void {\n if (this.scrollHandler) return;\n this.scrollHandler = () => this.handleScroll();\n window.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n private removeScrollListener(): void {\n if (!this.scrollHandler) return;\n window.removeEventListener(\"scroll\", this.scrollHandler, true);\n this.scrollHandler = null;\n }\n\n private handleScroll(): void {\n // Iterate a snapshot so callbacks can safely unregister during iteration\n for (const state of Array.from(this.registrations.values())) {\n const { reg } = state;\n const rect = reg.anchorEl.getBoundingClientRect();\n const visible = rect.bottom > 0 && rect.top < window.innerHeight;\n\n if (visible) {\n if (state.wasVisible) {\n reg.onReposition(rect);\n } else {\n state.wasVisible = true;\n reg.onScrollIn();\n }\n } else {\n if (state.wasVisible) {\n state.wasVisible = false;\n reg.onScrollOut();\n }\n }\n }\n }\n}\n\nfunction isInViewport(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect();\n return rect.bottom > 0 && rect.top < window.innerHeight;\n}\n","/**\n * Right-click context menu for blocks.\n *\n * Shows clipboard actions (Copy, Cut, Paste) and extensible action items\n * when the user right-clicks on a block. Reuses the shared ContextMenu\n * component for rendering and keyboard navigation.\n */\n\nimport { ContextMenu, type MenuItem } from \"../ui/context-menu\";\nimport { dismissOnClickOutside, type DismissHandle } from \"../ui/dismiss\";\n\nexport interface BlockContextMenuEntry {\n key: string;\n label: string;\n icon?: string | ((container: HTMLElement) => void);\n danger?: boolean;\n section?: string;\n disabled?: boolean;\n onAction: (blockIds: string[]) => void;\n}\n\nexport class BlockContextMenu {\n private editorRoot: HTMLElement;\n private menu: ContextMenu;\n private getMenuItems: (blockIds: string[]) => BlockContextMenuEntry[];\n private resolveTargetBlockIds: (e: MouseEvent) => string[];\n\n private menuOpen = false;\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private dismissHandle: DismissHandle | null = null;\n private scrollHandler: (() => void) | null = null;\n private currentBlockIds: string[] = [];\n\n constructor(\n editorRoot: HTMLElement,\n resolveTargetBlockIds: (e: MouseEvent) => string[],\n getMenuItems: (blockIds: string[]) => BlockContextMenuEntry[],\n ) {\n this.editorRoot = editorRoot;\n this.resolveTargetBlockIds = resolveTargetBlockIds;\n this.getMenuItems = getMenuItems;\n\n this.menu = new ContextMenu({ className: \"blx-context-menu\" });\n this.menu.onSelect = (mi: MenuItem) => {\n const entry = mi.data as BlockContextMenuEntry;\n const blockIds = this.currentBlockIds;\n this.close();\n entry.onAction(blockIds);\n };\n this.menu.onClose = () => this.close();\n\n this.editorRoot.addEventListener(\"contextmenu\", this.handleContextMenu);\n }\n\n get isOpen(): boolean {\n return this.menuOpen;\n }\n\n close(): void {\n this.menu.hide();\n this.menu.el.remove();\n this.menuOpen = false;\n this.currentBlockIds = [];\n\n if (this.scrollHandler) {\n window.removeEventListener(\"scroll\", this.scrollHandler, true);\n this.scrollHandler = null;\n }\n if (this.keyHandler) {\n document.removeEventListener(\"keydown\", this.keyHandler, true);\n this.keyHandler = null;\n }\n this.dismissHandle?.remove();\n this.dismissHandle = null;\n }\n\n destroy(): void {\n this.close();\n this.editorRoot.removeEventListener(\"contextmenu\", this.handleContextMenu);\n this.menu.destroy();\n }\n\n private handleContextMenu = (e: MouseEvent): void => {\n // Resolve target blocks from the click position\n const blockIds = this.resolveTargetBlockIds(e);\n if (blockIds.length === 0) return;\n\n e.preventDefault();\n\n // Close any existing menu first\n if (this.menuOpen) {\n this.close();\n }\n\n this.currentBlockIds = blockIds;\n const entries = this.getMenuItems(blockIds);\n if (entries.length === 0) return;\n\n const menuItems = this.toMenuItems(entries);\n\n // Append menu to editor root for CSS variable inheritance\n this.editorRoot.appendChild(this.menu.el);\n\n // Create a synthetic anchor rect at the click position\n const anchorRect = new DOMRect(e.clientX, e.clientY, 0, 0);\n this.menu.show(anchorRect, menuItems);\n this.menuOpen = true;\n\n // Close on scroll\n this.scrollHandler = () => this.close();\n window.addEventListener(\"scroll\", this.scrollHandler, true);\n\n // Keyboard handler (capture phase)\n this.keyHandler = (ev: KeyboardEvent) => {\n if (!this.menuOpen) return;\n const consumed = this.menu.handleKeyDown(ev);\n if (consumed) {\n ev.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", this.keyHandler, true);\n\n // Close on outside click/touch.\n // Use defer: false because `contextmenu` fires *after* `mousedown`,\n // so the triggering mousedown has already fully dispatched and won't\n // cause an immediate false dismiss. Deferring via setTimeout(0) can\n // race with early close() calls (e.g. scroll-triggered) and leave\n // the mousedown listener uninstalled.\n this.dismissHandle = dismissOnClickOutside(\n this.menu.el,\n () => this.close(),\n { defer: false },\n );\n };\n\n private toMenuItems(entries: BlockContextMenuEntry[]): MenuItem[] {\n return entries.map((entry) => ({\n id: entry.key,\n label: entry.label,\n icon: entry.icon,\n danger: entry.danger,\n section: entry.section,\n disabled: entry.disabled ?? false,\n data: entry,\n }));\n }\n}\n","const ACTIVE_RESET_MS = 600;\n\nexport class CustomCaret {\n private _el: HTMLDivElement;\n private _container: HTMLElement;\n private _x: number | null = null;\n private _y: number | null = null;\n private _currentBlock: Element | null = null;\n private _suppressNextSnap = false;\n private _instantNextMove = false;\n private _enabled = true;\n private _activeTimer: ReturnType<typeof setTimeout> | null = null;\n private _trailCleanup: (() => void) | null = null;\n private _destroyed = false;\n private _bound_onSelectionChange: () => void;\n private _bound_onKeyDown: (e: KeyboardEvent) => void;\n private _bound_onScroll: () => void;\n private _bound_onResize: () => void;\n private _resizeObserver: ResizeObserver;\n\n constructor(container: HTMLElement) {\n this._container = container;\n\n this._el = document.createElement(\"div\");\n this._el.className = \"blx-caret blx-caret--hidden\";\n this._el.style.height = \"1.15em\";\n container.appendChild(this._el);\n\n this._bound_onSelectionChange = this._onSelectionChange.bind(this);\n this._bound_onKeyDown = this._onKeyDown.bind(this);\n this._bound_onScroll = this._onScroll.bind(this);\n this._bound_onResize = this._onResize.bind(this);\n\n document.addEventListener(\"selectionchange\", this._bound_onSelectionChange);\n document.addEventListener(\"keydown\", this._bound_onKeyDown, true);\n document.addEventListener(\"scroll\", this._bound_onScroll, true);\n window.addEventListener(\"resize\", this._bound_onResize);\n\n this._resizeObserver = new ResizeObserver(this._bound_onResize);\n this._resizeObserver.observe(container);\n }\n\n hide(): void {\n this._el.classList.add(\"blx-caret--hidden\");\n }\n\n setEnabled(enabled: boolean): void {\n this._enabled = enabled;\n if (!enabled) {\n this._cancelTrail();\n this.hide();\n } else {\n this._update();\n }\n }\n\n destroy(): void {\n this._destroyed = true;\n document.removeEventListener(\"selectionchange\", this._bound_onSelectionChange);\n document.removeEventListener(\"keydown\", this._bound_onKeyDown, true);\n document.removeEventListener(\"scroll\", this._bound_onScroll, true);\n window.removeEventListener(\"resize\", this._bound_onResize);\n this._resizeObserver.disconnect();\n if (this._activeTimer !== null) {\n clearTimeout(this._activeTimer);\n this._activeTimer = null;\n }\n this._cancelTrail();\n this._el.remove();\n }\n\n private _onSelectionChange(): void {\n this._update();\n }\n\n private _onKeyDown(e: KeyboardEvent): void {\n if (e.key === \"ArrowUp\" || e.key === \"ArrowDown\") {\n this._suppressNextSnap = true;\n }\n this._el.classList.add(\"blx-caret--active\");\n if (this._activeTimer !== null) clearTimeout(this._activeTimer);\n this._activeTimer = setTimeout(() => {\n this._el.classList.remove(\"blx-caret--active\");\n this._activeTimer = null;\n }, ACTIVE_RESET_MS);\n }\n\n private _onScroll(): void {\n this._instantNextMove = true;\n this._update();\n }\n\n private _onResize(): void {\n this._instantNextMove = true;\n this._update();\n }\n\n private _update(): void {\n if (!this._enabled) return;\n\n this._cancelTrail();\n\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n this.hide();\n return;\n }\n\n if (!sel.isCollapsed) {\n this.hide();\n return;\n }\n\n const range = sel.getRangeAt(0);\n if (!this._container.contains(range.startContainer)) {\n this.hide();\n return;\n }\n\n // Only show caret inside contenteditable regions\n const anchorNode = range.startContainer instanceof Element\n ? range.startContainer\n : range.startContainer.parentElement;\n if (!anchorNode?.closest(\"[contenteditable='true']\")) {\n this.hide();\n return;\n }\n\n if (typeof range.getBoundingClientRect !== \"function\") {\n this.hide();\n return;\n }\n const rect = range.getBoundingClientRect();\n\n let newX: number;\n let newY: number;\n let newH: number;\n\n if (rect.height === 0) {\n const node = range.startContainer instanceof Element\n ? range.startContainer\n : range.startContainer.parentElement;\n const editable = node?.closest(\"[contenteditable]\") as HTMLElement | null;\n if (!editable) { this.hide(); return; }\n const elRect = editable.getBoundingClientRect();\n if (elRect.height === 0) { this.hide(); return; }\n const style = getComputedStyle(editable);\n const lh = parseFloat(style.lineHeight);\n newH = isNaN(lh) ? parseFloat(style.fontSize) * 1.2 : lh;\n const paddingLeft = parseFloat(style.paddingLeft) || 0;\n const paddingTop = parseFloat(style.paddingTop) || 0;\n\n // For pre-formatted elements (code/mermaid), getBoundingClientRect()\n // returns all zeros at \\n boundaries. Compute position from the text:\n // count \\n chars before cursor to get line number, then use line-height.\n const ws = style.whiteSpace;\n if (ws === \"pre\" || ws === \"pre-wrap\") {\n let lineNumber: number;\n if (range.startContainer.nodeType === Node.TEXT_NODE) {\n // Cursor inside a text node — count \\n before the offset\n const text = range.startContainer.textContent ?? \"\";\n const textBefore = text.slice(0, range.startOffset);\n lineNumber = (textBefore.match(/\\n/g) || []).length;\n } else {\n // Cursor after <br> on the last empty line — count all \\n in content\n const fullText = editable.textContent ?? \"\";\n lineNumber = (fullText.match(/\\n/g) || []).length;\n }\n newX = elRect.left + paddingLeft;\n newY = elRect.top + paddingTop + lineNumber * newH;\n } else {\n // Truly empty block — fall back to element rect top-left.\n newX = elRect.left + paddingLeft;\n newY = elRect.top + paddingTop;\n }\n } else {\n newX = rect.left;\n newY = rect.top;\n newH = rect.height;\n }\n\n const newBlock = (range.startContainer instanceof Element\n ? range.startContainer\n : range.startContainer.parentElement\n )?.closest(\".blx-block\") ?? null;\n\n const crossedBlock = this._currentBlock !== null && newBlock !== this._currentBlock;\n this._currentBlock = newBlock;\n\n const suppress = this._suppressNextSnap;\n this._suppressNextSnap = false;\n\n // First placement, within same block, or arrow-key navigation: smooth move\n if (this._x === null || this._y === null || !crossedBlock || suppress) {\n this._moveTo(newX, newY, newH);\n return;\n }\n\n this._animateSnap(newX, newY, newH);\n }\n\n private _moveTo(x: number, y: number, h: number): void {\n this._x = x;\n this._y = y;\n\n // Hide if caret is scrolled behind editor chrome (breadcrumb, etc.)\n const containerRect = this._container.getBoundingClientRect();\n if (y < containerRect.top || y + h > containerRect.bottom) {\n this.hide();\n return;\n }\n\n if (this._instantNextMove) {\n this._instantNextMove = false;\n this._el.classList.add(\"blx-caret--no-transition\");\n this._el.style.left = `${x}px`;\n this._el.style.top = `${y}px`;\n this._el.style.height = `${h}px`;\n this._el.classList.remove(\"blx-caret--hidden\");\n void this._el.offsetWidth; // force reflow before removing class\n this._el.classList.remove(\"blx-caret--no-transition\");\n } else {\n this._el.style.left = `${x}px`;\n this._el.style.top = `${y}px`;\n this._el.style.height = `${h}px`;\n this._el.classList.remove(\"blx-caret--hidden\");\n }\n }\n\n private _cancelTrail(): void {\n if (this._trailCleanup) {\n this._trailCleanup();\n this._trailCleanup = null;\n }\n }\n\n private _animateSnap(x: number, y: number, h: number): void {\n const oldX = this._x!;\n const oldY = this._y!;\n\n this._x = x;\n this._y = y;\n\n const dx = oldX - x;\n const dy = oldY - y;\n\n // Place at destination, translated back to old position\n this._el.classList.add(\"blx-caret--no-transition\");\n this._el.classList.remove(\"blx-caret--trailing\", \"blx-caret--active\");\n this._el.style.left = `${x}px`;\n this._el.style.top = `${y}px`;\n this._el.style.height = `${h}px`;\n const distance = Math.hypot(dx, dy);\n const stretch = Math.min(1 + distance / (h * 2), 8);\n\n // Stretch toward old position; fade the tail with a gradient mask\n const movingDown = dy < 0;\n const origin = movingDown ? \"bottom center\" : \"top center\";\n const mask = movingDown\n ? \"linear-gradient(to bottom, transparent, black 40%)\"\n : \"linear-gradient(to top, transparent, black 40%)\";\n\n this._el.style.transformOrigin = origin;\n this._el.style.transform = `translate(${dx}px, ${dy}px) scaleY(${stretch})`;\n this._el.style.opacity = \"0.5\";\n this._el.style.maskImage = mask;\n (this._el.style as any).webkitMaskImage = mask;\n this._el.classList.remove(\"blx-caret--hidden\");\n void this._el.offsetWidth;\n\n // Animate slide to destination + contract + unmask\n this._el.classList.remove(\"blx-caret--no-transition\");\n this._el.classList.add(\"blx-caret--trailing\");\n this._el.style.transform = \"scaleY(1)\";\n this._el.style.opacity = \"\";\n this._el.style.maskImage = \"\";\n (this._el.style as any).webkitMaskImage = \"\";\n\n const cleanup = () => {\n this._el.classList.remove(\"blx-caret--trailing\");\n this._el.style.transform = \"\";\n this._el.style.transformOrigin = \"\";\n this._el.style.opacity = \"\";\n this._el.style.maskImage = \"\";\n (this._el.style as any).webkitMaskImage = \"\";\n this._trailCleanup = null;\n };\n this._el.addEventListener(\"transitionend\", cleanup, { once: true });\n const fallback = setTimeout(cleanup, 300);\n this._trailCleanup = () => {\n clearTimeout(fallback);\n this._el.removeEventListener(\"transitionend\", cleanup);\n cleanup();\n };\n }\n}\n","/**\n * Clipboard manager: handles copy/cut/paste of blocks.\n *\n * Uses the Clipboard API to write both a custom MIME type\n * (`application/x-blx-blocks+json`) for lossless block round-trips\n * and `text/plain` (Markdown) for interop with other apps.\n *\n * Since the Clipboard API only supports `text/plain` and `text/html`,\n * we embed the JSON payload inside an HTML comment in the `text/html`\n * slot so both rich paste (back into BLX) and plain paste (into other\n * apps) work seamlessly.\n */\n\nimport type { Block, BlockJSON } from \"../types\";\nimport { blockToJSON } from \"../types\";\nimport { blocksToMarkdown } from \"../markdown\";\n\n/** MIME marker used to detect BLX block data inside HTML clipboard content */\nconst BLX_MARKER_START = \"<!--blx-blocks:\";\nconst BLX_MARKER_END = \":blx-blocks-->\";\n\n/**\n * Copy an array of blocks to the system clipboard.\n * Writes both `text/plain` (Markdown) and `text/html` (with embedded JSON).\n */\nexport async function copyBlocksToClipboard(blocks: ReadonlyArray<Block>): Promise<void> {\n const jsonBlocks = blocks.map((b) => blockToJSON(b));\n const markdown = blocksToMarkdown(jsonBlocks);\n const jsonPayload = JSON.stringify(jsonBlocks);\n const html = `${BLX_MARKER_START}${jsonPayload}${BLX_MARKER_END}`;\n\n try {\n const items = [\n new ClipboardItem({\n \"text/plain\": new Blob([markdown], { type: \"text/plain\" }),\n \"text/html\": new Blob([html], { type: \"text/html\" }),\n }),\n ];\n await navigator.clipboard.write(items);\n } catch {\n // Fallback: legacy execCommand approach (plain text only)\n try {\n const textarea = document.createElement(\"textarea\");\n textarea.value = markdown;\n textarea.style.position = \"fixed\";\n textarea.style.opacity = \"0\";\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(textarea);\n } catch {\n // execCommand not available (e.g. test environment)\n }\n }\n}\n\n/**\n * Read BLX block data from the clipboard.\n * Returns the array of BlockJSON if found, or null if the clipboard\n * contains no BLX data.\n */\nexport async function readBlocksFromClipboard(): Promise<BlockJSON[] | null> {\n try {\n const items = await navigator.clipboard.read();\n for (const item of items) {\n if (item.types.includes(\"text/html\")) {\n const blob = await item.getType(\"text/html\");\n const html = await blob.text();\n const blocks = extractBlocksFromHtml(html);\n if (blocks) return blocks;\n }\n }\n } catch {\n // Clipboard API not available or permission denied\n }\n return null;\n}\n\n/**\n * Extract BLX block JSON from an HTML string (e.g. from ClipboardEvent.clipboardData).\n */\nexport function extractBlocksFromHtml(html: string): BlockJSON[] | null {\n const startIdx = html.indexOf(BLX_MARKER_START);\n if (startIdx === -1) return null;\n\n const payloadStart = startIdx + BLX_MARKER_START.length;\n const endIdx = html.indexOf(BLX_MARKER_END, payloadStart);\n if (endIdx === -1) return null;\n\n try {\n const json = html.slice(payloadStart, endIdx);\n const parsed = JSON.parse(json);\n if (Array.isArray(parsed)) return parsed as BlockJSON[];\n } catch {\n // Malformed JSON — ignore\n }\n return null;\n}\n","/**\n * Parse external paste content (HTML or plain text) into BlockJSON arrays.\n *\n * When pasting from external apps (browsers, Google Docs, VS Code, etc.),\n * the clipboard may contain HTML structure or multi-paragraph plain text.\n * This module converts that content into BLX blocks so the editor can\n * create proper multi-block structure instead of dumping everything into\n * a single block.\n */\n\nimport type { BlockJSON } from \"../types\";\nimport type { Attributes, Span } from \"../attributed-string\";\nimport { generateId } from \"../util/id\";\n\n// ── HTML → Blocks ────────────────────────────────────────────────\n\n/**\n * Parse an HTML string from the clipboard into an array of BlockJSON.\n * Returns null if the HTML doesn't contain meaningful block structure\n * (i.e., it's just a single text fragment with no block-level elements).\n */\nexport function htmlToBlocks(html: string): BlockJSON[] | null {\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, \"text/html\");\n const body = doc.body;\n if (!body || !body.hasChildNodes()) return null;\n\n const blocks: BlockJSON[] = [];\n collectBlocks(body, blocks);\n\n // Only return multi-block results — if it's just one paragraph,\n // let the default single-block paste handle it so the text merges\n // into the current block instead of creating a new one.\n if (blocks.length <= 1) return null;\n\n return blocks;\n}\n\n/** Walk DOM nodes and collect block-level elements into BlockJSON entries */\nfunction collectBlocks(parent: Node, blocks: BlockJSON[]): void {\n for (const node of parent.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent?.trim();\n if (text) {\n blocks.push(makeParagraph(text));\n }\n continue;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n const el = node as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n // Headings\n if (/^h[1-6]$/.test(tag)) {\n const level = parseInt(tag[1], 10);\n const spans = inlineToSpans(el);\n if (spans.length > 0) {\n blocks.push({\n id: generateId(),\n type: \"heading\",\n content: { spans },\n metadata: { level: Math.min(level, 4) },\n });\n }\n continue;\n }\n\n // Paragraphs and divs (treated as paragraphs)\n if (tag === \"p\" || tag === \"div\") {\n const spans = inlineToSpans(el);\n if (spans.length > 0) {\n blocks.push({\n id: generateId(),\n type: \"paragraph\",\n content: { spans },\n metadata: {},\n });\n }\n continue;\n }\n\n // Lists (ordered and unordered)\n if (tag === \"ul\" || tag === \"ol\") {\n const ordered = tag === \"ol\";\n for (const li of el.querySelectorAll(\":scope > li\")) {\n const spans = inlineToSpans(li as HTMLElement);\n if (spans.length > 0) {\n blocks.push({\n id: generateId(),\n type: \"list\",\n content: { spans },\n metadata: { ordered },\n });\n }\n }\n continue;\n }\n\n // Preformatted / code blocks\n if (tag === \"pre\") {\n const codeEl = el.querySelector(\"code\");\n const text = (codeEl ?? el).textContent ?? \"\";\n if (text.trim()) {\n // Try to detect language from class (e.g. \"language-js\", \"hljs javascript\")\n const langClass = codeEl?.className ?? \"\";\n const langMatch = langClass.match(/(?:language-|lang-)(\\w+)/);\n blocks.push({\n id: generateId(),\n type: \"code\",\n content: { spans: [{ text, attributes: {} }] },\n metadata: { language: langMatch?.[1] ?? \"\" },\n });\n }\n continue;\n }\n\n // Horizontal rules\n if (tag === \"hr\") {\n blocks.push({\n id: generateId(),\n type: \"horizontal-rule\",\n content: { spans: [] },\n metadata: {},\n });\n continue;\n }\n\n // Blockquotes\n if (tag === \"blockquote\") {\n collectBlockquote(el, blocks, 0);\n continue;\n }\n\n // Tables, figures, etc. — skip for now, could be extended later\n\n // Unknown block-level element — recurse into children\n if (isBlockElement(tag)) {\n collectBlocks(el, blocks);\n continue;\n }\n\n // Inline-level element that's a direct child of body — treat as paragraph\n const spans = inlineToSpans(el);\n if (spans.length > 0) {\n blocks.push({\n id: generateId(),\n type: \"paragraph\",\n content: { spans },\n metadata: {},\n });\n }\n }\n}\n\n/** Walk a <blockquote> element, tracking nesting depth */\nfunction collectBlockquote(el: HTMLElement, blocks: BlockJSON[], depth: number): void {\n for (const child of el.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent?.trim();\n if (text) {\n blocks.push({\n id: generateId(),\n type: \"blockquote\",\n content: { spans: [{ text, attributes: {} }] },\n metadata: depth > 0 ? { indentLevel: depth } : {},\n });\n }\n continue;\n }\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const childEl = child as HTMLElement;\n const childTag = childEl.tagName.toLowerCase();\n\n if (childTag === \"blockquote\") {\n collectBlockquote(childEl, blocks, depth + 1);\n } else {\n const spans = inlineToSpans(childEl);\n if (spans.length > 0) {\n blocks.push({\n id: generateId(),\n type: \"blockquote\",\n content: { spans },\n metadata: depth > 0 ? { indentLevel: depth } : {},\n });\n }\n }\n }\n}\n\n/** Convert an element's inline content to attributed string spans */\nfunction inlineToSpans(el: HTMLElement): Span[] {\n const spans: Span[] = [];\n walkInline(el, {}, spans);\n // Merge adjacent spans with identical attributes\n return mergeSpans(spans);\n}\n\n/** Recursively walk inline nodes, accumulating formatting attributes */\nfunction walkInline(\n node: Node,\n inheritedAttrs: Attributes,\n spans: Span[],\n): void {\n for (const child of node.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent ?? \"\";\n if (text) {\n spans.push({ text, attributes: { ...inheritedAttrs } });\n }\n continue;\n }\n\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n // Build attributes based on inline formatting tags\n const attrs = { ...inheritedAttrs };\n\n if (tag === \"b\" || tag === \"strong\") attrs.bold = true;\n if (tag === \"i\" || tag === \"em\") attrs.italic = true;\n if (tag === \"u\") attrs.underline = true;\n if (tag === \"s\" || tag === \"del\" || tag === \"strike\") attrs.strikethrough = true;\n if (tag === \"code\") attrs.code = true;\n if (tag === \"a\") {\n const href = el.getAttribute(\"href\");\n if (href) attrs.href = href;\n }\n\n // Handle line breaks\n if (tag === \"br\") {\n spans.push({ text: \"\\n\", attributes: { ...inheritedAttrs } });\n continue;\n }\n\n walkInline(el, attrs, spans);\n }\n}\n\n/** Merge adjacent spans with identical attributes */\nfunction mergeSpans(spans: Span[]): Span[] {\n if (spans.length === 0) return [];\n\n const merged: Span[] = [{ ...spans[0], attributes: { ...spans[0].attributes } }];\n for (let i = 1; i < spans.length; i++) {\n const prev = merged[merged.length - 1];\n const curr = spans[i];\n if (attrsEqual(prev.attributes, curr.attributes)) {\n merged[merged.length - 1] = {\n text: prev.text + curr.text,\n attributes: prev.attributes,\n };\n } else {\n merged.push({ ...curr, attributes: { ...curr.attributes } });\n }\n }\n return merged;\n}\n\nfunction attrsEqual(a: Attributes, b: Attributes): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n return keysA.every((k) => a[k] === b[k]);\n}\n\nfunction isBlockElement(tag: string): boolean {\n return [\n \"address\", \"article\", \"aside\", \"details\", \"dialog\",\n \"fieldset\", \"figcaption\", \"figure\", \"footer\", \"form\",\n \"header\", \"hgroup\", \"main\", \"nav\", \"section\",\n \"summary\", \"table\", \"thead\", \"tbody\", \"tfoot\", \"tr\",\n ].includes(tag);\n}\n\n// ── Markdown → Blocks ─────────────────────────────────────────────\n\n/**\n * Parse a Markdown string into an array of BlockJSON.\n * Handles headings, lists, checklists, code fences, horizontal rules,\n * and inline formatting (**bold**, *italic*, `code`, ~~strikethrough~~, [links](url)).\n * Returns null if the text doesn't look like Markdown (no Markdown-specific\n * syntax found) so the caller can fall back to plain text splitting.\n */\nexport function markdownToBlocks(text: string): BlockJSON[] | null {\n const lines = text.split(\"\\n\");\n const blocks: BlockJSON[] = [];\n let i = 0;\n let foundMarkdown = false;\n\n while (i < lines.length) {\n const line = lines[i];\n\n // Skip blank lines (paragraph separators)\n if (line.trim() === \"\") {\n i++;\n continue;\n }\n\n // Fenced code block: ```lang ... ``` (may be indented, e.g. under a list item)\n const codeFenceMatch = /^(\\s*)(`{3,})(\\w*)\\s*$/.exec(line);\n if (codeFenceMatch) {\n foundMarkdown = true;\n const indent = codeFenceMatch[1];\n const fence = codeFenceMatch[2];\n const language = codeFenceMatch[3] || \"\";\n const codeLines: string[] = [];\n i++;\n while (i < lines.length) {\n if (lines[i].trim() === fence) {\n i++;\n break;\n }\n // Strip the same indentation prefix from code content lines\n const codeLine = indent && lines[i].startsWith(indent)\n ? lines[i].slice(indent.length)\n : lines[i];\n codeLines.push(codeLine);\n i++;\n }\n blocks.push({\n id: generateId(),\n type: \"code\",\n content: { spans: [{ text: codeLines.join(\"\\n\"), attributes: {} }] },\n metadata: { language },\n });\n continue;\n }\n\n // Horizontal rule: ---, ***, ___\n if (/^([-*_])\\1{2,}\\s*$/.test(line)) {\n foundMarkdown = true;\n blocks.push({\n id: generateId(),\n type: \"horizontal-rule\",\n content: { spans: [] },\n metadata: {},\n });\n i++;\n continue;\n }\n\n // Heading: # to ####\n const headingMatch = /^(#{1,4})\\s+(.+)/.exec(line);\n if (headingMatch) {\n foundMarkdown = true;\n const level = headingMatch[1].length;\n const spans = parseInlineMarkdown(headingMatch[2]);\n blocks.push({\n id: generateId(),\n type: \"heading\",\n content: { spans },\n metadata: { level },\n });\n i++;\n continue;\n }\n\n // Task list: - [ ] or - [x]\n const taskMatch = /^[-*+]\\s+\\[([ xX])\\]\\s+(.*)/.exec(line);\n if (taskMatch) {\n foundMarkdown = true;\n const checked = taskMatch[1].toLowerCase() === \"x\";\n const spans = parseInlineMarkdown(taskMatch[2]);\n blocks.push({\n id: generateId(),\n type: \"checklist\",\n content: { spans },\n metadata: { checked },\n });\n i++;\n continue;\n }\n\n // Unordered list: - , * , +\n const ulMatch = /^[-*+]\\s+(.+)/.exec(line);\n if (ulMatch) {\n foundMarkdown = true;\n const spans = parseInlineMarkdown(ulMatch[1]);\n blocks.push({\n id: generateId(),\n type: \"list\",\n content: { spans },\n metadata: { ordered: false },\n });\n i++;\n continue;\n }\n\n // Ordered list: 1. or 1)\n const olMatch = /^\\d+[.)]\\s+(.+)/.exec(line);\n if (olMatch) {\n foundMarkdown = true;\n const spans = parseInlineMarkdown(olMatch[1]);\n blocks.push({\n id: generateId(),\n type: \"list\",\n content: { spans },\n metadata: { ordered: true },\n });\n i++;\n continue;\n }\n\n // Blockquote: > or >> or >>> etc.\n const bqMatch = /^(>+)\\s?(.*)$/.exec(line);\n if (bqMatch) {\n foundMarkdown = true;\n const depth = bqMatch[1].length - 1; // 0-indexed: > = 0, >> = 1\n const text = bqMatch[2];\n if (text.trim()) {\n const spans = parseInlineMarkdown(text);\n blocks.push({\n id: generateId(),\n type: \"blockquote\",\n content: { spans },\n metadata: depth > 0 ? { indentLevel: depth } : {},\n });\n }\n i++;\n continue;\n }\n\n // Paragraph — collect consecutive non-blank, non-special lines\n const paraLines: string[] = [];\n while (i < lines.length && lines[i].trim() !== \"\") {\n // Stop if next line looks like a block-level element\n if (/^(#{1,4}\\s|[-*+]\\s|`{3,}|\\d+[.)]\\s|>+\\s|([-*_])\\2{2,}\\s*$)/.test(lines[i]) && paraLines.length > 0) {\n break;\n }\n paraLines.push(lines[i]);\n i++;\n }\n const paraText = paraLines.join(\"\\n\");\n const spans = parseInlineMarkdown(paraText);\n blocks.push({\n id: generateId(),\n type: \"paragraph\",\n content: { spans },\n metadata: {},\n });\n }\n\n // If we didn't find any Markdown-specific syntax, return null\n // so the caller can fall back to plain text splitting\n if (!foundMarkdown) return null;\n if (blocks.length <= 1) return null;\n\n return blocks;\n}\n\n/**\n * Parse inline Markdown formatting into attributed string spans.\n * Handles: **bold**, *italic*, __bold__, _italic_, `code`,\n * ~~strikethrough~~, [text](url)\n */\nfunction parseInlineMarkdown(text: string): Span[] {\n const spans: Span[] = [];\n\n // Regex matches inline formatting tokens in priority order:\n // 1. code (backtick) — highest priority, no nesting\n // 2. links [text](url)\n // 3. bold+italic (***text*** or ___text___)\n // 4. bold (**text** or __text__)\n // 5. italic (*text* or _text_)\n // 6. strikethrough (~~text~~)\n const inlineRe =\n /`([^`]+)`|\\[([^\\]]+)\\]\\(([^)]+)\\)|\\*{3}(.+?)\\*{3}|_{3}(.+?)_{3}|\\*{2}(.+?)\\*{2}|_{2}(.+?)_{2}|\\*(.+?)\\*|_(.+?)_|~~(.+?)~~/g;\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = inlineRe.exec(text)) !== null) {\n // Plain text before this match\n if (match.index > lastIndex) {\n spans.push({ text: text.slice(lastIndex, match.index), attributes: {} });\n }\n\n if (match[1] != null) {\n // `code`\n spans.push({ text: match[1], attributes: { code: true } });\n } else if (match[2] != null) {\n // [text](url)\n spans.push({ text: match[2], attributes: { href: match[3] } });\n } else if (match[4] != null) {\n // ***bold+italic*** (asterisks)\n spans.push({ text: match[4], attributes: { bold: true, italic: true } });\n } else if (match[5] != null) {\n // ___bold+italic___ (underscores)\n spans.push({ text: match[5], attributes: { bold: true, italic: true } });\n } else if (match[6] != null) {\n // **bold** (asterisks)\n spans.push({ text: match[6], attributes: { bold: true } });\n } else if (match[7] != null) {\n // __bold__ (underscores)\n spans.push({ text: match[7], attributes: { bold: true } });\n } else if (match[8] != null) {\n // *italic* (asterisks)\n spans.push({ text: match[8], attributes: { italic: true } });\n } else if (match[9] != null) {\n // _italic_ (underscores)\n spans.push({ text: match[9], attributes: { italic: true } });\n } else if (match[10] != null) {\n // ~~strikethrough~~\n spans.push({ text: match[10], attributes: { strikethrough: true } });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Trailing plain text\n if (lastIndex < text.length) {\n spans.push({ text: text.slice(lastIndex), attributes: {} });\n }\n\n // If nothing matched, return single plain span\n if (spans.length === 0) {\n spans.push({ text, attributes: {} });\n }\n\n return mergeSpans(spans);\n}\n\n// ── Plain text → Blocks ──────────────────────────────────────────\n\n/**\n * Split multi-paragraph plain text into BlockJSON arrays.\n * Paragraphs are separated by blank lines (`\\n\\n`).\n * Returns null if the text is a single paragraph (let default paste handle it).\n */\nexport function plainTextToBlocks(text: string): BlockJSON[] | null {\n // Split on double newlines (paragraph breaks)\n const paragraphs = text.split(/\\n{2,}/).map((p) => p.trim()).filter(Boolean);\n\n // If only one paragraph, let the default paste handle it\n if (paragraphs.length <= 1) return null;\n\n return paragraphs.map((p) => makeParagraph(p));\n}\n\nfunction makeParagraph(text: string): BlockJSON {\n return {\n id: generateId(),\n type: \"paragraph\",\n content: { spans: [{ text, attributes: {} }] },\n metadata: {},\n };\n}\n","/**\n * Toast notification widget.\n *\n * Displays brief, auto-dismissing notifications at the bottom-center of the\n * viewport. Uses static factory methods — callers never manage instances.\n *\n * Two aria-live containers are maintained:\n * - Polite container (info/success): does not interrupt screen readers\n * - Assertive container (error): interrupts screen readers immediately\n *\n * Both containers are created lazily on first use and persist indefinitely\n * so that aria-live regions are pre-registered before content is injected\n * (which is required for reliable screen reader announcements).\n *\n * @example\n * Toast.show(\"File saved\");\n * Toast.show(\"Connection failed\", { type: \"error\" });\n * Toast.show(\"Copied!\", { type: \"success\", duration: 2000 });\n */\n\n/** Visual variant of a toast notification. */\nexport type ToastType = \"info\" | \"error\" | \"success\";\n\n/** Options for {@link Toast.show}. */\nexport interface ToastShowOptions {\n /** Toast variant (default: \"info\"). */\n type?: ToastType;\n /** Auto-dismiss duration in milliseconds (default: 4000). */\n duration?: number;\n}\n\nexport class Toast {\n /** Polite aria-live container (info / success toasts). Created on first use. */\n private static container: HTMLElement | null = null;\n /** Assertive aria-live container (error toasts). Created on first use. */\n private static assertiveContainer: HTMLElement | null = null;\n\n // Private constructor — only static methods are public API.\n private constructor() {}\n\n /**\n * Display a toast notification.\n *\n * @param message - Text content to show in the toast.\n * @param opts - Optional configuration.\n */\n static show(message: string, opts?: ToastShowOptions): void {\n const type: ToastType = opts?.type ?? \"info\";\n const duration: number = opts?.duration ?? 4000;\n\n const container = Toast.getOrCreateContainer(type);\n\n const toast = document.createElement(\"div\");\n toast.classList.add(\"blx-toast\", `blx-toast-${type}`);\n toast.textContent = message;\n\n // Click-to-dismiss\n toast.addEventListener(\"click\", () => Toast.dismiss(toast));\n\n container.appendChild(toast);\n\n // Auto-dismiss after duration\n const timer = setTimeout(() => Toast.dismiss(toast), duration);\n\n // If click dismisses the toast, clear the auto-dismiss timer to avoid a\n // double-dismiss attempt (the element will already be removed).\n toast.addEventListener(\n \"click\",\n () => clearTimeout(timer),\n { once: true }\n );\n }\n\n // ── Private helpers ─────────────────────────────────────────────\n\n /**\n * Return the appropriate aria-live container for the given toast type,\n * creating and appending it to document.body if it doesn't exist yet.\n *\n * The container is created BEFORE any toast is appended so that\n * screen readers register the live region in advance.\n */\n private static getOrCreateContainer(type: ToastType): HTMLElement {\n const isAssertive = type === \"error\";\n\n if (isAssertive) {\n if (!Toast.assertiveContainer || !Toast.assertiveContainer.isConnected) {\n Toast.assertiveContainer = Toast.createContainer(\"assertive\");\n }\n return Toast.assertiveContainer;\n }\n\n if (!Toast.container || !Toast.container.isConnected) {\n Toast.container = Toast.createContainer(\"polite\");\n }\n return Toast.container;\n }\n\n /**\n * Create a new toast container element and append it to document.body.\n */\n private static createContainer(\n liveness: \"polite\" | \"assertive\"\n ): HTMLElement {\n const el = document.createElement(\"div\");\n el.classList.add(\"blx-toast-container\");\n el.setAttribute(\"aria-live\", liveness);\n el.setAttribute(\"aria-relevant\", \"additions\");\n el.setAttribute(\"aria-atomic\", \"false\");\n document.body.appendChild(el);\n return el;\n }\n\n /**\n * Dismiss a toast element with an exit animation.\n * Removes the element from DOM after the animation completes.\n * If prefers-reduced-motion is set, removes immediately.\n */\n private static dismiss(toast: HTMLElement): void {\n if (!toast.isConnected) return;\n\n const prefersReducedMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n if (prefersReducedMotion) {\n toast.remove();\n return;\n }\n\n toast.classList.add(\"blx-toast-exit\");\n toast.addEventListener(\"animationend\", () => toast.remove(), { once: true });\n }\n}\n","import type { Block, BlockJSON } from \"./types\";\nimport { blockToJSON, blockFromJSON } from \"./types\";\nimport { AttributedString } from \"./attributed-string\";\nimport type { Attributes, Span } from \"./attributed-string\";\nimport { EventBus } from \"./event-bus\";\nimport type { EditorEventMap, ThemeMode } from \"./event-bus\";\nimport { SchemaRegistry } from \"./schema\";\nimport type { BlockTypePlugin, BlockMetadata } from \"./schema\";\nimport { BlockController } from \"./block\";\nimport { Transaction } from \"./transaction\";\nimport type { TransactionResult } from \"./transaction\";\nimport { registerDefaultPlugins, setUrlResolver, setBlockRefRenderCallback, resolveUrl } from \"./plugins\";\nimport { blocksToMarkdown } from \"./markdown\";\nimport { generateId } from \"./util/id\";\nimport type { MultiBlockSelection } from \"./selection/types\";\nimport { SlashMenu, SLASH_MENU_ITEMS } from \"./slash-menu\";\nimport type { SlashMenuItem } from \"./slash-menu\";\nimport { AutoCompleteMenu } from \"./autocomplete\";\nimport type { AutoCompleteEntry, AutoCompleteProvider } from \"./autocomplete\";\nimport { EmojiPicker, searchEmoji } from \"./emoji-picker\";\nimport { DatePicker } from \"./date-picker\";\nimport type { DateSuggestion, DateRole, Recurrence } from \"./date-picker\";\nimport { DragHandle } from \"./drag-handle\";\nimport { InlineToolbar } from \"./inline-toolbar\";\nimport { LinkPopover } from \"./inline-toolbar/link-popover\";\nimport { HighlightPicker } from \"./inline-toolbar/highlight-picker\";\nimport type { ToolbarButton, ToolbarActionContext } from \"./inline-toolbar\";\nimport { BlockActionMenu } from \"./block-action-menu\";\nimport type { BlockActionMenuEntry } from \"./block-action-menu\";\nimport { DEFAULT_KEYBINDINGS, eventToDescriptor, KeySequencer } from \"./keybindings\";\nimport type { KeybindingMap } from \"./keybindings\";\nimport { SearchEngine } from \"./search/search-engine\";\nimport { SearchUI } from \"./search/search-ui\";\nimport type { SearchMatch, SearchOptions } from \"./search/search-engine\";\nimport { parseYouTubeUrl } from \"./plugins/youtube\";\nimport { openExcalidrawModal } from \"./plugins/excalidraw\";\nimport { storeFileAsBlob } from \"./blob-store\";\nimport { UndoManager } from \"./undo/undo-manager\";\nimport { JumpList } from \"./undo/jump-list\";\nimport type { CursorState, UndoAction, BlockSnapshot } from \"./undo/types\";\nimport { BlockViewport } from \"./viewport\";\nimport type { BlockViewportOptions } from \"./viewport\";\nimport { CrdtLog } from \"./crdt/crdt-log\";\nimport { ReplayUI } from \"./crdt/replay-ui\";\nimport { renderRemoteCursors, clearRemoteCursors, clearRemoteCursorsFromContainer, renderBlockSelectionBorder } from \"./crdt/remote-cursor-renderer\";\nimport { AutomergeSync } from \"./crdt/automerge-sync\";\nimport type { AutomergeSyncOptions } from \"./crdt/automerge-sync\";\nimport type { CrdtPeer, RemoteCursor, CrdtOperation } from \"./crdt/types\";\nimport { PEER_COLORS } from \"./crdt/types\";\nimport { TableOfContents } from \"./table-of-contents\";\nimport { FoldManager } from \"./fold\";\nimport type { FoldState } from \"./fold\";\nimport { CommandRegistry, type ExternalCommandEntry } from \"./commands/command-registry\";\nimport { FloatingScrollManager } from \"./ui/floating-scroll-manager\";\nimport { BlockContextMenu } from \"./block-context-menu\";\nimport { CustomCaret } from \"./caret/custom-caret\";\nimport type { BlockContextMenuEntry } from \"./block-context-menu\";\nimport { copyBlocksToClipboard, readBlocksFromClipboard, extractBlocksFromHtml, htmlToBlocks, markdownToBlocks, plainTextToBlocks } from \"./clipboard\";\nimport { Toast } from \"./ui/toast\";\nimport {\n iconHtml,\n Clipboard as ClipboardIcon,\n ClipboardPaste as ClipboardPasteIcon,\n Code as CodeIcon,\n CircleCheckBig,\n Copy as CopyIcon,\n Heading1,\n Heading2,\n Heading3,\n Heading4,\n Image as ImageIcon,\n Link as LinkIcon,\n List as ListIcon,\n ListChecks,\n ListOrdered,\n Pencil,\n Pilcrow,\n Play,\n Scissors,\n Sparkles,\n Trash2,\n TextQuote,\n ClockPlus,\n History,\n ClockFading,\n ChevronsLeft,\n} from \"./util/icons\";\n\n/**\n * Resolve the most relevant date from a block's metadata for display.\n * Priority: dueDate > scheduledDate > eventDate > (legacy) agendaDate.\n */\nfunction resolveBlockDisplayDate(block: Block): { date: string; role: \"due\" | \"scheduled\" | \"event\" } | null {\n const m = block.metadata;\n if (typeof m.dueDate === \"string\") return { date: m.dueDate, role: \"due\" };\n if (typeof m.scheduledDate === \"string\") return { date: m.scheduledDate, role: \"scheduled\" };\n if (typeof m.eventDate === \"string\") return { date: m.eventDate, role: \"event\" };\n if (typeof m.agendaDate === \"string\") return { date: m.agendaDate, role: \"due\" };\n return null;\n}\n\n/**\n * Provider that supplies date suggestions for the @ agenda trigger.\n * Register via `editor.setDateSuggestionProvider()`.\n */\nexport interface DateSuggestionProvider {\n /** Parse a natural language query and return date suggestions. */\n suggest(query: string): DateSuggestion[];\n}\n\nexport interface ExternalKeybinding {\n /** Key sequence descriptor, e.g. `\" ,a\"` for leader+a. */\n keys: string;\n /** Unique command ID for the action. */\n commandId: string;\n /** Handler invoked when the key sequence is matched. */\n handler: () => void;\n}\n\nexport interface EditorOptions {\n schema?: SchemaRegistry;\n eventBus?: EventBus<EditorEventMap>;\n defaultPlugins?: boolean;\n initialBlocks?: Block[];\n /**\n * Custom URL resolver for link hrefs. Receives the raw URL from the\n * content model and should return a fully-qualified URL.\n *\n * Default: prepends `https://` to URLs that lack a protocol and don't\n * look like internal references (`#`, `/`, `mailto:`, `tel:`).\n */\n resolveUrl?: (url: string) => string;\n /**\n * Auto-focus the last block when typing occurs while no block is focused.\n * The `editor:unfocusedInput` event is emitted regardless of this setting.\n */\n autoFocusOnInput?: boolean;\n /**\n * Custom keybinding map. Partial overrides are merged with the defaults.\n */\n keybindings?: Partial<KeybindingMap>;\n /**\n * Color theme. `\"system\"` (default) follows `prefers-color-scheme`,\n * `\"light\"` / `\"dark\"` forces a specific theme.\n */\n theme?: ThemeMode;\n /**\n * Handler for inline link clicks. Called when a user activates a link\n * (Cmd/Ctrl+Click on desktop, double-tap on mobile). If not provided,\n * links open in a new tab via `window.open()`.\n *\n * Return `true` to indicate the click was handled; the default\n * `window.open` will be suppressed.\n */\n onLinkClick?: (href: string, resolvedHref: string, event: MouseEvent) => boolean | void;\n /**\n * Called after a blockRef span is rendered. Use to add CSS classes or\n * data attributes for app-specific styling (e.g. broken-link indicators).\n */\n onBlockRefRender?: (element: HTMLElement, refId: string) => void;\n /**\n * Transform pasted plain text before BLX processes it.\n * Return an object to replace the paste with marked text, or null/undefined\n * for default handling.\n */\n transformPastedText?: (text: string) => { text: string; attributes: Attributes } | null;\n /**\n * Options for the virtual rendering viewport. When enabled, only blocks\n * visible in the viewport (plus a buffer zone) have their content rendered\n * in the DOM. Off-screen blocks keep lightweight placeholder containers\n * for scroll stability.\n *\n * Set to `false` to disable virtual rendering entirely (all blocks are\n * always rendered). Enabled by default.\n */\n viewport?: BlockViewportOptions | false;\n /** Callback when fold state changes. Host should persist this. */\n onFoldChanged?: (state: FoldState) => void;\n /** Initial fold state to restore. */\n initialFoldState?: FoldState;\n /**\n * An outer container element (e.g. the scroll host) that should also\n * respond to clicks by focusing the nearest block. Clicks inside the\n * editor root are ignored (handled by the editor's own mousedown).\n */\n clickContainer?: HTMLElement;\n}\n\nexport interface EditorJSON {\n blocks: BlockJSON[];\n}\n\nexport class Editor {\n readonly root: HTMLElement;\n readonly content: HTMLElement;\n readonly gutter: HTMLElement;\n readonly blocksContainer: HTMLElement;\n readonly schema: SchemaRegistry;\n readonly bus: EventBus<EditorEventMap>;\n readonly commands: CommandRegistry;\n\n private controllers: BlockController[] = [];\n private controllerMap = new Map<string, BlockController>();\n /** Sticky X position for consecutive ArrowUp/ArrowDown navigation */\n private goalX: number | null = null;\n\n /** Block selection state */\n private blockSelectAnchor: string | null = null;\n private blockSelectFocus: string | null = null;\n private editorMode: \"insert\" | \"normal\" | \"visualBlock\" = \"insert\";\n /** Whether visual block mode persists without Shift (true = vim V, false = shift-arrow transient) */\n private visualBlockSticky = false;\n\n /** Last action that mutated blocks — replayed by the dot (.) command */\n private lastRepeatableAction: string | null = null;\n /** Actions that count as repeatable mutations (navigation, mode changes, etc. are excluded) */\n private static readonly REPEATABLE_ACTIONS = new Set([\n \"deleteBlock\", \"deleteSelection\", \"newBlockBelow\", \"newBlockAbove\",\n \"joinWithNext\", \"pasteAfter\", \"pasteBefore\", \"indentSelection\",\n \"outdentSelection\", \"toggleChecklist\", \"moveBlockUp\", \"moveBlockDown\",\n \"changeBlock\", \"changeSelection\",\n ]);\n\n /** Slash command menu */\n private slashMenu: SlashMenu | null = null;\n private slashMenuBlockId: string | null = null;\n private slashCommandOffset: number | null = null;\n private slashMenuKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private customSlashHandlers = new Map<string, (blockId: string) => void>();\n private customSlashItems: SlashMenuItem[] = [];\n\n /** Emoji picker */\n private emojiPicker: EmojiPicker | null = null;\n private emojiBlockId: string | null = null;\n private emojiColonOffset: number | null = null;\n private emojiKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** Agenda date picker (@) */\n private agendaPicker: DatePicker | null = null;\n private agendaBlockId: string | null = null;\n private agendaAtOffset: number | null = null;\n private agendaKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private dateSuggestionProvider: DateSuggestionProvider | null = null;\n\n /** Autocomplete menu ([[) */\n private autoCompleteMenu: AutoCompleteMenu | null = null;\n private autoCompleteBlockId: string | null = null;\n private autoCompleteBracketOffset: number | null = null;\n private autoCompleteKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private autoCompleteProviders: AutoCompleteProvider[] = [];\n\n /** Drag handle */\n private dragHandle: DragHandle | null = null;\n\n /** Inline formatting toolbar */\n private inlineToolbar: InlineToolbar | null = null;\n private selectionChangeHandler: (() => void) | null = null;\n private _toolbarDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n private _mouseDown = false;\n private _onMouseDown: (() => void) | null = null;\n private _onMouseUp: (() => void) | null = null;\n private formatKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private floatingScroll = new FloatingScrollManager();\n /** Controller with active pending marks (for clearing when focus moves) */\n private _pendingMarksCtrl: BlockController | null = null;\n /** Block ID force-mounted because it has an active text selection */\n private selectionForceMountedId: string | null = null;\n\n /** Mouse drag → block selection */\n private mouseDragAnchorBlockId: string | null = null;\n private mouseDragActive = false;\n /** Saved text cursor offset within the anchor block when entering block selection */\n private mouseDragAnchorOffset: number | null = null;\n /** Auto-scroll during drag */\n private dragScrollRAF: number | null = null;\n private _lastDragMouseX = 0;\n private _lastDragMouseY = 0;\n\n /** Block action menu */\n private blockActionMenu: BlockActionMenu | null = null;\n private customCaret: CustomCaret | null = null;\n private customActionItems: BlockActionMenuEntry[] = [];\n\n /** Right-click context menu */\n private blockContextMenu: BlockContextMenu | null = null;\n private customContextItems: BlockContextMenuEntry[] = [];\n\n /** Link popover */\n private linkPopover: LinkPopover | null = null;\n\n /** Highlight picker */\n private highlightPicker: HighlightPicker | null = null;\n\n /** URL hash navigation handler (bound for cleanup) */\n private hashChangeHandler: (() => void) | null = null;\n\n /** Mobile double-tap tracking for link activation */\n private lastTapTarget: HTMLElement | null = null;\n private lastTapTime = 0;\n\n /** Search panel */\n private searchEngine = new SearchEngine();\n private searchUI: SearchUI | null = null;\n private searchKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n /** All current search matches (for dim highlighting) */\n private searchMatches: SearchMatch[] = [];\n /** Index of the currently focused search match (for bright highlighting) */\n private searchCurrentMatch: SearchMatch | null = null;\n\n /** Drop zone indicator for external image drag-drop */\n private imageDropZone: HTMLElement | null = null;\n\n /** Full-editor overlay shown when dragging unsupported files */\n private dropRejectOverlay: HTMLElement | null = null;\n\n /** Focused non-text block (image, youtube, etc.) */\n private focusedNonTextBlockId: string | null = null;\n private nonTextKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** Editor options (stored for runtime checks) */\n private options: EditorOptions | undefined;\n\n /** Outer click container for focus-on-click outside the editor root */\n private clickContainer: HTMLElement | null = null;\n\n /** Current theme mode */\n private themeMode: ThemeMode = \"system\";\n\n /** Keybinding map and sequencer for block selection mode */\n private keybindings: KeybindingMap;\n private keySequencer = new KeySequencer();\n /** Handlers registered by the host app via registerKeybindings(). */\n private externalActions = new Map<string, () => void>();\n\n /** Undo/redo history */\n private undoManager = new UndoManager();\n /** When true, mutations are not recorded in undo history (used during undo/redo) */\n private _suppressHistory = false;\n\n /** Navigation jumplist (Ctrl-O / Ctrl-I) */\n private jumpList = new JumpList();\n /** Last block that had focus (for jumplist tracking) */\n private _lastFocusedBlockId: string | null = null;\n /** Last edit position for g,. navigation */\n private _lastEditPosition: CursorState | null = null;\n /** Cursor position saved before an overlay (search, link popover, etc.) steals focus */\n private _preOverlayCursor: CursorState | null = null;\n\n /** Keyboard handler for undo/redo and jump shortcuts */\n private undoKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** CRDT operation log (null until enabled) */\n private crdtLog: CrdtLog | null = null;\n\n /** Replay state */\n private _replayActive = false;\n private _replayPosition = 0;\n private _replaySavedState: BlockJSON[] | null = null;\n private _replayUI: ReplayUI | null = null;\n private _replayTimer: ReturnType<typeof setInterval> | null = null;\n private _replaySpeed = 150; // ms per operation\n\n /** Multiplayer peer tracking */\n private _localPeer: CrdtPeer | null = null;\n private _peers = new Map<string, CrdtPeer>();\n private _remoteCursors = new Map<string, RemoteCursor>();\n private _remoteCursorRenderScheduled = false;\n private _cursorScrollCleanup: (() => void) | null = null;\n private _cursorIdleTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Automerge CRDT sync adapter (null until enabled) */\n private _automergeSync: AutomergeSync | null = null;\n\n /** Heading fold manager */\n private foldManager = new FoldManager();\n\n /** Table of contents navigation widget */\n private toc: TableOfContents | null = null;\n\n /** Virtual rendering viewport manager */\n private viewport: BlockViewport;\n\n constructor(root: HTMLElement, options?: EditorOptions) {\n this.root = root;\n this.root.classList.add(\"blx-editor\");\n (this.root as any).__blxEditor = this;\n\n this.content = document.createElement(\"div\");\n this.content.classList.add(\"blx-content\");\n this.root.appendChild(this.content);\n\n this.gutter = document.createElement(\"div\");\n this.gutter.classList.add(\"blx-gutter\");\n this.content.appendChild(this.gutter);\n\n this.blocksContainer = document.createElement(\"div\");\n this.blocksContainer.classList.add(\"blx-blocks\");\n this.content.appendChild(this.blocksContainer);\n\n this.options = options;\n\n this.schema = options?.schema ?? new SchemaRegistry();\n this.bus = options?.eventBus ?? new EventBus<EditorEventMap>();\n this.keybindings = {\n normal: {\n ...DEFAULT_KEYBINDINGS.normal,\n ...options?.keybindings?.normal,\n },\n visualBlock: {\n ...DEFAULT_KEYBINDINGS.visualBlock,\n ...options?.keybindings?.visualBlock,\n },\n };\n\n this.commands = new CommandRegistry();\n\n if (options?.defaultPlugins !== false) {\n registerDefaultPlugins(this.schema);\n }\n\n // Configure URL resolver for link rendering\n setUrlResolver(options?.resolveUrl);\n\n // Configure blockRef render decorator\n setBlockRefRenderCallback(options?.onBlockRefRender);\n\n // Initialize viewport manager for virtual rendering\n this.viewport = new BlockViewport(\n this.blocksContainer,\n options?.viewport === false ? { bufferPx: 0 } : options?.viewport,\n );\n // When viewport mounts a block's content, recompute list indices so\n // ordered lists get correct `start` attributes.\n this.viewport.onContentMounted = () => {\n this.recomputeListIndices();\n };\n\n this.setupEventHandlers();\n this.dragHandle = new DragHandle(this.root, this.gutter, this.moveBlock.bind(this), {\n getSelectedBlockIds: () => this.getSelectedBlockIds(),\n onMoveBlocks: (ids, toIndex) => this.moveBlocks(ids, toIndex),\n onDragStart: () => this.blockActionMenu?.notifyDragStart(),\n onDragEnd: () => this.blockActionMenu?.notifyDragEnd(),\n onDoubleTap: (blockId) => {\n const headingId = this.foldManager.findOwningHeading(blockId, this.getBlocks());\n if (headingId) this.toggleFold(headingId);\n },\n isBlockDraggable: (blockId) => {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return true;\n return !this.getPlugin(ctrl.getBlock().type).immovable;\n },\n });\n this.blockActionMenu = new BlockActionMenu(\n this.root,\n this.gutter,\n () => this.getActionTargetBlockIds(),\n () => this.buildActionMenuItems(),\n {\n shouldShowForBlock: (blockId) => {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return true;\n const plugin = this.getPlugin(ctrl.getBlock().type);\n return !(plugin.immovable && plugin.inconvertible);\n },\n },\n );\n this.blockActionMenu.onOpen = () => this.dragHandle?.notifyMenuOpen();\n this.blockActionMenu.onClose = () => this.dragHandle?.notifyMenuClosed();\n this.customCaret = new CustomCaret(this.root);\n this.blockContextMenu = new BlockContextMenu(\n this.root,\n (e) => this.resolveContextMenuBlockIds(e),\n (blockIds) => this.buildContextMenuItems(blockIds),\n );\n this.setupClipboardShortcuts();\n this.setupLinkClickHandler();\n this.setupInlineToolbar();\n this.setupMediaBlockHandlers();\n this.setupSearchShortcut();\n this.setupUndoShortcuts();\n this.setupUndoContentListener();\n this.setupJumpListTracking();\n this.setupRemoteCursorRefresh();\n if (options?.initialBlocks && options.initialBlocks.length > 0) {\n this.loadInitialBlocks(options.initialBlocks);\n }\n\n // Initialize theme\n this.setTheme(options?.theme ?? \"system\");\n\n this.bus.emit(\"editor:ready\", {});\n\n // Initial list index computation\n this.recomputeListIndices();\n\n // URL hash → block navigation\n this.setupHashNavigation();\n\n // Table of contents widget\n this.setupTableOfContents();\n\n // Register built-in commands for : command mode\n this.registerBuiltInCommands();\n\n // ── Fold management ──\n if (options?.onFoldChanged) {\n this.foldManager.setCallbacks({ onFoldChanged: options.onFoldChanged });\n }\n if (options?.initialFoldState) {\n this.foldManager.loadState(options.initialFoldState);\n this.foldManager.recompute(this.getBlocks());\n this.applyFoldVisibility();\n }\n const recomputeFolds = () => {\n this.foldManager.recompute(this.getBlocks());\n this.applyFoldVisibility();\n };\n this.bus.on(\"block:added\", recomputeFolds);\n this.bus.on(\"block:removed\", recomputeFolds);\n this.bus.on(\"block:moved\", recomputeFolds);\n this.bus.on(\"block:typeChanged\", recomputeFolds);\n\n this.root.addEventListener(\"blx:headingFoldToggle\", ((e: CustomEvent) => {\n const blockId = e.detail?.blockId as string;\n if (blockId) this.toggleFold(blockId);\n }) as EventListener);\n }\n\n // ── Bulk initial load ───────────────────────────────────────────\n\n /**\n * Fast path for loading the initial set of blocks. Bypasses the per-block\n * overhead of addBlock() — no events emitted, no undo history, no\n * individual DOM insertions. All containers are appended via a single\n * DocumentFragment and viewport registration is batched.\n */\n private loadInitialBlocks(blocks: Block[]): void {\n const fragment = document.createDocumentFragment();\n const newControllers: BlockController[] = [];\n\n for (const block of blocks) {\n // Migrate aliased block types (e.g. \"task-list\" → \"checklist\")\n block.type = this.schema.resolveType(block.type);\n const plugin = this.getPlugin(block.type);\n const controller = new BlockController(block, plugin, this.bus);\n // Append to fragment — no reflow until fragment is committed to DOM\n controller.mountContainer(fragment);\n newControllers.push(controller);\n this.controllers.push(controller);\n this.controllerMap.set(block.id, controller);\n }\n\n // Single DOM insertion for all block containers\n this.blocksContainer.appendChild(fragment);\n\n // Batch-register all controllers with the viewport\n this.viewport.registerBatch(newControllers);\n\n // Synchronously mount blocks visible in the initial viewport\n this.viewport.mountInitialViewport();\n }\n\n /**\n * Replace all blocks in a single batch operation. Destroys existing\n * controllers and bulk-loads the new set via DocumentFragment.\n * Used by AutomergeSync.applyDocToEditor() to avoid per-block overhead\n * on full document reload.\n * @internal\n */\n replaceAllBlocks(blocks: Block[]): void {\n // Destroy existing controllers\n for (const ctrl of this.controllers) {\n this.viewport.unregister(ctrl.blockId);\n ctrl.destroy();\n }\n this.controllers.length = 0;\n this.controllerMap.clear();\n\n // Bulk load new blocks\n if (blocks.length > 0) {\n this.loadInitialBlocks(blocks);\n }\n\n this.recomputeListIndices();\n }\n\n // ── Block CRUD ────────────────────────────────────────────────────\n\n addBlock(\n blockOrType: Block | string = \"paragraph\",\n index?: number,\n ): Block {\n let block: Block;\n if (typeof blockOrType === \"string\") {\n const plugin = this.getPlugin(blockOrType);\n block = {\n id: generateId(),\n type: blockOrType,\n content: plugin.defaultContent(),\n metadata: plugin.defaultMetadata(),\n };\n } else {\n block = blockOrType;\n }\n\n const plugin = this.getPlugin(block.type);\n const controller = new BlockController(block, plugin, this.bus);\n\n const insertIndex =\n index !== undefined\n ? Math.max(0, Math.min(index, this.controllers.length))\n : this.controllers.length;\n\n const beforeCtrl = this.controllers[insertIndex];\n // Insert container into the DOM; content rendering is managed by the\n // viewport (IntersectionObserver mounts content when in view).\n controller.mountContainer(this.blocksContainer, beforeCtrl?.container ?? null);\n this.viewport.register(controller);\n\n this.controllers.splice(insertIndex, 0, controller);\n this.controllerMap.set(block.id, controller);\n\n if (!this._suppressHistory) {\n const snap = this.snapshotBlock(block);\n this.recordUndoAction(\n { type: \"addBlock\", block: snap, index: insertIndex },\n null,\n { blockId: block.id, offset: 0 },\n );\n }\n\n this.bus.emit(\"block:added\", { blockId: block.id, index: insertIndex });\n return controller.getBlock();\n }\n\n removeBlock(id: string): boolean {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) return false;\n\n const plugin = this.getPlugin(ctrl.getBlock().type);\n if (plugin.immovable) return false;\n\n const index = this.controllers.indexOf(ctrl);\n if (!this._suppressHistory) {\n const snap = this.snapshotBlock(ctrl.getBlock());\n this.recordUndoAction(\n { type: \"removeBlock\", block: snap, index },\n null,\n null,\n );\n }\n this.viewport.unregister(id);\n ctrl.destroy();\n this.controllers.splice(index, 1);\n this.controllerMap.delete(id);\n\n this.bus.emit(\"block:removed\", { blockId: id });\n return true;\n }\n\n moveBlock(id: string, toIndex: number): boolean {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) return false;\n\n // Immovable blocks can't be moved\n const movePlugin = this.getPlugin(ctrl.getBlock().type);\n if (movePlugin.immovable) return false;\n\n const fromIndex = this.controllers.indexOf(ctrl);\n // Clamp to ≥1 if block[0] is immovable (can't displace it)\n const minIndex = this.controllers.length > 0 && this.getPlugin(this.controllers[0].getBlock().type).immovable ? 1 : 0;\n const clampedTo = Math.max(minIndex, Math.min(toIndex, this.controllers.length - 1));\n if (fromIndex === clampedTo) return true;\n\n if (!this._suppressHistory) {\n this.recordUndoAction(\n { type: \"moveBlock\", blockId: id, fromIndex, toIndex: clampedTo },\n null,\n null,\n );\n }\n\n // Remove from current position\n this.controllers.splice(fromIndex, 1);\n\n // Insert at new position\n this.controllers.splice(clampedTo, 0, ctrl);\n\n // Re-order DOM\n const beforeCtrl = this.controllers[clampedTo + 1];\n this.blocksContainer.insertBefore(ctrl.container, beforeCtrl?.container ?? null);\n\n this.bus.emit(\"block:moved\", {\n blockId: id,\n fromIndex,\n toIndex: clampedTo,\n });\n return true;\n }\n\n /**\n * Import an array of blocks into the editor, appending after existing content.\n * The entire import is treated as a single compound undo entry so the user\n * can undo the import in one step.\n *\n * @param blocks - Serialized blocks to import\n * @returns The created Block instances\n */\n importBlocks(blocks: ReadonlyArray<BlockJSON>): Block[] {\n if (blocks.length === 0) return [];\n const cursor = this.getCursorState();\n this.undoManager.beginGroup(cursor);\n const created: Block[] = [];\n try {\n for (const json of blocks) {\n created.push(this.addBlock(blockFromJSON(json)));\n }\n } finally {\n const endCursor = created.length > 0\n ? { blockId: created[0].id, offset: 0 }\n : cursor;\n this.undoManager.endGroup(endCursor);\n }\n this.recomputeListIndices();\n return created;\n }\n\n /**\n * Paste blocks at the current cursor position.\n * Splits the focused block at the cursor and inserts the given blocks\n * between the two halves. The entire operation is a single undo entry.\n *\n * If the first pasted block is a paragraph, its content merges into the\n * end of the \"before\" half (avoids an awkward empty line). Similarly,\n * if the last pasted block is a paragraph, its content merges into the\n * start of the \"after\" half.\n *\n * Falls back to importBlocks() when no block is focused.\n */\n pasteBlocks(blocks: ReadonlyArray<BlockJSON>): Block[] {\n if (blocks.length === 0) return [];\n\n // If no block is focused, delegate to importBlocks\n const focusedId = this.getFocusedBlockId();\n if (!focusedId) return this.importBlocks(blocks);\n\n const ctrl = this.controllerMap.get(focusedId);\n if (!ctrl) return this.importBlocks(blocks);\n\n const block = ctrl.getBlock();\n const offset = ctrl.getCursorOffset() ?? block.content.length;\n\n // Split content at cursor\n const beforeContent = block.content.slice(0, offset);\n const afterContent = block.content.slice(offset, block.content.length);\n\n // Begin compound undo group\n const cursor: CursorState = { blockId: focusedId, offset };\n this.undoManager.beginGroup(cursor);\n this.crdtLog?.beginGroup(cursor);\n\n const created: Block[] = [];\n try {\n // Remaining blocks to insert (we may consume first/last for merging)\n const remaining = [...blocks];\n\n // ── Merge first pasted block into current block's tail ──────\n if (remaining.length > 0 && remaining[0].type === \"paragraph\") {\n const first = remaining.shift()!;\n const firstContent = AttributedString.fromJSON(first.content);\n const mergedContent = beforeContent.concat(firstContent);\n\n // Record undo for content change\n if (!this._suppressHistory) {\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: focusedId,\n before: { content: block.content, metadata: { ...block.metadata }, blockType: block.type },\n after: { content: mergedContent, metadata: { ...block.metadata }, blockType: block.type },\n },\n null,\n null,\n );\n }\n ctrl.updateBlock({ content: mergedContent });\n ctrl.setPlugin(this.getPlugin(block.type));\n\n // Emit contentChanged so AutomergeSync propagates the merged content\n this.bus.emit(\"block:contentChanged\", {\n blockId: focusedId,\n content: mergedContent,\n metadata: block.metadata,\n });\n } else {\n // Non-paragraph first block: keep current block with just beforeContent\n if (!this._suppressHistory) {\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: focusedId,\n before: { content: block.content, metadata: { ...block.metadata }, blockType: block.type },\n after: { content: beforeContent, metadata: { ...block.metadata }, blockType: block.type },\n },\n null,\n null,\n );\n }\n ctrl.updateBlock({ content: beforeContent });\n ctrl.setPlugin(this.getPlugin(block.type));\n\n // Emit contentChanged so AutomergeSync propagates the truncated content\n this.bus.emit(\"block:contentChanged\", {\n blockId: focusedId,\n content: beforeContent,\n metadata: block.metadata,\n });\n }\n\n // ── Insert index: right after the current block ────────────\n let insertIndex = this.controllers.indexOf(ctrl) + 1;\n\n // ── Insert remaining blocks (possibly all, or middle portion) ──\n for (const json of remaining) {\n created.push(this.addBlock(blockFromJSON(json), insertIndex++));\n }\n\n // ── Handle afterContent ────────────────────────────────────\n if (afterContent.length > 0) {\n // Try to merge into the last created block if it's a paragraph\n if (created.length > 0 && created[created.length - 1].type === \"paragraph\") {\n const lastBlock = created[created.length - 1];\n const lastCtrl = this.controllerMap.get(lastBlock.id);\n if (lastCtrl) {\n const mergedContent = lastBlock.content.concat(afterContent);\n if (!this._suppressHistory) {\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: lastBlock.id,\n before: { content: lastBlock.content, metadata: { ...lastBlock.metadata }, blockType: lastBlock.type },\n after: { content: mergedContent, metadata: { ...lastBlock.metadata }, blockType: lastBlock.type },\n },\n null,\n null,\n );\n }\n lastCtrl.updateBlock({ content: mergedContent });\n lastCtrl.setPlugin(this.getPlugin(lastBlock.type));\n\n // Emit contentChanged so AutomergeSync propagates the merged content\n this.bus.emit(\"block:contentChanged\", {\n blockId: lastBlock.id,\n content: mergedContent,\n metadata: lastBlock.metadata,\n });\n }\n } else {\n // Create a new paragraph for afterContent\n const afterBlock: Block = {\n id: generateId(),\n type: \"paragraph\",\n content: afterContent,\n metadata: this.getPlugin(\"paragraph\").defaultMetadata(),\n };\n created.push(this.addBlock(afterBlock, insertIndex));\n }\n }\n } finally {\n // Determine end cursor: last created/modified block\n let endCursor: CursorState;\n if (created.length > 0) {\n const lastCreated = created[created.length - 1];\n endCursor = { blockId: lastCreated.id, offset: lastCreated.content.length };\n } else {\n // All merged into the current block\n endCursor = { blockId: focusedId, offset: ctrl.getBlock().content.length };\n }\n this.undoManager.endGroup(endCursor);\n this.crdtLog?.endGroup(endCursor);\n }\n\n this.recomputeListIndices();\n\n // Focus the last created/modified block at appropriate offset\n if (created.length > 0) {\n const lastCreated = created[created.length - 1];\n this.focusBlock(lastCreated.id, lastCreated.content.length);\n } else {\n this.focusBlock(focusedId, ctrl.getBlock().content.length);\n }\n\n return created;\n }\n\n /**\n * Move multiple blocks as a group to a new position, preserving their\n * internal order. `toIndex` is the target position in the array after\n * all the blocks have been removed.\n */\n moveBlocks(blockIds: string[], toIndex: number): boolean {\n // Collect controllers, sorted by their current document position\n const ctrlsUnsorted = blockIds\n .map((id) => this.controllerMap.get(id))\n .filter((ctrl): ctrl is BlockController => {\n if (!ctrl) return false;\n return !this.getPlugin(ctrl.getBlock().type).immovable;\n });\n if (ctrlsUnsorted.length === 0) return false;\n\n const ctrls = ctrlsUnsorted.sort(\n (a, b) => this.controllers.indexOf(a) - this.controllers.indexOf(b),\n );\n\n // Remove all from controllers array (iterate in reverse to keep indices stable)\n for (let i = ctrls.length - 1; i >= 0; i--) {\n const idx = this.controllers.indexOf(ctrls[i]);\n if (idx >= 0) this.controllers.splice(idx, 1);\n }\n\n // Clamp to ≥1 if block[0] is immovable\n const minIndex = this.controllers.length > 0 && this.getPlugin(this.controllers[0].getBlock().type).immovable ? 1 : 0;\n const clampedTo = Math.max(minIndex, Math.min(toIndex, this.controllers.length));\n\n // Insert at new position in document order\n this.controllers.splice(clampedTo, 0, ...ctrls);\n\n // Re-order DOM: insert each block before the element after the group\n const afterCtrl = this.controllers[clampedTo + ctrls.length];\n const beforeNode = afterCtrl?.container ?? null;\n for (const ctrl of ctrls) {\n this.blocksContainer.insertBefore(ctrl.container, beforeNode);\n }\n\n // Emit move events for each block\n for (const ctrl of ctrls) {\n this.bus.emit(\"block:moved\", {\n blockId: ctrl.getBlock().id,\n fromIndex: -1, // multi-block move, original indices not tracked\n toIndex: this.controllers.indexOf(ctrl),\n });\n }\n return true;\n }\n\n /** Get currently selected block IDs, or null if no selection */\n private getSelectedBlockIds(): string[] | null {\n if (this.editorMode === \"insert\" || !this.blockSelectAnchor || !this.blockSelectFocus) {\n return null;\n }\n const anchorIdx = this.getBlockIndex(this.blockSelectAnchor);\n const focusIdx = this.getBlockIndex(this.blockSelectFocus);\n const first = Math.min(anchorIdx, focusIdx);\n const last = Math.max(anchorIdx, focusIdx);\n return this.controllers.slice(first, last + 1).map((c) => c.getBlock().id);\n }\n\n /** Move a completed task to the bottom of consecutive checklist blocks */\n private moveCompletedChecklistToBottom(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const block = ctrl.getBlock();\n if (block.type !== \"checklist\") return;\n\n const currentIndex = this.controllers.indexOf(ctrl);\n const level = (block.metadata.indentLevel as number) ?? 0;\n\n // Collect the subtree: this block + nested children\n const subtreeIds = [blockId];\n for (let i = currentIndex + 1; i < this.controllers.length; i++) {\n const b = this.controllers[i].getBlock();\n if (((b.metadata.indentLevel as number) ?? 0) <= level) break;\n subtreeIds.push(b.id);\n }\n\n // Find the end of the sibling scope: walk forward from end of subtree,\n // stop at a block with indentLevel < ours (parent boundary) or non-checklist\n let lastPos = currentIndex + subtreeIds.length - 1;\n for (let i = currentIndex + subtreeIds.length; i < this.controllers.length; i++) {\n const b = this.controllers[i].getBlock();\n if (b.type !== \"checklist\" || ((b.metadata.indentLevel as number) ?? 0) < level) break;\n lastPos = i;\n }\n\n // Only move if there are sibling blocks after the subtree\n if (lastPos > currentIndex + subtreeIds.length - 1) {\n for (const id of subtreeIds) {\n this.moveBlock(id, lastPos);\n }\n }\n }\n\n /** Move an unchecked task (and its nested children) above the first checked sibling */\n private moveUncheckedTaskToTop(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const block = ctrl.getBlock();\n if (block.type !== \"checklist\") return;\n\n const currentIndex = this.controllers.indexOf(ctrl);\n const level = (block.metadata.indentLevel as number) ?? 0;\n\n // Collect the subtree: this block + nested children\n const subtreeIds = [blockId];\n for (let i = currentIndex + 1; i < this.controllers.length; i++) {\n const b = this.controllers[i].getBlock();\n if (((b.metadata.indentLevel as number) ?? 0) <= level) break;\n subtreeIds.push(b.id);\n }\n\n // Find the start of the sibling scope: walk backward,\n // stop at a block with indentLevel < ours (parent boundary) or non-checklist\n let scopeStart = currentIndex;\n for (let i = currentIndex - 1; i >= 0; i--) {\n const b = this.controllers[i].getBlock();\n if (b.type !== \"checklist\" || ((b.metadata.indentLevel as number) ?? 0) < level) break;\n scopeStart = i;\n }\n\n // Find the first checked sibling (same level) in the scope, skipping our subtree\n const subtreeSet = new Set(subtreeIds);\n let firstCheckedSibling = -1;\n for (let i = scopeStart; i < this.controllers.length; i++) {\n const b = this.controllers[i].getBlock();\n const bLevel = (b.metadata.indentLevel as number) ?? 0;\n if (b.type !== \"checklist\" || bLevel < level) break;\n if (subtreeSet.has(b.id)) continue;\n if (bLevel === level && b.metadata.checked) {\n firstCheckedSibling = i;\n break;\n }\n }\n\n // Move the subtree just before the first checked sibling\n if (firstCheckedSibling >= 0 && firstCheckedSibling < currentIndex) {\n for (let i = 0; i < subtreeIds.length; i++) {\n this.moveBlock(subtreeIds[i], firstCheckedSibling + i);\n }\n }\n }\n\n /** Set checked state on all nested checklist children of a toggled task */\n private cascadeChecklistToggle(blockId: string, checked: boolean): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const idx = this.controllers.indexOf(ctrl);\n const parentLevel = (ctrl.getBlock().metadata.indentLevel as number) ?? 0;\n\n // Walk subsequent blocks that are nested under this one\n for (let i = idx + 1; i < this.controllers.length; i++) {\n const childCtrl = this.controllers[i];\n const childBlock = childCtrl.getBlock();\n const childLevel = (childBlock.metadata.indentLevel as number) ?? 0;\n\n // Stop when we reach a block at the same or lower indent level\n if (childLevel <= parentLevel) break;\n\n // Only toggle checklist blocks that differ from the target state\n if (childBlock.type === \"checklist\" && childBlock.metadata.checked !== checked) {\n const tx = new Transaction(childBlock.id).setMetadata(\"checked\", checked);\n childCtrl.applyTransaction(tx);\n // Don't emit block:checklistToggled for children — avoids recursive moves\n }\n }\n }\n\n private toggleChecklist(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n if (block.type !== \"checklist\") return;\n const checked = !block.metadata.checked;\n const tx = new Transaction(blockId).setMetadata(\"checked\", checked);\n ctrl.applyTransaction(tx);\n this.bus.emit(\"block:checklistToggled\", { blockId, checked });\n }\n\n private cycleTaskStatus(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n if (block.type !== \"heading\") return;\n const CYCLE: Record<string, string> = {\n \"todo\": \"in-progress\", \"in-progress\": \"done\", \"done\": \"todo\",\n };\n const current = block.metadata.taskStatus as string | undefined;\n const next = current ? CYCLE[current] : \"todo\";\n const tx = new Transaction(blockId).setMetadata(\"taskStatus\", next);\n ctrl.applyTransaction(tx);\n }\n\n private setTaskStatusExplicit(blockId: string, status: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n if (ctrl.getBlock().type !== \"heading\") return;\n const tx = new Transaction(blockId).setMetadata(\"taskStatus\", status);\n ctrl.applyTransaction(tx);\n }\n\n private removeTaskStatus(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n if (ctrl.getBlock().type !== \"heading\") return;\n const tx = new Transaction(blockId)\n .setMetadata(\"taskStatus\", undefined)\n .setMetadata(\"dueDate\", undefined)\n .setMetadata(\"scheduledDate\", undefined)\n .setMetadata(\"eventDate\", undefined)\n .setMetadata(\"recurrence\", undefined)\n .setMetadata(\"agendaDate\", undefined);\n ctrl.applyTransaction(tx);\n }\n\n /** Block types that support agenda dates (have badge rendering). */\n static readonly AGENDA_BLOCK_TYPES = new Set([\"heading\", \"checklist\", \"paragraph\", \"list\"]);\n\n private openAgendaPickerForBlock(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n if (!Editor.AGENDA_BLOCK_TYPES.has(block.type)) return;\n const dateInfo = resolveBlockDisplayDate(block);\n const recurrence = block.metadata.recurrence as { interval: number; unit: \"day\" | \"week\" | \"month\" | \"year\"; anchor?: string; fromCompletion?: boolean } | undefined;\n this.ensureAgendaPicker();\n this.agendaBlockId = blockId;\n this.agendaAtOffset = null;\n const rect = ctrl.container.getBoundingClientRect();\n this.agendaPicker!.show(rect, {\n initialDate: dateInfo?.date,\n initialRole: dateInfo?.role,\n initialRecurrence: recurrence,\n blockType: block.type,\n });\n this.registerAgendaScrollAndKeys(ctrl);\n }\n\n getBlock(id: string): Block | undefined {\n return this.controllerMap.get(id)?.getBlock();\n }\n\n getBlocks(): ReadonlyArray<Block> {\n return this.controllers.map((c) => c.getBlock());\n }\n\n getBlockAt(index: number): Block | undefined {\n return this.controllers[index]?.getBlock();\n }\n\n getBlockIndex(id: string): number {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) return -1;\n return this.controllers.indexOf(ctrl);\n }\n\n getBlockCount(): number {\n return this.controllers.length;\n }\n\n // ── Block type change ─────────────────────────────────────────────\n\n changeBlockType(\n id: string,\n newType: string,\n metadata?: Record<string, unknown>,\n ): boolean {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) return false;\n\n const oldBlock = ctrl.getBlock();\n // Block with inconvertible plugin can't change type\n const oldPlugin = this.getPlugin(oldBlock.type);\n if (oldPlugin.inconvertible) return false;\n\n if (oldBlock.type === newType && !metadata) return true;\n\n const plugin = this.getPlugin(newType);\n\n // Metadata priority: explicit arg > plugin.metadataFromConversion() > plugin.defaultMetadata()\n let newMetadata: Record<string, unknown>;\n if (metadata) {\n newMetadata = { ...metadata };\n } else if (plugin.metadataFromConversion) {\n newMetadata = plugin.metadataFromConversion(oldBlock.type, oldBlock.metadata);\n } else {\n newMetadata = plugin.defaultMetadata();\n }\n\n // Preserve indent level across type conversions\n if (typeof oldBlock.metadata.indentLevel === \"number\" && oldBlock.metadata.indentLevel > 0) {\n newMetadata.indentLevel = oldBlock.metadata.indentLevel;\n }\n\n // Preserve date role fields across type conversions\n if (typeof oldBlock.metadata.dueDate === \"string\" && !(\"dueDate\" in newMetadata)) {\n newMetadata.dueDate = oldBlock.metadata.dueDate;\n }\n if (typeof oldBlock.metadata.scheduledDate === \"string\" && !(\"scheduledDate\" in newMetadata)) {\n newMetadata.scheduledDate = oldBlock.metadata.scheduledDate;\n }\n if (typeof oldBlock.metadata.eventDate === \"string\" && !(\"eventDate\" in newMetadata)) {\n newMetadata.eventDate = oldBlock.metadata.eventDate;\n }\n if (oldBlock.metadata.recurrence && !(\"recurrence\" in newMetadata)) {\n newMetadata.recurrence = oldBlock.metadata.recurrence;\n }\n // Legacy agendaDate fallback\n if (typeof oldBlock.metadata.agendaDate === \"string\" && !(\"agendaDate\" in newMetadata)) {\n newMetadata.agendaDate = oldBlock.metadata.agendaDate;\n }\n\n if (!this._suppressHistory) {\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: id,\n before: { content: oldBlock.content, metadata: { ...oldBlock.metadata }, blockType: oldBlock.type },\n after: { content: oldBlock.content, metadata: { ...newMetadata }, blockType: newType },\n },\n null,\n null,\n );\n }\n\n ctrl.updateBlock({ type: newType, metadata: newMetadata });\n ctrl.setPlugin(plugin);\n\n this.bus.emit(\"block:typeChanged\", {\n blockId: id,\n oldType: oldBlock.type,\n newType,\n });\n\n // Emit contentChanged so AutomergeSync propagates the new metadata\n // (block:typeChanged only updates the type field, not metadata)\n this.bus.emit(\"block:contentChanged\", {\n blockId: id,\n content: oldBlock.content,\n metadata: newMetadata,\n });\n\n return true;\n }\n\n // ── Focus ─────────────────────────────────────────────────────────\n\n /**\n * Focus the block nearest to the given viewport coordinates.\n * If the point is below the last block, focuses or creates an empty\n * paragraph at the end.\n */\n focusAtPoint(clientX: number, clientY: number): void {\n const lastCtrl = this.controllers[this.controllers.length - 1];\n if (!lastCtrl) return;\n\n const rootRect = this.root.getBoundingClientRect();\n const insideEditor =\n clientX >= rootRect.left && clientX <= rootRect.right &&\n clientY >= rootRect.top && clientY <= rootRect.bottom;\n\n // When inside the editor bounds, use precise caret positioning\n if (insideEditor) {\n const lastRect = lastCtrl.mounted\n ? lastCtrl.container.getBoundingClientRect()\n : null;\n if (lastRect && clientY > lastRect.bottom) {\n this.focusOrCreateAtEnd(lastCtrl);\n } else {\n this.focusNearestBlock(clientX, clientY);\n }\n return;\n }\n\n // Outside the editor bounds — find nearest block by Y and focus it\n // with a simple offset (caretRangeFromPoint won't work out here).\n const cy = Math.max(rootRect.top, Math.min(clientY, rootRect.bottom));\n\n const lastRect = lastCtrl.mounted\n ? lastCtrl.container.getBoundingClientRect()\n : null;\n if (lastRect && cy > lastRect.bottom) {\n this.focusOrCreateAtEnd(lastCtrl);\n return;\n }\n\n let bestCtrl: BlockController | null = null;\n let bestDist = Infinity;\n for (const ctrl of this.controllers) {\n if (!ctrl.mounted) continue;\n const rect = ctrl.container.getBoundingClientRect();\n const dist = cy < rect.top ? rect.top - cy\n : cy > rect.bottom ? cy - rect.bottom\n : 0;\n if (dist < bestDist) {\n bestDist = dist;\n bestCtrl = ctrl;\n }\n }\n if (!bestCtrl) return;\n const block = bestCtrl.getBlock();\n const plugin = this.getPlugin(block.type);\n if (plugin.hasTextContent) {\n const offset = clientX >= rootRect.right ? block.content.length : 0;\n this.focusBlock(block.id, offset);\n } else {\n this.focusNonTextBlock(block.id);\n }\n }\n\n private focusOrCreateAtEnd(lastCtrl: BlockController): void {\n const lastBlock = lastCtrl.getBlock();\n const plugin = this.getPlugin(lastBlock.type);\n if (plugin.hasTextContent && lastBlock.content.length === 0) {\n this.focusBlock(lastBlock.id, 0);\n } else {\n const newBlock = this.addBlock(\"paragraph\");\n this.focusBlock(newBlock.id, 0);\n }\n }\n\n focusBlock(id: string, offset?: number): void {\n // Clear non-text block focus when any text block gains focus\n this.blurNonTextBlock();\n const ctrl = this.controllerMap.get(id);\n if (ctrl) {\n // Ensure block content is rendered before focusing\n this.viewport.ensureMounted(id);\n ctrl.focus(offset);\n }\n }\n\n /** Focus a block and select the text range [start, end). */\n private selectBlockRange(blockId: string, start: number, end: number): void {\n this.blurNonTextBlock();\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n this.viewport.ensureMounted(blockId);\n const ce = ctrl.contentEditable;\n if (!ce) { ctrl.focus(start); return; }\n if (document.activeElement !== ce) ce.focus();\n const anchorPos = this.findTextPosition(ce, start);\n const focusPos = this.findTextPosition(ce, end);\n if (!anchorPos.node || !focusPos.node) { ctrl.focus(start); return; }\n const sel = window.getSelection();\n if (!sel) return;\n sel.setBaseAndExtent(anchorPos.node, anchorPos.offset, focusPos.node, focusPos.offset);\n }\n\n /**\n * Scroll a block into view and optionally focus it.\n * Returns `true` if the block was found.\n */\n scrollToBlock(id: string, focus?: boolean): boolean {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) return false;\n // Record current position in jumplist before scrolling\n this.recordJump();\n // Ensure block content is rendered before scrolling to it\n this.viewport.ensureMounted(id);\n ctrl.container.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n if (focus) ctrl.focus(0);\n return true;\n }\n\n /**\n * Focus the block whose container is closest to the given click point.\n * Used when a click lands in the editor but outside any block element.\n */\n private focusNearestBlock(clientX: number, clientY: number): void {\n let bestCtrl: BlockController | null = null;\n let bestDist = Infinity;\n for (const ctrl of this.controllers) {\n if (!ctrl.mounted) continue;\n const rect = ctrl.container.getBoundingClientRect();\n // Distance from click to closest vertical edge of block\n const dist = clientY < rect.top ? rect.top - clientY\n : clientY > rect.bottom ? clientY - rect.bottom\n : 0;\n if (dist < bestDist) {\n bestDist = dist;\n bestCtrl = ctrl;\n }\n }\n if (!bestCtrl) return;\n const block = bestCtrl.getBlock();\n const plugin = this.getPlugin(block.type);\n if (plugin.hasTextContent) {\n this.viewport.ensureMounted(block.id);\n bestCtrl.focusAtPoint(clientX, clientY);\n } else {\n this.focusNonTextBlock(block.id);\n }\n }\n\n /**\n * Handle a click that landed outside any block element.\n * If the click is below the last block, create a new empty paragraph\n * (or focus the existing empty last block). Otherwise focus the nearest block.\n */\n private handleEmptyAreaClick(e: MouseEvent): void {\n if (!this.controllers.length) return;\n e.preventDefault();\n this.focusAtPoint(e.clientX, e.clientY);\n }\n\n // ── Plugin registration ───────────────────────────────────────────\n\n registerBlockType(plugin: BlockTypePlugin): void {\n this.schema.register(plugin);\n }\n\n // ── Custom slash commands ────────────────────────────────────────\n\n /** Register a custom slash menu item with a handler. */\n addSlashMenuItem(\n item: SlashMenuItem,\n handler: (blockId: string) => void,\n ): void {\n this.customSlashItems.push(item);\n this.customSlashHandlers.set(item.type, handler);\n // If the menu was already created, recreate it with the new items\n if (this.slashMenu) {\n this.slashMenu.destroy();\n this.slashMenu = null;\n }\n }\n\n // ── Toolbar extension ───────────────────────────────────────────\n\n /**\n * Add a custom button to the inline formatting toolbar.\n *\n * Buttons with an `attribute` field act as simple toggles (the editor\n * applies/removes the attribute via transactions automatically).\n *\n * Buttons with an `onAction` callback receive a `ToolbarActionContext`\n * and can implement arbitrary behavior (open a popover, apply complex\n * formatting, etc.).\n *\n * Plugin buttons appear after a separator, to the right of the\n * built-in formatting buttons.\n *\n * @example\n * // Simple attribute toggle\n * editor.addToolbarButton({\n * key: \"highlight\",\n * label: \"Highlight\",\n * icon: \"H\",\n * attribute: \"highlight\",\n * });\n *\n * @example\n * // Custom action with render function\n * editor.addToolbarButton({\n * key: \"link\",\n * label: \"Link\",\n * icon: (container) => { container.textContent = \"🔗\"; },\n * onAction: (ctx) => showLinkDialog(ctx),\n * isActive: (ctx) => !!ctx.activeAttributes.href,\n * });\n */\n addToolbarButton(button: ToolbarButton): void {\n this.inlineToolbar?.addButton(button);\n }\n\n /**\n * Remove a previously-added custom toolbar button by key.\n * Returns `true` if the button was found and removed.\n */\n removeToolbarButton(key: string): boolean {\n return this.inlineToolbar?.removeButton(key) ?? false;\n }\n\n // ── Block action menu extension ─────────────────────────────────\n\n /** Add a custom item to the block action context menu. */\n addBlockActionItem(entry: BlockActionMenuEntry): void {\n this.customActionItems.push(entry);\n }\n\n /** Remove a custom block action item by key. Returns true if found. */\n removeBlockActionItem(key: string): boolean {\n const idx = this.customActionItems.findIndex((e) => e.key === key);\n if (idx < 0) return false;\n this.customActionItems.splice(idx, 1);\n return true;\n }\n\n // ── Serialization ─────────────────────────────────────────────────\n\n /** Return all registered commands with execute handlers for external integration. */\n getCommands(): ExternalCommandEntry[] {\n return this.commands.listFull();\n }\n\n toJSON(): EditorJSON {\n return {\n blocks: this.controllers.map((c) => blockToJSON(c.getBlock())),\n };\n }\n\n static fromJSON(\n root: HTMLElement,\n json: EditorJSON,\n options?: EditorOptions,\n ): Editor {\n const blocks = json.blocks.map(blockFromJSON);\n return new Editor(root, { ...options, initialBlocks: blocks });\n }\n\n // ── Theme ─────────────────────────────────────────────────────────\n\n /**\n * Set the color theme. `\"system\"` follows `prefers-color-scheme`,\n * `\"light\"` / `\"dark\"` forces a specific theme.\n */\n setTheme(mode: ThemeMode): void {\n this.themeMode = mode;\n if (mode === \"system\") {\n this.root.removeAttribute(\"data-blx-theme\");\n } else {\n this.root.setAttribute(\"data-blx-theme\", mode);\n }\n this.bus.emit(\"editor:themeChanged\", { theme: mode });\n }\n\n /** Return the current theme mode. */\n getTheme(): ThemeMode {\n return this.themeMode;\n }\n\n // ── Undo / Redo ───────────────────────────────────────────────────\n\n /** Undo the last action. Returns true if an entry was undone. */\n undo(): boolean {\n const entry = this.undoManager.popUndo();\n if (!entry) return false;\n\n this._suppressHistory = true;\n try {\n // Process actions in reverse order\n for (let i = entry.actions.length - 1; i >= 0; i--) {\n this.applyUndoAction(entry.actions[i], \"undo\");\n }\n\n // Restore cursor position\n if (entry.beforeCursor) {\n const ctrl = this.controllerMap.get(entry.beforeCursor.blockId);\n if (ctrl) {\n this.focusBlock(entry.beforeCursor.blockId, entry.beforeCursor.offset);\n }\n }\n } finally {\n this._suppressHistory = false;\n }\n\n this.recomputeListIndices();\n this.bus.emit(\"editor:undo\", {});\n this.emitHistoryChanged();\n return true;\n }\n\n /** Redo the last undone action. Returns true if an entry was redone. */\n redo(): boolean {\n const entry = this.undoManager.popRedo();\n if (!entry) return false;\n\n this._suppressHistory = true;\n try {\n // Process actions in forward order\n for (const action of entry.actions) {\n this.applyUndoAction(action, \"redo\");\n }\n\n // Restore cursor position\n if (entry.afterCursor) {\n const ctrl = this.controllerMap.get(entry.afterCursor.blockId);\n if (ctrl) {\n this.focusBlock(entry.afterCursor.blockId, entry.afterCursor.offset);\n }\n }\n } finally {\n this._suppressHistory = false;\n }\n\n this.recomputeListIndices();\n this.bus.emit(\"editor:redo\", {});\n this.emitHistoryChanged();\n return true;\n }\n\n /** Whether there are entries to undo */\n canUndo(): boolean {\n return this.undoManager.canUndo();\n }\n\n /** Whether there are entries to redo */\n canRedo(): boolean {\n return this.undoManager.canRedo();\n }\n\n /** Execute a function with history recording suppressed. */\n withSuppressedHistory(fn: () => void): void {\n const prev = this._suppressHistory;\n this._suppressHistory = true;\n try { fn(); } finally { this._suppressHistory = prev; }\n }\n\n /** Clear all undo/redo history */\n clearHistory(): void {\n this.undoManager.clear();\n this.emitHistoryChanged();\n }\n\n // ── Fold API ──────────────────────────────────────────────────\n\n /** Toggle fold on a heading block */\n toggleFold(headingBlockId: string): void {\n const block = this.getBlock(headingBlockId);\n if (!block || block.type !== \"heading\") return;\n this.foldManager.toggle(headingBlockId, this.getBlocks());\n this.applyFoldVisibility();\n this.bus.emit(\"editor:foldChanged\", {\n blockId: headingBlockId,\n folded: this.foldManager.isFolded(headingBlockId),\n });\n }\n\n /** Fold a heading section */\n foldBlock(headingBlockId: string): void {\n this.foldManager.fold(headingBlockId, this.getBlocks());\n this.applyFoldVisibility();\n this.bus.emit(\"editor:foldChanged\", {\n blockId: headingBlockId, folded: true,\n });\n }\n\n /** Unfold a heading section */\n unfoldBlock(headingBlockId: string): void {\n this.foldManager.unfold(headingBlockId, this.getBlocks());\n this.applyFoldVisibility();\n this.bus.emit(\"editor:foldChanged\", {\n blockId: headingBlockId, folded: false,\n });\n }\n\n /** Fold all headings */\n foldAll(): void {\n this.foldManager.foldAll(this.getBlocks());\n this.applyFoldVisibility();\n this.bus.emit(\"editor:foldChanged\", { blockId: null, folded: true });\n }\n\n /** Unfold all headings */\n unfoldAll(): void {\n this.foldManager.unfoldAll(this.getBlocks());\n this.applyFoldVisibility();\n this.bus.emit(\"editor:foldChanged\", { blockId: null, folded: false });\n }\n\n /** Check if a heading is folded */\n isFolded(headingBlockId: string): boolean {\n return this.foldManager.isFolded(headingBlockId);\n }\n\n /** Check if a block is hidden by a fold */\n isBlockHidden(blockId: string): boolean {\n return this.foldManager.isHidden(blockId);\n }\n\n /** Load fold state (e.g. from localStorage on document open) */\n loadFoldState(state: FoldState): void {\n this.foldManager.loadState(state);\n this.foldManager.recompute(this.getBlocks());\n this.applyFoldVisibility();\n }\n\n /** Get current fold state for persistence */\n getFoldState(): FoldState {\n return this.foldManager.getState();\n }\n\n private applyFoldVisibility(): void {\n const hidden = this.foldManager.getHiddenBlockIds();\n for (const ctrl of this.controllers) {\n const container = ctrl.container;\n const wasHidden = container.classList.contains(\"blx-fold-hidden\");\n if (hidden.has(ctrl.blockId)) {\n container.classList.add(\"blx-fold-hidden\");\n container.classList.remove(\"blx-fold-revealed\");\n } else {\n if (wasHidden) {\n // Block was hidden and is now revealed — animate in\n container.classList.add(\"blx-fold-revealed\");\n container.addEventListener(\"animationend\", () => {\n container.classList.remove(\"blx-fold-revealed\");\n }, { once: true });\n }\n container.classList.remove(\"blx-fold-hidden\");\n }\n if (this.foldManager.isFolded(ctrl.blockId)) {\n container.classList.add(\"blx-heading-folded\");\n } else {\n container.classList.remove(\"blx-heading-folded\");\n }\n }\n }\n\n // ── Navigation History (Jumplist) ────────────────────────────────\n\n /**\n * Navigate backwards in the jumplist (Ctrl-O).\n * Returns true if a jump was performed.\n */\n jumpBack(): boolean {\n // Push current position so forward() can return here.\n // This mirrors vim behavior: Ctrl-O records where you are before jumping.\n let cursor = this.getCursorState();\n if (!cursor && this.blockSelectFocus) {\n cursor = { blockId: this.blockSelectFocus, offset: 0 };\n }\n // Fallback: use last focused block (covers table cells, etc.)\n if (!cursor && this._lastFocusedBlockId) {\n cursor = { blockId: this._lastFocusedBlockId, offset: 0 };\n }\n if (cursor) {\n this.jumpList.push(cursor);\n }\n const target = this.jumpList.back();\n if (!target) return false;\n const ctrl = this.controllerMap.get(target.blockId);\n if (!ctrl) return false;\n // Exit normal/visualBlock mode before focusing\n if (this.editorMode !== \"insert\") {\n this.exitToInsertModeSilent();\n }\n if (ctrl.getBlock().type === \"table\") {\n this.focusTableCell(target.blockId, \"down\");\n } else {\n this.focusBlock(target.blockId, target.offset);\n }\n this.bus.emit(\"editor:jumpBack\", target);\n return true;\n }\n\n /**\n * Navigate forwards in the jumplist (Ctrl-I).\n * Returns true if a jump was performed.\n */\n jumpForward(): boolean {\n const target = this.jumpList.forward();\n if (!target) return false;\n const ctrl = this.controllerMap.get(target.blockId);\n if (!ctrl) return false;\n if (ctrl.getBlock().type === \"table\") {\n this.focusTableCell(target.blockId, \"down\");\n } else {\n this.focusBlock(target.blockId, target.offset);\n }\n this.bus.emit(\"editor:jumpForward\", target);\n return true;\n }\n\n /**\n * Jump to the last edit position.\n * Records current position in jumplist, then focuses the last edit.\n * Returns true if a jump was performed.\n */\n jumpToLastEdit(): boolean {\n if (!this._lastEditPosition) return false;\n const ctrl = this.controllerMap.get(this._lastEditPosition.blockId);\n if (!ctrl) return false;\n this.recordJump();\n this.focusBlock(this._lastEditPosition.blockId, this._lastEditPosition.offset);\n return true;\n }\n\n /** Record the current cursor position in the jumplist before a jump */\n recordJump(): void {\n let cursor = this.getCursorState();\n // In normal/visualBlock mode, no contenteditable is focused so\n // getCursorState() returns null. Fall back to block selection state.\n if (!cursor && this.blockSelectFocus) {\n cursor = { blockId: this.blockSelectFocus, offset: 0 };\n }\n // Fallback: use last focused block (covers table cells, etc.)\n if (!cursor && this._lastFocusedBlockId) {\n cursor = { blockId: this._lastFocusedBlockId, offset: 0 };\n }\n if (cursor) {\n this.jumpList.push(cursor);\n }\n }\n\n /** Whether there are entries to jump back to */\n canJumpBack(): boolean {\n return this.jumpList.canGoBack();\n }\n\n /** Whether there are entries to jump forward to */\n canJumpForward(): boolean {\n return this.jumpList.canGoForward();\n }\n\n // ── CRDT Log & Replay ─────────────────────────────────────────\n\n /**\n * Enable CRDT operation logging. Captures the current editor state as\n * the initial snapshot and begins recording every subsequent edit.\n * Returns the log instance.\n */\n enableCrdtLog(): CrdtLog {\n if (!this.crdtLog) {\n this.crdtLog = new CrdtLog();\n }\n this.crdtLog.setInitialState(this.toJSON().blocks);\n return this.crdtLog;\n }\n\n /** Get the CRDT log, or null if not enabled */\n getCrdtLog(): CrdtLog | null {\n return this.crdtLog;\n }\n\n /** Whether replay mode is currently active */\n get isReplayActive(): boolean {\n return this._replayActive;\n }\n\n /**\n * Show the replay bar UI at the bottom of the editor.\n * Automatically enables the CRDT log if not already enabled.\n */\n showReplayUI(): void {\n if (!this.crdtLog) this.enableCrdtLog();\n if (this._replayUI) return;\n\n this._replayUI = new ReplayUI(this.root, {\n onSeek: (pos) => this.replaySeekTo(pos),\n onPlay: () => this.replayPlay(),\n onPause: () => this.replayPause(),\n onStepForward: () => this.replayStepForward(),\n onStepBackward: () => this.replayStepBackward(),\n onExit: () => this.exitReplayMode(),\n getIsPlaying: () => this._replayTimer !== null,\n getCurrentPosition: () => this._replayPosition,\n getTotalOperations: () => this.crdtLog?.getOperationCount() ?? 0,\n });\n\n this.enterReplayMode();\n }\n\n /** Hide the replay bar UI */\n hideReplayUI(): void {\n this.exitReplayMode();\n }\n\n /** Enter replay mode: save state, disable editing */\n private enterReplayMode(): void {\n if (this._replayActive) return;\n if (!this.crdtLog) return;\n\n // Save current state so we can restore on exit\n this._replaySavedState = this.toJSON().blocks;\n this._replayActive = true;\n this._replayPosition = this.crdtLog.getOperationCount();\n\n // Disable editing\n this.root.classList.add(\"blx-replay-mode\");\n for (const ctrl of this.controllers) {\n const el = ctrl.container.querySelector(\"[contenteditable]\");\n if (el) (el as HTMLElement).contentEditable = \"false\";\n }\n }\n\n /** Exit replay mode: restore saved state, re-enable editing */\n private exitReplayMode(): void {\n this.replayPause();\n\n if (this._replaySavedState && this._replayActive) {\n // Restore editor to the state it was in when replay began\n this.loadBlockState(this._replaySavedState);\n }\n\n this._replayActive = false;\n this._replaySavedState = null;\n this._replayPosition = 0;\n this.root.classList.remove(\"blx-replay-mode\");\n\n // Re-enable editing\n for (const ctrl of this.controllers) {\n const el = ctrl.container.querySelector(\"[contenteditable]\");\n if (el) (el as HTMLElement).contentEditable = \"true\";\n }\n\n if (this._replayUI) {\n this._replayUI.destroy();\n this._replayUI = null;\n }\n }\n\n /** Seek to a specific position in the CRDT log */\n private replaySeekTo(position: number): void {\n if (!this.crdtLog || !this._replayActive) return;\n\n const total = this.crdtLog.getOperationCount();\n const target = Math.max(0, Math.min(position, total));\n\n if (target === this._replayPosition) return;\n\n if (target > this._replayPosition) {\n // Apply operations forward\n for (let i = this._replayPosition; i < target; i++) {\n const op = this.crdtLog.getOperation(i);\n if (op) this.applyCrdtOperation(op, \"forward\");\n }\n } else {\n // Revert operations backward\n for (let i = this._replayPosition - 1; i >= target; i--) {\n const op = this.crdtLog.getOperation(i);\n if (op) this.applyCrdtOperation(op, \"backward\");\n }\n }\n\n this._replayPosition = target;\n\n // Disable contentEditable on any newly created blocks\n for (const ctrl of this.controllers) {\n const el = ctrl.container.querySelector(\"[contenteditable]\");\n if (el) (el as HTMLElement).contentEditable = \"false\";\n }\n\n // Render remote cursors for all peers at this replay position\n this.renderReplayCursors();\n }\n\n /** Render peer cursors based on the current replay position */\n private renderReplayCursors(): void {\n const cursors = this.computeReplayCursors(this._replayPosition);\n\n // Group by blockId\n const byBlock = new Map<string, RemoteCursor[]>();\n for (const c of cursors) {\n let list = byBlock.get(c.blockId);\n if (!list) {\n list = [];\n byBlock.set(c.blockId, list);\n }\n list.push(c);\n }\n\n for (const ctrl of this.controllers) {\n const ce = ctrl.contentEditable;\n if (!ce) continue;\n const blockCursors = byBlock.get(ctrl.getBlock().id);\n if (blockCursors && blockCursors.length > 0) {\n renderRemoteCursors(ce, blockCursors);\n } else {\n clearRemoteCursors(ce);\n }\n }\n }\n\n /** Step one operation forward in replay */\n private replayStepForward(): void {\n if (!this.crdtLog) return;\n if (this._replayPosition < this.crdtLog.getOperationCount()) {\n this.replaySeekTo(this._replayPosition + 1);\n this._replayUI?.update();\n }\n }\n\n /** Step one operation backward in replay */\n private replayStepBackward(): void {\n if (this._replayPosition > 0) {\n this.replaySeekTo(this._replayPosition - 1);\n this._replayUI?.update();\n }\n }\n\n /** Start auto-playing operations */\n private replayPlay(): void {\n if (this._replayTimer !== null) return;\n this._replayTimer = setInterval(() => {\n if (!this.crdtLog || this._replayPosition >= this.crdtLog.getOperationCount()) {\n this.replayPause();\n this._replayUI?.update();\n return;\n }\n this.replayStepForward();\n }, this._replaySpeed);\n }\n\n /** Pause auto-play */\n private replayPause(): void {\n if (this._replayTimer !== null) {\n clearInterval(this._replayTimer);\n this._replayTimer = null;\n }\n }\n\n /** Apply a single CRDT operation in the given direction */\n private applyCrdtOperation(\n op: { actions: UndoAction[] },\n direction: \"forward\" | \"backward\",\n ): void {\n this._suppressHistory = true;\n try {\n if (direction === \"forward\") {\n for (const action of op.actions) {\n this.applyUndoAction(action, \"redo\");\n }\n } else {\n for (let i = op.actions.length - 1; i >= 0; i--) {\n this.applyUndoAction(op.actions[i], \"undo\");\n }\n }\n } finally {\n this._suppressHistory = false;\n }\n this.recomputeListIndices();\n }\n\n /**\n * Replace all blocks in the editor with the given block state.\n * Used by replay to restore state on exit.\n */\n private loadBlockState(blocks: BlockJSON[]): void {\n this._suppressHistory = true;\n try {\n // Remove all existing blocks\n const ids = this.controllers.map((c) => c.getBlock().id);\n for (const id of ids) {\n this.removeBlock(id);\n }\n // Add blocks from state\n for (const blockJson of blocks) {\n this.addBlock(blockFromJSON(blockJson));\n }\n } finally {\n this._suppressHistory = false;\n }\n this.recomputeListIndices();\n }\n\n // ── Multiplayer / Remote Cursors ─────────────────────────────────\n\n /**\n * Set the local peer identity. All subsequent CRDT operations will be\n * tagged with this peer ID. Call this before users start editing.\n */\n setLocalPeer(peer: CrdtPeer): void {\n this._localPeer = peer;\n this._peers.set(peer.id, peer);\n this.crdtLog?.setLocalPeerId(peer.id);\n }\n\n /** Get the local peer, or null if not set */\n getLocalPeer(): CrdtPeer | null {\n return this._localPeer;\n }\n\n /**\n * Register a remote peer. Their cursor will be rendered when\n * `setRemoteCursor()` is called.\n */\n addPeer(peer: CrdtPeer): void {\n this._peers.set(peer.id, peer);\n }\n\n /** Remove a remote peer and their cursor */\n removePeer(peerId: string): void {\n this._peers.delete(peerId);\n this._remoteCursors.delete(peerId);\n const timer = this._cursorIdleTimers.get(peerId);\n if (timer) {\n clearTimeout(timer);\n this._cursorIdleTimers.delete(peerId);\n }\n this.scheduleRemoteCursorRender();\n }\n\n /** Get all registered peers (including local) */\n getPeers(): CrdtPeer[] {\n return Array.from(this._peers.values());\n }\n\n /**\n * Update a remote peer's cursor position. Pass null blockId to hide the cursor.\n * When endOffset is provided and differs from offset, a selection highlight is rendered.\n */\n setRemoteCursor(\n peerId: string,\n blockId: string | null,\n offset?: number,\n endOffset?: number,\n endBlockId?: string,\n ): void {\n if (!blockId) {\n this._remoteCursors.delete(peerId);\n const existingTimer = this._cursorIdleTimers.get(peerId);\n if (existingTimer) {\n clearTimeout(existingTimer);\n this._cursorIdleTimers.delete(peerId);\n }\n } else {\n const peer = this._peers.get(peerId);\n if (!peer) return;\n this._remoteCursors.set(peerId, {\n peerId,\n displayName: peer.displayName,\n color: peer.color,\n blockId,\n offset: offset ?? 0,\n endOffset,\n endBlockId,\n lastUpdated: Date.now(),\n });\n\n // Set up idle timer: after 3s, re-render to transition active→idle\n const existingTimer = this._cursorIdleTimers.get(peerId);\n if (existingTimer) clearTimeout(existingTimer);\n this._cursorIdleTimers.set(\n peerId,\n setTimeout(() => {\n this._cursorIdleTimers.delete(peerId);\n this.scheduleRemoteCursorRender();\n }, 3000),\n );\n }\n this.scheduleRemoteCursorRender();\n }\n\n /** Get all current remote cursor positions */\n getRemoteCursors(): RemoteCursor[] {\n return Array.from(this._remoteCursors.values());\n }\n\n /**\n * Apply a remote peer's operation to the editor.\n * This applies the operation, records it in the CRDT log, and updates\n * the remote peer's cursor to the operation's afterCursor.\n */\n applyRemoteOperation(op: CrdtOperation): void {\n // Apply the actions to the editor (suppressing local history)\n this.applyCrdtOperation(op, \"forward\");\n\n // Record in the CRDT log\n this.crdtLog?.appendRemote(op);\n\n // Update the remote peer's cursor\n if (op.peerId && op.afterCursor) {\n this.setRemoteCursor(op.peerId, op.afterCursor.blockId, op.afterCursor.offset);\n }\n }\n\n /** Schedule a microtask to render remote cursors (batches rapid updates) */\n private scheduleRemoteCursorRender(): void {\n if (this._remoteCursorRenderScheduled) return;\n this._remoteCursorRenderScheduled = true;\n queueMicrotask(() => {\n this._remoteCursorRenderScheduled = false;\n this.renderAllRemoteCursors();\n });\n }\n\n /** Render remote cursors into all blocks that have them */\n private renderAllRemoteCursors(): void {\n // Build block order index for multi-block range computation\n const blockOrder: string[] = [];\n const ctrlMap = new Map<string, (typeof this.controllers)[number]>();\n for (const ctrl of this.controllers) {\n const id = ctrl.getBlock().id;\n blockOrder.push(id);\n ctrlMap.set(id, ctrl);\n }\n\n // For each cursor, compute the set of blocks it touches and how\n type BlockHit = {\n cursor: RemoteCursor;\n /** \"border\" = left-border indicator (multi-block), \"single\" = inline text cursor/selection */\n mode: \"border\" | \"single\";\n };\n const byBlock = new Map<string, BlockHit[]>();\n\n const addHit = (blockId: string, hit: BlockHit) => {\n let list = byBlock.get(blockId);\n if (!list) { list = []; byBlock.set(blockId, list); }\n list.push(hit);\n };\n\n for (const cursor of this._remoteCursors.values()) {\n if (cursor.endBlockId) {\n // Block selection — endBlockId being set means block-level selection.\n // When endBlockId === blockId, it's a single-block block selection.\n // When different, it's a multi-block selection spanning a range.\n const startIdx = blockOrder.indexOf(cursor.blockId);\n const endIdx = blockOrder.indexOf(cursor.endBlockId);\n if (startIdx === -1 || endIdx === -1) {\n addHit(cursor.blockId, { cursor, mode: \"border\" });\n continue;\n }\n const first = Math.min(startIdx, endIdx);\n const last = Math.max(startIdx, endIdx);\n for (let i = first; i <= last; i++) {\n addHit(blockOrder[i], { cursor, mode: \"border\" });\n }\n } else {\n addHit(cursor.blockId, { cursor, mode: \"single\" });\n }\n }\n\n // Render into each block\n for (const ctrl of this.controllers) {\n const block = ctrl.getBlock();\n const ce = ctrl.contentEditable;\n const hits = byBlock.get(block.id);\n\n if (!hits || hits.length === 0) {\n if (ce) clearRemoteCursors(ce);\n else clearRemoteCursorsFromContainer(ctrl.container);\n continue;\n }\n\n // Separate border hits (multi-block) from single hits (inline cursor/selection)\n const borderHits = hits.filter((h) => h.mode === \"border\");\n const singleHits = hits.filter((h) => h.mode === \"single\");\n\n // Clear first, then render both types — both render functions clear\n // the block's overlay elements, so we render borders first (they go\n // into the overlay), then inline cursors (which clear+re-add for this block).\n // To avoid conflicts, borders use the block container and inline uses CE.\n if (borderHits.length > 0) {\n renderBlockSelectionBorder(ctrl.container, borderHits.map((h) => h.cursor));\n }\n if (singleHits.length > 0 && ce) {\n renderRemoteCursors(ce, singleHits.map((h) => h.cursor));\n } else if (singleHits.length > 0) {\n // Non-text block with a single-block cursor — show border\n renderBlockSelectionBorder(ctrl.container, singleHits.map((h) => h.cursor));\n }\n if (borderHits.length === 0 && singleHits.length === 0) {\n if (ce) clearRemoteCursors(ce);\n else clearRemoteCursorsFromContainer(ctrl.container);\n }\n }\n }\n\n /**\n * Compute all peer cursor positions at a given replay position by\n * replaying the operation log. Returns the last known cursor for\n * each peer up to that point.\n */\n private computeReplayCursors(position: number): RemoteCursor[] {\n if (!this.crdtLog) return [];\n\n const peerCursors = new Map<string, { blockId: string; offset: number }>();\n\n for (let i = 0; i < position; i++) {\n const op = this.crdtLog.getOperation(i);\n if (!op || !op.peerId || !op.afterCursor) continue;\n peerCursors.set(op.peerId, {\n blockId: op.afterCursor.blockId,\n offset: op.afterCursor.offset,\n });\n }\n\n const result: RemoteCursor[] = [];\n for (const [peerId, cursor] of peerCursors) {\n const peer = this._peers.get(peerId);\n if (!peer) continue;\n // Verify the block still exists at this replay position\n if (!this.controllerMap.has(cursor.blockId)) continue;\n result.push({\n peerId,\n displayName: peer.displayName,\n color: peer.color,\n blockId: cursor.blockId,\n offset: cursor.offset,\n });\n }\n\n return result;\n }\n\n // ── Automerge CRDT ──────────────────────────────────────────────\n\n /**\n * Enable Automerge CRDT sync. Returns the AutomergeSync instance\n * which provides the sync protocol API (generateSyncMessage,\n * receiveSyncMessage, merge, save/load, etc.).\n *\n * Calling this multiple times returns the same instance.\n */\n enableAutomerge(options?: AutomergeSyncOptions): AutomergeSync {\n if (this._automergeSync) return this._automergeSync;\n\n this._automergeSync = new AutomergeSync(\n {\n getBlocks: () => this.getBlocks(),\n getBlock: (id) => this.getBlock(id),\n addBlock: (block, index) => {\n this._suppressHistory = true;\n try {\n return this.addBlock(block, index);\n } finally {\n this._suppressHistory = false;\n }\n },\n removeBlock: (id) => {\n this._suppressHistory = true;\n try {\n return this.removeBlock(id);\n } finally {\n this._suppressHistory = false;\n }\n },\n moveBlock: (id, toIndex) => {\n this._suppressHistory = true;\n try {\n return this.moveBlock(id, toIndex);\n } finally {\n this._suppressHistory = false;\n }\n },\n updateBlockContent: (blockId, content, metadata, blockType) => {\n this.updateBlockContent(blockId, content, metadata, blockType);\n },\n replaceAllBlocks: (blocks) => {\n this.replaceAllBlocks(blocks);\n },\n bus: this.bus,\n },\n options,\n );\n\n return this._automergeSync;\n }\n\n /** Get the AutomergeSync instance, or null if not enabled */\n getAutomergeSync(): AutomergeSync | null {\n return this._automergeSync;\n }\n\n /**\n * Update a block's content, metadata, and optionally type.\n * Suppresses undo history and re-renders with cursor preservation.\n * Used by AutomergeSync for remote changes and by consumers for\n * streaming / progressive content updates.\n */\n updateBlockContent(\n blockId: string,\n content: AttributedString,\n metadata?: Record<string, unknown>,\n blockType?: string,\n ): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const oldBlock = ctrl.getBlock();\n const effectiveType = blockType ?? oldBlock.type;\n const effectiveMetadata = metadata ?? oldBlock.metadata;\n\n this._suppressHistory = true;\n try {\n ctrl.updateBlock({\n content,\n metadata: effectiveMetadata,\n type: effectiveType,\n });\n\n if (effectiveType !== oldBlock.type) {\n // Type changed — full plugin swap required\n ctrl.setPlugin(this.getPlugin(effectiveType));\n } else {\n // Same type — re-render with cursor preservation so remote sync\n // doesn't destroy the user's editing position\n ctrl.rerender();\n }\n } finally {\n this._suppressHistory = false;\n }\n\n // Emit events so CRDT sync and persistence pipelines pick up the change\n this.bus.emit(\"block:contentChanged\", {\n blockId,\n content,\n metadata: effectiveMetadata,\n });\n if (effectiveType !== oldBlock.type) {\n this.bus.emit(\"block:typeChanged\", {\n blockId,\n oldType: oldBlock.type,\n newType: effectiveType,\n });\n }\n }\n\n // ── Undo internals ──────────────────────────────────────────────\n\n /**\n * Apply a single undo action in the given direction.\n * Called with _suppressHistory = true.\n */\n private applyUndoAction(\n action: UndoAction,\n direction: \"undo\" | \"redo\",\n ): void {\n switch (action.type) {\n case \"contentChange\": {\n const state = direction === \"undo\" ? action.before : action.after;\n const ctrl = this.controllerMap.get(action.blockId);\n if (!ctrl) break;\n // Ensure block is mounted so setPlugin() can re-render\n this.viewport.ensureMounted(action.blockId);\n const oldBlock = ctrl.getBlock();\n ctrl.updateBlock({\n content: state.content,\n metadata: state.metadata,\n type: state.blockType,\n });\n ctrl.setPlugin(this.getPlugin(state.blockType));\n this.bus.emit(\"block:contentChanged\", {\n blockId: action.blockId,\n content: state.content,\n metadata: state.metadata,\n });\n if (state.blockType !== oldBlock.type) {\n this.bus.emit(\"block:typeChanged\", {\n blockId: action.blockId,\n oldType: oldBlock.type,\n newType: state.blockType,\n });\n }\n break;\n }\n case \"addBlock\": {\n if (direction === \"undo\") {\n // Undo add = remove\n this.removeBlock(action.block.id);\n } else {\n // Redo add = re-insert\n this.addBlock(\n {\n id: action.block.id,\n type: action.block.type,\n content: action.block.content,\n metadata: action.block.metadata,\n },\n action.index,\n );\n }\n break;\n }\n case \"removeBlock\": {\n if (direction === \"undo\") {\n // Undo remove = re-insert\n this.addBlock(\n {\n id: action.block.id,\n type: action.block.type,\n content: action.block.content,\n metadata: action.block.metadata,\n },\n action.index,\n );\n } else {\n // Redo remove = remove again\n this.removeBlock(action.block.id);\n }\n break;\n }\n case \"moveBlock\": {\n if (direction === \"undo\") {\n this.moveBlock(action.blockId, action.fromIndex);\n } else {\n this.moveBlock(action.blockId, action.toIndex);\n }\n break;\n }\n }\n }\n\n /** Record a single undo action (delegates to compound group if active) */\n private recordUndoAction(\n action: UndoAction,\n beforeCursor: CursorState | null,\n afterCursor: CursorState | null,\n ): void {\n this.undoManager.record(action, beforeCursor, afterCursor);\n this.crdtLog?.record(action, beforeCursor, afterCursor);\n this.emitHistoryChanged();\n }\n\n /** Create a snapshot of a block for undo storage */\n private snapshotBlock(block: Block): BlockSnapshot {\n return {\n id: block.id,\n type: block.type,\n content: block.content, // immutable, safe to reference\n metadata: { ...block.metadata },\n };\n }\n\n /** Get the current cursor state, or null if nothing is focused */\n private getCursorState(): CursorState | null {\n const focusedId = this.getFocusedBlockId();\n if (!focusedId) return null;\n const ctrl = this.controllerMap.get(focusedId);\n if (!ctrl) return null;\n const offset = ctrl.getCursorOffset() ?? 0;\n return { blockId: focusedId, offset };\n }\n\n /** Save the current cursor so it can be restored after an overlay is dismissed. */\n saveOverlayCursor(): void {\n this._preOverlayCursor = this.getCursorState()\n ?? (this._lastFocusedBlockId\n ? { blockId: this._lastFocusedBlockId, offset: 0 }\n : null);\n }\n\n /** Restore focus to the position saved before an overlay opened, then clear it. */\n restoreOverlayCursor(): void {\n const saved = this._preOverlayCursor;\n this._preOverlayCursor = null;\n if (!saved) return;\n this.focusBlock(saved.blockId, saved.offset);\n }\n\n /** Emit historyChanged event with current canUndo/canRedo state */\n private emitHistoryChanged(): void {\n this.bus.emit(\"editor:historyChanged\", {\n canUndo: this.undoManager.canUndo(),\n canRedo: this.undoManager.canRedo(),\n });\n }\n\n /** Listen to block:contentChanged to record transaction-based content changes */\n private setupUndoContentListener(): void {\n this.bus.on(\"block:contentChanged\", (payload) => {\n // Track last edit position (always, even during undo/redo replay)\n if (!this._suppressHistory) {\n const editCursor = this.getCursorState();\n if (editCursor) {\n this._lastEditPosition = editCursor;\n }\n }\n\n if (this._suppressHistory) return;\n // Only record if we have before state (set by applyTransaction/applyTransactionToBlock)\n if (!payload.previousContent || !payload.previousMetadata) return;\n // Skip if within a compound group (split/merge handle their own recording)\n if (this.undoManager.isGrouping) return;\n\n const ctrl = this.controllerMap.get(payload.blockId);\n const blockType = ctrl?.getBlock().type ?? \"paragraph\";\n\n const beforeCursor: CursorState = {\n blockId: payload.blockId,\n offset: payload.previousCursorOffset ?? 0,\n };\n const afterCursor = this.getCursorState() ?? {\n blockId: payload.blockId,\n offset: payload.content.length,\n };\n\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: payload.blockId,\n before: {\n content: payload.previousContent,\n metadata: { ...payload.previousMetadata },\n blockType,\n },\n after: {\n content: payload.content,\n metadata: payload.metadata ? { ...payload.metadata } : { ...payload.previousMetadata },\n blockType,\n },\n },\n beforeCursor,\n afterCursor,\n );\n });\n }\n\n /** Set up keyboard shortcuts for undo/redo and navigation history */\n private setupUndoShortcuts(): void {\n this.undoKeyHandler = (e: KeyboardEvent) => {\n // Don't intercept when focus is in a native input (e.g. search panel)\n const tag = document.activeElement?.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return;\n\n const mod = e.metaKey || e.ctrlKey;\n\n // Cmd/Ctrl+Z = Undo\n if (mod && !e.altKey && e.key.toLowerCase() === \"z\" && !e.shiftKey) {\n e.preventDefault();\n this.undo();\n return;\n }\n\n // Cmd/Ctrl+Shift+Z = Redo | Cmd/Ctrl+Y = Redo\n if (\n (mod && !e.altKey && e.key.toLowerCase() === \"z\" && e.shiftKey) ||\n (mod && !e.altKey && e.key.toLowerCase() === \"y\" && !e.shiftKey)\n ) {\n e.preventDefault();\n this.redo();\n return;\n }\n\n // Mod+O = Jump back (cross-platform: both Ctrl and Cmd)\n if (mod && !e.altKey && !e.shiftKey && e.key.toLowerCase() === \"o\") {\n e.preventDefault();\n this.jumpBack();\n return;\n }\n\n // Mod+Shift+I = Jump forward (Shift avoids Mod+I = italic conflict)\n if (mod && !e.altKey && e.shiftKey && e.key.toLowerCase() === \"i\") {\n e.preventDefault();\n this.jumpForward();\n return;\n }\n };\n\n document.addEventListener(\"keydown\", this.undoKeyHandler);\n }\n\n /** Track block focus changes for the jumplist */\n private setupJumpListTracking(): void {\n this.bus.on(\"block:focus\", ({ blockId }) => {\n if (this._lastFocusedBlockId && this._lastFocusedBlockId !== blockId) {\n const lastIndex = this.getBlockIndex(this._lastFocusedBlockId);\n const newIndex = this.getBlockIndex(blockId);\n // Record as a jump if the focus moved more than 1 block away\n if (lastIndex >= 0 && newIndex >= 0 && Math.abs(lastIndex - newIndex) > 1) {\n const lastCtrl = this.controllerMap.get(this._lastFocusedBlockId);\n this.jumpList.push({\n blockId: this._lastFocusedBlockId,\n offset: lastCtrl?.getCursorOffset() ?? 0,\n });\n }\n }\n this._lastFocusedBlockId = blockId;\n });\n }\n\n /** Re-render remote cursors after any DOM change (content, add, remove) and on scroll */\n private setupRemoteCursorRefresh(): void {\n const refresh = () => {\n if (this._remoteCursors.size > 0 && !this._replayActive) {\n this.scheduleRemoteCursorRender();\n }\n };\n this.bus.on(\"block:contentChanged\", refresh);\n this.bus.on(\"block:added\", refresh);\n this.bus.on(\"block:removed\", refresh);\n this.bus.on(\"block:typeChanged\", refresh);\n\n // Re-render on scroll so overlay positions stay in sync with content.\n // Uses requestAnimationFrame to coalesce rapid scroll events.\n const scrollEl = this.findScrollParent();\n let scrollRaf = 0;\n const onScroll = () => {\n if (scrollRaf) return;\n scrollRaf = requestAnimationFrame(() => {\n scrollRaf = 0;\n refresh();\n });\n };\n scrollEl.addEventListener(\"scroll\", onScroll, { passive: true });\n this._cursorScrollCleanup = () => {\n scrollEl.removeEventListener(\"scroll\", onScroll);\n if (scrollRaf) cancelAnimationFrame(scrollRaf);\n };\n }\n\n // ── Internal: used by SelectionManager ─────────────────────────────\n\n /** @internal Apply a pre-computed transaction result to a block */\n applyTransactionToBlock(blockId: string, result: TransactionResult): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const before = ctrl.getBlock();\n ctrl.updateBlock({ content: result.content, metadata: result.metadata });\n ctrl.setPlugin(this.getPlugin(ctrl.getBlock().type));\n this.bus.emit(\"block:contentChanged\", {\n blockId,\n content: result.content,\n metadata: result.metadata,\n previousContent: before.content,\n previousMetadata: before.metadata,\n });\n }\n\n // ── Built-in commands ────────────────────────────────────────────\n\n private registerBuiltInCommands(): void {\n this.commands.register(\"w\", {\n description: \"Save\",\n handler: () => this.bus.emit(\"editor:save\", {}),\n });\n this.commands.register(\"q\", {\n description: \"Close\",\n handler: () => this.bus.emit(\"editor:close\", {}),\n });\n this.commands.register(\"wq\", {\n description: \"Save and close\",\n handler: () => {\n this.bus.emit(\"editor:save\", {});\n this.bus.emit(\"editor:close\", {});\n },\n });\n this.commands.register(\"search\", {\n description: \"Find in document\",\n handler: () => this.openSearch(),\n });\n this.commands.register(\"find\", {\n description: \"Find in document\",\n handler: () => this.openSearch(),\n });\n this.commands.register(\"undo\", {\n description: \"Undo last change\",\n handler: () => this.undo(),\n });\n this.commands.register(\"redo\", {\n description: \"Redo last change\",\n handler: () => this.redo(),\n });\n\n // Task commands\n this.commands.register(\"task\", {\n description: \"Cycle task status (or set: task todo/progress/done)\",\n handler: (args?: string) => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n if (args) {\n const STATUS_MAP: Record<string, string> = {\n todo: \"todo\", progress: \"in-progress\", done: \"done\",\n \"in-progress\": \"in-progress\",\n };\n const status = STATUS_MAP[args.trim().toLowerCase()];\n if (status) this.setTaskStatusExplicit(focusId, status);\n } else {\n this.cycleTaskStatus(focusId);\n }\n },\n });\n this.commands.register(\"notask\", {\n description: \"Remove task status from heading\",\n handler: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (focusId) this.removeTaskStatus(focusId);\n },\n });\n this.commands.register(\"agenda\", {\n description: \"Add or edit agenda date\",\n handler: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (focusId) this.openAgendaPickerForBlock(focusId);\n },\n });\n\n // Fold commands\n this.commands.register(\"fold\", {\n description: \"Fold current heading section\",\n handler: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n const headingId = this.foldManager.findOwningHeading(focusId, this.getBlocks());\n if (headingId) this.foldBlock(headingId);\n },\n });\n this.commands.register(\"unfold\", {\n description: \"Unfold current heading section\",\n handler: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n const headingId = this.foldManager.findOwningHeading(focusId, this.getBlocks());\n if (headingId) this.unfoldBlock(headingId);\n },\n });\n this.commands.register(\"foldall\", {\n description: \"Fold all headings\",\n handler: () => this.foldAll(),\n });\n this.commands.register(\"unfoldall\", {\n description: \"Unfold all headings\",\n handler: () => this.unfoldAll(),\n });\n }\n\n // ── Cleanup ───────────────────────────────────────────────────────\n\n destroy(): void {\n delete (this.root as any).__blxEditor;\n this.keySequencer.destroy();\n this.root.removeEventListener(\"mousedown\", this.handleMouseDown);\n if (this.clickContainer) {\n this.clickContainer.removeEventListener(\"mousedown\", this.handleClickContainerMouseDown);\n this.clickContainer = null;\n }\n this.teardownLinkClickHandler();\n setBlockRefRenderCallback(undefined);\n document.removeEventListener(\"keydown\", this.handleEditorKeyDown);\n if (this.editorMode !== \"insert\") {\n this.exitToInsertModeSilent();\n }\n this.closeSlashMenu();\n if (this.slashMenu) {\n this.slashMenu.destroy();\n this.slashMenu = null;\n }\n this.closeEmojiPicker();\n if (this.emojiPicker) {\n this.emojiPicker.destroy();\n this.emojiPicker = null;\n }\n this.closeAutoComplete();\n if (this.autoCompleteMenu) {\n this.autoCompleteMenu.destroy();\n this.autoCompleteMenu = null;\n }\n if (this.dragHandle) {\n this.dragHandle.destroy();\n this.dragHandle = null;\n }\n if (this.blockActionMenu) {\n this.blockActionMenu.destroy();\n this.blockActionMenu = null;\n }\n if (this.customCaret) {\n this.customCaret.destroy();\n this.customCaret = null;\n }\n if (this.blockContextMenu) {\n this.blockContextMenu.destroy();\n this.blockContextMenu = null;\n }\n if (this.clipboardKeyHandler) {\n document.removeEventListener(\"keydown\", this.clipboardKeyHandler);\n this.clipboardKeyHandler = null;\n }\n this.teardownInlineToolbar();\n this.floatingScroll.destroy();\n if (this.searchUI) {\n this.searchUI.destroy();\n this.searchUI = null;\n }\n if (this.searchKeyHandler) {\n document.removeEventListener(\"keydown\", this.searchKeyHandler);\n this.searchKeyHandler = null;\n }\n if (this.undoKeyHandler) {\n document.removeEventListener(\"keydown\", this.undoKeyHandler);\n this.undoKeyHandler = null;\n }\n this.undoManager.clear();\n this.jumpList.clear();\n this.replayPause();\n if (this._replayUI) {\n this._replayUI.destroy();\n this._replayUI = null;\n }\n this.crdtLog = null;\n this._replayActive = false;\n this._replaySavedState = null;\n if (this._automergeSync) {\n this._automergeSync.destroy();\n this._automergeSync = null;\n }\n this._localPeer = null;\n this._peers.clear();\n this._remoteCursors.clear();\n for (const timer of this._cursorIdleTimers.values()) clearTimeout(timer);\n this._cursorIdleTimers.clear();\n if (this._cursorScrollCleanup) {\n this._cursorScrollCleanup();\n this._cursorScrollCleanup = null;\n }\n this.blurNonTextBlock();\n this.removeImageDropZone();\n this.imageDropZone = null;\n this.removeDropRejectOverlay();\n this.dropRejectOverlay = null;\n // Clean up table of contents\n for (const unsub of this.tocUnsubs) unsub();\n this.tocUnsubs = [];\n if (this.toc) {\n this.toc.destroy();\n this.toc = null;\n }\n // Clean up mouse drag listeners if active\n if (this.mouseDragActive) {\n this.stopDragAutoScroll();\n document.removeEventListener(\"mousemove\", this.handleMouseDrag);\n document.removeEventListener(\"mouseup\", this.handleMouseDragEnd);\n this.mouseDragActive = false;\n }\n this.viewport.destroy();\n for (const ctrl of this.controllers) {\n ctrl.destroy();\n }\n this.controllers = [];\n this.controllerMap.clear();\n this.goalX = null;\n if (this.hashChangeHandler) {\n window.removeEventListener(\"hashchange\", this.hashChangeHandler);\n this.hashChangeHandler = null;\n }\n this.bus.clear();\n this.root.innerHTML = \"\";\n this.bus.emit(\"editor:destroyed\", {});\n }\n\n // ── Private ───────────────────────────────────────────────────────\n\n private setupHashNavigation(): void {\n // Navigate on initial load if hash present\n this.navigateToHash();\n // Listen for hash changes\n this.hashChangeHandler = () => this.navigateToHash();\n window.addEventListener(\"hashchange\", this.hashChangeHandler);\n }\n\n private navigateToHash(): void {\n const hash = window.location.hash.slice(1); // strip leading #\n if (!hash) return;\n this.scrollToBlock(hash, true);\n }\n\n /** Unsub callbacks for ToC event subscriptions */\n private tocUnsubs: (() => void)[] = [];\n\n private setupTableOfContents(): void {\n this.toc = new TableOfContents(\n this.root,\n () => this.getBlocks(),\n (blockId) => this.scrollToBlock(blockId, true),\n );\n\n // Update ToC on structural changes\n const tocUpdate = () => this.toc?.update();\n\n this.tocUnsubs.push(\n this.bus.on(\"block:added\", tocUpdate),\n this.bus.on(\"block:removed\", tocUpdate),\n this.bus.on(\"block:moved\", tocUpdate),\n this.bus.on(\"block:typeChanged\", tocUpdate),\n this.bus.on(\"block:contentChanged\", ({ blockId }) => {\n const block = this.getBlock(blockId);\n if (block && block.type === \"heading\") {\n this.toc?.update();\n }\n }),\n );\n }\n\n private setupEventHandlers(): void {\n this.bus.on(\"block:split\", ({ blockId, offset }) => {\n this.goalX = null;\n this.handleSplit(blockId, offset);\n });\n\n this.bus.on(\"block:merge\", ({ blockId, direction }) => {\n this.goalX = null;\n this.handleMerge(blockId, direction);\n });\n\n this.bus.on(\"block:focus\", ({ blockId, offset, caretX }) => {\n this.handleFocusNavigation(blockId, offset, caretX);\n });\n\n this.bus.on(\"block:convertType\", ({ blockId, newType, metadata }) => {\n this.goalX = null;\n this.changeBlockType(blockId, newType, metadata);\n const plugin = this.getPlugin(newType);\n if (!plugin.hasTextContent) {\n // Non-text block: create an empty paragraph after and focus it\n const index = this.getBlockIndex(blockId);\n const newBlock = this.addBlock(\"paragraph\", index + 1);\n this.focusBlock(newBlock.id, 0);\n } else {\n this.focusBlock(blockId, 0);\n }\n });\n\n this.bus.on(\"block:added\", () => {\n this.recomputeListIndices();\n });\n\n this.bus.on(\"block:removed\", () => {\n this.recomputeListIndices();\n });\n\n this.bus.on(\"block:moved\", () => {\n this.recomputeListIndices();\n });\n\n this.bus.on(\"block:typeChanged\", () => {\n this.recomputeListIndices();\n });\n\n this.bus.on(\"block:contentChanged\", ({ blockId }) => {\n this.goalX = null;\n // Hide gutter widgets when the user is typing\n this.dragHandle?.hide();\n this.blockActionMenu?.hide();\n // If the edited block is off-screen (user scrolled away from a\n // selection and typed), scroll back so the edit is visible and\n // re-evaluate the selection to restore the inline toolbar.\n const ctrl = this.controllerMap.get(blockId);\n if (ctrl) {\n const rect = ctrl.container.getBoundingClientRect();\n if (rect.bottom < 0 || rect.top > window.innerHeight) {\n ctrl.container.scrollIntoView({ behavior: \"instant\", block: \"nearest\" });\n this.handleSelectionChange();\n }\n }\n });\n\n this.bus.on(\"block:checklistToggled\", ({ blockId, checked }) => {\n this.cascadeChecklistToggle(blockId, checked);\n if (checked) {\n this.moveCompletedChecklistToBottom(blockId);\n } else {\n this.moveUncheckedTaskToTop(blockId);\n }\n });\n\n // Block nesting (Tab/Shift+Tab)\n this.bus.on(\"block:indent\", ({ blockId }) => {\n this.handleIndent(blockId);\n this.recomputeListIndices();\n });\n this.bus.on(\"block:outdent\", ({ blockId }) => {\n this.handleOutdent(blockId);\n this.recomputeListIndices();\n });\n\n // Block selection (Shift+Arrow across blocks)\n this.bus.on(\"block:selectTo\", ({ blockId, direction }) => {\n this.handleBlockSelectTo(blockId, direction);\n });\n\n // Block-level selection mode (Escape from editing)\n this.bus.on(\"block:enterBlockSelect\", ({ blockId }) => {\n this.enterNormalMode(blockId);\n });\n\n // Block reordering via keyboard (Alt+Arrow)\n this.bus.on(\"block:moveUp\", ({ blockId }) => {\n this.handleBlockMove(blockId, \"up\");\n });\n this.bus.on(\"block:moveDown\", ({ blockId }) => {\n this.handleBlockMove(blockId, \"down\");\n });\n\n // Document-level navigation (Mod+Home/End)\n this.bus.on(\"block:jumpToDocStart\", () => {\n if (this.controllers.length === 0) return;\n this.recordJump();\n const firstId = this.controllers[0].getBlock().id;\n this.focusBlock(firstId, 0);\n });\n this.bus.on(\"block:jumpToDocEnd\", () => {\n if (this.controllers.length === 0) return;\n this.recordJump();\n const lastCtrl = this.controllers[this.controllers.length - 1];\n const lastBlock = lastCtrl.getBlock();\n this.focusBlock(lastBlock.id, lastBlock.content.length);\n });\n this.bus.on(\"block:selectToDocStart\", ({ blockId }) => {\n if (this.controllers.length === 0) return;\n const firstId = this.controllers[0].getBlock().id;\n this.enterVisualBlockFromInsert(blockId, firstId);\n });\n this.bus.on(\"block:selectToDocEnd\", ({ blockId }) => {\n if (this.controllers.length === 0) return;\n const lastId = this.controllers[this.controllers.length - 1].getBlock().id;\n this.enterVisualBlockFromInsert(blockId, lastId);\n });\n\n // Page navigation (PageUp/PageDown)\n this.bus.on(\"block:pageUp\", ({ blockId }) => {\n this.handlePageJump(blockId, \"up\");\n });\n this.bus.on(\"block:pageDown\", ({ blockId }) => {\n this.handlePageJump(blockId, \"down\");\n });\n\n // Slash command menu\n this.bus.on(\"block:slashMenu\", ({ blockId, query, slashOffset }) => {\n this.openOrUpdateSlashMenu(blockId, query, slashOffset);\n });\n\n this.bus.on(\"block:slashClose\", ({ blockId }) => {\n if (this.slashMenuBlockId === blockId) {\n this.closeSlashMenu();\n }\n });\n\n // Emoji picker\n this.bus.on(\"block:emojiSearch\", ({ blockId, query, colonOffset }) => {\n this.openOrUpdateEmojiPicker(blockId, query, colonOffset);\n });\n\n this.bus.on(\"block:emojiClose\", ({ blockId }) => {\n if (this.emojiBlockId === blockId) {\n this.closeEmojiPicker();\n }\n });\n\n this.bus.on(\"block:emojiCommit\", ({ blockId, colonOffset, cursorOffset, emoji }) => {\n this.commitEmoji(blockId, colonOffset, cursorOffset, emoji);\n });\n\n // Agenda date picker (@)\n this.bus.on(\"block:agendaOpen\", ({ blockId, atOffset, role }) => {\n this.openAgendaPicker(blockId, atOffset, role);\n });\n\n this.bus.on(\"block:agendaSearch\", ({ blockId, query, role }) => {\n if (this.agendaBlockId === blockId && this.agendaPicker?.visible) {\n // If a role prefix was detected, update the picker's role\n if (role) {\n this.agendaPicker.setRole(role);\n }\n this.updateAgendaSearch(query);\n }\n });\n\n this.bus.on(\"block:agendaClose\", ({ blockId }) => {\n if (this.agendaBlockId === blockId) {\n this.closeAgendaPicker();\n }\n });\n\n this.bus.on(\"block:agendaAutoConfirm\", ({ blockId, query, role }) => {\n if (this.agendaBlockId === blockId && this.agendaPicker?.visible) {\n // Update role and search, then auto-confirm the first suggestion\n if (role) {\n this.agendaPicker.setRole(role);\n }\n this.updateAgendaSearch(query);\n // Confirm the current/first suggestion (like pressing Enter)\n this.agendaPicker.confirmSelection();\n }\n });\n\n this.bus.on(\"block:agendaEdit\", ({ blockId, date }) => {\n this.openAgendaPickerForEdit(blockId, date);\n });\n\n // Autocomplete menu ([[)\n this.bus.on(\"block:autoCompleteMenu\", ({ blockId, query, bracketOffset }) => {\n this.openOrUpdateAutoComplete(blockId, query, bracketOffset);\n });\n\n this.bus.on(\"block:autoCompleteClose\", ({ blockId }) => {\n if (this.autoCompleteBlockId === blockId) {\n this.closeAutoComplete();\n }\n });\n\n this.bus.on(\"block:blur\", ({ blockId }) => {\n if (this.slashMenuBlockId === blockId) {\n // Delay to allow mousedown on menu items to fire first\n setTimeout(() => {\n if (this.slashMenuBlockId === blockId) {\n this.closeSlashMenu();\n }\n }, 150);\n }\n if (this.emojiBlockId === blockId) {\n setTimeout(() => {\n if (this.emojiBlockId === blockId) {\n this.closeEmojiPicker();\n }\n }, 150);\n }\n if (this.autoCompleteBlockId === blockId) {\n setTimeout(() => {\n if (this.autoCompleteBlockId === blockId) {\n this.closeAutoComplete();\n }\n }, 150);\n }\n if (this.agendaBlockId === blockId) {\n setTimeout(() => {\n if (this.agendaBlockId === blockId) {\n // Don't close if focus moved to a form control inside the picker\n // (e.g. repeat config inputs, selects, checkboxes)\n if (this.agendaPicker?.isInteracting()) {\n return;\n }\n this.closeAgendaPicker();\n }\n }, 150);\n }\n });\n\n // Clear goalX on mouse interaction (click repositions caret)\n this.root.addEventListener(\"mousedown\", this.handleMouseDown);\n\n // Optional outer click container (e.g. scroll host)\n if (this.options?.clickContainer) {\n this.clickContainer = this.options.clickContainer;\n this.clickContainer.addEventListener(\"mousedown\", this.handleClickContainerMouseDown);\n }\n\n // Document-level keydown for block selection mode (blocks don't receive events when blurred)\n document.addEventListener(\"keydown\", this.handleEditorKeyDown);\n }\n\n private handleClickContainerMouseDown = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n // Only handle clicks outside the editor root — let the editor's own\n // handleMouseDown deal with clicks inside.\n if (target.closest(\".blx-editor\")) return;\n e.preventDefault();\n this.focusAtPoint(e.clientX, e.clientY);\n };\n\n private handleMouseDown = (e: MouseEvent): void => {\n this.goalX = null;\n this.blurNonTextBlock();\n\n // Don't exit block selection when clicking gutter widgets (action button / drag handle)\n // — these need the selection to operate on all selected blocks.\n const target = e.target as HTMLElement;\n const isGutterClick = target.closest?.(\".blx-action-btn\") || target.closest?.(\".blx-drag-handle\");\n if (this.editorMode !== \"insert\" && !isGutterClick) {\n this.exitToInsertModeSilent();\n }\n\n // Track which block the mousedown occurred in for drag-to-select\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (blockEl?.dataset.blockId) {\n this.mouseDragAnchorBlockId = blockEl.dataset.blockId;\n this.mouseDragActive = true;\n document.addEventListener(\"mousemove\", this.handleMouseDrag);\n document.addEventListener(\"mouseup\", this.handleMouseDragEnd);\n\n // Check if clicked block is a non-text block (image, youtube, hr)\n const clickedBlockId = blockEl.dataset.blockId;\n const clickedCtrl = this.controllerMap.get(clickedBlockId);\n if (clickedCtrl) {\n const clickedPlugin = this.getPlugin(clickedCtrl.getBlock().type);\n if (!clickedPlugin.hasTextContent && clickedCtrl.getBlock().type !== \"table\") {\n // Don't interfere if the click landed on an interactive element inside\n // the block (e.g. caption input, URL input, upload button)\n const isInteractive = target.tagName === \"INPUT\" || target.tagName === \"BUTTON\" ||\n target.tagName === \"TEXTAREA\" || target.isContentEditable;\n if (!isInteractive) {\n this.focusNonTextBlock(clickedBlockId);\n }\n } else if (clickedPlugin.hasTextContent) {\n const ce = clickedCtrl.contentEditable;\n if (ce) {\n const outsideCe = !ce.contains(target);\n let inCePadding = false;\n if (!outsideCe) {\n const style = getComputedStyle(ce);\n const ceRect = ce.getBoundingClientRect();\n const pt = parseFloat(style.paddingTop) || 0;\n const pb = parseFloat(style.paddingBottom) || 0;\n inCePadding = e.clientY < ceRect.top + pt || e.clientY > ceRect.bottom - pb;\n }\n if (outsideCe || inCePadding) {\n e.preventDefault();\n this.viewport.ensureMounted(clickedBlockId);\n clickedCtrl.focusAtPoint(e.clientX, e.clientY);\n }\n }\n }\n }\n } else if (!isGutterClick && (this.blocksContainer.contains(target) || target === this.root)) {\n // Click landed outside any block (gap between blocks, empty space\n // below, or the root itself). We check blocksContainer and root\n // so we don't steal focus from editor UI widgets.\n this.handleEmptyAreaClick(e);\n }\n };\n\n private handleMouseDrag = (e: MouseEvent): void => {\n if (!this.mouseDragActive || !this.mouseDragAnchorBlockId) return;\n\n // Cache mouse position for the auto-scroll RAF tick\n this._lastDragMouseX = e.clientX;\n this._lastDragMouseY = e.clientY;\n\n this.updateDragBlockUnderMouse(e.clientX, e.clientY, e);\n };\n\n /**\n * Detect the block under the given viewport coordinates and update\n * selection. Called from both mousemove (with event) and the auto-scroll\n * RAF tick (without event).\n */\n private updateDragBlockUnderMouse(clientX: number, clientY: number, e?: MouseEvent): void {\n if (!this.mouseDragAnchorBlockId) return;\n\n const el = document.elementFromPoint(clientX, clientY);\n const blockEl = el?.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl) return;\n\n const currentBlockId = blockEl.dataset.blockId;\n if (!currentBlockId) return;\n\n if (currentBlockId !== this.mouseDragAnchorBlockId) {\n // Mouse has crossed into a different block\n if (this.editorMode === \"insert\") {\n // Save the text selection anchor before clearing it\n const anchorCtrl = this.controllerMap.get(this.mouseDragAnchorBlockId);\n this.mouseDragAnchorOffset = anchorCtrl?.getCursorOffset() ?? 0;\n\n // Enter visual block mode directly\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n this.blockSelectAnchor = this.mouseDragAnchorBlockId;\n this.blockSelectFocus = currentBlockId;\n this.setMode(\"visualBlock\");\n // Start auto-scrolling once we enter block selection\n this.startDragAutoScroll();\n } else {\n // Update focus to the new block\n this.blockSelectFocus = currentBlockId;\n }\n\n // Suppress native text selection extension\n e?.preventDefault();\n\n this.applyBlockSelectionCSS();\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n } else if (this.editorMode !== \"insert\") {\n // Mouse moved back to anchor block — restore in-block selection\n this.stopDragAutoScroll();\n this.exitToInsertModeSilent();\n if (e) this.restoreDragSelection(this.mouseDragAnchorBlockId!, e);\n } else if (this.mouseDragAnchorOffset !== null && e) {\n // Still dragging within anchor block after returning from block selection —\n // keep updating the text selection from the saved anchor to the mouse position\n this.restoreDragSelection(this.mouseDragAnchorBlockId, e);\n }\n }\n\n /** Find the nearest scrollable ancestor of the editor root. */\n private findScrollParent(): HTMLElement {\n let el: HTMLElement | null = this.root;\n while (el) {\n const style = getComputedStyle(el);\n if (/(auto|scroll)/.test(style.overflowY) && el.scrollHeight > el.clientHeight) {\n return el;\n }\n el = el.parentElement;\n }\n return document.documentElement;\n }\n\n /** Start a RAF loop that auto-scrolls when the mouse is near viewport edges. */\n private startDragAutoScroll(): void {\n this.stopDragAutoScroll();\n const scrollEl = this.findScrollParent();\n\n const tick = () => {\n if (!this.mouseDragAnchorBlockId) return;\n\n const rect = scrollEl.getBoundingClientRect();\n const edgeZone = 80; // px from edge to trigger scroll\n const maxSpeed = 10; // max px per frame (deliberately gentle)\n const mouseY = this._lastDragMouseY;\n\n let scrolled = false;\n if (mouseY < rect.top + edgeZone) {\n const ratio = Math.max(0, Math.min(1, 1 - (mouseY - rect.top) / edgeZone));\n const delta = Math.ceil(maxSpeed * ratio);\n if (delta > 0) {\n scrollEl.scrollTop -= delta;\n scrolled = true;\n }\n } else if (mouseY > rect.bottom - edgeZone) {\n const ratio = Math.max(0, Math.min(1, 1 - (rect.bottom - mouseY) / edgeZone));\n const delta = Math.ceil(maxSpeed * ratio);\n if (delta > 0) {\n scrollEl.scrollTop += delta;\n scrolled = true;\n }\n }\n\n // After scrolling, re-detect block under mouse and update selection\n // (the DOM moved but the mouse didn't, so mousemove won't fire)\n if (scrolled) {\n this.updateDragBlockUnderMouse(this._lastDragMouseX, this._lastDragMouseY);\n }\n\n this.dragScrollRAF = requestAnimationFrame(tick);\n };\n this.dragScrollRAF = requestAnimationFrame(tick);\n }\n\n /** Stop the drag auto-scroll RAF loop. */\n private stopDragAutoScroll(): void {\n if (this.dragScrollRAF !== null) {\n cancelAnimationFrame(this.dragScrollRAF);\n this.dragScrollRAF = null;\n }\n }\n\n /**\n * Re-focus the anchor block and create a text selection from the saved\n * anchor offset to the position under the mouse cursor.\n */\n private restoreDragSelection(blockId: string, e: MouseEvent): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const ce = ctrl.contentEditable;\n if (!ce) return;\n\n // Ensure the block is mounted and focused\n this.viewport.ensureMounted(blockId);\n if (document.activeElement !== ce) {\n ce.focus();\n }\n\n const anchorOffset = this.mouseDragAnchorOffset ?? 0;\n\n // Get the caret position at the mouse coordinates\n const caretRange = document.caretRangeFromPoint?.(e.clientX, e.clientY);\n if (!caretRange || !ce.contains(caretRange.startContainer)) {\n // Fallback: just place cursor at the saved anchor\n ctrl.focus(anchorOffset);\n return;\n }\n\n // Compute the focus offset from the caret range\n const preRange = document.createRange();\n preRange.selectNodeContents(ce);\n preRange.setEnd(caretRange.startContainer, caretRange.startOffset);\n const focusOffset = preRange.toString().length;\n\n if (focusOffset === anchorOffset) {\n // Collapsed — just place cursor\n ctrl.focus(anchorOffset);\n return;\n }\n\n // Create selection from anchor to focus. We use Selection.setBaseAndExtent\n // which allows anchor and focus to be in different order (supporting both\n // forward and backward selections).\n const anchorPos = this.findTextPosition(ce, anchorOffset);\n const focusPos = { node: caretRange.startContainer, offset: caretRange.startOffset };\n if (!anchorPos.node) return;\n\n const sel = window.getSelection();\n if (!sel) return;\n sel.setBaseAndExtent(anchorPos.node, anchorPos.offset, focusPos.node, focusPos.offset);\n }\n\n /**\n * Walk text nodes within a container and find the DOM node + offset\n * for a given character offset.\n */\n private findTextPosition(container: HTMLElement, offset: number): { node: Node | null; offset: number } {\n const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);\n let remaining = offset;\n let node = walker.nextNode();\n\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n return { node, offset: remaining };\n }\n remaining -= len;\n node = walker.nextNode();\n }\n\n // Past end — position at end of last text node\n const lastChild = container.lastChild;\n if (lastChild?.nodeType === Node.TEXT_NODE) {\n return { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n }\n\n return { node: container, offset: 0 };\n }\n\n private handleMouseDragEnd = (): void => {\n this.stopDragAutoScroll();\n this.mouseDragActive = false;\n this.mouseDragAnchorBlockId = null;\n this.mouseDragAnchorOffset = null;\n document.removeEventListener(\"mousemove\", this.handleMouseDrag);\n document.removeEventListener(\"mouseup\", this.handleMouseDragEnd);\n };\n\n private handleSplit(blockId: string, offset: number): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const block = ctrl.getBlock();\n const isListBlock = block.type === \"list\";\n const isChecklist = block.type === \"checklist\";\n const isBlockquote = block.type === \"blockquote\";\n const indentLevel = typeof block.metadata.indentLevel === \"number\"\n ? block.metadata.indentLevel\n : 0;\n\n // Enter on an empty list/task/blockquote block → outdent first, or convert to paragraph\n if ((isListBlock || isChecklist || isBlockquote) && block.content.isEmpty()) {\n if (indentLevel > 0) {\n // Outdent instead of converting to paragraph\n this.handleOutdent(blockId);\n this.focusBlock(blockId, 0);\n return;\n }\n this.changeBlockType(blockId, \"paragraph\");\n this.focusBlock(blockId, 0);\n return;\n }\n\n const beforeContent = block.content.slice(0, offset);\n const afterContent = block.content.slice(offset, block.content.length);\n\n // Begin compound undo group: content change + new block\n if (!this._suppressHistory) {\n this.undoManager.beginGroup({ blockId, offset });\n this.crdtLog?.beginGroup({ blockId, offset });\n const splitAction: UndoAction = {\n type: \"contentChange\",\n blockId,\n before: { content: block.content, metadata: { ...block.metadata }, blockType: block.type },\n after: { content: beforeContent, metadata: { ...block.metadata }, blockType: block.type },\n };\n this.undoManager.record(\n splitAction,\n { blockId, offset },\n { blockId, offset: beforeContent.length },\n );\n this.crdtLog?.record(\n splitAction,\n { blockId, offset },\n { blockId, offset: beforeContent.length },\n );\n }\n\n // Update current block with content before cursor\n ctrl.updateBlock({ content: beforeContent });\n ctrl.setPlugin(this.getPlugin(block.type));\n\n // Emit contentChanged so AutomergeSync propagates the truncated content\n this.bus.emit(\"block:contentChanged\", {\n blockId,\n content: beforeContent,\n metadata: block.metadata,\n });\n\n // Lists, checklists, and blockquotes continue as the same type; everything else becomes a paragraph\n const newType = (isListBlock || isChecklist || isBlockquote) ? block.type : \"paragraph\";\n let newMetadata: Record<string, unknown>;\n if (isListBlock || isChecklist || isBlockquote) {\n newMetadata = { ...block.metadata, ...(isChecklist ? { checked: false } : {}) };\n } else {\n newMetadata = this.getPlugin(\"paragraph\").defaultMetadata();\n // Preserve indent level for non-list blocks too\n if (indentLevel > 0) {\n newMetadata.indentLevel = indentLevel;\n }\n }\n\n const newBlock: Block = {\n id: generateId(),\n type: newType,\n content: afterContent,\n metadata: newMetadata,\n };\n\n const currentIndex = this.controllers.indexOf(ctrl);\n const added = this.addBlock(newBlock, currentIndex + 1);\n\n // End compound undo group\n if (!this._suppressHistory) {\n this.undoManager.endGroup({ blockId: added.id, offset: 0 });\n this.crdtLog?.endGroup({ blockId: added.id, offset: 0 });\n }\n\n // Focus new block at start\n this.focusBlock(added.id, 0);\n }\n\n private handleMerge(\n blockId: string,\n direction: \"backward\" | \"forward\",\n ): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const index = this.controllers.indexOf(ctrl);\n\n if (direction === \"backward\") {\n // Backspace at start of indented block → outdent instead of merging\n const currentBlock = ctrl.getBlock();\n const indentLevel = typeof currentBlock.metadata.indentLevel === \"number\"\n ? currentBlock.metadata.indentLevel\n : 0;\n if (indentLevel > 0) {\n this.handleOutdent(blockId);\n this.focusBlock(blockId, 0);\n return;\n }\n\n // Non-paragraph text block → revert to paragraph instead of merging\n if (currentBlock.type !== \"paragraph\") {\n const currentPlugin = this.getPlugin(currentBlock.type);\n if (currentPlugin.inconvertible) return; // no-op for backspace at start of title\n if (currentPlugin.hasTextContent) {\n this.changeBlockType(blockId, \"paragraph\");\n this.focusBlock(blockId, 0);\n return;\n }\n }\n\n // Merge into previous block\n if (index <= 0) return;\n const prevCtrl = this.controllers[index - 1];\n const prevBlock = prevCtrl.getBlock();\n const prevPlugin = this.getPlugin(prevBlock.type);\n\n // Can't merge into an immovable block (e.g. title)\n if (prevPlugin.immovable) return;\n\n // If previous block is non-text (e.g. HR), delete it instead of merging\n if (!prevPlugin.hasTextContent) {\n this.removeBlock(prevBlock.id);\n this.focusBlock(blockId, 0);\n return;\n }\n\n const joinOffset = prevBlock.content.length;\n const merged = prevBlock.content.concat(currentBlock.content);\n\n // Compound undo: content change on previous block + remove current block\n if (!this._suppressHistory) {\n this.undoManager.beginGroup({ blockId, offset: 0 });\n this.crdtLog?.beginGroup({ blockId, offset: 0 });\n const mergeAction: UndoAction = {\n type: \"contentChange\",\n blockId: prevBlock.id,\n before: { content: prevBlock.content, metadata: { ...prevBlock.metadata }, blockType: prevBlock.type },\n after: { content: merged, metadata: { ...prevBlock.metadata }, blockType: prevBlock.type },\n };\n this.undoManager.record(\n mergeAction,\n { blockId, offset: 0 },\n { blockId: prevBlock.id, offset: joinOffset },\n );\n this.crdtLog?.record(\n mergeAction,\n { blockId, offset: 0 },\n { blockId: prevBlock.id, offset: joinOffset },\n );\n }\n\n prevCtrl.updateBlock({ content: merged });\n prevCtrl.setPlugin(this.getPlugin(prevBlock.type));\n\n // Emit contentChanged so AutomergeSync propagates the merged content\n this.bus.emit(\"block:contentChanged\", {\n blockId: prevBlock.id,\n content: merged,\n metadata: prevBlock.metadata,\n });\n\n this.removeBlock(blockId);\n\n if (!this._suppressHistory) {\n this.undoManager.endGroup({ blockId: prevBlock.id, offset: joinOffset });\n this.crdtLog?.endGroup({ blockId: prevBlock.id, offset: joinOffset });\n }\n\n this.focusBlock(prevBlock.id, joinOffset);\n } else {\n // Immovable blocks can't merge forward (delete at end of title = no-op)\n const currentPlugin = this.getPlugin(ctrl.getBlock().type);\n if (currentPlugin.immovable) return;\n\n // Merge next block into this one\n if (index >= this.controllers.length - 1) return;\n const nextCtrl = this.controllers[index + 1];\n const nextBlock = nextCtrl.getBlock();\n const nextPlugin = this.getPlugin(nextBlock.type);\n\n // If next block is non-text (e.g. HR), delete it instead of merging\n if (!nextPlugin.hasTextContent) {\n this.removeBlock(nextBlock.id);\n this.focusBlock(blockId, ctrl.getBlock().content.length);\n return;\n }\n\n const currentBlock = ctrl.getBlock();\n const joinOffset = currentBlock.content.length;\n const merged = currentBlock.content.concat(nextBlock.content);\n\n // Compound undo: content change on current block + remove next block\n if (!this._suppressHistory) {\n this.undoManager.beginGroup({ blockId, offset: joinOffset });\n this.crdtLog?.beginGroup({ blockId, offset: joinOffset });\n const fwdMergeAction: UndoAction = {\n type: \"contentChange\",\n blockId,\n before: { content: currentBlock.content, metadata: { ...currentBlock.metadata }, blockType: currentBlock.type },\n after: { content: merged, metadata: { ...currentBlock.metadata }, blockType: currentBlock.type },\n };\n this.undoManager.record(\n fwdMergeAction,\n { blockId, offset: joinOffset },\n { blockId, offset: joinOffset },\n );\n this.crdtLog?.record(\n fwdMergeAction,\n { blockId, offset: joinOffset },\n { blockId, offset: joinOffset },\n );\n }\n\n ctrl.updateBlock({ content: merged });\n ctrl.setPlugin(this.getPlugin(currentBlock.type));\n\n // Emit contentChanged so AutomergeSync propagates the merged content\n this.bus.emit(\"block:contentChanged\", {\n blockId,\n content: merged,\n metadata: currentBlock.metadata,\n });\n\n this.removeBlock(nextBlock.id);\n\n if (!this._suppressHistory) {\n this.undoManager.endGroup({ blockId, offset: joinOffset });\n this.crdtLog?.endGroup({ blockId, offset: joinOffset });\n }\n\n this.focusBlock(blockId, joinOffset);\n }\n }\n\n private handleFocusNavigation(\n blockId: string,\n offset?: number,\n caretX?: number,\n ): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const index = this.controllers.indexOf(ctrl);\n\n if (caretX !== undefined) {\n // Vertical navigation — use sticky goalX\n this.goalX ??= caretX;\n } else {\n // Horizontal navigation — clear goalX\n this.goalX = null;\n }\n\n if (offset === -1) {\n // Move to previous block\n for (let i = index - 1; i >= 0; i--) {\n const ctrl = this.controllers[i];\n const plugin = this.getPlugin(ctrl.getBlock().type);\n if (plugin.hasTextContent) {\n this.viewport.ensureMounted(ctrl.blockId);\n if (this.goalX !== null) {\n ctrl.focusAtX(this.goalX, \"last\");\n } else {\n const block = ctrl.getBlock();\n this.focusBlock(block.id, block.content.length);\n }\n break;\n } else if (ctrl.getBlock().type === \"table\") {\n this.focusTableCell(ctrl.getBlock().id, \"up\");\n break;\n } else {\n // Non-text block: select it visually\n this.focusNonTextBlock(ctrl.getBlock().id);\n break;\n }\n }\n } else if (offset === 1) {\n // Move to next block\n let found = false;\n for (let i = index + 1; i < this.controllers.length; i++) {\n const ctrl = this.controllers[i];\n const plugin = this.getPlugin(ctrl.getBlock().type);\n if (plugin.hasTextContent) {\n this.viewport.ensureMounted(ctrl.blockId);\n if (this.goalX !== null) {\n ctrl.focusAtX(this.goalX, \"first\");\n } else {\n this.focusBlock(ctrl.getBlock().id, 0);\n }\n found = true;\n break;\n } else if (ctrl.getBlock().type === \"table\") {\n this.focusTableCell(ctrl.getBlock().id, \"down\");\n found = true;\n break;\n } else {\n // Non-text block: select it visually\n this.focusNonTextBlock(ctrl.getBlock().id);\n found = true;\n break;\n }\n }\n if (!found) {\n const block = ctrl.getBlock();\n if (block.content.length > 0) {\n // Last block with content — create a new empty paragraph below\n const newBlock = this.addBlock(\"paragraph\", index + 1);\n this.focusBlock(newBlock.id, 0);\n } else {\n // Last block is empty — just move cursor to end\n this.focusBlock(block.id, block.content.length);\n }\n }\n }\n }\n\n // ── Block nesting ─────────────────────────────────────────────\n\n private static MAX_INDENT_LEVEL = 3;\n\n private handleIndent(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n // Plugin must opt in to indentation (default: true)\n const plugin = this.getPlugin(ctrl.getBlock().type);\n if (plugin.indentable === false) return;\n\n const block = ctrl.getBlock();\n const currentLevel = typeof block.metadata.indentLevel === \"number\"\n ? block.metadata.indentLevel\n : 0;\n\n // Cannot indent past max level\n if (currentLevel >= Editor.MAX_INDENT_LEVEL) return;\n\n // Cannot indent deeper than previous sibling's level + 1\n const index = this.controllers.indexOf(ctrl);\n if (index > 0) {\n const prevBlock = this.controllers[index - 1].getBlock();\n const prevLevel = typeof prevBlock.metadata.indentLevel === \"number\"\n ? prevBlock.metadata.indentLevel\n : 0;\n if (currentLevel >= prevLevel + 1) return;\n }\n // First block has no sibling constraint — only the max level applies\n\n const newLevel = currentLevel + 1;\n const tx = new Transaction(blockId).setMetadata(\"indentLevel\", newLevel);\n ctrl.applyTransaction(tx);\n }\n\n private handleOutdent(blockId: string): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n // Plugin must opt in to indentation (default: true)\n const plugin = this.getPlugin(ctrl.getBlock().type);\n if (plugin.indentable === false) return;\n\n const block = ctrl.getBlock();\n const currentLevel = typeof block.metadata.indentLevel === \"number\"\n ? block.metadata.indentLevel\n : 0;\n\n // Cannot outdent at level 0\n if (currentLevel <= 0) return;\n\n const newLevel = currentLevel - 1;\n const tx = new Transaction(blockId).setMetadata(\"indentLevel\", newLevel);\n ctrl.applyTransaction(tx);\n }\n\n // ── Block selection ────────────────────────────────────────────\n\n /** Enter normal mode on a single block (Escape from editing) */\n private enterNormalMode(blockId: string): void {\n this.blockSelectAnchor = blockId;\n this.blockSelectFocus = blockId;\n this.setMode(\"normal\");\n\n // Exit text editing: clear native selection and blur\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n /** Enter visual block mode from normal mode (v key or shift+arrow) */\n private enterVisualBlockMode(sticky = true): void {\n this.visualBlockSticky = sticky;\n this.setMode(\"visualBlock\");\n // anchor/focus stay the same\n this.applyBlockSelectionCSS();\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n /** Enter visual block mode from insert mode (Shift+Arrow, mouse drag) */\n private enterVisualBlockFromInsert(anchorId: string, focusId: string): void {\n this.blockSelectAnchor = anchorId;\n this.blockSelectFocus = focusId;\n this.visualBlockSticky = false;\n this.setMode(\"visualBlock\");\n\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n /** Calculate the approximate number of blocks that fit in a page (viewport) */\n private calculatePageJump(): number {\n const viewportHeight = window.innerHeight;\n if (this.controllers.length === 0) return 10;\n\n // Sample up to 10 mounted blocks for average height\n let totalHeight = 0;\n let sampleCount = 0;\n for (const ctrl of this.controllers) {\n if (!ctrl.contentRendered) continue;\n totalHeight += ctrl.container.offsetHeight;\n sampleCount++;\n if (sampleCount >= 10) break;\n }\n\n if (sampleCount === 0 || totalHeight === 0) return 10;\n const avgHeight = totalHeight / sampleCount;\n return Math.max(1, Math.round(viewportHeight / avgHeight));\n }\n\n /** Handle PageUp/PageDown — jump focus by approximately one viewport of blocks */\n private handlePageJump(blockId: string, direction: \"up\" | \"down\"): void {\n const index = this.getBlockIndex(blockId);\n if (index < 0) return;\n\n this.recordJump();\n const jumpCount = this.calculatePageJump();\n const targetIndex = direction === \"up\"\n ? Math.max(0, index - jumpCount)\n : Math.min(this.controllers.length - 1, index + jumpCount);\n\n const targetCtrl = this.controllers[targetIndex];\n const targetBlock = targetCtrl.getBlock();\n const plugin = this.getPlugin(targetBlock.type);\n\n if (plugin.hasTextContent) {\n this.focusBlock(targetBlock.id, direction === \"up\" ? 0 : targetBlock.content.length);\n } else {\n this.focusNonTextBlock(targetBlock.id);\n }\n targetCtrl.container.scrollIntoView?.({ behavior: \"smooth\", block: \"center\" });\n }\n\n /** Select all blocks (enter visual block mode spanning first to last) */\n private selectAllBlocks(): void {\n if (this.controllers.length === 0) return;\n const firstId = this.controllers[0].getBlock().id;\n const lastId = this.controllers[this.controllers.length - 1].getBlock().id;\n this.enterVisualBlockFromInsert(firstId, lastId);\n }\n\n /** Move a block up or down by one position */\n private handleBlockMove(blockId: string, direction: \"up\" | \"down\"): void {\n const index = this.getBlockIndex(blockId);\n if (index < 0) return;\n\n const newIndex = direction === \"up\" ? index - 1 : index + 1;\n if (newIndex < 0 || newIndex >= this.controllers.length) return;\n\n this.moveBlock(blockId, newIndex);\n const plugin = this.getPlugin(this.getBlock(blockId)!.type);\n if (plugin.hasTextContent) {\n this.focusBlock(blockId, this.controllerMap.get(blockId)?.getCursorOffset() ?? 0);\n } else {\n this.focusNonTextBlock(blockId);\n }\n }\n\n private handleBlockSelectTo(blockId: string, direction: \"up\" | \"down\"): void {\n if (this.editorMode === \"insert\") {\n // Enter visual block mode directly from insert\n const index = this.getBlockIndex(blockId);\n const neighborIndex = direction === \"up\" ? index - 1 : index + 1;\n if (neighborIndex < 0 || neighborIndex >= this.controllers.length) return;\n\n this.enterVisualBlockFromInsert(blockId, this.controllers[neighborIndex].getBlock().id);\n } else {\n // Already in normal or visual block — extend/contract selection\n if (this.editorMode === \"normal\") {\n // Transition to visual block mode (transient — shift-based)\n this.visualBlockSticky = false;\n this.setMode(\"visualBlock\");\n }\n\n const focusIndex = this.getBlockIndex(this.blockSelectFocus!);\n const nextIndex = direction === \"up\" ? focusIndex - 1 : focusIndex + 1;\n if (nextIndex < 0 || nextIndex >= this.controllers.length) return;\n\n const nextId = this.controllers[nextIndex].getBlock().id;\n\n // In visual block mode, allow focus to move freely through and past\n // the anchor (like vim visual mode). No collapsing — the user exits\n // via Escape or v.\n\n this.blockSelectFocus = nextId;\n\n // Clear native selection and blur\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n\n this.applyBlockSelectionCSS();\n this.goalX = null;\n\n // Scroll the focus block into view\n this.viewport.scrollIntoView(this.blockSelectFocus!);\n\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n }\n\n /** Action dispatch map for normal mode keybindings (single-block) */\n private get normalModeActions(): Record<string, () => void> {\n return {\n moveDown: () => {\n const focusIdx = this.getBlockIndex(this.blockSelectFocus!);\n const neighborIdx = focusIdx + 1;\n if (neighborIdx >= this.controllers.length) return;\n const neighborId = this.controllers[neighborIdx].getBlock().id;\n this.blockSelectAnchor = neighborId;\n this.blockSelectFocus = neighborId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(neighborId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n moveUp: () => {\n const focusIdx = this.getBlockIndex(this.blockSelectFocus!);\n const neighborIdx = focusIdx - 1;\n if (neighborIdx < 0) return;\n const neighborId = this.controllers[neighborIdx].getBlock().id;\n this.blockSelectAnchor = neighborId;\n this.blockSelectFocus = neighborId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(neighborId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n jumpToFirst: () => {\n if (this.controllers.length === 0) return;\n this.recordJump();\n const targetId = this.controllers[0].getBlock().id;\n this.blockSelectAnchor = targetId;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n jumpToLast: () => {\n if (this.controllers.length === 0) return;\n this.recordJump();\n const targetId = this.controllers[this.controllers.length - 1].getBlock().id;\n this.blockSelectAnchor = targetId;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n deleteBlock: () => {\n this.deleteBlockSelection();\n },\n changeBlock: () => {\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n const ctrl = this.controllerMap.get(focusId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const plugin = this.getPlugin(block.type);\n if (!plugin.hasTextContent) return;\n\n // Record content change for undo\n const beforeContent = block.content;\n const emptyContent = AttributedString.empty();\n const beforeCursor = { blockId: focusId, offset: 0 };\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: focusId,\n before: {\n content: beforeContent,\n metadata: { ...block.metadata },\n blockType: block.type,\n },\n after: {\n content: emptyContent,\n metadata: { ...block.metadata },\n blockType: block.type,\n },\n },\n beforeCursor,\n { blockId: focusId, offset: 0 },\n );\n\n // Clear the content\n ctrl.updateBlock({ content: emptyContent });\n ctrl.rerender();\n this.bus.emit(\"block:contentChanged\", {\n blockId: focusId,\n content: emptyContent,\n metadata: block.metadata,\n });\n\n // Enter insert mode\n this.exitToInsertMode(focusId, 0);\n },\n moveBlockUp: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (!selectedIds || selectedIds.length === 0) return;\n const firstIdx = this.getBlockIndex(this.blockSelectFocus!);\n if (firstIdx <= 0) return;\n this.moveBlocks(selectedIds, firstIdx - 1);\n this.applyBlockSelectionCSS();\n },\n moveBlockDown: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (!selectedIds || selectedIds.length === 0) return;\n const lastIdx = this.getBlockIndex(this.blockSelectFocus!);\n if (lastIdx >= this.controllers.length - 1) return;\n this.moveBlocks(selectedIds, lastIdx + 1);\n this.applyBlockSelectionCSS();\n },\n exitToEditing: () => {\n const focusId = this.blockSelectFocus;\n this.exitToInsertModeSilent();\n if (focusId) {\n this.focusBlock(focusId, 0);\n }\n },\n enterEditingAtStart: () => {\n this.exitToInsertMode(this.blockSelectFocus!);\n },\n enterEditingAtEnd: () => {\n const focusId = this.blockSelectFocus!;\n const block = this.getBlock(focusId);\n this.exitToInsertModeSilent();\n if (block) {\n this.focusBlock(focusId, block.content.length);\n }\n },\n newBlockBelow: () => {\n const focusId = this.blockSelectFocus!;\n const block = this.getBlock(focusId)!;\n const index = this.getBlockIndex(focusId);\n this.exitToInsertModeSilent();\n\n // Respect block type like Enter does\n if (block.type === \"list\" || block.type === \"checklist\") {\n const newBlock = this.addBlock({\n id: generateId(),\n type: block.type,\n content: AttributedString.empty(),\n metadata: {\n ...block.metadata,\n ...(block.type === \"checklist\" ? { checked: false } : {}),\n },\n }, index + 1);\n this.focusBlock(newBlock.id, 0);\n } else {\n const newBlock = this.addBlock(\"paragraph\", index + 1);\n this.focusBlock(newBlock.id, 0);\n }\n },\n newBlockAbove: () => {\n const focusId = this.blockSelectFocus!;\n const block = this.getBlock(focusId)!;\n const index = this.getBlockIndex(focusId);\n this.exitToInsertModeSilent();\n\n // Respect block type like Enter does\n if (block.type === \"list\" || block.type === \"checklist\") {\n const newBlock = this.addBlock({\n id: generateId(),\n type: block.type,\n content: AttributedString.empty(),\n metadata: {\n ...block.metadata,\n ...(block.type === \"checklist\" ? { checked: false } : {}),\n },\n }, index);\n this.focusBlock(newBlock.id, 0);\n } else {\n const newBlock = this.addBlock(\"paragraph\", index);\n this.focusBlock(newBlock.id, 0);\n }\n },\n joinWithNext: () => {\n const focusId = this.blockSelectFocus!;\n const index = this.getBlockIndex(focusId);\n if (index >= this.controllers.length - 1) return;\n this.handleMerge(focusId, \"forward\");\n // Stay in normal mode — re-apply CSS since blocks changed\n this.applyBlockSelectionCSS();\n },\n enterVisualBlock: () => {\n this.enterVisualBlockMode();\n },\n extendDown: () => {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"down\");\n },\n extendUp: () => {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"up\");\n },\n extendToFirst: () => {\n if (this.controllers.length === 0) return;\n this.enterVisualBlockMode(false);\n const targetId = this.controllers[0].getBlock().id;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n extendToLast: () => {\n if (this.controllers.length === 0) return;\n this.enterVisualBlockMode(false);\n const targetId = this.controllers[this.controllers.length - 1].getBlock().id;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n indentSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds) {\n for (const id of selectedIds) {\n this.handleIndent(id);\n }\n this.recomputeListIndices();\n }\n },\n outdentSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds) {\n for (const id of selectedIds) {\n this.handleOutdent(id);\n }\n this.recomputeListIndices();\n }\n },\n toggleChecklist: () => {\n if (this.blockSelectFocus) {\n const block = this.getBlock(this.blockSelectFocus);\n if (block?.type === \"heading\") {\n this.cycleTaskStatus(this.blockSelectFocus);\n } else {\n this.toggleChecklist(this.blockSelectFocus);\n }\n }\n },\n yankBlock: () => {\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n const block = this.getBlock(focusId);\n if (block) copyBlocksToClipboard([block]);\n },\n pasteAfter: () => {\n this.pasteBlocksFromClipboard();\n },\n pasteBefore: () => {\n this.pasteBlocksBeforeFromClipboard();\n },\n jumpToLastEdit: () => {\n this.jumpToLastEdit();\n },\n selectAllBlocks: () => {\n this.selectAllBlocks();\n },\n jumpBack: () => {\n this.jumpBack();\n },\n jumpForward: () => {\n this.jumpForward();\n },\n pageUp: () => {\n if (!this.blockSelectFocus) return;\n const index = this.getBlockIndex(this.blockSelectFocus);\n if (index < 0) return;\n this.recordJump();\n const jumpCount = this.calculatePageJump();\n const targetIndex = Math.max(0, index - jumpCount);\n const targetId = this.controllers[targetIndex].getBlock().id;\n this.blockSelectAnchor = targetId;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n pageDown: () => {\n if (!this.blockSelectFocus) return;\n const index = this.getBlockIndex(this.blockSelectFocus);\n if (index < 0) return;\n this.recordJump();\n const jumpCount = this.calculatePageJump();\n const targetIndex = Math.min(this.controllers.length - 1, index + jumpCount);\n const targetId = this.controllers[targetIndex].getBlock().id;\n this.blockSelectAnchor = targetId;\n this.blockSelectFocus = targetId;\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n openSearch: () => {\n this.openSearch();\n },\n searchNext: () => {\n if (this.searchUI?.visible) {\n this.searchUI.next();\n }\n },\n searchPrev: () => {\n if (this.searchUI?.visible) {\n this.searchUI.prev();\n }\n },\n undo: () => {\n this.undo();\n },\n redo: () => {\n this.redo();\n },\n dotRepeat: () => {\n if (!this.lastRepeatableAction) return;\n const action = this.normalModeActions[this.lastRepeatableAction];\n if (action) action();\n },\n cycleTaskStatus: () => {\n if (this.blockSelectFocus) this.cycleTaskStatus(this.blockSelectFocus);\n },\n openTaskStatusMenu: () => {\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n const ctrl = this.controllerMap.get(focusId);\n if (!ctrl || ctrl.getBlock().type !== \"heading\") return;\n const indicator = ctrl.container.querySelector<HTMLButtonElement>(\".blx-heading-task-indicator\");\n if (indicator) {\n // Synthesize a right-click on the indicator to open the status menu\n const rect = indicator.getBoundingClientRect();\n indicator.dispatchEvent(new MouseEvent(\"contextmenu\", {\n bubbles: true, cancelable: true,\n clientX: rect.left + rect.width / 2,\n clientY: rect.top + rect.height / 2,\n }));\n } else {\n // No indicator yet — just cycle to \"todo\" first\n this.cycleTaskStatus(focusId);\n }\n },\n openAgendaPickerFromNormal: () => {\n if (this.blockSelectFocus) this.openAgendaPickerForBlock(this.blockSelectFocus);\n },\n removeTaskStatus: () => {\n if (this.blockSelectFocus) this.removeTaskStatus(this.blockSelectFocus);\n },\n foldBlock: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n const headingId = this.foldManager.findOwningHeading(focusId, this.getBlocks());\n if (headingId) this.foldBlock(headingId);\n },\n unfoldBlock: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n const headingId = this.foldManager.findOwningHeading(focusId, this.getBlocks());\n if (headingId) this.unfoldBlock(headingId);\n },\n toggleFold: () => {\n const focusId = this.blockSelectFocus ?? this.getFocusedBlockId();\n if (!focusId) return;\n const headingId = this.foldManager.findOwningHeading(focusId, this.getBlocks());\n if (headingId) this.toggleFold(headingId);\n },\n foldAll: () => this.foldAll(),\n unfoldAll: () => this.unfoldAll(),\n openCommandMode: () => {\n this.bus.emit(\"editor:openCommandMode\", { commands: this.commands });\n },\n openSlashMenu: () => {\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n this.bus.emit(\"editor:openSlashMenu\", { blockId: focusId });\n },\n openDocumentSwitcher: () => {\n this.bus.emit(\"editor:openDocumentSwitcher\", {});\n },\n };\n }\n\n /** Action dispatch map for visual block mode keybindings (multi-block) */\n private get visualBlockModeActions(): Record<string, () => void> {\n return {\n moveOrExtendDown: () => {\n if (this.visualBlockSticky) {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"down\");\n } else {\n this.exitVisualBlockToNormal();\n this.normalModeActions.moveDown();\n }\n },\n moveOrExtendUp: () => {\n if (this.visualBlockSticky) {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"up\");\n } else {\n this.exitVisualBlockToNormal();\n this.normalModeActions.moveUp();\n }\n },\n extendDown: () => {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"down\");\n },\n extendUp: () => {\n this.handleBlockSelectTo(this.blockSelectFocus!, \"up\");\n },\n extendToFirst: () => {\n if (this.controllers.length === 0) return;\n const targetId = this.controllers[0].getBlock().id;\n this.blockSelectFocus = targetId;\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n extendToLast: () => {\n if (this.controllers.length === 0) return;\n const targetId = this.controllers[this.controllers.length - 1].getBlock().id;\n this.blockSelectFocus = targetId;\n window.getSelection()?.removeAllRanges();\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n this.applyBlockSelectionCSS();\n this.goalX = null;\n this.viewport.scrollIntoView(targetId);\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n },\n deleteSelection: () => {\n this.deleteBlockSelection();\n },\n changeSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (!selectedIds || selectedIds.length === 0) return;\n\n const anchorIdx = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIdx = this.getBlockIndex(this.blockSelectFocus!);\n const firstIdx = Math.min(anchorIdx, focusIdx);\n const firstId = this.controllers[firstIdx].getBlock().id;\n const firstCtrl = this.controllerMap.get(firstId)!;\n const firstBlock = firstCtrl.getBlock();\n const plugin = this.getPlugin(firstBlock.type);\n\n // Begin compound undo group\n const groupCursor = { blockId: firstId, offset: 0 };\n this.undoManager.beginGroup(groupCursor);\n this.crdtLog?.beginGroup(groupCursor);\n\n // Remove all selected blocks except the first (reverse order for stable indices)\n const idsToRemove = selectedIds.filter((id) => id !== firstId);\n for (let i = idsToRemove.length - 1; i >= 0; i--) {\n this.removeBlock(idsToRemove[i]);\n }\n\n // Clear the first block's content (if it has text content)\n if (plugin.hasTextContent) {\n const beforeContent = firstBlock.content;\n const emptyContent = AttributedString.empty();\n\n this.recordUndoAction(\n {\n type: \"contentChange\",\n blockId: firstId,\n before: {\n content: beforeContent,\n metadata: { ...firstBlock.metadata },\n blockType: firstBlock.type,\n },\n after: {\n content: emptyContent,\n metadata: { ...firstBlock.metadata },\n blockType: firstBlock.type,\n },\n },\n groupCursor,\n { blockId: firstId, offset: 0 },\n );\n\n firstCtrl.updateBlock({ content: emptyContent });\n firstCtrl.rerender();\n this.bus.emit(\"block:contentChanged\", {\n blockId: firstId,\n content: emptyContent,\n metadata: firstBlock.metadata,\n });\n }\n\n // End compound undo group\n this.undoManager.endGroup({ blockId: firstId, offset: 0 });\n this.crdtLog?.endGroup({ blockId: firstId, offset: 0 });\n\n // Enter insert mode on the first block\n this.exitToInsertMode(firstId, 0);\n },\n moveBlockUp: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (!selectedIds || selectedIds.length === 0) return;\n const anchorIdx = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIdx = this.getBlockIndex(this.blockSelectFocus!);\n const firstIdx = Math.min(anchorIdx, focusIdx);\n if (firstIdx <= 0) return;\n this.moveBlocks(selectedIds, firstIdx - 1);\n this.applyBlockSelectionCSS();\n },\n moveBlockDown: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (!selectedIds || selectedIds.length === 0) return;\n const anchorIdx = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIdx = this.getBlockIndex(this.blockSelectFocus!);\n const firstIdx = Math.min(anchorIdx, focusIdx);\n const lastIdx = Math.max(anchorIdx, focusIdx);\n if (lastIdx >= this.controllers.length - 1) return;\n this.moveBlocks(selectedIds, firstIdx + 1);\n this.applyBlockSelectionCSS();\n },\n indentSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds) {\n for (const id of selectedIds) {\n this.handleIndent(id);\n }\n this.recomputeListIndices();\n }\n },\n outdentSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds) {\n for (const id of selectedIds) {\n this.handleOutdent(id);\n }\n this.recomputeListIndices();\n }\n },\n exitToNormal: () => {\n this.exitVisualBlockToNormal();\n },\n enterEditingAtStart: () => {\n this.exitToInsertMode(this.blockSelectFocus!);\n },\n enterEditingAtEnd: () => {\n const focusId = this.blockSelectFocus!;\n const block = this.getBlock(focusId);\n this.exitToInsertModeSilent();\n if (block) {\n this.focusBlock(focusId, block.content.length);\n }\n },\n yankSelection: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds && selectedIds.length > 0) {\n const blocks = selectedIds.map((id) => this.getBlock(id)).filter(Boolean) as Block[];\n copyBlocksToClipboard(blocks);\n }\n },\n pasteAfter: () => {\n this.pasteBlocksFromClipboard();\n },\n pasteBefore: () => {\n this.pasteBlocksBeforeFromClipboard();\n },\n toggleChecklist: () => {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds) {\n for (const id of selectedIds) {\n const block = this.getBlock(id);\n if (block?.type === \"heading\") {\n this.cycleTaskStatus(id);\n } else {\n this.toggleChecklist(id);\n }\n }\n }\n },\n selectAllBlocks: () => {\n this.selectAllBlocks();\n },\n jumpBack: () => {\n this.jumpBack();\n },\n jumpForward: () => {\n this.jumpForward();\n },\n openSearch: () => {\n this.openSearch();\n },\n undo: () => {\n this.undo();\n },\n redo: () => {\n this.redo();\n },\n dotRepeat: () => {\n if (!this.lastRepeatableAction) return;\n const action = this.visualBlockModeActions[this.lastRepeatableAction];\n if (action) action();\n },\n openCommandMode: () => {\n this.bus.emit(\"editor:openCommandMode\", { commands: this.commands });\n },\n openSlashMenu: () => {\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n this.bus.emit(\"editor:openSlashMenu\", { blockId: focusId });\n },\n openDocumentSwitcher: () => {\n this.bus.emit(\"editor:openDocumentSwitcher\", {});\n },\n };\n }\n\n private handleEditorKeyDown = (e: KeyboardEvent): void => {\n if (this.editorMode === \"insert\") {\n this.handleUnfocusedInput(e);\n return;\n }\n\n // Don't steal focus from native form fields (search panel, quick switcher, etc.)\n const active = document.activeElement;\n if (active) {\n const tag = active.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") {\n return;\n }\n }\n\n // The initial Shift+Arrow that entered block selection bubbles from the\n // contenteditable up to document. BlockController already called\n // preventDefault(), so skip it here to avoid double-extending.\n if (e.defaultPrevented) return;\n\n const descriptor = eventToDescriptor(e);\n const bindingMap = this.editorMode === \"normal\"\n ? this.keybindings.normal\n : this.keybindings.visualBlock;\n const actionMap = this.editorMode === \"normal\"\n ? this.normalModeActions\n : this.visualBlockModeActions;\n\n const result = this.keySequencer.resolve(descriptor, bindingMap, (fallbackAction) => {\n // Timeout fired while waiting for a sequence — execute the single-key fallback\n const fbMap = this.editorMode === \"normal\"\n ? this.normalModeActions\n : this.visualBlockModeActions;\n const fn = fbMap[fallbackAction] ?? this.externalActions.get(fallbackAction);\n if (fn) {\n fn();\n if (Editor.REPEATABLE_ACTIONS.has(fallbackAction)) {\n this.lastRepeatableAction = fallbackAction;\n }\n }\n });\n\n if (result === \"pending\") {\n e.preventDefault();\n return;\n }\n\n if (result !== null) {\n const action = actionMap[result] ?? this.externalActions.get(result);\n if (action) {\n e.preventDefault();\n action();\n // Track for dot repeat\n if (Editor.REPEATABLE_ACTIONS.has(result)) {\n this.lastRepeatableAction = result;\n }\n }\n return;\n }\n\n // In visual block mode, unbound printable characters delete the\n // selection and type the character (standard text-editor behavior\n // when blocks are selected via Shift+Arrow or mouse drag).\n if (this.editorMode === \"visualBlock\" && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n const nextFocusId = this.deleteBlockSelection();\n // deleteBlockSelection enters normal mode — switch to insert and type\n this.exitToInsertMode(nextFocusId);\n const ctrl = this.controllerMap.get(nextFocusId);\n if (ctrl?.contentEditable) {\n ctrl.contentEditable.dispatchEvent(new InputEvent(\"beforeinput\", {\n inputType: \"insertText\",\n data: e.key,\n cancelable: true,\n }));\n }\n return;\n }\n\n // Unknown key — ignore (stay in current mode)\n };\n\n /**\n * Handle keyboard input when no block is focused.\n * Emits `editor:unfocusedInput` and optionally auto-focuses the last block.\n */\n private handleUnfocusedInput(e: KeyboardEvent): void {\n // Only handle printable characters (length === 1) and avoid modifier combos\n if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;\n\n // Don't steal focus from native form fields (inside or outside the editor,\n // e.g. search panel inputs live inside this.root)\n const active = document.activeElement;\n if (active) {\n const tag = active.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") {\n return;\n }\n // Don't interfere with content-editables outside the editor\n if (!this.root.contains(active) && (active as HTMLElement).isContentEditable) {\n return;\n }\n }\n\n // Check whether any block in this editor is focused\n const focusedId = this.getFocusedBlockId();\n if (focusedId) return; // A block is focused — normal flow handles it\n\n // No block is focused — emit the unfocused input event\n this.bus.emit(\"editor:unfocusedInput\", {\n key: e.key,\n isComposing: e.isComposing,\n });\n\n // Auto-focus if enabled\n if (this.options?.autoFocusOnInput && this.controllers.length > 0) {\n e.preventDefault();\n const lastCtrl = this.controllers[this.controllers.length - 1];\n const lastBlock = lastCtrl.getBlock();\n const plugin = this.getPlugin(lastBlock.type);\n\n if (plugin.hasTextContent) {\n // Focus at end and type the character\n this.focusBlock(lastBlock.id, lastBlock.content.length);\n // Dispatch the character as a beforeinput event so it gets inserted\n if (lastCtrl.contentEditable) {\n lastCtrl.contentEditable.dispatchEvent(new InputEvent(\"beforeinput\", {\n inputType: \"insertText\",\n data: e.key,\n cancelable: true,\n }));\n }\n }\n }\n }\n\n private deleteBlockSelection(): string {\n const anchorIndex = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIndex = this.getBlockIndex(this.blockSelectFocus!);\n const firstIndex = Math.min(anchorIndex, focusIndex);\n const lastIndex = Math.max(anchorIndex, focusIndex);\n\n // Determine which block to select after deletion:\n // prefer block after the range, then block before, then create new\n const blockAfterIndex = lastIndex + 1 < this.controllers.length ? lastIndex + 1 : -1;\n const blockBeforeIndex = firstIndex > 0 ? firstIndex - 1 : -1;\n\n let nextFocusId: string | null = null;\n if (blockAfterIndex >= 0) {\n nextFocusId = this.controllers[blockAfterIndex].getBlock().id;\n } else if (blockBeforeIndex >= 0) {\n nextFocusId = this.controllers[blockBeforeIndex].getBlock().id;\n }\n\n // Collect IDs to remove (snapshot before mutation)\n const idsToRemove: string[] = [];\n for (let i = firstIndex; i <= lastIndex; i++) {\n const block = this.controllers[i].getBlock();\n if (this.getPlugin(block.type).immovable) continue; // skip immovable blocks\n idsToRemove.push(block.id);\n }\n if (idsToRemove.length === 0) return this.controllers[firstIndex].getBlock().id; // nothing to delete\n\n // Compound undo group for multi-block delete\n if (!this._suppressHistory) {\n const deleteGroupCursor = this.blockSelectAnchor\n ? { blockId: this.blockSelectAnchor, offset: 0 }\n : null;\n this.undoManager.beginGroup(deleteGroupCursor);\n this.crdtLog?.beginGroup(deleteGroupCursor);\n }\n\n // Remove all selected blocks (reverse order to keep indices stable)\n for (let i = idsToRemove.length - 1; i >= 0; i--) {\n this.removeBlock(idsToRemove[i]);\n }\n\n // If no blocks remain, create an empty paragraph\n if (this.controllers.length === 0) {\n const newBlock = this.addBlock(\"paragraph\");\n nextFocusId = newBlock.id;\n }\n\n if (!this._suppressHistory) {\n const deleteEndCursor = nextFocusId ? { blockId: nextFocusId, offset: 0 } : null;\n this.undoManager.endGroup(deleteEndCursor);\n this.crdtLog?.endGroup(deleteEndCursor);\n }\n\n this.exitToInsertModeSilent();\n // Enter normal mode on the next focus block\n if (nextFocusId) {\n this.enterNormalMode(nextFocusId);\n }\n return nextFocusId!;\n }\n\n private buildMultiBlockSelection(): MultiBlockSelection {\n const anchorIndex = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIndex = this.getBlockIndex(this.blockSelectFocus!);\n const first = Math.min(anchorIndex, focusIndex);\n const last = Math.max(anchorIndex, focusIndex);\n const selectedBlockIds = this.controllers\n .slice(first, last + 1)\n .map((c) => c.getBlock().id);\n\n const anchorBlock = this.controllers[anchorIndex].getBlock();\n const focusBlock = this.controllers[focusIndex].getBlock();\n\n return {\n anchorBlockId: this.blockSelectAnchor!,\n anchorOffset: anchorIndex <= focusIndex ? 0 : anchorBlock.content.length,\n focusBlockId: this.blockSelectFocus!,\n focusOffset: focusIndex >= anchorIndex ? focusBlock.content.length : 0,\n selectedBlockIds,\n };\n }\n\n private applyBlockSelectionCSS(): void {\n const anchorIndex = this.getBlockIndex(this.blockSelectAnchor!);\n const focusIndex = this.getBlockIndex(this.blockSelectFocus!);\n const first = Math.min(anchorIndex, focusIndex);\n const last = Math.max(anchorIndex, focusIndex);\n\n for (let i = 0; i < this.controllers.length; i++) {\n const container = this.controllers[i].container;\n if (i >= first && i <= last) {\n container.classList.add(\"blx-block-selected\");\n } else {\n container.classList.remove(\"blx-block-selected\");\n }\n }\n }\n\n private clearBlockSelectionCSS(): void {\n for (const ctrl of this.controllers) {\n ctrl.container.classList.remove(\"blx-block-selected\");\n }\n }\n\n /** Exit to insert mode and focus a block */\n private exitToInsertMode(focusBlockId: string, offset?: number): void {\n this.setMode(\"insert\");\n this.blockSelectAnchor = null;\n this.blockSelectFocus = null;\n this.clearBlockSelectionCSS();\n this.bus.emit(\"selection:blockSelect\", { state: null });\n this.focusBlock(focusBlockId, offset ?? 0);\n }\n\n /** Exit to insert mode without focusing any block */\n private exitToInsertModeSilent(): void {\n this.setMode(\"insert\");\n this.blockSelectAnchor = null;\n this.blockSelectFocus = null;\n this.clearBlockSelectionCSS();\n this.bus.emit(\"selection:blockSelect\", { state: null });\n }\n\n /** Exit visual block mode back to normal mode (Escape or v from visual) */\n private exitVisualBlockToNormal(): void {\n const focusId = this.blockSelectFocus;\n this.setMode(\"normal\");\n // Collapse selection to focus block\n if (focusId) {\n this.blockSelectAnchor = focusId;\n this.blockSelectFocus = focusId;\n }\n this.applyBlockSelectionCSS();\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n /** Set editor mode and update CSS classes on root */\n private setMode(mode: \"insert\" | \"normal\" | \"visualBlock\"): void {\n this.editorMode = mode;\n this.root.classList.remove(\"blx-mode-normal\", \"blx-mode-visual-block\");\n if (mode === \"normal\") {\n this.root.classList.add(\"blx-mode-normal\");\n } else if (mode === \"visualBlock\") {\n this.root.classList.add(\"blx-mode-visual-block\");\n }\n this.bus.emit(\"editor:modeChanged\", { mode });\n this.customCaret?.setEnabled(mode === \"insert\");\n }\n\n /** @internal Whether the editor is in block selection mode (normal or visual block) */\n get isBlockSelecting(): boolean {\n return this.editorMode !== \"insert\";\n }\n\n /** @internal Get the current editor mode */\n get mode(): \"insert\" | \"normal\" | \"visualBlock\" {\n return this.editorMode;\n }\n\n // ── Slash command menu ──────────────────────────────────────────\n\n private openOrUpdateSlashMenu(blockId: string, query: string, slashOffset: number): void {\n // Don't show slash menu for inconvertible blocks (e.g. title)\n const slashCtrl = this.controllerMap.get(blockId);\n if (slashCtrl && this.getPlugin(slashCtrl.getBlock().type).inconvertible) return;\n\n if (!this.slashMenu) {\n const allItems = [...SLASH_MENU_ITEMS, ...this.customSlashItems];\n this.slashMenu = new SlashMenu(\n allItems,\n (item) => this.handleSlashMenuSelect(item),\n () => this.closeSlashMenu(),\n );\n this.root.appendChild(this.slashMenu.element);\n }\n\n this.slashMenuBlockId = blockId;\n this.slashCommandOffset = slashOffset;\n\n this.slashMenu.updateFilter(query);\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n if (this.slashMenu.hasItems) {\n if (!this.slashMenu.visible) {\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n this.slashMenu.show(rect);\n\n // Register with floating scroll manager\n this.floatingScroll.register({\n key: \"slash-menu\",\n anchorEl: ctrl.container,\n onReposition: () => {\n const c = this.controllerMap.get(this.slashMenuBlockId!);\n if (!c) return;\n const r = c.getCaretRect() ?? c.container.getBoundingClientRect();\n this.slashMenu!.reposition(r);\n },\n onScrollOut: () => this.closeSlashMenu(),\n onScrollIn: () => {},\n });\n }\n } else {\n // No matches — hide menu but keep state alive (backspace may widen filter)\n this.slashMenu.hide();\n }\n\n // Install capture-phase keydown handler (only once)\n if (!this.slashMenuKeyHandler) {\n this.slashMenuKeyHandler = (e: KeyboardEvent) => {\n if (!this.slashMenu?.visible) return;\n const consumed = this.slashMenu.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", this.slashMenuKeyHandler, true);\n }\n }\n\n private closeSlashMenu(): void {\n this.floatingScroll.unregister(\"slash-menu\");\n if (this.slashMenu) {\n this.slashMenu.hide();\n }\n if (this.slashMenuKeyHandler) {\n document.removeEventListener(\"keydown\", this.slashMenuKeyHandler, true);\n this.slashMenuKeyHandler = null;\n }\n // Clear slash state on the block controller\n if (this.slashMenuBlockId) {\n const ctrl = this.controllerMap.get(this.slashMenuBlockId);\n ctrl?.clearSlashState();\n }\n this.slashMenuBlockId = null;\n this.slashCommandOffset = null;\n }\n\n private handleSlashMenuSelect(item: SlashMenuItem): void {\n const blockId = this.slashMenuBlockId;\n const slashOffset = this.slashCommandOffset;\n this.closeSlashMenu();\n if (!blockId) return;\n\n // Delete the \"/query\" text from the block\n if (slashOffset !== null) {\n const ctrl = this.controllerMap.get(blockId);\n if (ctrl) {\n const cursorOffset = ctrl.getCursorOffset() ?? ctrl.getBlock().content.length;\n const tx = new Transaction(blockId).deleteRange(slashOffset, cursorOffset);\n ctrl.applyTransaction(tx);\n }\n }\n\n // Check custom handlers first\n const customHandler = this.customSlashHandlers.get(item.type);\n if (customHandler) {\n customHandler(blockId);\n return;\n }\n\n const metadata = item.metadata ?? this.getPlugin(item.type).defaultMetadata();\n this.changeBlockType(blockId, item.type, metadata);\n\n const plugin = this.getPlugin(item.type);\n if (!plugin.hasTextContent) {\n const ctrl = this.controllerMap.get(blockId);\n if (item.type === \"table\" && ctrl) {\n // Tables have their own cell-level focus — skip focusNonTextBlock\n // which would add a focus ring and intercept keys\n const firstCell = ctrl.container.querySelector<HTMLElement>('[data-row=\"0\"][data-col=\"0\"]');\n if (firstCell) firstCell.focus();\n } else {\n this.focusNonTextBlock(blockId);\n if (ctrl) {\n const input = ctrl.container.querySelector(\"input:not([type=file])\") as HTMLElement | null;\n input?.focus();\n }\n }\n // Auto-open excalidraw modal for newly created blocks\n if (item.type === \"excalidraw\" && ctrl) {\n requestAnimationFrame(() => {\n ctrl.container.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n });\n }\n } else {\n this.focusBlock(blockId, 0);\n }\n }\n\n // ── Emoji picker ──────────────────────────────────────────────\n\n private openOrUpdateEmojiPicker(blockId: string, query: string, colonOffset: number): void {\n if (!this.emojiPicker) {\n this.emojiPicker = new EmojiPicker(\n (emoji) => {\n // onSelect: commit the currently-typed emoji query\n if (this.emojiBlockId && this.emojiColonOffset !== null) {\n const ctrl = this.controllerMap.get(this.emojiBlockId);\n const cursorOffset = ctrl?.getCursorOffset() ?? 0;\n this.commitEmoji(this.emojiBlockId, this.emojiColonOffset, cursorOffset, emoji);\n }\n },\n () => this.closeEmojiPicker(),\n );\n this.root.appendChild(this.emojiPicker.element);\n }\n\n this.emojiBlockId = blockId;\n this.emojiColonOffset = colonOffset;\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const trimmed = query.trim();\n\n const wasVisible = this.emojiPicker.visible;\n\n if (trimmed === \"\") {\n // No query — show browse mode with category tabs\n this.emojiPicker.enterBrowseMode();\n if (!this.emojiPicker.visible) {\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n this.emojiPicker.show(rect);\n }\n } else {\n const results = searchEmoji(trimmed);\n if (results.length > 0) {\n this.emojiPicker.enterSearchMode(results);\n if (!this.emojiPicker.visible) {\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n this.emojiPicker.show(rect);\n }\n } else {\n this.emojiPicker.enterSearchMode([]);\n // Keep state active — user may keep typing and get results again\n }\n }\n\n // Register with floating scroll manager when picker becomes visible\n if (this.emojiPicker.visible && !wasVisible) {\n this.floatingScroll.register({\n key: \"emoji-picker\",\n anchorEl: ctrl.container,\n onReposition: () => {\n const c = this.controllerMap.get(this.emojiBlockId!);\n if (!c) return;\n const r = c.getCaretRect() ?? c.container.getBoundingClientRect();\n this.emojiPicker!.reposition(r);\n },\n onScrollOut: () => this.closeEmojiPicker(),\n onScrollIn: () => {},\n });\n }\n\n // Install capture-phase keydown handler (only once)\n if (!this.emojiKeyHandler) {\n this.emojiKeyHandler = (e: KeyboardEvent) => {\n if (!this.emojiPicker?.visible) return;\n const consumed = this.emojiPicker.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", this.emojiKeyHandler, true);\n }\n }\n\n private closeEmojiPicker(): void {\n this.floatingScroll.unregister(\"emoji-picker\");\n if (this.emojiPicker) {\n this.emojiPicker.hide();\n }\n if (this.emojiKeyHandler) {\n document.removeEventListener(\"keydown\", this.emojiKeyHandler, true);\n this.emojiKeyHandler = null;\n }\n // Clear emoji state on the block controller\n if (this.emojiBlockId) {\n const ctrl = this.controllerMap.get(this.emojiBlockId);\n ctrl?.clearEmojiState();\n }\n this.emojiBlockId = null;\n this.emojiColonOffset = null;\n }\n\n private commitEmoji(\n blockId: string,\n colonOffset: number,\n cursorOffset: number,\n emoji: string,\n ): void {\n this.closeEmojiPicker();\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n // Delete the `:query` range (from colonOffset to cursorOffset) and insert the emoji\n const tx = new Transaction(blockId)\n .deleteRange(colonOffset, cursorOffset)\n .insertText(colonOffset, emoji);\n ctrl.applyTransaction(tx);\n ctrl.focus(colonOffset + emoji.length);\n }\n\n // ── Agenda date picker (@) ─────────────────────────────────\n\n /**\n * Register a provider that supplies date suggestions when the user types\n * after `@`. If no provider is set, the @ trigger shows only the calendar.\n */\n setDateSuggestionProvider(provider: DateSuggestionProvider): void {\n this.dateSuggestionProvider = provider;\n }\n\n /** Remove the date suggestion provider. */\n removeDateSuggestionProvider(): void {\n this.dateSuggestionProvider = null;\n }\n\n // ── External keybindings ─────────────────────────────────────\n\n /**\n * Register additional keybindings from the host application.\n * Each binding adds a key sequence to the normal-mode binding map\n * and registers its handler so the editor can dispatch it.\n */\n registerKeybindings(bindings: ExternalKeybinding[]): void {\n for (const binding of bindings) {\n this.keybindings.normal[binding.keys] = binding.commandId;\n this.externalActions.set(binding.commandId, binding.handler);\n }\n }\n\n /** Pass the current query to the date suggestion provider and update the picker. */\n private updateAgendaSearch(query: string): void {\n if (!this.agendaPicker?.visible) return;\n\n if (!query || query.trim() === \"\" || !this.dateSuggestionProvider) {\n this.agendaPicker.updateSuggestions(null);\n return;\n }\n\n const suggestions = this.dateSuggestionProvider.suggest(query);\n this.agendaPicker.updateSuggestions(suggestions.length > 0 ? suggestions : null);\n\n // Reposition — the suggestion list may change the picker height\n if (this.agendaBlockId) {\n const ctrl = this.controllerMap.get(this.agendaBlockId);\n if (ctrl) {\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n this.agendaPicker.reposition(rect);\n }\n }\n }\n\n setBlockAgenda(blockId: string, role: \"due\" | \"scheduled\" | \"event\", date: string | null, recurrence?: { interval: number; unit: string; anchor?: string; fromCompletion?: boolean } | null): void {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = this.getBlock(blockId);\n if (!block) return;\n\n const metaKey = role === \"due\" ? \"dueDate\" : role === \"scheduled\" ? \"scheduledDate\" : \"eventDate\";\n const previous = (block.metadata[metaKey] as string) ?? null;\n\n const allKeys = [\"dueDate\", \"scheduledDate\", \"eventDate\"] as const;\n const otherKeys = allKeys.filter((k) => k !== metaKey);\n const hasOtherRole = otherKeys.some((k) => typeof block.metadata[k] === \"string\");\n\n const prevRecurrence = block.metadata.recurrence as { interval: number; unit: string; anchor?: string; fromCompletion?: boolean } | undefined ?? null;\n const recurrenceChanged = recurrence !== undefined && JSON.stringify(prevRecurrence) !== JSON.stringify(recurrence);\n if (previous === date && !hasOtherRole && !recurrenceChanged) return;\n\n const tx = new Transaction(blockId).setMetadata(metaKey, date ?? undefined);\n for (const k of otherKeys) {\n if (typeof block.metadata[k] === \"string\") {\n tx.setMetadata(k, undefined);\n }\n }\n\n if (recurrence !== undefined) {\n if (recurrence) {\n // Automerge rejects undefined values — only include defined fields\n const rec: Record<string, unknown> = { interval: recurrence.interval, unit: recurrence.unit };\n if (recurrence.anchor != null) rec.anchor = recurrence.anchor;\n if (recurrence.fromCompletion != null) rec.fromCompletion = recurrence.fromCompletion;\n tx.setMetadata(\"recurrence\", rec);\n } else {\n tx.setMetadata(\"recurrence\", undefined);\n }\n }\n\n ctrl.applyTransaction(tx);\n\n this.bus.emit(\"block:agendaChanged\", {\n blockId,\n role,\n date,\n previous,\n ...(recurrence !== undefined ? { recurrence } : {}),\n });\n }\n\n /** @deprecated Use `setBlockAgenda` instead. */\n setBlockRecurrence(blockId: string, recurrence: { interval: number; unit: string; anchor?: string; fromCompletion?: boolean } | null): void {\n const block = this.getBlock(blockId);\n if (!block) return;\n const { role, date } = resolveBlockDisplayDate(block) ?? { role: \"due\" as const, date: null };\n this.setBlockAgenda(blockId, role, date, recurrence);\n }\n\n /** @deprecated Use `setBlockAgenda(blockId, \"due\", date)` instead. */\n setBlockAgendaDate(blockId: string, agendaDate: string | null): void {\n this.setBlockAgenda(blockId, \"due\", agendaDate);\n }\n\n /** @deprecated Use `setBlockAgenda(blockId, role, null)` instead. */\n removeBlockAgendaDate(blockId: string): void {\n this.setBlockAgendaDate(blockId, null);\n }\n\n /** Open the date picker for a new agenda item (triggered by `@` in text) */\n private openAgendaPicker(blockId: string, atOffset: number, inlineRole?: \"due\" | \"scheduled\" | \"event\"): void {\n this.ensureAgendaPicker();\n this.agendaBlockId = blockId;\n this.agendaAtOffset = atOffset;\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const block = this.getBlock(blockId);\n const dateInfo = block ? resolveBlockDisplayDate(block) : null;\n const recurrence = block?.metadata.recurrence as { interval: number; unit: \"day\" | \"week\" | \"month\" | \"year\"; anchor?: string; fromCompletion?: boolean } | undefined;\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n this.agendaPicker!.show(rect, {\n initialDate: dateInfo?.date,\n initialRole: inlineRole ?? dateInfo?.role,\n initialRecurrence: recurrence,\n blockType: block?.type,\n });\n\n this.registerAgendaScrollAndKeys(ctrl);\n }\n\n /** Open the date picker for editing an existing agenda item (triggered by badge/label click) */\n private openAgendaPickerForEdit(blockId: string, agendaDate: string): void {\n this.ensureAgendaPicker();\n this.agendaBlockId = blockId;\n this.agendaAtOffset = null; // No @ in text to clean up\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const block = this.getBlock(blockId);\n const dateInfo = block ? resolveBlockDisplayDate(block) : null;\n const recurrence = block?.metadata.recurrence as { interval: number; unit: \"day\" | \"week\" | \"month\" | \"year\"; anchor?: string; fromCompletion?: boolean } | undefined;\n\n // Anchor to the badge/label element\n const badgeOrLabel = ctrl.container.querySelector(\".blx-agenda-badge, .blx-agenda-label\");\n const rect = badgeOrLabel?.getBoundingClientRect() ?? ctrl.container.getBoundingClientRect();\n this.agendaPicker!.show(rect, {\n initialDate: agendaDate || dateInfo?.date,\n initialRole: dateInfo?.role,\n initialRecurrence: recurrence,\n blockType: block?.type,\n });\n\n this.registerAgendaScrollAndKeys(ctrl);\n }\n\n private ensureAgendaPicker(): void {\n if (!this.agendaPicker) {\n this.agendaPicker = new DatePicker(\n // onSelect — receives date, role, and optional recurrence from the picker\n (isoDate: string, role: DateRole, recurrence?: Recurrence) => {\n if (this.agendaBlockId) {\n this.commitAgendaDate(this.agendaBlockId, isoDate, role, recurrence);\n }\n },\n // onRemove — clear all date roles\n () => {\n if (this.agendaBlockId) {\n const block = this.getBlock(this.agendaBlockId);\n const dateInfo = block ? resolveBlockDisplayDate(block) : null;\n\n const ctrl = this.controllerMap.get(this.agendaBlockId);\n if (ctrl) {\n const tx = new Transaction(this.agendaBlockId)\n .setMetadata(\"dueDate\", undefined)\n .setMetadata(\"scheduledDate\", undefined)\n .setMetadata(\"eventDate\", undefined)\n .setMetadata(\"recurrence\", undefined)\n .setMetadata(\"agendaDate\", undefined);\n ctrl.applyTransaction(tx);\n }\n\n // Emit so external apps (e.g. inkami) can update caches instantly\n if (dateInfo) {\n this.bus.emit(\"block:agendaChanged\", {\n blockId: this.agendaBlockId,\n role: dateInfo.role,\n date: null,\n previous: dateInfo.date,\n });\n }\n\n this.closeAgendaPicker();\n }\n },\n // onClose\n () => this.closeAgendaPicker(),\n );\n this.root.appendChild(this.agendaPicker.element);\n }\n }\n\n private registerAgendaScrollAndKeys(ctrl: BlockController): void {\n // Register with floating scroll manager\n this.floatingScroll.register({\n key: \"agenda-picker\",\n anchorEl: ctrl.container,\n onReposition: () => {\n const c = this.controllerMap.get(this.agendaBlockId!);\n if (!c) return;\n const r = c.getCaretRect() ?? c.container.getBoundingClientRect();\n this.agendaPicker!.reposition(r);\n },\n onScrollOut: () => this.closeAgendaPicker(),\n onScrollIn: () => {},\n });\n\n // Capture-phase keydown handler\n if (!this.agendaKeyHandler) {\n this.agendaKeyHandler = (e: KeyboardEvent) => {\n if (!this.agendaPicker?.visible) return;\n const consumed = this.agendaPicker.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n }\n };\n document.addEventListener(\"keydown\", this.agendaKeyHandler, true);\n }\n }\n\n private closeAgendaPicker(): void {\n this.floatingScroll.unregister(\"agenda-picker\");\n if (this.agendaPicker) {\n this.agendaPicker.hide();\n }\n if (this.agendaKeyHandler) {\n document.removeEventListener(\"keydown\", this.agendaKeyHandler, true);\n this.agendaKeyHandler = null;\n }\n // Clean up the \"@query\" text if it was a trigger (not an edit of existing badge)\n if (this.agendaBlockId && this.agendaAtOffset !== null) {\n const ctrl = this.controllerMap.get(this.agendaBlockId);\n if (ctrl) {\n // Delete from @ to cursor position (covers \"@\" + any typed query text)\n const cursorOffset = ctrl.getCursorOffset() ?? (this.agendaAtOffset + 1);\n const tx = new Transaction(this.agendaBlockId)\n .deleteRange(this.agendaAtOffset, cursorOffset);\n ctrl.applyTransaction(tx);\n ctrl.focus(this.agendaAtOffset);\n ctrl.clearAgendaState();\n }\n } else if (this.agendaBlockId) {\n const ctrl = this.controllerMap.get(this.agendaBlockId);\n ctrl?.clearAgendaState();\n }\n this.agendaBlockId = null;\n this.agendaAtOffset = null;\n }\n\n private commitAgendaDate(blockId: string, isoDate: string, role: DateRole, recurrence?: Recurrence): void {\n // Clean up the \"@query\" trigger text if present\n if (this.agendaAtOffset !== null) {\n const ctrl = this.controllerMap.get(blockId);\n if (ctrl) {\n // Delete from @ to cursor position (covers \"@\" + any typed query text)\n const cursorOffset = ctrl.getCursorOffset() ?? (this.agendaAtOffset + 1);\n const tx = new Transaction(blockId)\n .deleteRange(this.agendaAtOffset, cursorOffset);\n ctrl.applyTransaction(tx);\n ctrl.focus(this.agendaAtOffset);\n ctrl.clearAgendaState();\n }\n }\n this.agendaAtOffset = null; // Prevent closeAgendaPicker from double-deleting\n\n this.setBlockAgenda(blockId, role, isoDate, recurrence ?? null);\n\n // Close the picker\n this.floatingScroll.unregister(\"agenda-picker\");\n if (this.agendaPicker) {\n this.agendaPicker.hide();\n }\n if (this.agendaKeyHandler) {\n document.removeEventListener(\"keydown\", this.agendaKeyHandler, true);\n this.agendaKeyHandler = null;\n }\n // Refocus the block\n const ctrl = this.controllerMap.get(blockId);\n ctrl?.focus();\n this.agendaBlockId = null;\n }\n\n // ── Autocomplete menu ([[) ──────────────────────────────────\n\n /**\n * Register an autocomplete provider that supplies entries when `[[` is typed.\n * Multiple providers can be registered; results are merged in order.\n */\n addAutoCompleteProvider(provider: AutoCompleteProvider): void {\n // Replace existing provider with same id\n this.autoCompleteProviders = this.autoCompleteProviders.filter(p => p.id !== provider.id);\n this.autoCompleteProviders.push(provider);\n }\n\n /** Remove a previously-registered autocomplete provider by id. */\n removeAutoCompleteProvider(id: string): boolean {\n const before = this.autoCompleteProviders.length;\n this.autoCompleteProviders = this.autoCompleteProviders.filter(p => p.id !== id);\n return this.autoCompleteProviders.length < before;\n }\n\n private async openOrUpdateAutoComplete(blockId: string, query: string, bracketOffset: number): Promise<void> {\n if (!this.autoCompleteMenu) {\n this.autoCompleteMenu = new AutoCompleteMenu(\n (entry) => this.commitAutoComplete(entry),\n () => this.closeAutoComplete(),\n );\n this.root.appendChild(this.autoCompleteMenu.element);\n }\n\n this.autoCompleteBlockId = blockId;\n this.autoCompleteBracketOffset = bracketOffset;\n\n // Gather results from all providers\n const allResults: AutoCompleteEntry[] = [];\n for (const provider of this.autoCompleteProviders) {\n const results = await provider.search(query);\n allResults.push(...results);\n }\n\n // Also search headings in the current document (built-in)\n const docResults = this.searchDocumentHeadings(query);\n // Prepend document results (they have priority)\n const merged = [...docResults, ...allResults];\n // Deduplicate by id\n const seen = new Set<string>();\n const deduped = merged.filter(e => {\n if (seen.has(e.id)) return false;\n seen.add(e.id);\n return true;\n });\n\n this.autoCompleteMenu.updateResults(deduped.slice(0, 12));\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const rect = ctrl.getCaretRect() ?? ctrl.container.getBoundingClientRect();\n if (!this.autoCompleteMenu.visible) {\n this.autoCompleteMenu.show(rect);\n\n // Register with floating scroll manager\n this.floatingScroll.register({\n key: \"autocomplete-menu\",\n anchorEl: ctrl.container,\n onReposition: () => {\n const c = this.controllerMap.get(this.autoCompleteBlockId!);\n if (!c) return;\n const r = c.getCaretRect() ?? c.container.getBoundingClientRect();\n this.autoCompleteMenu!.reposition(r);\n },\n onScrollOut: () => this.closeAutoComplete(),\n onScrollIn: () => {},\n });\n } else {\n // Reposition on every keystroke so the menu tracks the caret\n this.autoCompleteMenu.reposition(rect);\n }\n\n // Install capture-phase keydown handler (only once)\n if (!this.autoCompleteKeyHandler) {\n this.autoCompleteKeyHandler = (e: KeyboardEvent) => {\n if (!this.autoCompleteMenu?.visible) return;\n const consumed = this.autoCompleteMenu.handleKeyDown(e);\n if (consumed) {\n e.stopPropagation();\n e.preventDefault();\n }\n };\n document.addEventListener(\"keydown\", this.autoCompleteKeyHandler, true);\n }\n }\n\n /** Search headings in the current document. */\n private searchDocumentHeadings(query: string): AutoCompleteEntry[] {\n const q = query.toLowerCase().trim();\n const results: AutoCompleteEntry[] = [];\n\n for (const block of this.getBlocks()) {\n if (block.type !== \"heading\") continue;\n const text = block.content.text;\n if (!text) continue;\n if (q && !text.toLowerCase().includes(q)) continue;\n const level = typeof block.metadata.level === \"number\" ? block.metadata.level : 1;\n results.push({\n id: block.id,\n label: text,\n description: `Heading ${level}`,\n icon: Editor.convertTargetIcon(\"heading\", { level }) ?? iconHtml(Heading1, 14),\n insertText: text,\n attributes: { blockRef: `@:${block.id}` },\n });\n }\n\n return results;\n }\n\n private commitAutoComplete(entry: AutoCompleteEntry): void {\n const blockId = this.autoCompleteBlockId;\n const bracketOffset = this.autoCompleteBracketOffset;\n this.closeAutoComplete();\n\n if (!blockId || bracketOffset === null) return;\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n const cursorOffset = ctrl.getCursorOffset() ?? ctrl.getBlock().content.length;\n const insertText = entry.insertText ?? entry.label;\n const attrs = entry.attributes ?? {};\n\n // Delete the `[[query` range and insert the reference text.\n const tx = new Transaction(blockId)\n .deleteRange(bracketOffset, cursorOffset)\n .insertText(bracketOffset, insertText, attrs);\n ctrl.applyTransaction(tx);\n ctrl.focus(bracketOffset + insertText.length);\n\n // One-shot attribute override: the next character typed will get\n // empty attributes, preventing inheritance of the pill's blockRef\n // (same pattern used by inline markdown shortcuts like **bold**).\n ctrl.setNextInsertAttrs({});\n }\n\n private closeAutoComplete(): void {\n this.floatingScroll.unregister(\"autocomplete-menu\");\n this.autoCompleteMenu?.hide();\n // Clear autocomplete state on the block controller\n if (this.autoCompleteBlockId) {\n const ctrl = this.controllerMap.get(this.autoCompleteBlockId);\n ctrl?.clearAutoCompleteState();\n }\n this.autoCompleteBlockId = null;\n this.autoCompleteBracketOffset = null;\n\n if (this.autoCompleteKeyHandler) {\n document.removeEventListener(\"keydown\", this.autoCompleteKeyHandler, true);\n this.autoCompleteKeyHandler = null;\n }\n }\n\n // ── Link & blockRef click handling ─────────────────────────\n\n private linkClickHandler = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n\n // ── blockRef pill click ──\n const refEl = target.closest<HTMLElement>(\".blx-block-ref\");\n if (refEl?.dataset.blockRef) {\n this.activateBlockRef(refEl.dataset.blockRef, e);\n return;\n }\n\n // ── Link activation ──\n // Desktop: Cmd/Ctrl+Click. Mobile: double-tap.\n const linkEl = target.closest<HTMLAnchorElement>(\"a.blx-link\");\n if (!linkEl) return;\n\n const isMod = e.metaKey || e.ctrlKey;\n const isDoubleTap = this.isDoubleTap(target);\n if (isMod || isDoubleTap) {\n const rawHref = linkEl.getAttribute(\"href\") ?? \"\";\n this.activateLink(rawHref, e);\n }\n };\n\n private touchEndHandler = (e: TouchEvent): void => {\n const target = e.target as HTMLElement;\n // Track taps for double-tap detection on links\n this.lastTapTarget = target;\n this.lastTapTime = Date.now();\n };\n\n private blockRefHoverHandler = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n const refEl = target.closest<HTMLElement>(\".blx-block-ref\");\n if (refEl?.dataset.blockRef) {\n this.bus.emit(\"blockRef:hover\", {\n blockId: refEl.dataset.blockRef,\n element: refEl,\n originalEvent: e,\n });\n }\n };\n\n private blockRefHoverEndHandler = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n const refEl = target.closest<HTMLElement>(\".blx-block-ref\");\n if (refEl?.dataset.blockRef) {\n this.bus.emit(\"blockRef:hoverEnd\", { blockId: refEl.dataset.blockRef });\n }\n };\n\n private setupLinkClickHandler(): void {\n this.root.addEventListener(\"click\", this.linkClickHandler);\n this.root.addEventListener(\"touchend\", this.touchEndHandler);\n this.root.addEventListener(\"mouseenter\", this.blockRefHoverHandler, true);\n this.root.addEventListener(\"mouseleave\", this.blockRefHoverEndHandler, true);\n }\n\n private teardownLinkClickHandler(): void {\n this.root.removeEventListener(\"click\", this.linkClickHandler);\n this.root.removeEventListener(\"touchend\", this.touchEndHandler);\n this.root.removeEventListener(\"mouseenter\", this.blockRefHoverHandler, true);\n this.root.removeEventListener(\"mouseleave\", this.blockRefHoverEndHandler, true);\n }\n\n /**\n * Open a link, delegating to the consumer's `onLinkClick` callback if set.\n * Falls back to `window.open()` in a new tab.\n */\n private activateLink(rawHref: string, event: MouseEvent): void {\n const resolved = resolveUrl(rawHref);\n this.bus.emit(\"link:click\", { href: rawHref, resolvedHref: resolved, originalEvent: event });\n\n const handled = this.options?.onLinkClick?.(rawHref, resolved, event);\n if (!handled) {\n window.open(resolved, \"_blank\", \"noopener,noreferrer\");\n }\n }\n\n /**\n * Handle a click on a blockRef pill.\n * Scrolls to the referenced block by default.\n * Emits `blockRef:click` so external consumers can also react.\n */\n private activateBlockRef(blockId: string, event: MouseEvent): void {\n this.bus.emit(\"blockRef:click\", { blockId, originalEvent: event });\n // For same-page refs (@:blockId), extract the block ID for scrolling\n const scrollTarget = blockId.startsWith(\"@:\") ? blockId.slice(2) : blockId;\n this.scrollToBlock(scrollTarget, true);\n }\n\n /** Returns true when two taps on the same element occur within 400ms. */\n private isDoubleTap(target: HTMLElement): boolean {\n const now = Date.now();\n const dt = now - this.lastTapTime;\n const same = this.lastTapTarget === target;\n // Reset after reading so triple-tap doesn't re-trigger\n this.lastTapTarget = null;\n this.lastTapTime = 0;\n return same && dt < 400;\n }\n\n // ── Inline toolbar ──────────────────────────────────────────\n\n private setupInlineToolbar(): void {\n this.inlineToolbar = new InlineToolbar((attribute, active) => {\n this.applyInlineFormat(attribute, active);\n });\n this.root.appendChild(this.inlineToolbar.element);\n\n // Add link button to the toolbar\n this.setupLinkButton();\n\n // Add highlight button to the toolbar\n this.setupHighlightButton();\n\n // Track mouse state so toolbar only appears after mouseup\n this._onMouseDown = () => {\n this._mouseDown = true;\n // Clicking clears pending marks (cursor is moving to a new position)\n this.clearPendingMarks();\n };\n this._onMouseUp = () => {\n this._mouseDown = false;\n this.handleSelectionChange();\n };\n document.addEventListener(\"mousedown\", this._onMouseDown);\n document.addEventListener(\"mouseup\", this._onMouseUp);\n\n // Listen for selection changes to show/hide toolbar\n this.selectionChangeHandler = () => this.handleSelectionChange();\n document.addEventListener(\"selectionchange\", this.selectionChangeHandler);\n\n // Keyboard shortcuts for formatting (Cmd/Ctrl + B/I/U/K) and\n // clearing pending marks on navigation keys\n this.formatKeyHandler = (e: KeyboardEvent) => {\n // Navigation keys clear pending marks (cursor is moving)\n if (this._pendingMarksCtrl && !e.metaKey && !e.ctrlKey) {\n const nav = e.key === \"ArrowLeft\" || e.key === \"ArrowRight\" ||\n e.key === \"ArrowUp\" || e.key === \"ArrowDown\" ||\n e.key === \"Home\" || e.key === \"End\" ||\n e.key === \"PageUp\" || e.key === \"PageDown\" ||\n e.key === \"Escape\" || e.key === \"Tab\";\n if (nav) {\n this.clearPendingMarks();\n }\n }\n this.handleFormatKeyDown(e);\n };\n this.root.addEventListener(\"keydown\", this.formatKeyHandler);\n }\n\n private setupLinkButton(): void {\n this.linkPopover = new LinkPopover(\n (url) => this.applyLinkToSelection(url),\n () => this.removeLinkFromSelection(),\n () => {\n this.floatingScroll.unregister(\"link-popover\");\n this.restoreOverlayCursor();\n },\n );\n this.root.appendChild(this.linkPopover.element);\n\n this.inlineToolbar?.addButton({\n key: \"link\",\n label: \"Link\",\n icon: (container) => {\n container.innerHTML = iconHtml(LinkIcon, 14, { \"stroke-width\": \"2.5\" });\n },\n onAction: (ctx) => {\n this.showLinkPopover(ctx);\n },\n isActive: (ctx) => !!ctx.activeAttributes.href,\n });\n }\n\n private showLinkPopover(ctx: ToolbarActionContext): void {\n if (!this.linkPopover) return;\n\n this.saveOverlayCursor();\n\n // Save the selection context for when the popover is submitted\n this._linkContext = ctx;\n\n // Get existing href if the selection already has one\n const existingUrl = typeof ctx.activeAttributes.href === \"string\"\n ? ctx.activeAttributes.href\n : undefined;\n\n // Use the toolbar element position or selection rect\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const selectionRect = sel.getRangeAt(0).getBoundingClientRect();\n\n this.linkPopover.show(selectionRect, existingUrl);\n\n // Register with floating scroll manager\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (ctrl) {\n this.floatingScroll.register({\n key: \"link-popover\",\n anchorEl: ctrl.container,\n onReposition: () => {\n // Link popover focuses its input — just close on scroll\n this.linkPopover?.hide();\n },\n onScrollOut: () => this.linkPopover?.hide(),\n onScrollIn: () => {},\n });\n }\n }\n\n private _linkContext: ToolbarActionContext | null = null;\n\n private applyLinkToSelection(url: string): void {\n const ctx = this._linkContext;\n this._linkContext = null;\n this._preOverlayCursor = null; // applied — don't restore old position\n if (!ctx) return;\n\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (!ctrl) return;\n\n const tx = new Transaction(ctrl.blockId)\n .applyAttributes(ctx.start, ctx.end, { href: url });\n ctrl.applyTransaction(tx);\n this.restoreSelection(ctrl, ctx.start, ctx.end);\n }\n\n private removeLinkFromSelection(): void {\n const ctx = this._linkContext;\n this._linkContext = null;\n this._preOverlayCursor = null; // applied — don't restore old position\n if (!ctx) return;\n\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (!ctrl) return;\n\n const tx = new Transaction(ctrl.blockId)\n .removeAttributes(ctx.start, ctx.end, [\"href\"]);\n ctrl.applyTransaction(tx);\n this.restoreSelection(ctrl, ctx.start, ctx.end);\n }\n\n // ── Highlight picker ──────────────────────────────────────────\n\n private _highlightContext: ToolbarActionContext | null = null;\n\n private setupHighlightButton(): void {\n this.highlightPicker = new HighlightPicker(\n (color) => this.applyHighlightToSelection(color),\n () => this.removeHighlightFromSelection(),\n () => {\n this.floatingScroll.unregister(\"highlight-picker\");\n this.restoreOverlayCursor();\n },\n );\n this.root.appendChild(this.highlightPicker.element);\n\n this.inlineToolbar?.addButton({\n key: \"highlight\",\n label: \"Highlight\",\n icon: (container) => {\n container.innerHTML = iconHtml(Pencil, 14);\n },\n onAction: (ctx) => {\n this.showHighlightPicker(ctx);\n },\n isActive: (ctx) => !!ctx.activeAttributes.backgroundColor,\n });\n }\n\n private showHighlightPicker(ctx: ToolbarActionContext): void {\n if (!this.highlightPicker) return;\n\n this.saveOverlayCursor();\n this._highlightContext = ctx;\n\n const activeColor = typeof ctx.activeAttributes.backgroundColor === \"string\"\n ? ctx.activeAttributes.backgroundColor\n : undefined;\n\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const selectionRect = sel.getRangeAt(0).getBoundingClientRect();\n\n this.highlightPicker.show(selectionRect, activeColor);\n\n // Register with floating scroll manager\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (ctrl) {\n this.floatingScroll.register({\n key: \"highlight-picker\",\n anchorEl: ctrl.container,\n onReposition: () => this.highlightPicker?.hide(),\n onScrollOut: () => this.highlightPicker?.hide(),\n onScrollIn: () => {},\n });\n }\n }\n\n private applyHighlightToSelection(color: string): void {\n const ctx = this._highlightContext;\n this._highlightContext = null;\n this._preOverlayCursor = null;\n if (!ctx) return;\n\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (!ctrl) return;\n\n const tx = new Transaction(ctrl.blockId)\n .applyAttributes(ctx.start, ctx.end, { backgroundColor: color });\n ctrl.applyTransaction(tx);\n this.restoreSelection(ctrl, ctx.start, ctx.end);\n }\n\n private removeHighlightFromSelection(): void {\n const ctx = this._highlightContext;\n this._highlightContext = null;\n this._preOverlayCursor = null;\n if (!ctx) return;\n\n const ctrl = this.controllerMap.get(ctx.blockId);\n if (!ctrl) return;\n\n const tx = new Transaction(ctrl.blockId)\n .removeAttributes(ctx.start, ctx.end, [\"backgroundColor\"]);\n ctrl.applyTransaction(tx);\n this.restoreSelection(ctrl, ctx.start, ctx.end);\n }\n\n private teardownInlineToolbar(): void {\n if (this._toolbarDebounceTimer !== null) {\n clearTimeout(this._toolbarDebounceTimer);\n this._toolbarDebounceTimer = null;\n }\n if (this.inlineToolbar) {\n this.inlineToolbar.destroy();\n this.inlineToolbar = null;\n }\n if (this.linkPopover) {\n this.linkPopover.destroy();\n this.linkPopover = null;\n }\n if (this.highlightPicker) {\n this.highlightPicker.destroy();\n this.highlightPicker = null;\n }\n if (this.selectionChangeHandler) {\n document.removeEventListener(\"selectionchange\", this.selectionChangeHandler);\n this.selectionChangeHandler = null;\n }\n if (this._onMouseDown) {\n document.removeEventListener(\"mousedown\", this._onMouseDown);\n this._onMouseDown = null;\n }\n if (this._onMouseUp) {\n document.removeEventListener(\"mouseup\", this._onMouseUp);\n this._onMouseUp = null;\n }\n this._mouseDown = false;\n this.selectionForceMountedId = null;\n if (this.formatKeyHandler) {\n this.root.removeEventListener(\"keydown\", this.formatKeyHandler);\n this.formatKeyHandler = null;\n }\n this.floatingScroll.unregister(\"inline-toolbar\");\n }\n\n private handleSelectionChange(): void {\n // Keep the block with the active selection force-mounted so the\n // viewport never unloads it while the user has a selection there.\n this.updateSelectionForceMount();\n\n // Let the controller with pending marks know the selection changed,\n // so it can clear them unless the change was caused by text insertion.\n if (this._pendingMarksCtrl) {\n const selNode = window.getSelection()?.anchorNode;\n const selCtrl = selNode ? this.findControllerForNode(selNode) : null;\n if (selCtrl !== this._pendingMarksCtrl) {\n // Focus moved to a different block — force clear\n this._pendingMarksCtrl.clearPendingMarks();\n this._pendingMarksCtrl = null;\n } else {\n this._pendingMarksCtrl.selectionDidChange();\n if (!this._pendingMarksCtrl.getPendingMarks()) {\n this._pendingMarksCtrl = null;\n }\n }\n }\n\n if (!this.inlineToolbar) return;\n if (this.editorMode !== \"insert\") {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n const sel = window.getSelection();\n if (!sel || sel.isCollapsed || sel.rangeCount === 0) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n const range = sel.getRangeAt(0);\n\n // Only show when selection is within the editor\n if (!this.root.contains(range.commonAncestorContainer)) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n // Find the block controller that contains the selection\n const ctrl = this.findControllerForNode(range.startContainer);\n if (!ctrl) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n const block = ctrl.getBlock();\n const plugin = this.getPlugin(block.type);\n\n // Don't show for non-text blocks or code blocks (code has its own styling)\n // Exception: table cells are contenteditable and support inline formatting\n const isTableCell = block.type === \"table\" && range.startContainer.parentElement?.closest(\".blx-table-cell\") != null;\n if ((!plugin.hasTextContent && !isTableCell) || block.type === \"code\" || (Array.isArray(plugin.allowedAttributes) && plugin.allowedAttributes.length === 0)) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n // Position at focus (head of selection), not at full selection bounding rect\n let positionRect: DOMRect = range.getBoundingClientRect();\n if (sel.focusNode) {\n try {\n const focusRange = document.createRange();\n focusRange.setStart(sel.focusNode, sel.focusOffset);\n focusRange.collapse(true);\n const r = focusRange.getBoundingClientRect();\n if (r.height > 0) positionRect = r;\n } catch {\n // fall through to full selection rect\n }\n }\n // Guard against zero-size rects (jsdom or collapsed selections)\n if (positionRect.width === 0 && positionRect.height === 0) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n\n // Determine which attributes are active across the selection\n let start: number;\n let end: number;\n let activeAttrs: Attributes;\n let applyAttributeFn: (attribute: string, active: boolean) => void;\n\n if (isTableCell) {\n // Table cell: compute selection relative to the <td>, use cell's AttributedString\n const td = range.startContainer.parentElement?.closest(\".blx-table-cell\") as HTMLElement | null\n ?? (range.startContainer.nodeType === Node.ELEMENT_NODE\n ? (range.startContainer as HTMLElement).closest(\".blx-table-cell\") as HTMLElement | null\n : null);\n if (!td) {\n this.inlineToolbar.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n const rowIdx = parseInt(td.getAttribute(\"data-row\") || \"0\", 10);\n const colIdx = parseInt(td.getAttribute(\"data-col\") || \"0\", 10);\n\n // Compute selection range relative to the <td>\n const startRange = document.createRange();\n startRange.selectNodeContents(td);\n startRange.setEnd(range.startContainer, range.startOffset);\n const rawStart = startRange.toString().length;\n const endRange = document.createRange();\n endRange.selectNodeContents(td);\n endRange.setEnd(range.endContainer, range.endOffset);\n const rawEnd = endRange.toString().length;\n start = Math.min(rawStart, rawEnd);\n end = Math.max(rawStart, rawEnd);\n\n // Get active attributes from the cell's AttributedString spans\n const meta = block.metadata;\n const headerArr = meta.header as (AttributedString | Span[])[];\n const bodyRows = meta.rows as (AttributedString | Span[])[][];\n const rawCell = rowIdx === 0 ? headerArr[colIdx] : bodyRows[rowIdx - 1]?.[colIdx];\n const cell = rawCell instanceof AttributedString ? rawCell\n : Array.isArray(rawCell) ? AttributedString.fromSpans(rawCell as Span[])\n : null;\n\n if (cell && start < end) {\n activeAttrs = this.getAttributesFromSpans(cell.spans, start, end);\n } else {\n activeAttrs = {};\n }\n\n applyAttributeFn = (attribute: string, active: boolean) => {\n const currentBlock = ctrl.getBlock();\n const currentMeta = currentBlock.metadata;\n const toAS2 = (v: unknown): AttributedString =>\n v instanceof AttributedString ? v\n : Array.isArray(v) ? AttributedString.fromSpans(v as Span[])\n : AttributedString.empty();\n const currentHeader = (currentMeta.header as unknown[]).map(toAS2);\n const currentBodyRows = (currentMeta.rows as unknown[][]).map(r => r.map(toAS2));\n const currentCell = rowIdx === 0 ? currentHeader[colIdx] : currentBodyRows[rowIdx - 1]?.[colIdx];\n if (!currentCell) return;\n\n const newCell = active\n ? currentCell.applyAttributes(start, end, { [attribute]: true })\n : currentCell.removeAttributes(start, end, [attribute]);\n\n if (rowIdx === 0) {\n currentHeader[colIdx] = newCell;\n } else {\n currentBodyRows[rowIdx - 1][colIdx] = newCell;\n }\n\n const tx = new Transaction(ctrl.blockId)\n .setMetadata(\"header\", currentHeader)\n .setMetadata(\"rows\", currentBodyRows);\n ctrl.applyTransaction(tx);\n\n // Re-render the block\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(ctrl.container, updated.content, updated.metadata);\n\n // Restore selection in the re-rendered cell\n this.restoreTableCellSelection(ctrl, rowIdx, colIdx, start, end);\n };\n } else {\n ({ start, end } = this.getControllerSelectionRange(ctrl));\n activeAttrs = this.getSelectionAttributes(ctrl, start, end);\n applyAttributeFn = (attribute: string, active: boolean) => {\n this.applyFormatToController(ctrl, attribute, active, start, end);\n };\n }\n\n const context: ToolbarActionContext = {\n blockId: ctrl.blockId,\n start,\n end,\n activeAttributes: activeAttrs,\n applyAttribute: applyAttributeFn,\n };\n\n const registerFloatingScroll = () => {\n this.floatingScroll.register({\n key: \"inline-toolbar\",\n anchorEl: ctrl.container,\n onReposition: () => {\n const s = window.getSelection();\n if (!s || s.isCollapsed || s.rangeCount === 0) {\n this.inlineToolbar!.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n const rect = s.getRangeAt(0).getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) {\n this.inlineToolbar!.hide();\n this.floatingScroll.unregister(\"inline-toolbar\");\n return;\n }\n if (this.inlineToolbar!.visible) {\n this.inlineToolbar!.reposition(rect);\n } else {\n this.handleSelectionChange();\n }\n },\n onScrollOut: () => this.inlineToolbar!.hide(),\n onScrollIn: () => this.handleSelectionChange(),\n });\n };\n\n if (this.inlineToolbar.visible) {\n // Already showing — update button states immediately, no reposition\n this.inlineToolbar.updateActiveAttributes(activeAttrs, context);\n registerFloatingScroll();\n } else if (!this._mouseDown) {\n // Not yet showing and mouse is up — debounce to confirm stability\n if (this._toolbarDebounceTimer !== null) {\n clearTimeout(this._toolbarDebounceTimer);\n }\n this._toolbarDebounceTimer = setTimeout(() => {\n this._toolbarDebounceTimer = null;\n const s = window.getSelection();\n if (!s || s.isCollapsed || s.rangeCount === 0) return;\n // Recompute position from current focus\n let freshRect = positionRect;\n try {\n const fr = document.createRange();\n fr.setStart(s.focusNode!, s.focusOffset);\n fr.collapse(true);\n const r = fr.getBoundingClientRect();\n if (r.height > 0) freshRect = r;\n } catch {\n // use captured positionRect\n }\n if (freshRect.width === 0 && freshRect.height === 0) return;\n this.inlineToolbar!.show(freshRect, activeAttrs, context);\n registerFloatingScroll();\n }, 50);\n }\n // When mouse is down and toolbar not visible: do nothing (wait for mouseup)\n }\n\n /**\n * Force-mount the block that owns the active text selection so the\n * viewport never unloads it. Release the previous force-mount when\n * the selection moves or collapses.\n */\n private updateSelectionForceMount(): void {\n let newId: string | null = null;\n\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0);\n if (this.root.contains(range.commonAncestorContainer)) {\n const ctrl = this.findControllerForNode(range.startContainer);\n if (ctrl) newId = ctrl.blockId;\n }\n }\n\n if (newId === this.selectionForceMountedId) return;\n\n // Release previous\n if (this.selectionForceMountedId) {\n this.viewport.releaseForceMounted(this.selectionForceMountedId);\n }\n // Lock new\n if (newId) {\n this.viewport.ensureMounted(newId);\n }\n this.selectionForceMountedId = newId;\n }\n\n private handleFormatKeyDown(e: KeyboardEvent): void {\n const mod = e.metaKey || e.ctrlKey;\n if (!mod) return;\n\n // Mod+A: select all toggle — first press selects all text in block,\n // second press (when already fully selected) selects all blocks\n if (e.key.toLowerCase() === \"a\" && !e.shiftKey) {\n // In normal/visualBlock mode, Mod+A is handled by the keybinding system\n // (setupDocumentKeydown → normalModeActions/visualBlockModeActions)\n // so this handler only fires in insert mode (on this.root).\n\n // In insert mode, check if current block text is already fully selected\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0) {\n const ctrl = this.findControllerForNode(sel.getRangeAt(0).startContainer);\n if (ctrl) {\n const block = ctrl.getBlock();\n const { start, end } = this.getControllerSelectionRange(ctrl);\n if (start === 0 && end === block.content.length && block.content.length > 0) {\n // Already fully selected → select all blocks\n e.preventDefault();\n this.selectAllBlocks();\n return;\n }\n }\n }\n // Not fully selected → let browser handle (native select all within block)\n return;\n }\n\n // Cmd/Ctrl+Shift+Enter: open link at cursor\n if (e.shiftKey && e.key === \"Enter\") {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const ctrl = this.findControllerForNode(sel.getRangeAt(0).startContainer);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const plugin = this.getPlugin(block.type);\n if (!plugin.hasTextContent) return;\n\n const offset = ctrl.getCursorOffset() ?? 0;\n const attrs = block.content.attributesAt(offset > 0 ? offset - 1 : 0);\n if (typeof attrs.href === \"string\") {\n e.preventDefault();\n this.activateLink(attrs.href, e as unknown as MouseEvent);\n }\n return;\n }\n\n // Block type conversion shortcuts: Cmd/Ctrl+Shift+0-6\n if (e.shiftKey) {\n const conversionMap: Record<string, { type: string; metadata?: Record<string, unknown> }> = {\n \"0\": { type: \"paragraph\" },\n \"1\": { type: \"heading\", metadata: { level: 1 } },\n \"2\": { type: \"heading\", metadata: { level: 2 } },\n \"3\": { type: \"heading\", metadata: { level: 3 } },\n \"4\": { type: \"heading\", metadata: { level: 4 } },\n \"5\": { type: \"list\", metadata: { ordered: false } },\n \"6\": { type: \"list\", metadata: { ordered: true } },\n };\n\n const conversion = conversionMap[e.key];\n if (conversion) {\n e.preventDefault();\n const blockId = this.getFocusedBlockId();\n if (blockId) {\n this.changeBlockType(blockId, conversion.type, conversion.metadata);\n this.focusBlock(blockId, this.getBlock(blockId)?.content.length ?? 0);\n }\n return;\n }\n }\n\n // Ctrl/Cmd+Shift+T: cycle heading task status\n if (e.shiftKey && e.key.toLowerCase() === \"t\") {\n e.preventDefault();\n const blockId = this.getFocusedBlockId();\n if (blockId) this.cycleTaskStatus(blockId);\n return;\n }\n\n // Ctrl+K: link shortcut\n if (e.key.toLowerCase() === \"k\" && !e.shiftKey) {\n const sel = window.getSelection();\n if (!sel || sel.isCollapsed || sel.rangeCount === 0) return;\n const ctrl = this.findControllerForNode(sel.getRangeAt(0).startContainer);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const plugin = this.getPlugin(block.type);\n if (!plugin.hasTextContent || block.type === \"code\") return;\n\n e.preventDefault();\n const { start, end } = this.getControllerSelectionRange(ctrl);\n if (start === end) return;\n\n const activeAttrs = this.getSelectionAttributes(ctrl, start, end);\n const context: ToolbarActionContext = {\n blockId: ctrl.blockId,\n start,\n end,\n activeAttributes: activeAttrs,\n applyAttribute: (attribute, active) => {\n this.applyFormatToController(ctrl, attribute, active, start, end);\n },\n };\n this.showLinkPopover(context);\n return;\n }\n\n let attribute: string | null = null;\n\n switch (e.key.toLowerCase()) {\n case \"b\":\n attribute = \"bold\";\n break;\n case \"i\":\n attribute = \"italic\";\n break;\n case \"u\":\n attribute = \"underline\";\n break;\n }\n\n if (!attribute) return;\n\n // Find the active block controller\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n\n const ctrl = this.findControllerForNode(sel.getRangeAt(0).startContainer);\n if (!ctrl) return;\n\n const block = ctrl.getBlock();\n const plugin = this.getPlugin(block.type);\n const isTableCell = block.type === \"table\";\n if ((!plugin.hasTextContent && !isTableCell) || block.type === \"code\") return;\n // Block formatting in blocks with no allowed attributes (e.g. title)\n if (Array.isArray(plugin.allowedAttributes) && plugin.allowedAttributes.length === 0) return;\n\n e.preventDefault();\n\n // Table cell: use the selection-aware table formatting path with toggle\n if (isTableCell) {\n const range = sel.getRangeAt(0);\n const td = range.startContainer.parentElement?.closest(\".blx-table-cell\") as HTMLElement | null\n ?? (range.startContainer.nodeType === Node.ELEMENT_NODE\n ? (range.startContainer as HTMLElement).closest(\".blx-table-cell\") as HTMLElement | null\n : null);\n if (!td) return;\n const rowIdx = parseInt(td.getAttribute(\"data-row\") || \"0\", 10);\n const colIdx = parseInt(td.getAttribute(\"data-col\") || \"0\", 10);\n const meta = block.metadata;\n const rawCell = rowIdx === 0\n ? (meta.header as unknown[])[colIdx]\n : (meta.rows as unknown[][])[rowIdx - 1]?.[colIdx];\n const cell = rawCell instanceof AttributedString ? rawCell\n : Array.isArray(rawCell) ? AttributedString.fromSpans(rawCell as Span[])\n : null;\n // Compute selection range relative to <td> to check active state\n const sr = document.createRange();\n sr.selectNodeContents(td);\n sr.setEnd(range.startContainer, range.startOffset);\n const s = sr.toString().length;\n const er = document.createRange();\n er.selectNodeContents(td);\n er.setEnd(range.endContainer, range.endOffset);\n const eLen = er.toString().length;\n const cellStart = Math.min(s, eLen);\n const cellEnd = Math.max(s, eLen);\n const isActive = cell && cellStart < cellEnd\n ? !!this.getAttributesFromSpans(cell.spans, cellStart, cellEnd)[attribute]\n : false;\n this.applyFormatToTableCell(ctrl, range, attribute, !isActive);\n return;\n }\n\n const { start, end } = this.getControllerSelectionRange(ctrl);\n\n if (start === end) {\n // Collapsed cursor: toggle a pending mark for future typing\n ctrl.togglePendingMark(attribute, start);\n this._pendingMarksCtrl = ctrl.getPendingMarks() ? ctrl : null;\n return;\n }\n\n // Check if the attribute is already active\n const activeAttrs = this.getSelectionAttributes(ctrl, start, end);\n const isActive = !!activeAttrs[attribute];\n\n this.applyFormatToController(ctrl, attribute, !isActive, start, end);\n }\n\n /** Apply inline formatting to the current selection */\n private applyInlineFormat(attribute: string, active: boolean): void {\n const sel = window.getSelection();\n if (!sel || sel.isCollapsed || sel.rangeCount === 0) return;\n\n const range = sel.getRangeAt(0);\n const ctrl = this.findControllerForNode(range.startContainer);\n if (!ctrl) return;\n\n const block = ctrl.getBlock();\n\n // Table cell: format via metadata (cells are contenteditable <td>s, not block content)\n if (block.type === \"table\") {\n this.applyFormatToTableCell(ctrl, range, attribute, active);\n return;\n }\n\n const { start, end } = this.getControllerSelectionRange(ctrl);\n if (start === end) return;\n\n this.applyFormatToController(ctrl, attribute, active, start, end);\n }\n\n /** Apply inline formatting to a table cell via metadata */\n private applyFormatToTableCell(ctrl: BlockController, range: Range, attribute: string, active: boolean): void {\n const td = range.startContainer.parentElement?.closest(\".blx-table-cell\") as HTMLElement | null\n ?? (range.startContainer.nodeType === Node.ELEMENT_NODE\n ? (range.startContainer as HTMLElement).closest(\".blx-table-cell\") as HTMLElement | null\n : null);\n if (!td) return;\n\n const rowIdx = parseInt(td.getAttribute(\"data-row\") || \"0\", 10);\n const colIdx = parseInt(td.getAttribute(\"data-col\") || \"0\", 10);\n\n // Compute selection range relative to the <td>\n const startRange = document.createRange();\n startRange.selectNodeContents(td);\n startRange.setEnd(range.startContainer, range.startOffset);\n const rawStart = startRange.toString().length;\n const endRange = document.createRange();\n endRange.selectNodeContents(td);\n endRange.setEnd(range.endContainer, range.endOffset);\n const rawEnd = endRange.toString().length;\n const start = Math.min(rawStart, rawEnd);\n const end = Math.max(rawStart, rawEnd);\n if (start === end) return;\n\n const meta = ctrl.getBlock().metadata;\n const toAS = (v: unknown): AttributedString =>\n v instanceof AttributedString ? v\n : Array.isArray(v) ? AttributedString.fromSpans(v as Span[])\n : AttributedString.empty();\n const header = (meta.header as unknown[]).map(toAS);\n const bodyRows = (meta.rows as unknown[][]).map(r => r.map(toAS));\n const cell = rowIdx === 0 ? header[colIdx] : bodyRows[rowIdx - 1]?.[colIdx];\n if (!cell) return;\n\n const newCell = active\n ? cell.applyAttributes(start, end, { [attribute]: true })\n : cell.removeAttributes(start, end, [attribute]);\n\n if (rowIdx === 0) {\n header[colIdx] = newCell;\n } else {\n bodyRows[rowIdx - 1][colIdx] = newCell;\n }\n\n const tx = new Transaction(ctrl.blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", bodyRows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(ctrl.container, updated.content, updated.metadata);\n this.restoreTableCellSelection(ctrl, rowIdx, colIdx, start, end);\n }\n\n /** Clear pending marks from the tracked controller */\n private clearPendingMarks(): void {\n if (this._pendingMarksCtrl) {\n this._pendingMarksCtrl.clearPendingMarks();\n this._pendingMarksCtrl = null;\n }\n }\n\n private applyFormatToController(\n ctrl: BlockController,\n attribute: string,\n active: boolean,\n start: number,\n end: number,\n ): void {\n const tx = new Transaction(ctrl.blockId);\n if (active) {\n tx.applyAttributes(start, end, { [attribute]: true });\n } else {\n tx.removeAttributes(start, end, [attribute]);\n }\n ctrl.applyTransaction(tx);\n\n // Re-select the formatted range so the user can continue formatting\n this.restoreSelection(ctrl, start, end);\n }\n\n /**\n * Get the attributes that are common across the entire selection range.\n * An attribute is \"active\" only if every character in the range has it.\n * Checks all attribute keys used by registered toolbar buttons.\n */\n private getSelectionAttributes(ctrl: BlockController, start: number, end: number): Attributes {\n if (start >= end) return {};\n\n // Collect all attribute keys from registered toolbar buttons\n const attrKeys = new Set<string>();\n if (this.inlineToolbar) {\n for (const btn of this.inlineToolbar.getButtons()) {\n if (btn.attribute) attrKeys.add(btn.attribute);\n }\n }\n\n const content = ctrl.getBlock().content;\n const attrs: Record<string, boolean> = {};\n // Track string-valued attributes (like href, backgroundColor) separately\n const STRING_ATTR_KEYS = [\"href\", \"backgroundColor\"] as const;\n const stringAttrs: Record<string, string | false> = {};\n let first = true;\n let spanStart = 0;\n\n for (const span of content.spans) {\n const spanEnd = spanStart + span.text.length;\n\n // Check if this span overlaps with the selection\n if (spanEnd > start && spanStart < end) {\n if (first) {\n for (const key of attrKeys) {\n attrs[key] = !!span.attributes[key];\n }\n for (const key of STRING_ATTR_KEYS) {\n stringAttrs[key] = typeof span.attributes[key] === \"string\"\n ? span.attributes[key] as string\n : false;\n }\n first = false;\n } else {\n for (const key of attrKeys) {\n if (attrs[key] && !span.attributes[key]) {\n attrs[key] = false;\n }\n }\n for (const key of STRING_ATTR_KEYS) {\n if (stringAttrs[key] !== false) {\n if (typeof span.attributes[key] !== \"string\" || span.attributes[key] !== stringAttrs[key]) {\n stringAttrs[key] = false;\n }\n }\n }\n }\n }\n\n spanStart = spanEnd;\n }\n\n // Filter to only active attributes\n const result: Attributes = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (value) result[key] = true;\n }\n // Add string attributes\n for (const key of STRING_ATTR_KEYS) {\n if (typeof stringAttrs[key] === \"string\") {\n result[key] = stringAttrs[key] as string;\n }\n }\n return result;\n }\n\n /** Get the selection range (start, end) within a block controller's content */\n private getControllerSelectionRange(ctrl: BlockController): { start: number; end: number } {\n const ce = ctrl.contentEditable;\n if (!ce) return { start: 0, end: 0 };\n\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return { start: 0, end: 0 };\n\n const range = sel.getRangeAt(0);\n if (!ce.contains(range.startContainer) && !ce.contains(range.endContainer)) {\n return { start: 0, end: 0 };\n }\n\n const startRange = document.createRange();\n startRange.selectNodeContents(ce);\n startRange.setEnd(range.startContainer, range.startOffset);\n const start = startRange.toString().length;\n\n const endRange = document.createRange();\n endRange.selectNodeContents(ce);\n endRange.setEnd(range.endContainer, range.endOffset);\n const end = endRange.toString().length;\n\n return { start: Math.min(start, end), end: Math.max(start, end) };\n }\n\n /** Restore a text selection after re-rendering */\n private restoreSelection(ctrl: BlockController, start: number, end: number): void {\n const ce = ctrl.contentEditable;\n if (!ce) return;\n\n const findPos = (offset: number): { node: Node; offset: number } | null => {\n const walker = document.createTreeWalker(ce, NodeFilter.SHOW_TEXT);\n let remaining = offset;\n let node = walker.nextNode();\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n return { node, offset: remaining };\n }\n remaining -= len;\n node = walker.nextNode();\n }\n // Past end — position at end of last text node\n const lastChild = ce.lastChild;\n if (lastChild?.nodeType === Node.TEXT_NODE) {\n return { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n }\n return null;\n };\n\n const startPos = findPos(start);\n const endPos = findPos(end);\n if (!startPos || !endPos) return;\n\n const sel = window.getSelection();\n if (!sel) return;\n\n const range = document.createRange();\n range.setStart(startPos.node, startPos.offset);\n range.setEnd(endPos.node, endPos.offset);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n /**\n * Get attributes common across a selection range within an array of spans.\n * Used for table cells where content is in metadata, not block content.\n */\n private getAttributesFromSpans(spans: ReadonlyArray<{ text: string; attributes: Record<string, string | number | boolean> }>, start: number, end: number): Attributes {\n if (start >= end) return {};\n const attrKeys = new Set<string>();\n if (this.inlineToolbar) {\n for (const btn of this.inlineToolbar.getButtons()) {\n if (btn.attribute) attrKeys.add(btn.attribute);\n }\n }\n const attrs: Record<string, boolean> = {};\n let first = true;\n let spanStart = 0;\n for (const span of spans) {\n const spanEnd = spanStart + span.text.length;\n if (spanEnd > start && spanStart < end) {\n if (first) {\n for (const key of attrKeys) {\n attrs[key] = !!span.attributes[key];\n }\n first = false;\n } else {\n for (const key of attrKeys) {\n if (attrs[key] && !span.attributes[key]) {\n attrs[key] = false;\n }\n }\n }\n }\n spanStart = spanEnd;\n }\n const result: Attributes = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (value) result[key] = true;\n }\n return result;\n }\n\n /** Restore selection in a table cell after re-render */\n private restoreTableCellSelection(ctrl: BlockController, row: number, col: number, start: number, end: number): void {\n const td = ctrl.container.querySelector<HTMLElement>(`[data-row=\"${row}\"][data-col=\"${col}\"]`);\n if (!td) return;\n\n const findPos = (root: HTMLElement, offset: number): { node: Node; offset: number } | null => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n let remaining = offset;\n let node = walker.nextNode();\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) {\n return { node, offset: remaining };\n }\n remaining -= len;\n node = walker.nextNode();\n }\n const lastChild = root.lastChild;\n if (lastChild?.nodeType === Node.TEXT_NODE) {\n return { node: lastChild, offset: lastChild.textContent?.length ?? 0 };\n }\n return null;\n };\n\n const startPos = findPos(td, start);\n const endPos = findPos(td, end);\n if (!startPos || !endPos) return;\n\n const sel = window.getSelection();\n if (!sel) return;\n const range = document.createRange();\n range.setStart(startPos.node, startPos.offset);\n range.setEnd(endPos.node, endPos.offset);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n /** Get the block ID of the currently focused block, or null */\n private getFocusedBlockId(): string | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const ctrl = this.findControllerForNode(sel.getRangeAt(0).startContainer);\n return ctrl?.blockId ?? null;\n }\n\n /** Find the BlockController that contains the given DOM node */\n private findControllerForNode(node: Node): BlockController | null {\n let current: Node | null = node;\n while (current && current !== this.root) {\n if (current instanceof HTMLElement && current.classList.contains(\"blx-block\")) {\n const blockId = current.dataset.blockId;\n if (blockId) {\n return this.controllerMap.get(blockId) ?? null;\n }\n }\n current = current.parentNode;\n }\n return null;\n }\n\n // ── Block action menu helpers ─────────────────────────────────\n\n private getActionTargetBlockIds(): string[] {\n if (this.editorMode !== \"insert\" && this.blockSelectAnchor && this.blockSelectFocus) {\n const anchorIdx = this.getBlockIndex(this.blockSelectAnchor);\n const focusIdx = this.getBlockIndex(this.blockSelectFocus);\n const first = Math.min(anchorIdx, focusIdx);\n const last = Math.max(anchorIdx, focusIdx);\n return this.controllers.slice(first, last + 1).map((c) => c.getBlock().id);\n }\n const hovered = this.blockActionMenu?.hoveredBlockId;\n return hovered ? [hovered] : [];\n }\n\n /** Map a conversion target (type + metadata) to a lucide icon HTML string */\n private static convertTargetIcon(type: string, metadata?: Record<string, unknown>): string | undefined {\n switch (type) {\n case \"paragraph\": return iconHtml(Pilcrow, 14);\n case \"heading\": {\n const level = metadata?.level;\n if (level === 1) return iconHtml(Heading1, 14);\n if (level === 2) return iconHtml(Heading2, 14);\n if (level === 3) return iconHtml(Heading3, 14);\n if (level === 4) return iconHtml(Heading4, 14);\n return iconHtml(Heading1, 14);\n }\n case \"list\":\n return metadata?.ordered ? iconHtml(ListOrdered, 14) : iconHtml(ListIcon, 14);\n case \"checklist\": return iconHtml(ListChecks, 14);\n case \"blockquote\": return iconHtml(TextQuote, 14);\n case \"code\": return iconHtml(CodeIcon, 14);\n default: return undefined;\n }\n }\n\n /** Returns true if a key descriptor is a non-vim binding (modifier combos or named keys). */\n private static isNonVimKey(descriptor: string): boolean {\n if (/^(ctrl|meta|shift|alt)\\+/.test(descriptor)) return true;\n const named = new Set([\n \"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\",\n \"Delete\", \"Backspace\", \"Enter\", \"Escape\", \"Tab\",\n \"Home\", \"End\", \"PageUp\", \"PageDown\",\n \"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\",\n \"F7\", \"F8\", \"F9\", \"F10\", \"F11\", \"F12\",\n ]);\n return named.has(descriptor);\n }\n\n /** Format a key descriptor as a human-readable OS-aware hint string. */\n private static formatKeyHint(descriptor: string): string {\n const isMac = /Mac|iPhone|iPad|iPod/i.test(navigator.platform);\n const parts = descriptor.split(\"+\");\n const key = parts[parts.length - 1];\n const modifiers = parts.slice(0, -1);\n\n if (isMac) {\n const modMap: Record<string, string> = { ctrl: \"⌃\", meta: \"⌘\", shift: \"⇧\", alt: \"⌥\" };\n const keyMap: Record<string, string> = {\n Delete: \"⌦\", Backspace: \"⌫\", Enter: \"↩\", Tab: \"⇥\", Escape: \"⎋\",\n ArrowUp: \"↑\", ArrowDown: \"↓\", ArrowLeft: \"←\", ArrowRight: \"→\",\n };\n return modifiers.map((m) => modMap[m] ?? m).join(\"\") + (keyMap[key] ?? key);\n } else {\n const modMap: Record<string, string> = { ctrl: \"Ctrl\", shift: \"Shift\", alt: \"Alt\", meta: \"Win\" };\n const keyMap: Record<string, string> = { Delete: \"Del\", Escape: \"Esc\" };\n const modStr = modifiers.length > 0\n ? modifiers.map((m) => modMap[m] ?? m).join(\"+\") + \"+\"\n : \"\";\n return modStr + (keyMap[key] ?? key);\n }\n }\n\n /** Return the display hint for the first non-vim keybinding for a command, or undefined. */\n private getKeybindingHint(commandName: string): string | undefined {\n const isMac = /Mac|iPhone|iPad|iPod/i.test(navigator.platform);\n\n const candidates: string[] = [];\n for (const [key, cmd] of Object.entries(this.keybindings.normal)) {\n if (cmd === commandName && Editor.isNonVimKey(key)) {\n candidates.push(key);\n }\n }\n\n if (candidates.length === 0) return undefined;\n\n let preferred: string | undefined;\n if (isMac) {\n preferred =\n candidates.find((k) => k.startsWith(\"meta+\")) ??\n candidates.find((k) => !k.startsWith(\"ctrl+\")) ??\n candidates[0];\n } else {\n const nonMeta = candidates.filter((k) => !k.startsWith(\"meta+\"));\n preferred = nonMeta[0] ?? candidates[0];\n }\n\n return preferred ? Editor.formatKeyHint(preferred) : undefined;\n }\n\n private buildActionMenuItems(): BlockActionMenuEntry[] {\n const blockIds = this.getActionTargetBlockIds();\n if (blockIds.length === 0) return [];\n\n const blocks = blockIds.map((id) => this.getBlock(id)).filter(Boolean) as import(\"./types\").Block[];\n\n // If all target blocks are both immovable AND inconvertible, hide entire menu\n if (blocks.every((b) => {\n const p = this.getPlugin(b.type);\n return p.immovable && p.inconvertible;\n })) return [];\n\n const items: BlockActionMenuEntry[] = [];\n\n // ── Convert section ──\n\n const makeTargetKey = (type: string, metadata?: Record<string, unknown>) =>\n metadata ? `${type}:${JSON.stringify(metadata)}` : type;\n\n /** Check if a block already matches a conversion target */\n const blockMatchesTarget = (block: import(\"./types\").Block, targetType: string, targetMeta?: Record<string, unknown>) => {\n if (block.type !== targetType) return false;\n if (!targetMeta) return true;\n // Check that all keys in targetMeta match the block's metadata\n return Object.entries(targetMeta).every(([k, v]) => block.metadata[k] === v);\n };\n\n // Get conversion targets for each block, intersect to find common targets\n const targetSets = blocks.map((block) =>\n this.schema.getConversionTargets(block.type),\n );\n\n // Union of all target types (show all possible), mark disabled if not in intersection\n const allTargetKeys = new Map<string, { type: string; label: string; metadata?: Record<string, unknown> }>();\n for (const targets of targetSets) {\n for (const t of targets) {\n const key = makeTargetKey(t.type, t.metadata as Record<string, unknown> | undefined);\n if (!allTargetKeys.has(key)) {\n allTargetKeys.set(key, t);\n }\n }\n }\n\n // Check which targets are available for ALL blocks\n for (const [key, target] of allTargetKeys) {\n // Skip if ALL blocks already match this target\n const allAlready = blocks.every((b) =>\n blockMatchesTarget(b, target.type, target.metadata as Record<string, unknown> | undefined),\n );\n if (allAlready) continue;\n\n const availableForAll = targetSets.every((targets) =>\n targets.some((t) => {\n const tKey = makeTargetKey(t.type, t.metadata as Record<string, unknown> | undefined);\n return tKey === key;\n }),\n );\n\n items.push({\n key: `convert:${key}`,\n label: target.label,\n icon: Editor.convertTargetIcon(target.type, target.metadata as Record<string, unknown> | undefined),\n section: \"convert\",\n disabled: !availableForAll,\n onAction: (ids) => {\n // Code block special case: merge all selected blocks into one\n // code block with their content exported as markdown.\n if (target.type === \"code\" && ids.length > 1) {\n const jsonBlocks = ids\n .map((id) => this.getBlock(id))\n .filter(Boolean)\n .map((b) => blockToJSON(b!));\n const md = blocksToMarkdown(jsonBlocks);\n const firstId = ids[0];\n // Remove all blocks except the first\n for (let i = ids.length - 1; i >= 1; i--) {\n this.removeBlock(ids[i]);\n }\n this.changeBlockType(firstId, \"code\", { language: \"markdown\" });\n const ctrl = this.controllerMap.get(firstId);\n if (ctrl) {\n const newContent = AttributedString.fromPlain(md.trimEnd());\n ctrl.updateBlock({ content: newContent });\n ctrl.rerender();\n\n // Emit contentChanged so AutomergeSync propagates the new code content\n this.bus.emit(\"block:contentChanged\", {\n blockId: firstId,\n content: newContent,\n metadata: { language: \"markdown\" },\n });\n }\n this.focusBlock(firstId, 0);\n return;\n }\n\n for (const id of ids) {\n this.changeBlockType(id, target.type, target.metadata as Record<string, unknown> | undefined);\n }\n // Focus the first block after conversion\n if (ids.length > 0) {\n this.focusBlock(ids[0], 0);\n }\n },\n });\n }\n\n // ── Action section ──\n items.push({\n key: \"refine-ai\",\n label: \"Refine with AI\",\n icon: iconHtml(Sparkles, 14),\n section: \"action\",\n onAction: (ids) => {\n this.bus.emit(\"block:refineWithAI\", { blockIds: ids });\n },\n });\n\n items.push({\n key: \"copy-link\",\n label: \"Copy Link To\",\n icon: iconHtml(CopyIcon, 14),\n section: \"action\",\n disabled: blockIds.length > 1,\n onAction: (ids) => {\n if (ids.length === 1) {\n const url = `${window.location.origin}${window.location.pathname}#block-${ids[0]}`;\n navigator.clipboard?.writeText(url).then(() => {\n Toast.show(\"Link copied!\", { type: \"success\", duration: 2500 });\n }).catch(() => {\n Toast.show(\"Failed to copy link\", { type: \"error\" });\n });\n }\n },\n });\n\n // ── Heading task status ──\n const headingBlocks = blocks.filter((b) => b.type === \"heading\");\n if (headingBlocks.length > 0 && headingBlocks.length === blocks.length) {\n const currentStatus = headingBlocks.length === 1\n ? (headingBlocks[0].metadata.taskStatus as string | undefined)\n : undefined;\n const hasAnyStatus = headingBlocks.some((b) => b.metadata.taskStatus);\n\n if (!hasAnyStatus) {\n items.push({\n key: \"task-make\",\n label: \"Make task\",\n icon: iconHtml(CircleCheckBig, 14),\n section: \"task\",\n onAction: (ids) => {\n for (const id of ids) {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) continue;\n const tx = new Transaction(id).setMetadata(\"taskStatus\", \"todo\");\n ctrl.applyTransaction(tx);\n }\n },\n });\n } else {\n const statuses: Array<{ key: string; label: string; value: string }> = [\n { key: \"task-todo\", label: \"Todo\", value: \"todo\" },\n { key: \"task-in-progress\", label: \"In Progress\", value: \"in-progress\" },\n { key: \"task-done\", label: \"Done\", value: \"done\" },\n ];\n\n for (const s of statuses) {\n if (s.value === currentStatus) continue;\n items.push({\n key: s.key,\n label: s.label,\n icon: iconHtml(CircleCheckBig, 14),\n section: \"task\",\n onAction: (ids) => {\n for (const id of ids) {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) continue;\n const tx = new Transaction(id).setMetadata(\"taskStatus\", s.value);\n ctrl.applyTransaction(tx);\n }\n },\n });\n }\n\n items.push({\n key: \"task-remove\",\n label: \"Remove task status\",\n icon: iconHtml(CircleCheckBig, 14),\n section: \"task\",\n onAction: (ids) => {\n for (const id of ids) {\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) continue;\n const tx = new Transaction(id).setMetadata(\"taskStatus\", undefined);\n ctrl.applyTransaction(tx);\n }\n },\n });\n }\n }\n\n // ── Agenda items (available on all blocks except code) ──\n const agendaBlocks = blocks.filter((b) => b.type !== \"code\");\n if (agendaBlocks.length > 0 && agendaBlocks.length === blocks.length) {\n const hasAgendaDate = agendaBlocks.some((b) =>\n b.metadata.dueDate || b.metadata.scheduledDate || b.metadata.eventDate || b.metadata.agendaDate,\n );\n if (hasAgendaDate) {\n items.push({\n key: \"agenda-edit\",\n label: \"Change agenda item\",\n icon: iconHtml(History, 14),\n section: \"task\",\n onAction: (ids) => {\n const id = ids[0];\n const block = this.getBlock(id);\n if (!block) return;\n // Resolve the active date and role\n const dateInfo = resolveBlockDisplayDate(block);\n if (dateInfo) {\n this.bus.emit(\"block:agendaEdit\", {\n blockId: id,\n role: dateInfo.role,\n date: dateInfo.date,\n });\n }\n },\n });\n items.push({\n key: \"agenda-remove\",\n label: \"Remove agenda item\",\n icon: iconHtml(ClockFading, 14),\n section: \"task\",\n onAction: (ids) => {\n for (const id of ids) {\n const block = this.getBlock(id);\n if (!block) continue;\n // Remove all date roles\n const ctrl = this.controllerMap.get(id);\n if (!ctrl) continue;\n const tx = new Transaction(id)\n .setMetadata(\"dueDate\", undefined)\n .setMetadata(\"scheduledDate\", undefined)\n .setMetadata(\"eventDate\", undefined)\n .setMetadata(\"recurrence\", undefined)\n .setMetadata(\"agendaDate\", undefined);\n ctrl.applyTransaction(tx);\n }\n },\n });\n } else {\n items.push({\n key: \"agenda-set\",\n label: \"Set agenda item\",\n icon: iconHtml(ClockPlus, 14),\n section: \"task\",\n onAction: (ids) => {\n // Open date picker for the first block\n const id = ids[0];\n this.openAgendaPickerForEdit(id, \"\");\n },\n });\n }\n }\n\n // ── Custom (plugin) items ──\n for (const custom of this.customActionItems) {\n items.push({\n ...custom,\n section: custom.section ?? \"action\",\n disabled: custom.disabled ?? (custom.isDisabled ? custom.isDisabled(blockIds) : false),\n } as BlockActionMenuEntry);\n }\n\n // ── Danger section (separated) ──\n const hasImmovable = blocks.some((b) => this.getPlugin(b.type).immovable);\n if (!hasImmovable) {\n items.push({\n key: \"delete\",\n label: \"Delete\",\n icon: iconHtml(Trash2, 14),\n section: \"danger\",\n danger: true,\n commandName: \"deleteBlock\",\n hint: this.getKeybindingHint(\"deleteBlock\"),\n onAction: (ids) => {\n if (this.editorMode !== \"insert\") {\n this.deleteBlockSelection();\n } else {\n for (const id of ids) {\n this.removeBlock(id);\n }\n // Ensure at least one block exists\n if (this.controllers.length === 0) {\n const newBlock = this.addBlock(\"paragraph\");\n this.focusBlock(newBlock.id, 0);\n }\n }\n },\n });\n }\n\n return items;\n }\n\n // ── Right-click context menu ──────────────────────────────────\n\n /**\n * Resolve block IDs for right-click context menu.\n * If blocks are selected and the click is on a selected block, use the selection.\n * Otherwise, use the single block under the click.\n */\n private resolveContextMenuBlockIds(e: MouseEvent): string[] {\n const target = e.target as HTMLElement;\n const blockEl = target.closest?.(\".blx-block\") as HTMLElement | null;\n if (!blockEl || !this.root.contains(blockEl)) return [];\n\n const clickedBlockId = blockEl.dataset.blockId;\n if (!clickedBlockId) return [];\n\n // If we have a block selection and the clicked block is within it, use the selection\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds && selectedIds.includes(clickedBlockId)) {\n return selectedIds;\n }\n\n return [clickedBlockId];\n }\n\n /** Build context menu items for given block IDs */\n private buildContextMenuItems(blockIds: string[]): BlockContextMenuEntry[] {\n const items: BlockContextMenuEntry[] = [];\n\n // ── Clipboard section ──\n items.push({\n key: \"copy\",\n label: \"Copy\",\n icon: iconHtml(CopyIcon, 14),\n section: \"clipboard\",\n onAction: (ids) => {\n const blocks = ids.map((id) => this.getBlock(id)).filter(Boolean) as Block[];\n if (blocks.length > 0) {\n copyBlocksToClipboard(blocks);\n }\n },\n });\n\n items.push({\n key: \"cut\",\n label: \"Cut\",\n icon: iconHtml(Scissors, 14),\n section: \"clipboard\",\n onAction: (ids) => {\n const blocks = ids.map((id) => this.getBlock(id)).filter(Boolean) as Block[];\n if (blocks.length > 0) {\n copyBlocksToClipboard(blocks);\n // Delete the blocks\n if (this.editorMode !== \"insert\" && this.getSelectedBlockIds()?.length) {\n this.deleteBlockSelection();\n } else {\n for (const id of ids) {\n this.removeBlock(id);\n }\n if (this.controllers.length === 0) {\n const newBlock = this.addBlock(\"paragraph\");\n this.focusBlock(newBlock.id, 0);\n }\n }\n }\n },\n });\n\n items.push({\n key: \"paste\",\n label: \"Paste\",\n icon: iconHtml(ClipboardPasteIcon, 14),\n section: \"clipboard\",\n onAction: (ids) => {\n readBlocksFromClipboard().then((clipboardBlocks) => {\n if (clipboardBlocks && clipboardBlocks.length > 0) {\n // Assign fresh IDs to avoid duplicates\n for (const b of clipboardBlocks) {\n b.id = generateId();\n }\n // If in block selection mode, delete first, then paste\n if (this.editorMode !== \"insert\" && this.getSelectedBlockIds()?.length) {\n const nextId = this.deleteBlockSelection();\n this.exitToInsertMode(nextId);\n this.pasteBlocks(clipboardBlocks);\n } else {\n // Insert after the last target block\n const lastId = ids[ids.length - 1];\n const lastIdx = this.getBlockIndex(lastId);\n if (lastIdx >= 0) {\n this.focusBlock(lastId, this.getBlock(lastId)?.content.length ?? 0);\n }\n this.pasteBlocks(clipboardBlocks);\n }\n }\n });\n },\n });\n\n // ── Danger section ──\n items.push({\n key: \"delete\",\n label: \"Delete\",\n icon: iconHtml(Trash2, 14),\n section: \"danger\",\n danger: true,\n onAction: (ids) => {\n if (this.editorMode !== \"insert\" && this.getSelectedBlockIds()?.length) {\n this.deleteBlockSelection();\n } else {\n for (const id of ids) {\n this.removeBlock(id);\n }\n if (this.controllers.length === 0) {\n const newBlock = this.addBlock(\"paragraph\");\n this.focusBlock(newBlock.id, 0);\n }\n }\n },\n });\n\n // ── Custom items ──\n for (const custom of this.customContextItems) {\n items.push({ ...custom });\n }\n\n return items;\n }\n\n /** Add a custom item to the right-click context menu */\n addContextMenuItem(entry: BlockContextMenuEntry): void {\n this.customContextItems.push(entry);\n }\n\n /** Remove a custom item from the right-click context menu */\n removeContextMenuItem(key: string): void {\n const idx = this.customContextItems.findIndex((e) => e.key === key);\n if (idx >= 0) this.customContextItems.splice(idx, 1);\n }\n\n // ── Clipboard keyboard shortcuts ────────────────────────────────\n\n private clipboardKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n\n private setupClipboardShortcuts(): void {\n this.clipboardKeyHandler = (e: KeyboardEvent) => {\n // Don't intercept when focus is in a native input\n const tag = document.activeElement?.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return;\n\n const mod = e.metaKey || e.ctrlKey;\n if (!mod) return;\n\n const key = e.key.toLowerCase();\n\n // Cmd/Ctrl+C: copy blocks when in block selection mode\n if (key === \"c\" && !e.shiftKey) {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds && selectedIds.length > 0) {\n e.preventDefault();\n const blocks = selectedIds.map((id) => this.getBlock(id)).filter(Boolean) as Block[];\n copyBlocksToClipboard(blocks);\n return;\n }\n }\n\n // Cmd/Ctrl+X: cut blocks when in block selection mode\n if (key === \"x\" && !e.shiftKey) {\n const selectedIds = this.getSelectedBlockIds();\n if (selectedIds && selectedIds.length > 0) {\n e.preventDefault();\n const blocks = selectedIds.map((id) => this.getBlock(id)).filter(Boolean) as Block[];\n copyBlocksToClipboard(blocks);\n this.deleteBlockSelection();\n return;\n }\n }\n\n // Cmd/Ctrl+V: paste blocks from clipboard (when in block selection mode)\n if (key === \"v\" && !e.shiftKey) {\n if (this.editorMode !== \"insert\") {\n e.preventDefault();\n this.pasteBlocksFromClipboard();\n return;\n }\n }\n };\n\n document.addEventListener(\"keydown\", this.clipboardKeyHandler);\n }\n\n /**\n * Read blocks from clipboard and paste AFTER the focused block as discrete\n * new blocks (no content merging). Used by `p` in normal/visual modes.\n */\n private async pasteBlocksFromClipboard(): Promise<void> {\n const clipboardBlocks = await readBlocksFromClipboard();\n if (!clipboardBlocks || clipboardBlocks.length === 0) return;\n\n // Assign fresh IDs to avoid duplicates\n for (const b of clipboardBlocks) {\n b.id = generateId();\n }\n\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n const focusIdx = this.getBlockIndex(focusId);\n if (focusIdx < 0) return;\n\n const cursor: CursorState = { blockId: focusId, offset: 0 };\n this.undoManager.beginGroup(cursor);\n this.crdtLog?.beginGroup(cursor);\n\n const created: Block[] = [];\n try {\n let insertIndex = focusIdx + 1;\n for (const json of clipboardBlocks) {\n created.push(this.addBlock(blockFromJSON(json), insertIndex++));\n }\n } finally {\n const endCursor = created.length > 0\n ? { blockId: created[created.length - 1].id, offset: 0 }\n : cursor;\n this.undoManager.endGroup(endCursor);\n this.crdtLog?.endGroup(endCursor);\n }\n\n // Move focus to last pasted block\n if (created.length > 0) {\n const lastId = created[created.length - 1].id;\n this.blockSelectAnchor = lastId;\n this.blockSelectFocus = lastId;\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n this.recomputeListIndices();\n this.applyBlockSelectionCSS();\n }\n\n /**\n * Read blocks from clipboard and paste BEFORE the focused block as discrete\n * new blocks. Used by `P` in normal/visual modes.\n */\n private async pasteBlocksBeforeFromClipboard(): Promise<void> {\n const clipboardBlocks = await readBlocksFromClipboard();\n if (!clipboardBlocks || clipboardBlocks.length === 0) return;\n\n // Assign fresh IDs to avoid duplicates\n for (const b of clipboardBlocks) {\n b.id = generateId();\n }\n\n const focusId = this.blockSelectFocus;\n if (!focusId) return;\n const focusIdx = this.getBlockIndex(focusId);\n if (focusIdx < 0) return;\n\n const cursor: CursorState = { blockId: focusId, offset: 0 };\n this.undoManager.beginGroup(cursor);\n this.crdtLog?.beginGroup(cursor);\n\n const created: Block[] = [];\n try {\n let insertIndex = focusIdx;\n for (const json of clipboardBlocks) {\n created.push(this.addBlock(blockFromJSON(json), insertIndex++));\n }\n } finally {\n const endCursor = created.length > 0\n ? { blockId: created[created.length - 1].id, offset: 0 }\n : cursor;\n this.undoManager.endGroup(endCursor);\n this.crdtLog?.endGroup(endCursor);\n }\n\n // Move focus to last pasted block\n if (created.length > 0) {\n const lastId = created[created.length - 1].id;\n this.blockSelectAnchor = lastId;\n this.blockSelectFocus = lastId;\n this.bus.emit(\"selection:blockSelect\", { state: this.buildMultiBlockSelection() });\n }\n\n this.recomputeListIndices();\n this.applyBlockSelectionCSS();\n }\n\n // ── Ordered list index recomputation ─────────────────────────\n\n /**\n * Walk all blocks and set `<ol start=\"N\">` on consecutive ordered list\n * blocks at the same indent level. Non-list blocks or a change in\n * indent level reset the counter.\n */\n private recomputeListIndices(): void {\n // Track running counters per indent level.\n // When we encounter a non-ordered-list block or the indent level\n // changes, we reset counters at that level and deeper.\n const counters = new Map<number, number>();\n\n for (const ctrl of this.controllers) {\n const block = ctrl.getBlock();\n const indentLevel = typeof block.metadata.indentLevel === \"number\"\n ? block.metadata.indentLevel\n : 0;\n const isOrderedList = block.type === \"list\" && block.metadata.ordered === true;\n\n if (!isOrderedList) {\n // Non-ordered-list block resets counter at its indent level and deeper\n counters.delete(indentLevel);\n // Also reset deeper levels\n for (const key of counters.keys()) {\n if (key >= indentLevel) counters.delete(key);\n }\n continue;\n }\n\n // Ordered list: get or initialize counter at this indent level\n const currentCount = counters.get(indentLevel) ?? 0;\n const startValue = currentCount + 1;\n counters.set(indentLevel, startValue);\n\n // Set the `start` attribute on the <ol> element\n const ol = ctrl.container.querySelector(\"ol\");\n if (ol) {\n ol.setAttribute(\"start\", String(startValue));\n }\n }\n }\n\n /**\n * Focus a table block's cell directly, bypassing block-level focus.\n * @param direction \"down\" focuses first row, \"up\" focuses last row.\n */\n private focusTableCell(\n blockId: string,\n direction: \"up\" | \"down\",\n ): void {\n this.blurNonTextBlock();\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n this.viewport.ensureMounted(blockId);\n const block = ctrl.getBlock();\n const bodyRows = block.metadata.rows as unknown[];\n const totalRows = 1 + (Array.isArray(bodyRows) ? bodyRows.length : 0);\n const row = direction === \"down\" ? 0 : totalRows - 1;\n const cell = ctrl.container.querySelector<HTMLElement>(\n `[data-row=\"${row}\"][data-col=\"0\"]`,\n );\n if (cell) {\n cell.focus();\n this._lastFocusedBlockId = blockId;\n } else {\n // Fallback to block-level focus\n this.focusNonTextBlock(blockId);\n }\n }\n\n // ── Non-text block focus (Image, YouTube, HR) ──────────────────\n\n private focusNonTextBlock(blockId: string): void {\n // Clear any existing non-text focus\n this.blurNonTextBlock();\n\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n\n // Ensure block content is rendered before focusing\n this.viewport.ensureMounted(blockId);\n this.focusedNonTextBlockId = blockId;\n ctrl.container.classList.add(\"blx-block-focused\");\n ctrl.container.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n\n // Blur any focused contenteditable to ensure keydown goes to document\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n\n // Hide custom caret — non-text blocks use a focus ring instead\n this.customCaret?.hide();\n\n // Install capture-phase keydown handler\n this.nonTextKeyHandler = (e: KeyboardEvent) => {\n if (!this.focusedNonTextBlockId) return;\n const id = this.focusedNonTextBlockId;\n const idx = this.getBlockIndex(id);\n\n // If focus is inside an input/textarea in the block, let keys pass through\n // (except Escape, which returns to block-level focus)\n const active = document.activeElement;\n const blockCtrl = this.controllerMap.get(id);\n if (\n active &&\n blockCtrl?.container.contains(active) &&\n (active.tagName === \"INPUT\" || active.tagName === \"TEXTAREA\")\n ) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n (active as HTMLElement).blur();\n }\n return;\n }\n\n // Alt+Arrow: block reordering (same as text blocks)\n if (e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n e.preventDefault();\n this.bus.emit(e.key === \"ArrowUp\" ? \"block:moveUp\" : \"block:moveDown\", { blockId: id });\n return;\n }\n\n if (e.key === \"ArrowDown\" || e.key === \"ArrowRight\") {\n e.preventDefault();\n this.blurNonTextBlock();\n // Move to next block\n for (let i = idx + 1; i < this.controllers.length; i++) {\n const c = this.controllers[i];\n const p = this.getPlugin(c.getBlock().type);\n if (p.hasTextContent) {\n this.focusBlock(c.getBlock().id, 0);\n return;\n } else {\n this.focusNonTextBlock(c.getBlock().id);\n return;\n }\n }\n // No next block found — create a new paragraph at the end\n const newBlock = this.addBlock(\"paragraph\", idx + 1);\n this.focusBlock(newBlock.id, 0);\n } else if (e.key === \"ArrowUp\" || e.key === \"ArrowLeft\") {\n e.preventDefault();\n this.blurNonTextBlock();\n // Move to previous block\n for (let i = idx - 1; i >= 0; i--) {\n const c = this.controllers[i];\n const p = this.getPlugin(c.getBlock().type);\n if (p.hasTextContent) {\n const block = c.getBlock();\n this.focusBlock(block.id, block.content.length);\n return;\n } else {\n this.focusNonTextBlock(c.getBlock().id);\n return;\n }\n }\n } else if (e.key === \"Backspace\" || e.key === \"Delete\") {\n e.preventDefault();\n this.blurNonTextBlock();\n // Focus neighbor before removing\n const prevTextIdx = this.findTextBlockIndex(idx, -1);\n const nextTextIdx = this.findTextBlockIndex(idx, 1);\n this.removeBlock(id);\n if (nextTextIdx !== -1 && nextTextIdx - 1 < this.controllers.length) {\n // After removal, the block that was at nextTextIdx is now at nextTextIdx - 1\n const c = this.controllers[nextTextIdx - 1];\n if (c) this.focusBlock(c.getBlock().id, 0);\n } else if (prevTextIdx !== -1) {\n const c = this.controllers[prevTextIdx];\n if (c) {\n const b = c.getBlock();\n this.focusBlock(b.id, b.content.length);\n }\n } else if (this.controllers.length === 0) {\n this.addBlock(\"paragraph\");\n this.focusBlock(this.controllers[0].getBlock().id, 0);\n }\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n // Table blocks: Enter focuses the first cell for editing\n const blockCtrl2 = this.controllerMap.get(id);\n if (blockCtrl2 && blockCtrl2.getBlock().type === \"table\") {\n this.blurNonTextBlock();\n const firstCell = blockCtrl2.container.querySelector<HTMLElement>(\n '[data-row=\"0\"][data-col=\"0\"]',\n );\n if (firstCell) {\n firstCell.focus();\n }\n return;\n }\n // Excalidraw blocks: Enter opens the editor modal\n if (blockCtrl2 && blockCtrl2.getBlock().type === \"excalidraw\") {\n this.blurNonTextBlock();\n blockCtrl2.container.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n return;\n }\n this.blurNonTextBlock();\n const newBlock = this.addBlock(\"paragraph\", idx + 1);\n this.focusBlock(newBlock.id, 0);\n } else if (e.key === \" \") {\n e.preventDefault();\n // Excalidraw blocks: Space opens the editor modal\n const blockCtrl3 = this.controllerMap.get(id);\n if (blockCtrl3 && blockCtrl3.getBlock().type === \"excalidraw\") {\n this.blurNonTextBlock();\n blockCtrl3.container.dispatchEvent(\n new CustomEvent(\"blx-excalidraw-open\", { bubbles: true }),\n );\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n this.blurNonTextBlock();\n }\n };\n document.addEventListener(\"keydown\", this.nonTextKeyHandler, true);\n }\n\n private blurNonTextBlock(): void {\n if (this.focusedNonTextBlockId) {\n const ctrl = this.controllerMap.get(this.focusedNonTextBlockId);\n if (ctrl) {\n ctrl.container.classList.remove(\"blx-block-focused\");\n }\n this.focusedNonTextBlockId = null;\n }\n if (this.nonTextKeyHandler) {\n document.removeEventListener(\"keydown\", this.nonTextKeyHandler, true);\n this.nonTextKeyHandler = null;\n }\n }\n\n /** Find the nearest text block index in the given direction (-1 or 1). */\n private findTextBlockIndex(fromIndex: number, direction: -1 | 1): number {\n const start = fromIndex + direction;\n const end = direction === 1 ? this.controllers.length : -1;\n for (let i = start; i !== end; i += direction) {\n if (this.getPlugin(this.controllers[i].getBlock().type).hasTextContent) {\n return i;\n }\n }\n return -1;\n }\n\n // ── Media block handlers (YouTube, Image) ──────────────────────\n\n private removeImageDropZone(): void {\n if (this.imageDropZone?.parentNode) {\n this.imageDropZone.remove();\n }\n }\n\n private showDropRejectOverlay(): void {\n if (!this.dropRejectOverlay) {\n this.dropRejectOverlay = document.createElement(\"div\");\n this.dropRejectOverlay.classList.add(\"blx-drop-reject-overlay\");\n this.dropRejectOverlay.innerHTML =\n `<span class=\"blx-drop-reject-nudge\">${iconHtml(ChevronsLeft, 28)}</span>` +\n `<span class=\"blx-drop-reject-msg\">Drop on sidebar to import</span>`;\n }\n if (!this.dropRejectOverlay.parentNode) {\n this.root.appendChild(this.dropRejectOverlay);\n }\n }\n\n private removeDropRejectOverlay(): void {\n if (this.dropRejectOverlay?.parentNode) {\n this.dropRejectOverlay.remove();\n }\n }\n\n private setupMediaBlockHandlers(): void {\n // YouTube: listen for blx-youtube-commit custom events bubbling up\n this.root.addEventListener(\"blx-youtube-commit\", ((e: CustomEvent) => {\n const detail = e.detail as { videoId: string; startTime?: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId)\n .setMetadata(\"videoId\", detail.videoId);\n if (detail.startTime !== undefined) {\n tx.setMetadata(\"startTime\", detail.startTime);\n }\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // Image: listen for blx-image-commit custom events\n this.root.addEventListener(\"blx-image-commit\", ((e: CustomEvent) => {\n const detail = e.detail as { src: string };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId).setMetadata(\"src\", detail.src);\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // Image: persist intrinsic dimensions on first load so subsequent\n // renders can reserve the correct aspect-ratio space, preventing CLS.\n this.root.addEventListener(\"blx-image-dimensions\", ((e: CustomEvent) => {\n const detail = e.detail as { naturalWidth: number; naturalHeight: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId)\n .setMetadata(\"naturalWidth\", detail.naturalWidth)\n .setMetadata(\"naturalHeight\", detail.naturalHeight);\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // Image: resize events\n this.root.addEventListener(\"blx-image-resize\", ((e: CustomEvent) => {\n const detail = e.detail as { width: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId).setMetadata(\"width\", detail.width);\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // Image: caption change events\n this.root.addEventListener(\"blx-image-caption-change\", ((e: CustomEvent) => {\n const detail = e.detail as { caption: string };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId).setMetadata(\"caption\", detail.caption);\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // ── Table events ──────────────────────────────────────────────\n\n // Helper functions for Format A table operations\n // Cells may be AttributedString instances or raw Span[] after Automerge sync\n const toAS = (v: unknown): AttributedString =>\n v instanceof AttributedString ? v\n : Array.isArray(v) ? AttributedString.fromSpans(v as Span[])\n : AttributedString.empty();\n\n function getTableAllRows(meta: Record<string, unknown>): AttributedString[][] {\n const header = meta.header as unknown[];\n const bodyRows = meta.rows as unknown[][];\n return [header.map(toAS), ...bodyRows.map((r) => r.map(toAS))];\n }\n\n function splitTableAllRows(allRows: AttributedString[][]): { header: AttributedString[]; rows: AttributedString[][] } {\n return { header: allRows[0] || [], rows: allRows.slice(1) };\n }\n\n function emptyTableRow(numCols: number): AttributedString[] {\n return Array.from({ length: numCols }, () => AttributedString.empty());\n }\n\n function getTableNumCols(meta: Record<string, unknown>): number {\n return (meta.header as AttributedString[]).length;\n }\n\n // Table: cell content edit\n this.root.addEventListener(\"blx:tableCellEdit\", ((e: CustomEvent) => {\n const detail = e.detail as { row: number; col: number; value: string };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n if (detail.value) {\n allRows[detail.row][detail.col] = AttributedString.fromPlain(detail.value);\n } else {\n allRows[detail.row][detail.col] = AttributedString.empty();\n }\n const { header, rows } = splitTableAllRows(allRows);\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n this.bus.emit(\"table:cellEdit\", { blockId, row: detail.row, col: detail.col, value: detail.value });\n }) as EventListener);\n\n // Table: bulk clear selected cells\n this.root.addEventListener(\"blx:tableBulkClear\", ((e: CustomEvent) => {\n const detail = e.detail as { keys: string[] };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n for (const key of detail.keys) {\n const [rStr, cStr] = key.split(\",\");\n const r = parseInt(rStr, 10);\n const c = parseInt(cStr, 10);\n if (allRows[r]) allRows[r][c] = AttributedString.empty();\n }\n const { header, rows } = splitTableAllRows(allRows);\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n this.bus.emit(\"table:bulkClear\", { blockId, keys: detail.keys });\n }) as EventListener);\n\n // Table: create row below\n this.root.addEventListener(\"blx:tableCreateRowBelow\", ((e: CustomEvent) => {\n const detail = e.detail as { row: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const numCols = getTableNumCols(block.metadata);\n const allRows = getTableAllRows(block.metadata);\n allRows.splice(detail.row + 1, 0, emptyTableRow(numCols));\n const { header, rows } = splitTableAllRows(allRows);\n\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n // applyTransaction skips DOM re-render for non-text blocks when\n // focus is inside the container. Force a rebuild for structural\n // changes so the new row appears.\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:createRowBelow\", { blockId, row: detail.row });\n\n // Focus the first cell of the new row\n const newRow = detail.row + 1;\n const cell = ctrl.container.querySelector<HTMLElement>(\n `[data-row=\"${newRow}\"][data-col=\"0\"]`,\n );\n if (cell) cell.focus();\n }) as EventListener);\n\n // Table: delete row\n this.root.addEventListener(\"blx:tableDeleteRow\", ((e: CustomEvent) => {\n const detail = e.detail as { row: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n if (allRows.length <= 1) return; // Don't delete the last row\n allRows.splice(detail.row, 1);\n const { header, rows } = splitTableAllRows(allRows);\n\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n // Force DOM rebuild (applyTransaction skips for focused non-text blocks)\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:deleteRow\", { blockId, row: detail.row });\n }) as EventListener);\n\n // Table: add column\n this.root.addEventListener(\"blx:tableAddColumn\", ((e: CustomEvent) => {\n const detail = e.detail as { col: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n for (const row of allRows) {\n row.splice(detail.col, 0, AttributedString.empty());\n }\n const { header, rows } = splitTableAllRows(allRows);\n\n // Adjust columnAlignments if present\n const meta = block.metadata;\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n if (Array.isArray(meta.columnAlignments)) {\n const aligns = [...(meta.columnAlignments as string[])];\n aligns.splice(detail.col, 0, \"none\");\n tx.setMetadata(\"columnAlignments\", aligns);\n }\n if (block.metadata.columnWidths) {\n const widths = [...(block.metadata.columnWidths as number[])];\n const splitIdx = detail.col > 0 ? detail.col - 1 : 0;\n const splitWidth = widths[splitIdx] / 2;\n widths[splitIdx] = splitWidth;\n widths.splice(detail.col, 0, splitWidth);\n tx.setMetadata(\"columnWidths\", widths);\n }\n ctrl.applyTransaction(tx);\n\n // Force DOM rebuild\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n\n // Focus the first cell of the new column\n const cell = ctrl.container.querySelector<HTMLElement>(\n `[data-row=\"0\"][data-col=\"${detail.col}\"]`,\n );\n if (cell) cell.focus();\n\n this.bus.emit(\"table:addColumn\", { blockId, col: detail.col });\n }) as EventListener);\n\n // Table: delete column\n this.root.addEventListener(\"blx:tableDeleteColumn\", ((e: CustomEvent) => {\n const detail = e.detail as { col: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const numCols = getTableNumCols(block.metadata);\n if (numCols <= 1) return; // Don't delete the last column\n const allRows = getTableAllRows(block.metadata);\n for (const row of allRows) {\n row.splice(detail.col, 1);\n }\n const { header, rows } = splitTableAllRows(allRows);\n\n const meta = block.metadata;\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n if (Array.isArray(meta.columnAlignments)) {\n const aligns = [...(meta.columnAlignments as string[])];\n aligns.splice(detail.col, 1);\n tx.setMetadata(\"columnAlignments\", aligns);\n }\n if (block.metadata.columnWidths) {\n const widths = [...(block.metadata.columnWidths as number[])];\n widths.splice(detail.col, 1);\n tx.setMetadata(\"columnWidths\", widths);\n }\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:deleteColumn\", { blockId, col: detail.col });\n }) as EventListener);\n\n // Table: move row (reorder)\n this.root.addEventListener(\"blx:tableMoveRow\", ((e: CustomEvent) => {\n const detail = e.detail as { from: number; to: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n if (detail.from < 0 || detail.from >= allRows.length || detail.to < 0 || detail.to >= allRows.length) return;\n const [moved] = allRows.splice(detail.from, 1);\n allRows.splice(detail.to, 0, moved);\n const { header, rows } = splitTableAllRows(allRows);\n\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:moveRow\", { blockId, from: detail.from, to: detail.to });\n }) as EventListener);\n\n // Table: move column (reorder)\n this.root.addEventListener(\"blx:tableMoveColumn\", ((e: CustomEvent) => {\n const detail = e.detail as { from: number; to: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const numCols = getTableNumCols(block.metadata);\n if (detail.from < 0 || detail.from >= numCols || detail.to < 0 || detail.to >= numCols) return;\n const allRows = getTableAllRows(block.metadata);\n for (const row of allRows) {\n const [m] = row.splice(detail.from, 1);\n row.splice(detail.to, 0, m);\n }\n const { header, rows } = splitTableAllRows(allRows);\n\n const meta = block.metadata;\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n if (Array.isArray(meta.columnAlignments)) {\n const aligns = [...(meta.columnAlignments as string[])];\n const [ma] = aligns.splice(detail.from, 1);\n aligns.splice(detail.to, 0, ma);\n tx.setMetadata(\"columnAlignments\", aligns);\n }\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:moveColumn\", { blockId, from: detail.from, to: detail.to });\n }) as EventListener);\n\n // Table: navigate out of table\n this.root.addEventListener(\"blx:tableNavigateOut\", ((e: CustomEvent) => {\n const detail = e.detail as { direction: \"up\" | \"down\" };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const idx = this.getBlockIndex(blockId);\n\n if (detail.direction === \"up\") {\n // Focus previous block\n for (let i = idx - 1; i >= 0; i--) {\n const c = this.controllers[i];\n const p = this.getPlugin(c.getBlock().type);\n if (p.hasTextContent) {\n const b = c.getBlock();\n this.focusBlock(b.id, b.content.length);\n return;\n } else if (c.getBlock().type === \"table\") {\n this.focusTableCell(c.getBlock().id, \"up\");\n return;\n } else {\n this.focusNonTextBlock(c.getBlock().id);\n return;\n }\n }\n } else {\n // Focus next block\n for (let i = idx + 1; i < this.controllers.length; i++) {\n const c = this.controllers[i];\n const p = this.getPlugin(c.getBlock().type);\n if (p.hasTextContent) {\n this.focusBlock(c.getBlock().id, 0);\n return;\n } else if (c.getBlock().type === \"table\") {\n this.focusTableCell(c.getBlock().id, \"down\");\n return;\n }\n }\n }\n this.bus.emit(\"table:navigateOut\", { blockId, direction: detail.direction });\n }) as EventListener);\n\n // Table: exit (Enter on empty row → new block below)\n // The event may carry `deleteRow` so the empty row is removed atomically\n // before creating the paragraph (avoids dispatching two events where the\n // first force-renders and detaches the wrapper before the second bubbles).\n this.root.addEventListener(\"blx:tableExit\", ((e: CustomEvent) => {\n const detail = (e.detail ?? {}) as { deleteRow?: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n\n // Delete the empty row that triggered the exit (if specified)\n if (ctrl && detail.deleteRow !== undefined) {\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n if (allRows.length > 1) {\n allRows.splice(detail.deleteRow, 1);\n const { header, rows } = splitTableAllRows(allRows);\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n // Force DOM rebuild\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:deleteRow\", { blockId, row: detail.deleteRow });\n }\n }\n\n const idx = this.getBlockIndex(blockId);\n const newBlock = this.addBlock(\"paragraph\", idx + 1);\n this.focusBlock(newBlock.id, 0);\n this.bus.emit(\"table:exit\", { blockId });\n }) as EventListener);\n\n // Table: escape (Escape key → enter block-level focus)\n this.root.addEventListener(\"blx:tableEscape\", ((e: CustomEvent) => {\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n this.focusNonTextBlock(blockId);\n this.bus.emit(\"table:escape\", { blockId });\n }) as EventListener);\n\n // Table: insert row above\n this.root.addEventListener(\"blx:tableInsertRowAbove\", ((e: CustomEvent) => {\n const detail = e.detail as { row: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const numCols = getTableNumCols(block.metadata);\n const allRows = getTableAllRows(block.metadata);\n allRows.splice(detail.row, 0, emptyTableRow(numCols));\n const { header, rows } = splitTableAllRows(allRows);\n\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:insertRowAbove\", { blockId, row: detail.row });\n\n const cell = ctrl.container.querySelector<HTMLElement>(\n `[data-row=\"${detail.row}\"][data-col=\"0\"]`,\n );\n if (cell) cell.focus();\n }) as EventListener);\n\n // Table: duplicate row(s)\n this.root.addEventListener(\"blx:tableDuplicateRow\", ((e: CustomEvent) => {\n const detail = e.detail as { startRow: number; endRow: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n const copies = allRows.slice(detail.startRow, detail.endRow + 1).map((r) => r.map((c) => c));\n allRows.splice(detail.endRow + 1, 0, ...copies);\n const { header, rows } = splitTableAllRows(allRows);\n\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:duplicateRow\", { blockId, startRow: detail.startRow, endRow: detail.endRow });\n }) as EventListener);\n\n // Table: clear row(s) contents\n this.root.addEventListener(\"blx:tableClearRow\", ((e: CustomEvent) => {\n const detail = e.detail as { startRow: number; endRow: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const numCols = getTableNumCols(block.metadata);\n const allRows = getTableAllRows(block.metadata);\n\n for (let r = detail.startRow; r <= detail.endRow; r++) {\n for (let c = 0; c < numCols; c++) {\n allRows[r][c] = AttributedString.empty();\n }\n }\n\n const { header, rows } = splitTableAllRows(allRows);\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:clearRow\", { blockId, startRow: detail.startRow, endRow: detail.endRow });\n }) as EventListener);\n\n // Table: duplicate column(s)\n this.root.addEventListener(\"blx:tableDuplicateColumn\", ((e: CustomEvent) => {\n const detail = e.detail as { startCol: number; endCol: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n for (const row of allRows) {\n const copies = row.slice(detail.startCol, detail.endCol + 1);\n row.splice(detail.endCol + 1, 0, ...copies);\n }\n const { header, rows } = splitTableAllRows(allRows);\n\n const meta = block.metadata;\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n if (Array.isArray(meta.columnAlignments)) {\n const aligns = [...(meta.columnAlignments as string[])];\n const copies = aligns.slice(detail.startCol, detail.endCol + 1);\n aligns.splice(detail.endCol + 1, 0, ...copies);\n tx.setMetadata(\"columnAlignments\", aligns);\n }\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:duplicateColumn\", { blockId, startCol: detail.startCol, endCol: detail.endCol });\n }) as EventListener);\n\n // Table: clear column(s) contents\n this.root.addEventListener(\"blx:tableClearColumn\", ((e: CustomEvent) => {\n const detail = e.detail as { startCol: number; endCol: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n\n for (const row of allRows) {\n for (let c = detail.startCol; c <= detail.endCol; c++) {\n row[c] = AttributedString.empty();\n }\n }\n\n const { header, rows } = splitTableAllRows(allRows);\n const tx = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(\n ctrl.container,\n updated.content,\n updated.metadata,\n );\n this.bus.emit(\"table:clearColumn\", { blockId, startCol: detail.startCol, endCol: detail.endCol });\n }) as EventListener);\n\n // Table: column widths (from resize handles)\n this.root.addEventListener(\"blx:tableColumnWidths\", ((e: CustomEvent) => {\n const detail = e.detail as { widths: number[] };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const tx = new Transaction(blockId).setMetadata(\"columnWidths\", detail.widths);\n ctrl.applyTransaction(tx);\n }) as EventListener);\n\n // Table: bulk format (bold/italic/underline across multi-cell selection)\n this.root.addEventListener(\"blx:tableBulkFormat\", ((e: CustomEvent) => {\n const detail = e.detail as {\n startRow: number; endRow: number;\n startCol: number; endCol: number;\n attribute: string;\n };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const allRows = getTableAllRows(block.metadata);\n\n // Determine toggle: if ALL selected non-empty cells have the attribute, remove it\n let allHaveAttr = true;\n outer: for (let r = detail.startRow; r <= detail.endRow; r++) {\n for (let c = detail.startCol; c <= detail.endCol; c++) {\n const cell = allRows[r][c];\n if (cell.isEmpty()) continue;\n if (!cell.spans.every((s) => s.attributes?.[detail.attribute])) {\n allHaveAttr = false;\n break outer;\n }\n }\n }\n\n const shouldApply = !allHaveAttr;\n for (let r = detail.startRow; r <= detail.endRow; r++) {\n for (let c = detail.startCol; c <= detail.endCol; c++) {\n const cell = allRows[r][c];\n if (cell.isEmpty()) continue;\n const newSpans = cell.spans.map((s) => ({\n text: s.text,\n attributes: shouldApply\n ? { ...s.attributes, [detail.attribute]: true }\n : Object.fromEntries(\n Object.entries(s.attributes).filter(([k]) => k !== detail.attribute),\n ),\n }));\n allRows[r][c] = AttributedString.fromSpans(newSpans);\n }\n }\n\n const { header, rows } = splitTableAllRows(allRows);\n const tx2 = new Transaction(blockId)\n .setMetadata(\"header\", header)\n .setMetadata(\"rows\", rows);\n ctrl.applyTransaction(tx2);\n\n const updated = ctrl.getBlock();\n this.getPlugin(updated.type).render(ctrl.container, updated.content, updated.metadata);\n this.bus.emit(\"table:bulkFormat\", { blockId, ...detail, applied: shouldApply });\n }) as EventListener);\n\n // Table: selection changed\n this.root.addEventListener(\"blx:tableSelectionChanged\", ((e: CustomEvent) => {\n const detail = e.detail as { startRow: number; endRow: number; startCol: number; endCol: number };\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n this.bus.emit(\"table:selectionChanged\", { blockId, ...detail });\n }) as EventListener);\n\n // ── Excalidraw events ────────────────────────────────────────\n\n // Excalidraw: open modal editor\n this.root.addEventListener(\"blx-excalidraw-open\", ((e: CustomEvent) => {\n const container = (e.target as HTMLElement).closest(\"[data-block-id]\");\n if (!container) return;\n const blockId = container.getAttribute(\"data-block-id\");\n if (!blockId) return;\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) return;\n const block = ctrl.getBlock();\n const sceneData = (block.metadata.sceneData as string) || null;\n\n // Resolve effective theme for Excalidraw\n let exTheme: \"light\" | \"dark\" = \"light\";\n if (this.themeMode === \"dark\") {\n exTheme = \"dark\";\n } else if (this.themeMode === \"system\") {\n exTheme = window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\" : \"light\";\n }\n\n openExcalidrawModal(\n sceneData,\n (newSceneData: string, previewSvg: string) => {\n const tx = new Transaction(blockId)\n .setMetadata(\"sceneData\", newSceneData)\n .setMetadata(\"previewSvg\", previewSvg);\n ctrl.applyTransaction(tx);\n },\n () => {\n this.focusNonTextBlock(blockId);\n },\n { theme: exTheme },\n );\n }) as EventListener);\n\n // BLX blocks: intercept paste with BLX block data (from copy/cut within editor)\n this.root.addEventListener(\"paste\", (e: ClipboardEvent) => {\n // Let code/mermaid blocks handle paste inline (plain text insert)\n const _fbId = this.getFocusedBlockId();\n const _fbType = _fbId ? this.getBlocks().find((b: Block) => b.id === _fbId)?.type : null;\n if (_fbType === \"code\" || _fbType === \"mermaid\") return;\n\n const html = e.clipboardData?.getData(\"text/html\");\n if (!html) return;\n const blocks = extractBlocksFromHtml(html);\n if (!blocks || blocks.length === 0) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n // Assign fresh IDs\n for (const b of blocks) {\n b.id = generateId();\n }\n this.pasteBlocks(blocks);\n });\n\n // Transform pasted text hook: let host app convert plain text (e.g. URLs → blockRefs)\n this.root.addEventListener(\"paste\", (e: ClipboardEvent) => {\n if (e.defaultPrevented) return;\n // Let code/mermaid blocks handle paste inline (plain text insert)\n const _tfId = this.getFocusedBlockId();\n const _tfType = _tfId ? this.getBlocks().find((b: Block) => b.id === _tfId)?.type : null;\n if (_tfType === \"code\" || _tfType === \"mermaid\") return;\n\n const hook = this.options?.transformPastedText;\n if (!hook) return;\n\n const text = e.clipboardData?.getData(\"text/plain\");\n if (!text) return;\n\n const result = hook(text);\n if (!result) return;\n\n const focusedId = this.getFocusedBlockId();\n if (!focusedId) return;\n const ctrl = this.controllerMap.get(focusedId);\n if (!ctrl) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n const offset = ctrl.getCursorOffset() ?? ctrl.getBlock().content.length;\n const tx = new Transaction(focusedId)\n .insertText(offset, result.text, result.attributes);\n ctrl.applyTransaction(tx);\n ctrl.focus(offset + result.text.length);\n ctrl.setNextInsertAttrs({});\n });\n\n // External paste: convert pasted HTML or multi-paragraph text into blocks\n this.root.addEventListener(\"paste\", (e: ClipboardEvent) => {\n // Skip if already handled by BLX blocks handler above\n if (e.defaultPrevented) return;\n // Let code/mermaid blocks handle paste inline (plain text insert)\n const _epId = this.getFocusedBlockId();\n const _epType = _epId ? this.getBlocks().find((b: Block) => b.id === _epId)?.type : null;\n if (_epType === \"code\" || _epType === \"mermaid\") return;\n\n // Try HTML first — richer structure (headings, lists, formatting)\n const html = e.clipboardData?.getData(\"text/html\");\n if (html) {\n const blocks = htmlToBlocks(html);\n if (blocks && blocks.length > 0) {\n e.preventDefault();\n this.pasteBlocks(blocks);\n return;\n }\n }\n\n // Try Markdown parsing on plain text\n const text = e.clipboardData?.getData(\"text/plain\");\n if (text) {\n const mdBlocks = markdownToBlocks(text);\n if (mdBlocks && mdBlocks.length > 0) {\n e.preventDefault();\n this.pasteBlocks(mdBlocks);\n return;\n }\n\n // Fall back to plain text paragraph splitting\n const blocks = plainTextToBlocks(text);\n if (blocks && blocks.length > 0) {\n e.preventDefault();\n this.pasteBlocks(blocks);\n return;\n }\n }\n });\n\n // Image: handle paste with image data in any block\n this.root.addEventListener(\"paste\", (e: ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith(\"image/\")) {\n e.preventDefault();\n const file = item.getAsFile();\n if (!file) return;\n storeFileAsBlob(file).then((src) => {\n // Find focused block and insert an image block after it\n const focusedId = this.getFocusedBlockId();\n const index = focusedId\n ? this.getBlockIndex(focusedId) + 1\n : this.controllers.length;\n const newBlock = this.addBlock(\n {\n id: generateId(),\n type: \"image\",\n content: AttributedString.empty(),\n metadata: { src },\n },\n index,\n );\n this.focusBlock(newBlock.id, 0);\n });\n return; // Only handle first image\n }\n }\n });\n\n // External drag-drop: image files and YouTube URLs\n this.root.addEventListener(\"dragover\", (e: DragEvent) => {\n const dt = e.dataTransfer;\n if (!dt?.types) return;\n const hasFiles = dt.types.includes(\"Files\");\n const hasUri = dt.types.includes(\"text/uri-list\") || dt.types.includes(\"text/plain\");\n if (!hasFiles && !hasUri) return;\n\n // Check if any dragged file is an image (items are readable during dragover)\n let hasImage = false;\n if (hasFiles && dt.items) {\n for (const item of dt.items) {\n if (item.kind === \"file\" && item.type.startsWith(\"image/\")) {\n hasImage = true;\n break;\n }\n }\n }\n\n // Non-image files: show full-editor overlay directing to sidebar\n if (hasFiles && !hasImage) {\n e.preventDefault();\n dt.dropEffect = \"none\";\n this.showDropRejectOverlay();\n return;\n }\n\n // If switching from non-image to image drag, clear the reject overlay\n this.removeDropRejectOverlay();\n\n e.preventDefault();\n dt.dropEffect = \"copy\";\n\n // Compute nearest insertion slot\n const y = e.clientY;\n let insertIndex = this.controllers.length;\n for (let i = 0; i < this.controllers.length; i++) {\n const rect = this.controllers[i].container.getBoundingClientRect();\n if (y < rect.top + rect.height / 2) {\n insertIndex = i;\n break;\n }\n }\n\n // Show or move the drop zone indicator (clear disabled state if set)\n const label = hasImage ? \"Drop image here\" : \"Drop link here\";\n const icon = hasImage\n ? iconHtml(ImageIcon, 18)\n : iconHtml(Play, 18);\n if (!this.imageDropZone) {\n this.imageDropZone = document.createElement(\"div\");\n this.imageDropZone.classList.add(\"blx-image-drop-zone\");\n }\n this.imageDropZone.innerHTML = `${icon} ${label}`;\n\n const beforeEl = this.controllers[insertIndex]?.container ?? null;\n this.blocksContainer.insertBefore(this.imageDropZone, beforeEl);\n });\n\n this.root.addEventListener(\"dragleave\", (e: DragEvent) => {\n // Only remove if truly leaving the editor root (not entering a child)\n if (e.relatedTarget && this.root.contains(e.relatedTarget as Node)) return;\n this.removeImageDropZone();\n this.removeDropRejectOverlay();\n });\n\n this.root.addEventListener(\"drop\", (e: DragEvent) => {\n this.removeImageDropZone();\n this.removeDropRejectOverlay();\n // Always prevent default to stop the browser from navigating to the\n // dropped file or URL.\n e.preventDefault();\n\n // Compute insertion index from drop position\n const y = e.clientY;\n let insertIndex = this.controllers.length;\n for (let i = 0; i < this.controllers.length; i++) {\n const rect = this.controllers[i].container.getBoundingClientRect();\n if (y < rect.top + rect.height / 2) {\n insertIndex = i;\n break;\n }\n }\n\n // Handle image file drops\n const files = e.dataTransfer?.files;\n if (files?.length) {\n const file = files[0];\n if (file.type.startsWith(\"image/\")) {\n storeFileAsBlob(file).then((src) => {\n const newBlock = this.addBlock(\n {\n id: generateId(),\n type: \"image\",\n content: AttributedString.empty(),\n metadata: { src },\n },\n insertIndex,\n );\n this.focusBlock(newBlock.id, 0);\n });\n return;\n }\n }\n\n // Handle YouTube URL drops\n const text =\n e.dataTransfer?.getData(\"text/uri-list\") ||\n e.dataTransfer?.getData(\"text/plain\");\n if (text) {\n const parsed = parseYouTubeUrl(text.split(\"\\n\")[0].trim());\n if (parsed) {\n const newBlock = this.addBlock(\n {\n id: generateId(),\n type: \"youtube\",\n content: AttributedString.empty(),\n metadata: {\n videoId: parsed.videoId,\n ...(parsed.startTime !== undefined\n ? { startTime: parsed.startTime }\n : {}),\n },\n },\n insertIndex,\n );\n this.focusNonTextBlock(newBlock.id);\n }\n }\n });\n\n // YouTube: handle paste of YouTube URLs to auto-create embed\n this.root.addEventListener(\"paste\", (e: ClipboardEvent) => {\n const text = e.clipboardData?.getData(\"text/plain\");\n if (!text) return;\n const parsed = parseYouTubeUrl(text);\n if (!parsed) return;\n\n // Only auto-embed if the focused block is empty\n const focusedId = this.getFocusedBlockId();\n if (!focusedId) return;\n const block = this.getBlock(focusedId);\n if (!block || block.content.length > 0) return;\n\n e.preventDefault();\n this.changeBlockType(focusedId, \"youtube\", {\n videoId: parsed.videoId,\n startTime: parsed.startTime,\n });\n const newBlock = this.addBlock(\"paragraph\", this.getBlockIndex(focusedId) + 1);\n this.focusBlock(newBlock.id, 0);\n });\n }\n\n // ── Search ────────────────────────────────────────────────────\n\n private setupSearchShortcut(): void {\n this.searchKeyHandler = (e: KeyboardEvent) => {\n // Cmd/Ctrl+F opens search\n if ((e.metaKey || e.ctrlKey) && e.key === \"f\") {\n e.preventDefault();\n this.openSearch();\n }\n };\n document.addEventListener(\"keydown\", this.searchKeyHandler);\n }\n\n /** Open (or re-focus) the search panel. */\n openSearch(): void {\n if (!this.searchUI) {\n this.searchUI = new SearchUI({\n onSearch: (query: string, options: SearchOptions) => {\n this.clearSearchHighlights();\n const matches = this.searchEngine.search(this.getBlocks(), query, options);\n this.searchMatches = matches;\n this.highlightAllSearchMatches(matches);\n return matches;\n },\n onNavigate: (match: SearchMatch) => {\n this.clearCurrentSearchHighlight();\n this.searchCurrentMatch = match;\n this.highlightSearchMatch(match);\n this.scrollToBlock(match.blockId, false);\n },\n onReplace: (match: SearchMatch, replacement: string) => {\n this.replaceSearchMatch(match, replacement);\n },\n onReplaceAll: (matches: SearchMatch[], replacement: string) => {\n this.replaceAllSearchMatches(matches, replacement);\n },\n onClose: () => {\n this.clearSearchHighlights();\n this.searchUI?.hide();\n this.restoreOverlayCursor();\n },\n });\n this.root.appendChild(this.searchUI.element);\n }\n\n if (this.searchUI.visible) {\n this.searchUI.focus();\n } else {\n this.saveOverlayCursor();\n this.searchUI.show();\n }\n }\n\n /** Close the search panel. */\n closeSearch(): void {\n this.clearSearchHighlights();\n this.searchUI?.hide();\n this.restoreOverlayCursor();\n }\n\n /** Highlight ALL search matches dimly across all blocks. */\n private highlightAllSearchMatches(matches: SearchMatch[]): void {\n // Group matches by blockId and sort by start offset descending\n // so we can insert marks from end-to-start without shifting earlier offsets.\n const byBlock = new Map<string, SearchMatch[]>();\n for (const m of matches) {\n const arr = byBlock.get(m.blockId) ?? [];\n arr.push(m);\n byBlock.set(m.blockId, arr);\n }\n\n for (const [blockId, blockMatches] of byBlock) {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) continue;\n // Process in reverse offset order to preserve earlier offsets\n const sorted = blockMatches.sort((a, b) => b.start - a.start);\n for (const m of sorted) {\n ctrl.highlightRange(m.start, m.end, \"blx-search-match\");\n }\n }\n }\n\n /** Add bright highlight to the current/focused search match. */\n private highlightSearchMatch(match: SearchMatch): void {\n const ctrl = this.controllerMap.get(match.blockId);\n if (!ctrl) return;\n\n // Find the dim mark that corresponds to this match and upgrade it\n const marks = ctrl.container.querySelectorAll(\"mark.blx-search-match\");\n for (const mark of marks) {\n // Walk text nodes inside the mark to compute its character offset\n // relative to the contentEditable. We compare text content and\n // position to identify the right mark.\n if (mark.textContent === match.matchText) {\n // Compute this mark's offset within the block\n const ce = ctrl.contentEditable;\n if (!ce) continue;\n const range = document.createRange();\n range.selectNodeContents(ce);\n range.setEnd(mark, 0);\n const offset = range.toString().length;\n if (offset === match.start) {\n mark.classList.add(\"blx-search-highlight\");\n return;\n }\n }\n }\n }\n\n /** Remove bright highlight from the current match (keep dim highlights). */\n private clearCurrentSearchHighlight(): void {\n if (!this.searchCurrentMatch) return;\n const ctrl = this.controllerMap.get(this.searchCurrentMatch.blockId);\n if (ctrl) {\n const marks = ctrl.container.querySelectorAll(\"mark.blx-search-highlight\");\n for (const mark of marks) {\n mark.classList.remove(\"blx-search-highlight\");\n }\n }\n this.searchCurrentMatch = null;\n }\n\n /** Clear ALL search highlights (dim + bright) from all blocks. */\n private clearSearchHighlights(): void {\n // Collect unique blockIds that had highlights\n const blockIds = new Set<string>();\n for (const m of this.searchMatches) {\n blockIds.add(m.blockId);\n }\n if (this.searchCurrentMatch) {\n blockIds.add(this.searchCurrentMatch.blockId);\n }\n\n for (const blockId of blockIds) {\n const ctrl = this.controllerMap.get(blockId);\n if (ctrl) {\n ctrl.clearHighlights(\"blx-search-highlight\");\n ctrl.clearHighlights(\"blx-search-match\");\n }\n }\n this.searchMatches = [];\n this.searchCurrentMatch = null;\n }\n\n private replaceSearchMatch(match: SearchMatch, replacement: string): void {\n const ctrl = this.controllerMap.get(match.blockId);\n if (!ctrl) return;\n const tx = new Transaction(match.blockId)\n .deleteRange(match.start, match.end)\n .insertText(match.start, replacement);\n ctrl.applyTransaction(tx);\n }\n\n private replaceAllSearchMatches(matches: SearchMatch[], replacement: string): void {\n // Group matches by blockId and process in reverse offset order\n // to avoid offset shifting issues\n const byBlock = new Map<string, SearchMatch[]>();\n for (const m of matches) {\n const arr = byBlock.get(m.blockId) ?? [];\n arr.push(m);\n byBlock.set(m.blockId, arr);\n }\n\n for (const [blockId, blockMatches] of byBlock) {\n const ctrl = this.controllerMap.get(blockId);\n if (!ctrl) continue;\n\n // Sort by offset descending so replacements don't shift earlier offsets\n const sorted = blockMatches.sort((a, b) => b.start - a.start);\n for (const m of sorted) {\n const tx = new Transaction(blockId)\n .deleteRange(m.start, m.end)\n .insertText(m.start, replacement);\n ctrl.applyTransaction(tx);\n }\n }\n }\n\n private getPlugin(type: string): BlockTypePlugin {\n const plugin = this.schema.get(type);\n if (!plugin) {\n throw new Error(`Unknown block type: \"${type}\"`);\n }\n return plugin;\n }\n}\n","/** Selection within a single block */\nexport interface InlineSelection {\n blockId: string;\n start: number;\n end: number;\n}\n\n/** Selection spanning multiple blocks */\nexport interface MultiBlockSelection {\n anchorBlockId: string;\n anchorOffset: number;\n focusBlockId: string;\n focusOffset: number;\n selectedBlockIds: string[];\n}\n\n/** Current selection state — either inline, multi-block, or null */\nexport type SelectionState = InlineSelection | MultiBlockSelection | null;\n\n/** Type guard for MultiBlockSelection */\nexport function isMultiBlockSelection(\n sel: SelectionState,\n): sel is MultiBlockSelection {\n return sel !== null && \"selectedBlockIds\" in sel;\n}\n\n/** Type guard for InlineSelection */\nexport function isInlineSelection(\n sel: SelectionState,\n): sel is InlineSelection {\n return sel !== null && !(\"selectedBlockIds\" in sel);\n}\n","import type { Editor } from \"../editor\";\nimport type { EventBus } from \"../event-bus\";\nimport type { EditorEventMap } from \"../event-bus\";\nimport type {\n InlineSelection,\n MultiBlockSelection,\n SelectionState,\n} from \"./types\";\nimport { isMultiBlockSelection, isInlineSelection } from \"./types\";\nimport { Transaction } from \"../transaction\";\nimport { AttributedString } from \"../attributed-string\";\nimport type { Attributes } from \"../attributed-string\";\n\n/**\n * Tracks the native browser selection and maps it to block-level selection state.\n * Provides cross-block operations: deleteSelection(), formatSelection().\n */\nexport class SelectionManager {\n private editor: Editor;\n private bus: EventBus<EditorEventMap>;\n private current: SelectionState = null;\n private blockSelectionActive = false;\n private handleSelectionChange: () => void;\n\n constructor(editor: Editor) {\n this.editor = editor;\n this.bus = editor.bus;\n\n this.handleSelectionChange = () => {\n this.syncFromDOM();\n };\n\n document.addEventListener(\"selectionchange\", this.handleSelectionChange);\n\n this.bus.on(\"selection:blockSelect\", ({ state }) => {\n if (state) {\n this.setBlockSelection(state);\n } else {\n this.clearBlockSelection();\n }\n });\n }\n\n /** Whether the current selection is a programmatic block selection */\n isBlockSelection(): boolean {\n return this.blockSelectionActive;\n }\n\n /** Set a programmatic block selection state */\n setBlockSelection(state: MultiBlockSelection): void {\n this.current = state;\n this.blockSelectionActive = true;\n this.bus.emit(\"selection:changed\", {\n blockId: state.anchorBlockId,\n start: state.anchorOffset,\n end: state.focusOffset,\n endBlockId: state.focusBlockId,\n });\n }\n\n /** Clear the programmatic block selection */\n clearBlockSelection(): void {\n this.blockSelectionActive = false;\n this.current = null;\n }\n\n /** Get the current selection state */\n getSelection(): SelectionState {\n return this.current;\n }\n\n /**\n * Delete the current selection.\n * For multi-block: trim first block, remove middle blocks, trim last block,\n * then merge first and last.\n */\n deleteSelection(): void {\n if (!this.current) return;\n\n if (isInlineSelection(this.current)) {\n const { blockId, start, end } = this.current;\n if (start === end) return;\n\n const tx = new Transaction(blockId).deleteRange(start, end);\n this.applyToBlock(blockId, tx);\n this.current = { blockId, start, end: start };\n } else if (isMultiBlockSelection(this.current)) {\n const { selectedBlockIds, anchorBlockId, anchorOffset, focusBlockId, focusOffset } =\n this.current;\n\n if (selectedBlockIds.length === 0) return;\n\n const blocks = this.editor.getBlocks();\n const blockIds = blocks.map((b) => b.id);\n\n // Determine which is first and which is last\n const anchorIndex = blockIds.indexOf(anchorBlockId);\n const focusIndex = blockIds.indexOf(focusBlockId);\n const firstId = anchorIndex <= focusIndex ? anchorBlockId : focusBlockId;\n const lastId = anchorIndex <= focusIndex ? focusBlockId : anchorBlockId;\n const firstOffset = anchorIndex <= focusIndex ? anchorOffset : focusOffset;\n const lastOffset = anchorIndex <= focusIndex ? focusOffset : anchorOffset;\n const firstIndex = Math.min(anchorIndex, focusIndex);\n const lastIndex = Math.max(anchorIndex, focusIndex);\n\n // Trim first block: delete from firstOffset to end\n const firstBlock = this.editor.getBlock(firstId);\n if (firstBlock) {\n const tx = new Transaction(firstId).deleteRange(\n firstOffset,\n firstBlock.content.length,\n );\n this.applyToBlock(firstId, tx);\n }\n\n // Remove middle blocks\n for (let i = lastIndex - 1; i > firstIndex; i--) {\n this.editor.removeBlock(blockIds[i]);\n }\n\n // Trim last block: delete from 0 to lastOffset, then merge into first\n if (firstId !== lastId) {\n const lastBlock = this.editor.getBlock(lastId);\n if (lastBlock) {\n const remaining = lastBlock.content.slice(\n lastOffset,\n lastBlock.content.length,\n );\n\n // Get current first block content and concat\n const updatedFirst = this.editor.getBlock(firstId);\n if (updatedFirst) {\n const merged = updatedFirst.content.concat(remaining);\n const tx = new Transaction(firstId).replaceContent(merged);\n this.applyToBlock(firstId, tx);\n }\n\n this.editor.removeBlock(lastId);\n }\n }\n\n this.current = { blockId: firstId, start: firstOffset, end: firstOffset };\n this.editor.focusBlock(firstId, firstOffset);\n }\n }\n\n /**\n * Apply formatting attributes to the current selection.\n */\n formatSelection(attrs: Attributes): void {\n if (!this.current) return;\n\n if (isInlineSelection(this.current)) {\n const { blockId, start, end } = this.current;\n if (start === end) return;\n\n const tx = new Transaction(blockId).applyAttributes(start, end, attrs);\n this.applyToBlock(blockId, tx);\n } else if (isMultiBlockSelection(this.current)) {\n const { selectedBlockIds, anchorBlockId, anchorOffset, focusBlockId, focusOffset } =\n this.current;\n\n const blocks = this.editor.getBlocks();\n const blockIds = blocks.map((b) => b.id);\n const anchorIndex = blockIds.indexOf(anchorBlockId);\n const focusIndex = blockIds.indexOf(focusBlockId);\n const firstOffset = anchorIndex <= focusIndex ? anchorOffset : focusOffset;\n const lastOffset = anchorIndex <= focusIndex ? focusOffset : anchorOffset;\n\n for (let i = 0; i < selectedBlockIds.length; i++) {\n const id = selectedBlockIds[i];\n const block = this.editor.getBlock(id);\n if (!block) continue;\n\n let start = 0;\n let end = block.content.length;\n\n if (i === 0) start = firstOffset;\n if (i === selectedBlockIds.length - 1) end = lastOffset;\n\n if (start < end) {\n const tx = new Transaction(id).applyAttributes(start, end, attrs);\n this.applyToBlock(id, tx);\n }\n }\n }\n }\n\n /** Manually set selection (used by tests or programmatic control) */\n setSelection(sel: SelectionState): void {\n this.current = sel;\n if (sel) {\n const blockId = isMultiBlockSelection(sel) ? sel.anchorBlockId : sel.blockId;\n const start = isMultiBlockSelection(sel) ? sel.anchorOffset : sel.start;\n const end = isMultiBlockSelection(sel) ? sel.focusOffset : sel.end;\n const endBlockId = isMultiBlockSelection(sel) ? sel.focusBlockId : undefined;\n this.bus.emit(\"selection:changed\", { blockId, start, end, endBlockId });\n } else {\n this.bus.emit(\"selection:changed\", { blockId: null, start: 0, end: 0 });\n }\n }\n\n /** Clean up event listeners */\n destroy(): void {\n document.removeEventListener(\"selectionchange\", this.handleSelectionChange);\n this.current = null;\n this.blockSelectionActive = false;\n }\n\n // ── Private ─────────────────────────────────────────────────────\n\n private syncFromDOM(): void {\n if (this.blockSelectionActive) return;\n\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n this.current = null;\n return;\n }\n\n const range = sel.getRangeAt(0);\n\n // Find which block(s) the selection belongs to\n const startBlock = this.findBlockFromNode(range.startContainer);\n const endBlock = this.findBlockFromNode(range.endContainer);\n\n if (!startBlock) {\n this.current = null;\n return;\n }\n\n if (!endBlock || startBlock === endBlock) {\n // Inline selection — use range (document-ordered) for internal state,\n // but anchor/focus from the Selection for the event (preserves direction).\n const startOffset = this.getOffsetInBlock(startBlock, range.startContainer, range.startOffset);\n const endOffset = this.getOffsetInBlock(startBlock, range.endContainer, range.endOffset);\n this.current = {\n blockId: startBlock,\n start: Math.min(startOffset, endOffset),\n end: Math.max(startOffset, endOffset),\n };\n } else {\n // Multi-block selection\n const blocks = this.editor.getBlocks();\n const blockIds = blocks.map((b) => b.id);\n const startIndex = blockIds.indexOf(startBlock);\n const endIndex = blockIds.indexOf(endBlock);\n const first = Math.min(startIndex, endIndex);\n const last = Math.max(startIndex, endIndex);\n const selectedBlockIds = blockIds.slice(first, last + 1);\n\n const anchorOffset = this.getOffsetInBlock(startBlock, range.startContainer, range.startOffset);\n const focusOffset = this.getOffsetInBlock(endBlock, range.endContainer, range.endOffset);\n\n this.current = {\n anchorBlockId: startBlock,\n anchorOffset,\n focusBlockId: endBlock,\n focusOffset,\n selectedBlockIds,\n };\n }\n\n if (isMultiBlockSelection(this.current)) {\n this.bus.emit(\"selection:changed\", {\n blockId: this.current.anchorBlockId,\n start: this.current.anchorOffset,\n end: this.current.focusOffset,\n endBlockId: this.current.focusBlockId,\n });\n } else {\n // Use anchor/focus from the DOM Selection to preserve direction\n // (start/end in InlineSelection are always ordered for internal use)\n const anchorOff = sel.anchorNode\n ? this.getOffsetInBlock(this.current.blockId, sel.anchorNode, sel.anchorOffset)\n : this.current.start;\n const focusOff = sel.focusNode\n ? this.getOffsetInBlock(this.current.blockId, sel.focusNode, sel.focusOffset)\n : this.current.end;\n this.bus.emit(\"selection:changed\", {\n blockId: this.current.blockId,\n start: anchorOff,\n end: focusOff,\n });\n }\n }\n\n private findBlockFromNode(node: Node): string | null {\n let el: Node | null = node;\n while (el && el !== this.editor.root) {\n if (el instanceof HTMLElement && el.dataset.blockId) {\n return el.dataset.blockId;\n }\n el = el.parentNode;\n }\n return null;\n }\n\n private getOffsetInBlock(\n _blockId: string,\n container: Node,\n offset: number,\n ): number {\n // Find the contenteditable ancestor\n let ce: HTMLElement | null = null;\n let el: Node | null = container;\n while (el) {\n if (el instanceof HTMLElement && el.getAttribute(\"contenteditable\") === \"true\") {\n ce = el;\n break;\n }\n el = el.parentNode;\n }\n\n if (!ce) return 0;\n\n const range = document.createRange();\n range.selectNodeContents(ce);\n range.setEnd(container, offset);\n return range.toString().length;\n }\n\n private applyToBlock(blockId: string, tx: Transaction): void {\n const block = this.editor.getBlock(blockId);\n if (!block) return;\n\n const result = tx.apply(block.content, block.metadata);\n this.editor.applyTransactionToBlock(blockId, result);\n }\n}\n","import type { UndoAction, CursorState } from \"../undo/types\";\nimport type { BlockJSON } from \"../types\";\n\n/** Identity and display info for a collaborating peer */\nexport interface CrdtPeer {\n /** Unique peer identifier */\n id: string;\n /** Display name shown on cursor labels */\n displayName: string;\n /** CSS color for cursor and selection highlights */\n color: string;\n}\n\n/** A single CRDT operation entry in the log */\nexport interface CrdtOperation {\n /** Sequential operation ID */\n id: number;\n /** Timestamp of the operation */\n timestamp: number;\n /** Peer who authored this operation (null = local before peers were set up) */\n peerId: string | null;\n /** One or more actions forming an atomic unit (compound ops like split) */\n actions: UndoAction[];\n /** Cursor state before the operation */\n beforeCursor: CursorState | null;\n /** Cursor state after the operation */\n afterCursor: CursorState | null;\n}\n\n/** A remote peer's cursor position, optionally with a selection range */\nexport interface RemoteCursor {\n peerId: string;\n displayName: string;\n color: string;\n blockId: string;\n offset: number;\n /** If set, the peer has a selection from offset..endOffset */\n endOffset?: number;\n /** If set, the selection spans into this block (multi-block selection) */\n endBlockId?: string;\n /** Timestamp of last cursor update (ms since epoch) */\n lastUpdated?: number;\n}\n\n/** Serializable snapshot of a CRDT log */\nexport interface CrdtLogSnapshot {\n initialState: BlockJSON[];\n operations: CrdtOperation[];\n}\n\n/** Default peer colors for multiplayer (soft, distinct hues) */\nexport const PEER_COLORS = [\n \"#e06c75\", // red\n \"#61afef\", // blue\n \"#e5c07b\", // yellow\n \"#98c379\", // green\n \"#c678dd\", // purple\n \"#d19a66\", // orange\n \"#56b6c2\", // cyan\n \"#be5046\", // rust\n] as const;\n"],"names":["AttributedString","spans","text","attrs","normalize","copied","s","json","len","offset","side","pos","prev","span","spanEnd","clamped","clamp","insertAttrs","before","after","splitSpans","inserted","start","end","e","result","overlapStart","overlapEnd","keys","newAttrs","key","afterStart","other","combined","i","a","b","attrsEqual","val","min","max","keysA","keysB","k","last","blockToJSON","block","blockFromJSON","EventBus","event","handler","set","unsub","payload","err","SchemaRegistry","plugin","type","oldType","newType","blocks","migrated","resolved","targets","p","Transaction","blockId","attributes","value","content","metadata","currentContent","currentMetadata","op","detectInlineShortcut","existingText","cursorOffset","charBeingTyped","detectBold","detectItalicAsterisk","detectItalic","detectCode","detectStrikethrough","detectLink","contentEnd","openMarkerStart","openMarkerEnd","contentStart","bracketCloseParenIdx","urlStart","urlEnd","url","bracketOpenIdx","textStart","textEnd","LANG_ALIASES","matchBlockShortcutPattern","prefix","taskHeadingMatch","headingMatch","codeMatch","raw","detectBlockShortcut","match","detectImmediateBlockShortcut","EMOTICON_MAP","SORTED_PATTERNS","detectEmoticon","pattern","patLen","prefixLen","startInText","charBefore","segmenter","prevGraphemeBoundary","index","segment","nextGraphemeBoundary","EMOJI_LIST","EMOJI_CATEGORIES","getEmojiByCategory","category","searchEmoji","query","limit","q","results","entry","kw","GRID_COLS","EmojiPicker","onSelect","onClose","anchorRect","menuRect","entries","next","nextCat","prevCat","col","lastRow","cat","tab","btn","cells","cell","name","anchor","gridRect","cellRect","BlockController","bus","parent","preReadHeight","h","height","tx","previousContent","previousMetadata","previousCursorOffset","updates","wrapper","sel","range","rect","elRect","caretRange","caretRect","firstTextNode","startRange","startRect","walker","lastTextNode","node","endRange","endRect","x","line","y","ceRect","style","paddingTop","paddingBottom","clampedX","lineY","atEnd","textNode","className","textNodes","tn","localStart","localEnd","mark","matchNode","marks","viewportHeight","isAboveViewport","isBelowViewport","target","hadFocus","newCE","inputType","selStart","selEnd","delTx","char","storedAttrs","attrs2","tx2","immediateMatch","remaining","blockMatch","inlineMatch","middle","newContent","emoticon","rawAfterAt","role","parseAgendaRolePrefix","inherited","effective","v","delStart","delEnd","beforeCursor","lastNewline","currentLine","indentMatch","insertion","replacement","targetRanges","isCollapsed","tabOffset","newText","oldText","minLen","suffixLen","deleteEnd","level","prevMargin","newMargin","attr","inheritedOn","desired","preRange","nodeOffset","lastChild","AGENDA_ROLE_PREFIXES","textAfterAt","afterPrefix","defaultResolveUrl","urlResolver","setUrlResolver","resolver","resolveUrl","blockRefRenderCallback","setBlockRefRenderCallback","cb","getBlockDir","updateEmptyState","el","placeholder","applySpanAttributes","color","HIGHLIGHT_COLOR_NAMES","isBlockReadOnly","container","createLinkElement","rawHref","renderAttributedString","href","parseAgendaDate","iso","m","d","date","formatAgendaDateISO","DAY_NAMES","MONTH_NAMES","MONTH_NAMES_FULL","formatShortDate","referenceDate","month","day","daysBetween","from","to","fromMidnight","toMidnight","classifyAgendaDate","agendaDate","now","reference","days","agendaStateClass","state","Check","ChevronDown","ChevronsLeft","ChevronsRight","CircleCheckBig","ClipboardPaste","ClockFading","ClockPlus","Code","Copy","GripVertical","Heading1","Heading2","Heading3","Heading4","History","Image","Link","ListChecks","ListOrdered","List","Pause","Pencil","Pilcrow","Play","Plus","Repeat2","Scissors","Sparkles","TextQuote","Trash2","X","iconHtml","def","size","mergedAttrs","attrStr","children","tag","tagAttrs","paragraphPlugin","dateInfo","resolveParagraphDisplayDate","renderParagraphAgendaBadge","_fromType","fromMetadata","contentEditable","existingBadge","display","existingRecur","recur","out","dateStr","recurring","badge","positionFixed","options","gap","align","preferred","pad","vp","vh","finalPlacement","spaceBelow","spaceAbove","left","vw","ContextMenu","items","menuHeight","item","direction","idx","empty","lastSection","sep","iconEl","textWrap","label","desc","hintEl","buttons","isListbox","selected","itemRect","dismissOnClickOutside","onDismiss","escapeKey","defer","mouseHandler","keyHandler","deferTimer","cleanup","ig","install","TASK_STATUS_CYCLE","TASK_STATUS_ITEMS","openTaskStatusMenu","menu","dismissHandle","status","createFoldIndicator","bar","headingPlugin","fromType","readOnly","indicator","current","longPressTimer","touch","synth","resolveDisplayDate","renderAgendaLabel","currentTag","hasIndicator","needsIndicator","hasWrapper","needsWrapper","existingLabel","textEl","n","done","UNORDERED_STYLES","ORDERED_STYLES","applyListStyleByLevel","list","ordered","indentLevel","styles","listPlugin","li","resolveListDisplayDate","renderListAgendaBadge","currentList","_self","Prism","lang","uniqueId","plainTextGrammar","_","encode","tokens","Token","o","obj","deepClone","visited","clone","id","element","language","src","scripts","defaultActivation","no","classList","redef","inside","insert","root","grammar","ret","token","newToken","old","DFS","callback","objId","property","propertyType","async","env","code","insertHighlightedCode","highlightedCode","worker","evt","rest","tokenList","LinkedList","addAfter","matchGrammar","toArray","hooks","callbacks","alias","matchedStr","stringify","aliases","matchPattern","lookbehind","lookbehindLength","startNode","startPos","rematch","patterns","j","patternObj","greedy","flags","currentNode","str","removeCount","matchStr","reach","removeFrom","removeRange","wrapped","nestedRematch","head","tail","newNode","count","array","message","immediateClose","script","highlightAutomaticallyCallback","readyState","module","global","tagName","includedCdataInside","attrName","string","markup","LOADING_MESSAGE","FAILURE_MESSAGE","FAILURE_EMPTY_MESSAGE","EXTENSIONS","STATUS_ATTR","STATUS_LOADING","STATUS_LOADED","STATUS_FAILED","SELECTOR","loadFile","success","error","xhr","parseRange","comma","pre","extension","autoloader","lines","elements","logged","typeInside","keywords","classNamePrefix","keyword","modName","multilineComment","anchorOrAlias","properties","plainKey","createValuePattern","Dropdown","menuItem","it","checkIcon","menuItems","menuEl","menuWidth","triggerRight","CODE_LANGUAGES","VALID_LANGUAGE_IDS","l","prismGrammarName","pendingHighlights","saveCursorOffset","restoreCursorOffset","scheduleHighlight","codeEl","existing","grammarName","frame","renderCodeContent","codeLangDropdowns","codeBlockPlugin","contentWrapper","codeBlock","picker","langItems","langDropdown","dropdown","horizontalRulePlugin","hr","checklistPlugin","checkbox","contentSpan","resolveChecklistDisplayDate","renderAgendaBadge","li2","checked","parseYouTubeUrl","trimmed","shortMatch","parseStart","longMatch","tMatch","youtubePlugin","_content","aspect","iframe","icon","input","parsed","_contentEditable","hasVideo","hasIframe","expected","_blobStore","setBlobStore","store","getBlobStore","BLOB_REF_PREFIX","isBlobRef","makeBlobRef","sha256Hex","blobRefHash","ref","resolveBlobSrc","srcStr","storeFileAsBlob","file","buffer","readFileAsArrayBuffer","resolve","reject","reader","data","hashBuffer","bytes","hex","extractString","imagePlugin","rawMetadata","figure","imgContainer","img","nw","nh","resizeHandle","setupResizeHandle","caption","ImageIcon","actions","uploadBtn","fileInput","urlInput","handle","startX","startWidth","onMouseMove","delta","newWidth","onMouseUp","width","MIN_ROWS","MIN_COLS","DEFAULT_COLS","buildTable","numCols","totalRows","getCellContent","r","c","table","tbody","inner","focusedRow","focusedCol","selection","isDragPending","isCellSelecting","getSelectionRect","startRow","endRow","startCol","endCol","hasMultiCellSelection","selectionOverlay","updateSelectionOverlay","topLeft","bottomRight","innerRect","tlRect","brRect","clearSelection","updateFocusHandles","rowWidget","colWidget","applySelection","anchorRow","anchorCol","focusCell","clearSelectedCells","emitTableEvent","focusHandles","handleNames","cr","t","w","edgeW","cornerS","focused","makeDots","frag","dot","addRowWidget","addColWidget","hoveredRowIndex","hoveredColIndex","detail","emitCellEdit","row","cursorEnd","lastNode","tr","td","cellContent","attribute","curOffset","getCellCursorOffset","textLen","rowEmpty","ci","rowCells","selFocusOffset","getCellSelectionFocusOffset","atStart","onFirstLine","isCellCaretOnFirstLine","onLastLine","isCellCaretOnLastLine","focusRow","focusCol","shouldSelect","colgroup","positionResizeHandles","handles","resizingCol","resizeStartX","resizeStartWidths","tableWidth","me","dx","tw","dxPct","minPct","newWidths","leftW","rightW","cols","finalWidths","tableContextMenu","tableContextDismiss","tableContextKeyHandler","dismissTableContextMenu","showContextMenu","anchorEl","mi","showRowContextMenu","showColContextMenu","positionWidgets","tableRect","mouseX","mouseY","rows","foundRow","firstRowCells","foundCol","tablePlugin","rawMeta","toSpans","fromSpans","numRows","toAS","header","rawHeader","rawRows","blockquotePlugin","bq","_container","_fromMetadata","_m","_raw","mermaidMod","mermaidInitialized","mermaidLoadPromise","ensureMermaid","theme","mod","pendingRenders","renderCounter","renderQueue","scheduleMermaidRender","previewEl","source","timer","renderMermaidDiagram","diagramEl","errorEl","svg","tempEl","renderMermaidSvg","mermaidTheme","mermaidPlugin","_metadata","preview","diagram","codeArea","fe","excalidrawPlugin","noPreview","noPreviewLabel","editOverlay","editBtn","createBtn","renderExcalidrawSvg","sceneData","ExcalidrawMod","scene","svgElement","openExcalidrawModal","onSave","React","ReactDOM","resolvedUrl","link","initialData","overlay","backdrop","modalContent","title","closeBtn","body","latestElements","latestAppState","excalidrawEl","appState","previewSvg","sceneJSON","registerDefaultPlugins","registry","INDENT","blocksToMarkdown","orderedCounter","prevWasList","isList","spansToMarkdown","indent","alt","videoId","exportTable","cellToText","headerCells","escapePipe","generateId","isUUID","SLASH_MENU_ITEMS","SlashMenu","AutoCompleteMenu","DAY_NAMES_SHORT","MONTH_NAMES_SHORT","DatePicker","onRemove","prevBtn","nextBtn","footerSpacer","crossBtn","existingDate","initialRole","initialRecurrence","blockType","adjusted","suggestions","roles","recurrence","unit","pendingMonth","dt","dateChip","everyLabel","numInput","unitSelect","units","u","opt","checkRow","checkLabel","year","firstDay","daysInMonth","today","DAY_ABBREVS","MONTH_ABBREVS","MONTH_NAMES_LOWER","MONTH_SHORT","formatDescription","dayName","nextDayOfWeek","targetDay","currentDay","daysAhead","nextWeekDayOfWeek","refMidnight","makeSuggestion","parseDateQuery","seen","add","relatives","rel","fullName","abbrev","d7","dm","fullMonth","monthMatched","restAfterMonth","dayNum","slashMatch","offsetMatch","firstLineCenterY","blockEl","editorRoot","firstChild","headingRow","rowRect","lineHeight","contentEl","contentRect","DragHandle","gutterEl","onMoveBlock","blockAtY","clientY","clientX","_e","editorRect","gutterRect","firstLineCenter","dy","selectedIds","firstDragIndex","firstBlockRect","lastDragIndex","lastBlockRect","dragIdx","ghostHandle","handleRect","ghostTop","ghostCenter","dropSlot","isDragged","draggedBefore","effectivePos","effectiveDropSlot","gapHeight","sum","compensation","movedBlockIds","firstFromIndex","draggedBeforeDrop","effectiveIndex","firstEffectiveFrom","fromIndex","singleEffective","slot","midY","effectiveMidY","Popover","TOOLBAR_BUTTONS","InlineToolbar","onFormat","builtinButtons","button","selectionRect","activeAttrs","context","renderGroup","isActive","LinkPopover","onApply","existingUrl","HIGHLIGHT_COLORS","HighlightPicker","swatch","removeBtn","activeColor","BlockActionMenu","getTargetBlockIds","getMenuItems","blockIds","btnRect","eventToDescriptor","parts","isSingleChar","KeySequencer","descriptor","bindings","onFallback","candidate","exactAction","isPrefix","fallbackAction","DEFAULT_KEYBINDINGS","VIM_KEYBINDINGS","SearchEngine","matches","escaped","contextChars","ctxStart","ctxEnd","SearchUI","scrollParent","overflow","panel","expandBtn","searchRow","inputWrap","caseSensitiveBtn","regexBtn","replaceRow","replaceInputWrap","replaceInput","replaceBtn","replaceAllBtn","UndoManager","action","afterCursor","JumpList","BlockViewport","bufferPx","controller","controllers","ctrl","behavior","avg","viewHeight","toFirstMount","toRestore","toEject","anchorTop","heights","CrdtLog","peerId","ReplayUI","controls","sliderWrap","total","CURSOR_CLASS","LABEL_CLASS","SELECTION_CLASS","OVERLAY_CLASS","BLOCK_BORDER_CLASS","renderRemoteCursors","cursors","rootRect","cursor","selRects","getSelectionRects","sr","caretOffset","getCaretRect","clearRemoteCursors","clearRemoteCursorsFromContainer","renderBlockSelectionBorder","blockRect","startOffset","endOffset","findTextPosition","rects","containerRect","MARK_ATTRIBUTES","AutomergeSync","editorApi","Automerge","actorId","otherDoc","oldDoc","syncState","newState","msg","newDoc","changes","heads","sinceDoc","stripUndefined","spanSignature","onContentChanged","onBlockAdded","onBlockRemoved","onBlockMoved","toIndex","onBlockTypeChanged","newSig","oldSig","formattingChanged","diff","diffText","currentMarks","stripped","fromIdx","oldOrder","newOrder","oldBlocks","newBlocks","newOrderSet","oldOrderSet","newData","oldData","textChanged","typeChanged","oldMeta","newMeta","metadataChanged","metadataEqual","marksChanged","newMarks","oldMarks","order","rawId","doc","cachedMarks","boundarySet","boundaries","merged","maxSuffix","sig","flattenValue","deepEqual","arrB","objA","objB","leadingEmoji","REST_W","ACTIVE_W","BROWSE_W","REST_H","ACTIVE_H","BROWSE_H","MAGNIFY_RADIUS","REST_HALF_GAP","ACTIVE_HALF_GAP","BROWSE_HALF_GAP","TableOfContents","getBlocks","onNavigate","emoji","emojiEl","cy","bestEl","bestDist","mid","dist","blocksContainer","my","sigma","bestBrowseIdx","bestBrowseVal","browse","entryRect","entryCenterY","rw","aw","bw","rh","ah","bh","restOp","activeOp","browseOp","opacity","halfGap","sp","isWindow","scrollTop","clientH","scrollH","spTop","viewportRef","activeId","FoldManager","headingBlockId","allBlocks","computeHiddenBlocks","getHeadingScope","headingBlock","scope","foldedHeadingIds","hidden","CommandRegistry","args","cmd","FloatingScrollManager","reg","wasVisible","isInViewport","BlockContextMenu","resolveTargetBlockIds","ev","ACTIVE_RESET_MS","CustomCaret","enabled","newX","newY","newH","editable","lh","paddingLeft","ws","lineNumber","newBlock","crossedBlock","suppress","oldX","oldY","distance","stretch","movingDown","origin","mask","fallback","BLX_MARKER_START","BLX_MARKER_END","copyBlocksToClipboard","jsonBlocks","markdown","jsonPayload","html","textarea","readBlocksFromClipboard","extractBlocksFromHtml","startIdx","payloadStart","endIdx","htmlToBlocks","collectBlocks","makeParagraph","inlineToSpans","langMatch","collectBlockquote","isBlockElement","depth","child","childEl","walkInline","mergeSpans","inheritedAttrs","curr","markdownToBlocks","foundMarkdown","codeFenceMatch","fence","codeLines","codeLine","parseInlineMarkdown","taskMatch","ulMatch","olMatch","bqMatch","paraLines","paraText","inlineRe","lastIndex","plainTextToBlocks","paragraphs","Toast","opts","duration","toast","liveness","resolveBlockDisplayDate","Editor","ids","headingId","recomputeFolds","fragment","newControllers","blockOrType","insertIndex","beforeCtrl","snap","minIndex","clampedTo","created","endCursor","focusedId","beforeContent","afterContent","first","firstContent","mergedContent","lastBlock","lastCtrl","afterBlock","lastCreated","ctrlsUnsorted","ctrls","beforeNode","anchorIdx","focusIdx","currentIndex","subtreeIds","lastPos","scopeStart","subtreeSet","firstCheckedSibling","bLevel","parentLevel","childCtrl","childBlock","CYCLE","oldBlock","newMetadata","lastRect","bestCtrl","ce","anchorPos","focusPos","focus","mode","fn","wasHidden","position","byBlock","blockCursors","blockJson","peer","endBlockId","existingTimer","blockOrder","ctrlMap","addHit","hit","hits","borderHits","singleHits","peerCursors","effectiveType","effectiveMetadata","saved","editCursor","newIndex","refresh","scrollEl","scrollRaf","onScroll","focusId","hash","tocUpdate","caretX","firstId","lastId","slashOffset","colonOffset","atOffset","bracketOffset","isGutterClick","clickedBlockId","clickedCtrl","clickedPlugin","outsideCe","inCePadding","pt","pb","currentBlockId","anchorCtrl","tick","edgeZone","maxSpeed","scrolled","ratio","anchorOffset","isListBlock","isChecklist","isBlockquote","splitAction","added","currentBlock","currentPlugin","prevCtrl","prevBlock","prevPlugin","joinOffset","mergeAction","nextBlock","fwdMergeAction","found","currentLevel","prevLevel","newLevel","sticky","anchorId","totalHeight","sampleCount","avgHeight","jumpCount","targetIndex","targetCtrl","targetBlock","neighborIndex","focusIndex","nextIndex","nextId","neighborIdx","neighborId","targetId","emptyContent","firstIdx","lastIdx","firstCtrl","firstBlock","groupCursor","idsToRemove","active","bindingMap","actionMap","nextFocusId","anchorIndex","firstIndex","blockAfterIndex","blockBeforeIndex","deleteGroupCursor","deleteEndCursor","selectedBlockIds","anchorBlock","focusBlock","focusBlockId","slashCtrl","allItems","customHandler","firstCell","provider","binding","metaKey","previous","otherKeys","hasOtherRole","prevRecurrence","recurrenceChanged","rec","inlineRole","isoDate","allResults","deduped","insertText","refEl","linkEl","isMod","isDoubleTap","scrollTarget","same","LinkIcon","ctx","selNode","isTableCell","positionRect","focusRange","applyAttributeFn","rowIdx","colIdx","rawStart","rawEnd","meta","headerArr","bodyRows","rawCell","currentMeta","toAS2","currentHeader","currentBodyRows","currentCell","newCell","updated","registerFloatingScroll","freshRect","fr","newId","conversion","er","eLen","cellStart","cellEnd","attrKeys","STRING_ATTR_KEYS","stringAttrs","spanStart","findPos","endPos","hovered","ListIcon","CodeIcon","isMac","modifiers","modMap","keyMap","commandName","candidates","makeTargetKey","blockMatchesTarget","targetType","targetMeta","targetSets","allTargetKeys","availableForAll","md","CopyIcon","headingBlocks","currentStatus","statuses","agendaBlocks","custom","ClipboardPasteIcon","clipboardBlocks","counters","startValue","ol","blockCtrl","prevTextIdx","nextTextIdx","blockCtrl2","blockCtrl3","getTableAllRows","splitTableAllRows","allRows","emptyTableRow","getTableNumCols","rStr","cStr","newRow","aligns","widths","splitIdx","splitWidth","moved","ma","copies","allHaveAttr","outer","shouldApply","newSpans","exTheme","newSceneData","_fbId","_fbType","_tfId","_tfType","hook","_epId","_epType","mdBlocks","hasFiles","hasUri","hasImage","beforeEl","files","arr","blockMatches","sorted","isMultiBlockSelection","isInlineSelection","SelectionManager","editor","anchorBlockId","focusOffset","firstOffset","lastOffset","updatedFirst","startBlock","endBlock","startIndex","endIndex","anchorOff","focusOff","_blockId","PEER_COLORS"],"mappings":"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","x_google_ignoreList":[14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67]}
|