@codemerge/kernel 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/document.d.ts.map +1 -1
- package/dist/index.cjs +32 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +32 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/document.ts","../src/selection.ts","../src/schema.ts","../src/operations.ts","../src/transform.ts","../src/structure.ts","../src/normalize.ts","../src/transaction.ts","../src/history.ts","../src/commands.ts"],"sourcesContent":["import type { DocNode, JSONDoc, Mark } from './types';\n\nlet idCounter = 0;\n\nexport function resetIdCounter(n = 0): void {\n idCounter = n;\n}\n\nexport function nextId(prefix = 'n'): string {\n idCounter += 1;\n return `${prefix}${idCounter}`;\n}\n\nexport function createText(text: string, marks: Mark[] = []): DocNode {\n return { marks: marks.length > 0 ? marks.map((m) => ({ ...m })) : undefined, text, type: 'text' };\n}\n\nexport function createParagraph(\n content: DocNode[] = [createText('')],\n attrs?: Record<string, unknown>\n): DocNode {\n return {\n attrs: copyAttrs(attrs),\n content: [...content],\n id: nextId('p'),\n type: 'paragraph',\n };\n}\n\nexport function createDoc(content?: DocNode[]): DocNode {\n return {\n content: content !== undefined && content.length > 0 ? [...content] : [createParagraph()],\n id: nextId('doc'),\n type: 'doc',\n };\n}\n\nfunction isAttrsRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/** Null-prototype attrs bag (no __proto__ pollution). */\nexport function emptyAttrsRecord(): Record<string, unknown> {\n const raw: unknown = Object.create(null);\n if (!isAttrsRecord(raw)) {\n return {};\n }\n return raw;\n}\n\n/** Copy own enumerable attrs onto a null-prototype bag (no __proto__ pollution). */\nexport function copyAttrs(\n src?: Record<string, unknown> | null\n): Record<string, unknown> | undefined {\n if (!src) {\n return undefined;\n }\n const out = emptyAttrsRecord();\n for (const key of Object.keys(src)) {\n out[key] = src[key];\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/** Shallow clone node; children array is new, child refs shared (structural sharing). */\nexport function cloneNode(node: DocNode): DocNode {\n return {\n ...node,\n attrs: copyAttrs(node.attrs),\n content: node.content ? [...node.content] : undefined,\n marks: node.marks ? node.marks.map((m) => ({ ...m, attrs: copyAttrs(m.attrs) })) : undefined,\n text: node.text,\n };\n}\n\n/** Deep clone node tree (content recursively cloned). */\nexport function deepCloneNode(node: DocNode): DocNode {\n const cloned = cloneNode(node);\n if (cloned.content) {\n cloned.content = cloned.content.map(deepCloneNode);\n }\n return cloned;\n}\n\n/** Assign stable ids to every non-text node missing `id`. */\nexport function ensureNodeIds(node: DocNode): DocNode {\n const out: DocNode = {\n ...node,\n content: node.content ? node.content.map(ensureNodeIds) : undefined,\n marks: node.marks ? node.marks.map((m) => ({ ...m })) : undefined,\n };\n if (out.type !== 'text' && !out.id) {\n const prefix =\n out.type === 'doc'\n ? 'doc'\n : out.type === 'paragraph'\n ? 'p'\n : out.type === 'listItem'\n ? 'li'\n : 'n';\n out.id = nextId(prefix);\n }\n return out;\n}\n\nfunction deepClone<T>(value: T): T {\n return structuredClone(value);\n}\n\n/** Document JSON format version — bump when the on-disk shape changes. */\nexport const JSON_DOC_VERSION = 1;\n\nexport function docToJSON(doc: DocNode): JSONDoc {\n return { doc: deepClone(doc), version: JSON_DOC_VERSION };\n}\n\nfunction isJSONDoc(value: object): value is JSONDoc {\n if (!('version' in value) || !('doc' in value)) {\n return false;\n }\n const doc = Reflect.get(value, 'doc');\n return typeof doc === 'object' && doc !== null;\n}\n\nfunction isDocNode(value: object): value is DocNode {\n return typeof Reflect.get(value, 'type') === 'string';\n}\n\nexport function docFromJSON(json: JSONDoc | DocNode | object): DocNode {\n if (isJSONDoc(json)) {\n if (json.version !== JSON_DOC_VERSION) {\n throw new Error(`Unsupported JSONDoc version: ${json.version}`);\n }\n if (json.doc.type !== 'doc') {\n throw new Error('Expected root type \"doc\"');\n }\n assertTreeDepth(json.doc);\n return ensureNodeIds(deepClone(json.doc));\n }\n if (isDocNode(json) && json.type === 'doc') {\n assertTreeDepth(json);\n return ensureNodeIds(deepClone(json));\n }\n throw new Error('Expected root type \"doc\"');\n}\n\nfunction assertTreeDepth(node: DocNode, max = 64): void {\n const stack: { n: DocNode; d: number }[] = [{ n: node, d: 0 }];\n while (stack.length > 0) {\n const { n, d } = stack.pop()!;\n if (d > max) {\n throw new Error(`Tree exceeds MAX_TREE_DEPTH (${max})`);\n }\n for (const child of n.content ?? []) {\n stack.push({ n: child, d: d + 1 });\n }\n }\n}\n\nexport function getNodeAt(doc: DocNode, path: number[]): DocNode {\n let cur = doc;\n for (const index of path) {\n if (!cur.content || index < 0 || index >= cur.content.length) {\n throw new Error(`Invalid path: ${path.join('.')}`);\n }\n cur = cur.content[index];\n }\n return cur;\n}\n\nexport function replaceAt(doc: DocNode, path: number[], next: DocNode): DocNode {\n if (path.length === 0) {\n return next;\n }\n const [head, ...rest] = path,\n cloned = cloneNode(doc);\n if (!cloned.content) {\n throw new Error('Cannot replace in leaf');\n }\n cloned.content[head] = replaceAt(cloned.content[head], rest, next);\n return cloned;\n}\n\nexport function textLength(node: DocNode): number {\n if (node.type === 'text') {\n return node.text?.length ?? 0;\n }\n if (!node.content) {\n return 0;\n }\n return node.content.reduce((sum, child) => sum + textLength(child), 0);\n}\n","import type { DocNode, Point, Selection } from './types';\nimport { getNodeAt, textLength } from './document';\n\nexport function createSelection(anchor: Point, focus: Point = anchor): Selection {\n return {\n anchor: { ...anchor, path: [...anchor.path] },\n focus: { ...focus, path: [...focus.path] },\n };\n}\n\nexport function collapsedAt(path: number[], offset: number): Selection {\n return createSelection({ offset, path: [...path] });\n}\n\nexport function isCollapsed(sel: Selection): boolean {\n return (\n sel.anchor.offset === sel.focus.offset &&\n sel.anchor.path.length === sel.focus.path.length &&\n sel.anchor.path.every((v, i) => v === sel.focus.path[i])\n );\n}\n\n/** Resolve a point inside a paragraph path to ensure offset is within text bounds. */\nexport function clampPoint(doc: DocNode, point: Point): Point {\n try {\n let path = [...point.path];\n let node = getNodeAt(doc, path);\n // Selection must address a text-bearing block, never a text leaf\n while (node.type === 'text' && path.length > 0) {\n path = path.slice(0, -1);\n node = path.length === 0 ? doc : getNodeAt(doc, path);\n }\n if (path.length === 0 || node.type === 'doc') {\n return { offset: 0, path: [0] };\n }\n const max = textLength(node);\n return { offset: Math.max(0, Math.min(point.offset, max)), path };\n } catch {\n // Path became invalid mid-transaction (structural edits) — fall back to doc start.\n return { offset: 0, path: [0] };\n }\n}\n\nexport function clampSelection(doc: DocNode, sel: Selection): Selection {\n return {\n anchor: clampPoint(doc, sel.anchor),\n focus: clampPoint(doc, sel.focus),\n };\n}\n\n/** Compare points: -1 if a < b, 0 equal, 1 if a > b (path then offset). */\nexport function comparePoints(a: Point, b: Point): number {\n const len = Math.max(a.path.length, b.path.length);\n for (let i = 0; i < len; i++) {\n const av = a.path[i] ?? -1,\n bv = b.path[i] ?? -1;\n if (av !== bv) {\n return av < bv ? -1 : 1;\n }\n }\n if (a.offset !== b.offset) {\n return a.offset < b.offset ? -1 : 1;\n }\n return 0;\n}\n\nexport function orderedRange(sel: Selection): { from: Point; to: Point } {\n return comparePoints(sel.anchor, sel.focus) <= 0\n ? { from: sel.anchor, to: sel.focus }\n : { from: sel.focus, to: sel.anchor };\n}\n","import type { Mark } from './types';\n\nexport interface NodeSpec {\n name: string;\n group?: 'block' | 'inline' | 'atom';\n atom?: boolean;\n attrs?: Record<string, unknown>;\n}\n\nexport interface MarkSpec {\n name: string;\n attrs?: Record<string, unknown>;\n}\n\nexport interface Schema {\n nodes: Map<string, NodeSpec>;\n marks: Map<string, MarkSpec>;\n sealed: boolean;\n}\n\nexport function createSchema(): Schema {\n const schema: Schema = {\n marks: new Map(),\n nodes: new Map(),\n sealed: false,\n };\n registerNode(schema, { group: 'block', name: 'doc' });\n registerNode(schema, { group: 'block', name: 'paragraph' });\n registerNode(schema, { group: 'inline', name: 'text' });\n registerNode(schema, { atom: true, group: 'inline', name: 'hardBreak' });\n registerMark(schema, { name: 'bold' });\n registerMark(schema, { name: 'italic' });\n registerMark(schema, { name: 'underline' });\n registerMark(schema, { name: 'strike' });\n return schema;\n}\n\nexport function registerNode(schema: Schema, spec: NodeSpec): void {\n if (schema.sealed) {\n throw new Error('Schema is sealed');\n }\n if (schema.nodes.has(spec.name)) {\n throw new Error(`Node already registered: ${spec.name}`);\n }\n schema.nodes.set(spec.name, spec);\n}\n\nexport function registerMark(schema: Schema, spec: MarkSpec): void {\n if (schema.sealed) {\n throw new Error('Schema is sealed');\n }\n if (schema.marks.has(spec.name)) {\n throw new Error(`Mark already registered: ${spec.name}`);\n }\n schema.marks.set(spec.name, spec);\n}\n\nexport function sealSchema(schema: Schema): void {\n schema.sealed = true;\n}\n\nexport function assertMark(schema: Schema, mark: Mark): void {\n if (!schema.marks.has(mark.type)) {\n throw new Error(`Unknown mark: ${mark.type}`);\n }\n}\n\nexport function assertNodeType(schema: Schema, type: string): void {\n if (!schema.nodes.has(type)) {\n throw new Error(`Unknown node type: ${type}`);\n }\n}\n","import type { DocNode, Mark, Selection } from './types';\nimport {\n cloneNode,\n copyAttrs,\n emptyAttrsRecord,\n createText,\n deepCloneNode,\n ensureNodeIds,\n getNodeAt,\n nextId,\n replaceAt,\n textLength,\n} from './document';\nimport { clampSelection, collapsedAt, orderedRange } from './selection';\nimport type { Schema } from './schema';\nimport { assertMark, assertNodeType } from './schema';\n\nexport { textLength };\n\nexport type TextRun = { text: string; marks: Mark[] };\n\n/** Inline keep (hardBreak etc.) relative to a slice start. */\nexport type SliceKeep = { at: number; node: DocNode };\n\nexport type Operation =\n | {\n type: 'insert_text';\n path: number[];\n offset: number;\n text: string;\n marks?: Mark[];\n marksByOffset?: Mark[][];\n }\n | { type: 'delete_text'; path: number[]; offset: number; length: number }\n | {\n type: 'split_paragraph';\n path: number[];\n offset: number;\n /** When set (merge inverse), restore this node as the right block. */\n rightNode?: DocNode;\n }\n | { type: 'merge_paragraph'; path: number[] }\n | { type: 'set_selection'; selection: Selection }\n | { type: 'set_mark'; path: number[]; from: number; to: number; mark: Mark }\n | { type: 'remove_mark'; path: number[]; from: number; to: number; markType: string }\n | {\n type: 'replace_slice';\n path: number[];\n from: number;\n to: number;\n runs: TextRun[];\n keeps?: SliceKeep[];\n }\n | { type: 'insert_node'; path: number[]; index: number; node: DocNode }\n | { type: 'remove_node'; path: number[]; index: number }\n | {\n type: 'set_attrs';\n path: number[];\n attrs: Record<string, unknown>;\n replace?: boolean;\n };\n\nexport type InvertibleOp = { op: Operation; inverse: Operation };\n\ntype FlatKeep = { at: number; node: DocNode };\ntype FlatRun = { start: number; end: number; node: DocNode };\n\nconst BLOCK_CHILD_TYPES = new Set([\n 'paragraph',\n 'heading',\n 'listItem',\n 'blockquote',\n 'codeBlock',\n 'bulletList',\n 'orderedList',\n 'table',\n 'tableRow',\n 'tableCell',\n]);\n\nfunction assertIntegerPath(path: number[]): void {\n for (const seg of path) {\n if (!Number.isInteger(seg)) {\n throw new TypeError(`Path segments must be integers: ${path.join('.')}`);\n }\n }\n}\n\nfunction assertLeafTextBlock(node: DocNode): void {\n if (node.type === 'text') {\n throw new Error('Text ops require a leaf text block');\n }\n if ((node.content ?? []).some((c) => BLOCK_CHILD_TYPES.has(c.type))) {\n throw new Error('Text ops require a leaf text block');\n }\n}\n\nfunction flattenText(paragraph: DocNode): {\n text: string;\n runs: FlatRun[];\n keeps: FlatKeep[];\n} {\n const runs: FlatRun[] = [];\n const keeps: FlatKeep[] = [];\n let text = '';\n for (const child of paragraph.content ?? []) {\n if (child.type === 'text') {\n const start = text.length;\n const chunk = child.text ?? '';\n text += chunk;\n runs.push({ start, end: text.length, node: child });\n } else {\n keeps.push({ at: text.length, node: deepCloneNode(child) });\n }\n }\n return { text, runs, keeps };\n}\n\nfunction rebuildParagraph(\n paragraph: DocNode,\n text: string,\n markAt: (i: number) => Mark[],\n keeps: FlatKeep[] = []\n): DocNode {\n const keepsSorted = [...keeps].toSorted((a, b) => a.at - b.at);\n if (text.length === 0) {\n if (keepsSorted.length === 0) {\n return { ...cloneNode(paragraph), content: [createText('')] };\n }\n return {\n ...cloneNode(paragraph),\n content: keepsSorted.map((k) => deepCloneNode(k.node)),\n };\n }\n\n const content: DocNode[] = [];\n let keepIdx = 0;\n let i = 0;\n\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at <= 0) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n\n while (i < text.length) {\n const marks = markAt(i);\n let j = i + 1;\n const nextKeepAt = keepsSorted[keepIdx]?.at ?? text.length + 1;\n while (j < text.length && j < nextKeepAt && sameMarks(markAt(j), marks)) {\n j++;\n }\n const end = Math.min(j, nextKeepAt, text.length);\n if (end > i) {\n content.push(createText(text.slice(i, end), marks));\n i = end;\n }\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at === i) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n }\n\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at >= text.length) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n\n if (content.length === 0) {\n content.push(createText(''));\n }\n return { ...cloneNode(paragraph), content };\n}\n\nfunction shiftKeeps(keeps: FlatKeep[], offset: number, delta: number): FlatKeep[] {\n return keeps.map((k) => (k.at >= offset ? { ...k, at: k.at + delta } : k));\n}\n\nfunction deleteKeepsInRange(keeps: FlatKeep[], offset: number, length: number): FlatKeep[] {\n const end = offset + length;\n return keeps\n .filter((k) => k.at <= offset || k.at >= end)\n .map((k) => (k.at >= end ? { ...k, at: k.at - length } : k));\n}\n\nfunction captureKeepsInRange(keeps: FlatKeep[], from: number, to: number): SliceKeep[] {\n return keeps\n .filter((k) => k.at > from && k.at < to)\n .map((k) => ({ at: k.at - from, node: deepCloneNode(k.node) }));\n}\n\nfunction mergeSliceKeeps(\n base: FlatKeep[],\n from: number,\n sliceKeeps: SliceKeep[] | undefined\n): FlatKeep[] {\n if (sliceKeeps === undefined || sliceKeeps.length === 0) {\n return base;\n }\n return [...base, ...sliceKeeps.map((k) => ({ at: from + k.at, node: deepCloneNode(k.node) }))];\n}\n\nfunction assertOpSchema(schema: Schema | undefined, op: Operation): void {\n if (!schema) {\n return;\n }\n if (op.type === 'set_mark') {\n assertMark(schema, op.mark);\n } else if (op.type === 'insert_text') {\n if (op.marks) {\n for (const m of op.marks) {\n assertMark(schema, m);\n }\n }\n if (op.marksByOffset) {\n for (const ms of op.marksByOffset) {\n for (const m of ms) {\n assertMark(schema, m);\n }\n }\n }\n } else if (op.type === 'replace_slice') {\n for (const run of op.runs) {\n for (const m of run.marks) {\n assertMark(schema, m);\n }\n }\n for (const k of op.keeps ?? []) {\n assertMaxTreeDepth(k.node);\n assertNodeTree(schema, k.node);\n }\n } else if (op.type === 'split_paragraph') {\n if (op.rightNode) {\n assertMaxTreeDepth(op.rightNode);\n assertNodeTree(schema, op.rightNode);\n }\n } else if (op.type === 'insert_node') {\n assertNodeTree(schema, op.node);\n }\n}\n\nfunction assertNodeTree(schema: Schema, node: DocNode, depthChecked = false): void {\n if (!depthChecked) {\n assertMaxTreeDepth(node);\n }\n assertNodeType(schema, node.type);\n if (node.marks) {\n for (const m of node.marks) {\n assertMark(schema, m);\n }\n }\n for (const child of node.content ?? []) {\n assertNodeTree(schema, child, true);\n }\n}\n\nfunction sameMarks(a: Mark[], b: Mark[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n return a.every(\n (m, i) =>\n m.type === b[i].type && JSON.stringify(m.attrs ?? {}) === JSON.stringify(b[i].attrs ?? {})\n );\n}\n\nfunction cloneMarks(marks: Mark[]): Mark[] {\n return marks.map((m) => ({ ...m, attrs: m.attrs ? { ...m.attrs } : undefined }));\n}\n\nfunction marksAt(runs: FlatRun[], index: number): Mark[] {\n for (const run of runs) {\n if (index >= run.start && index < run.end) {\n return run.node.marks ? cloneMarks(run.node.marks) : [];\n }\n }\n // caret at end — inherit last run marks\n const lastRun = runs.at(-1);\n if (lastRun && index === lastRun.end) {\n return lastRun.node.marks ? cloneMarks(lastRun.node.marks) : [];\n }\n return [];\n}\n\nfunction captureRuns(text: string, runs: FlatRun[], from: number, to: number): TextRun[] {\n const result: TextRun[] = [];\n let i = from;\n while (i < to) {\n const marks = marksAt(runs, i);\n let j = i + 1;\n while (j < to && sameMarks(marksAt(runs, j), marks)) {\n j++;\n }\n result.push({ text: text.slice(i, j), marks });\n i = j;\n }\n return result;\n}\n\n/** True when every offset in `[from, to)` carries `markType`. Empty range → false. */\nexport function rangeHasMark(\n paragraph: DocNode,\n from: number,\n to: number,\n markType: string\n): boolean {\n const { text, runs } = flattenText(paragraph);\n const start = Math.max(0, Math.min(from, text.length));\n const end = Math.max(start, Math.min(to, text.length));\n if (start >= end) {\n return false;\n }\n for (let i = start; i < end; i++) {\n if (!marksAt(runs, i).some((m) => m.type === markType)) {\n return false;\n }\n }\n return true;\n}\n\n/** Mark presence at a single offset (caret / left of caret). */\nexport function offsetHasMark(paragraph: DocNode, offset: number, markType: string): boolean {\n const { text, runs } = flattenText(paragraph);\n if (text.length === 0) {\n return false;\n }\n const i = Math.max(0, Math.min(offset, text.length - 1));\n return marksAt(runs, i).some((m) => m.type === markType);\n}\n\n/** Merge marks by type — `extra` wins on conflict. */\nexport function mergeMarksByType(base: Mark[], extra: Mark[]): Mark[] {\n const map = new Map<string, Mark>();\n for (const m of base) {\n map.set(m.type, { ...m, attrs: m.attrs ? { ...m.attrs } : undefined });\n }\n for (const m of extra) {\n map.set(m.type, { ...m, attrs: m.attrs ? { ...m.attrs } : undefined });\n }\n return [...map.values()];\n}\n\n/** Hard cap on a single insert_text / replace_slice payload (paste / programmatic flood). */\nexport const MAX_INSERT_CHARS = 100_000;\n/** Cap on keep nodes injected via replace_slice (hardBreak floods). */\nexport const MAX_SLICE_KEEPS = 10_000;\n/** Max nesting depth for op/JSON trees (empty structural bombs). */\nexport const MAX_TREE_DEPTH = 64;\n\n/** Iterative depth check — fail closed before recursive clone/walk. */\nexport function assertMaxTreeDepth(node: DocNode, max = MAX_TREE_DEPTH): void {\n const stack: { n: DocNode; d: number }[] = [{ n: node, d: 0 }];\n while (stack.length > 0) {\n const { n, d } = stack.pop()!;\n if (d > max) {\n throw new Error(`Tree exceeds MAX_TREE_DEPTH (${max})`);\n }\n for (const child of n.content ?? []) {\n stack.push({ n: child, d: d + 1 });\n }\n }\n}\n\nexport function applyOp(\n doc: DocNode,\n op: Operation,\n schema?: Schema\n): { doc: DocNode; inverse: Operation } {\n if ('path' in op) {\n assertIntegerPath(op.path);\n }\n assertOpSchema(schema, op);\n\n switch (op.type) {\n case 'insert_text': {\n if (op.text.length > MAX_INSERT_CHARS) {\n throw new Error(`insert_text exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const nextText = text.slice(0, offset) + op.text + text.slice(offset);\n const nextKeeps = shiftKeeps(keeps, offset, op.text.length);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n if (i >= offset && i < offset + op.text.length) {\n if (op.marksByOffset) {\n return cloneMarks(op.marksByOffset[i - offset] ?? []);\n }\n const inherited = marksAt(runs, Math.max(0, offset - 1));\n return op.marks && op.marks.length > 0\n ? mergeMarksByType(inherited, op.marks)\n : inherited;\n }\n const src = i < offset ? i : i - op.text.length;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: { type: 'delete_text', path: op.path, offset, length: op.text.length },\n };\n }\n case 'delete_text': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const length = Math.min(op.length, text.length - offset);\n const deletedKeeps = captureKeepsInRange(keeps, offset, offset + length);\n const captured = captureRuns(text, runs, offset, offset + length);\n const nextText = text.slice(0, offset) + text.slice(offset + length);\n const nextKeeps = deleteKeepsInRange(keeps, offset, length);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n const src = i < offset ? i : i + length;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from: offset,\n to: offset,\n runs: captured,\n keeps: deletedKeeps,\n },\n };\n }\n case 'split_paragraph': {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined) {\n throw new Error('split_paragraph path is empty');\n }\n assertIntegerPath(parentPath);\n const parent = parentPath.length > 0 ? getNodeAt(doc, parentPath) : doc;\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const leftKeeps = keeps.filter((k) => k.at < offset);\n const left = rebuildParagraph(\n para,\n text.slice(0, offset),\n (i) => marksAt(runs, i),\n leftKeeps\n );\n let rightRebuilt: DocNode;\n if (op.rightNode) {\n rightRebuilt = deepCloneNode(op.rightNode);\n } else {\n const rightKeeps = keeps\n .filter((k) => k.at >= offset)\n .map((k) => ({ ...k, at: k.at - offset }));\n const rightSeed = {\n ...cloneNode(para),\n content: [createText('')],\n id: nextId(para.type === 'listItem' ? 'li' : 'p'),\n };\n rightRebuilt = rebuildParagraph(\n rightSeed,\n text.slice(offset),\n (i) => marksAt(runs, offset + i),\n rightKeeps\n );\n }\n const nextParent = cloneNode(parent);\n if (!nextParent.content) {\n throw new Error('split parent has no content');\n }\n nextParent.content.splice(index, 1, left, rightRebuilt);\n const nextDoc = parentPath.length > 0 ? replaceAt(doc, parentPath, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'merge_paragraph', path: [...parentPath, index + 1] },\n };\n }\n case 'merge_paragraph': {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined || index <= 0) {\n throw new Error('Cannot merge first paragraph');\n }\n assertIntegerPath(parentPath);\n const parent = parentPath.length > 0 ? getNodeAt(doc, parentPath) : doc;\n const left = getNodeAt(doc, [...parentPath, index - 1]);\n const right = getNodeAt(doc, op.path);\n assertLeafTextBlock(left);\n assertLeafTextBlock(right);\n const rightSnap = deepCloneNode(right);\n const leftFlat = flattenText(left);\n const rightFlat = flattenText(right);\n const mergedText = leftFlat.text + rightFlat.text;\n const joinAt = leftFlat.text.length;\n const mergedKeeps = [\n ...leftFlat.keeps,\n ...rightFlat.keeps.map((k) => ({ ...k, at: k.at + joinAt })),\n ];\n const merged = rebuildParagraph(\n left,\n mergedText,\n (i) => {\n if (i < joinAt) {\n return marksAt(leftFlat.runs, i);\n }\n return marksAt(rightFlat.runs, i - joinAt);\n },\n mergedKeeps\n );\n const nextParent = cloneNode(parent);\n if (!nextParent.content) {\n throw new Error('merge parent has no content');\n }\n nextParent.content.splice(index - 1, 2, merged);\n const nextDoc = parentPath.length > 0 ? replaceAt(doc, parentPath, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: {\n type: 'split_paragraph',\n path: [...parentPath, index - 1],\n offset: joinAt,\n rightNode: rightSnap,\n },\n };\n }\n case 'set_selection': {\n return { doc, inverse: op };\n }\n case 'set_attrs': {\n const node = getNodeAt(doc, op.path);\n const prevSnapshot = copyAttrs(node.attrs) ?? emptyAttrsRecord();\n let nextAttrs: Record<string, unknown>;\n if (op.replace) {\n nextAttrs = copyAttrs(op.attrs) ?? emptyAttrsRecord();\n } else {\n nextAttrs = copyAttrs(node.attrs) ?? emptyAttrsRecord();\n for (const [key, value] of Object.entries(op.attrs)) {\n if (value === null) {\n delete nextAttrs[key];\n } else {\n nextAttrs[key] = value;\n }\n }\n }\n const next = {\n ...cloneNode(node),\n attrs: Object.keys(nextAttrs).length > 0 ? nextAttrs : undefined,\n };\n return {\n doc: replaceAt(doc, op.path, next),\n inverse: { type: 'set_attrs', path: op.path, attrs: prevSnapshot, replace: true },\n };\n }\n case 'set_mark': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const nextPara = rebuildParagraph(\n para,\n text,\n (i) => {\n const base = marksAt(runs, i);\n if (i >= from && i < to) {\n const filtered = base.filter((m) => m.type !== op.mark.type);\n return [...filtered, { ...op.mark, attrs: copyAttrs(op.mark.attrs) }];\n }\n return base;\n },\n keeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'remove_mark': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const nextPara = rebuildParagraph(\n para,\n text,\n (i) => {\n const base = marksAt(runs, i);\n if (i >= from && i < to) {\n return base.filter((m) => m.type !== op.markType);\n }\n return base;\n },\n keeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'replace_slice': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const newText = op.runs.map((r) => r.text).join('');\n if (newText.length > MAX_INSERT_CHARS) {\n throw new Error(`replace_slice exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n if ((op.keeps?.length ?? 0) > MAX_SLICE_KEEPS) {\n throw new Error(`replace_slice exceeds MAX_SLICE_KEEPS (${MAX_SLICE_KEEPS})`);\n }\n const insertedMarks: Mark[][] = [];\n for (const run of op.runs) {\n const marks = cloneMarks(run.marks);\n for (const _ of run.text) {\n insertedMarks.push(cloneMarks(marks));\n }\n }\n const nextText = text.slice(0, from) + newText + text.slice(to);\n const delta = newText.length - (to - from);\n const shifted = keeps\n .filter((k) => k.at <= from || k.at >= to)\n .map((k) => (k.at >= to ? { ...k, at: k.at + delta } : k));\n const nextKeeps = mergeSliceKeeps(shifted, from, op.keeps);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n if (i >= from && i < from + newText.length) {\n return insertedMarks[i - from] ?? [];\n }\n const src = i < from ? i : i - delta;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to: from + newText.length,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'insert_node': {\n assertMaxTreeDepth(op.node);\n if (textLength(op.node) > MAX_INSERT_CHARS) {\n throw new Error(`insert_node exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n const parent = op.path.length > 0 ? getNodeAt(doc, op.path) : doc;\n const nextParent = cloneNode(parent);\n nextParent.content ??= [];\n const index = Math.max(0, Math.min(op.index, nextParent.content.length));\n nextParent.content.splice(index, 0, ensureNodeIds(deepCloneNode(op.node)));\n const nextDoc = op.path.length > 0 ? replaceAt(doc, op.path, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'remove_node', path: op.path, index },\n };\n }\n case 'remove_node': {\n const parent = op.path.length > 0 ? getNodeAt(doc, op.path) : doc;\n const nextParent = cloneNode(parent);\n if (!nextParent.content || op.index < 0 || op.index >= nextParent.content.length) {\n throw new Error('remove_node out of bounds');\n }\n const [removed] = nextParent.content.splice(op.index, 1);\n const nextDoc = op.path.length > 0 ? replaceAt(doc, op.path, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'insert_node', path: op.path, index: op.index, node: removed },\n };\n }\n default: {\n const _exhaustive: never = op;\n throw new Error(`Unknown op: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\nexport function applyOps(\n doc: DocNode,\n ops: Operation[],\n selection: Selection,\n schema?: Schema\n): { doc: DocNode; selection: Selection; inverses: Operation[] } {\n let current = doc;\n let sel = selection;\n const inverses: Operation[] = [];\n for (const op of ops) {\n if (op.type === 'set_selection') {\n inverses.push({ type: 'set_selection', selection: sel });\n sel = clampSelection(current, op.selection);\n continue;\n }\n const result = applyOp(current, op, schema);\n current = result.doc;\n inverses.push(result.inverse);\n if (op.type === 'insert_text') {\n sel = collapsedAt(op.path, op.offset + op.text.length);\n } else if (op.type === 'delete_text') {\n sel = collapsedAt(op.path, op.offset);\n } else if (op.type === 'split_paragraph') {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined) {\n throw new Error('split_paragraph path is empty');\n }\n sel = collapsedAt([...parentPath, index + 1], 0);\n } else if (op.type === 'merge_paragraph') {\n const inv = result.inverse;\n if (inv.type === 'split_paragraph') {\n sel = collapsedAt(inv.path, inv.offset);\n }\n } else if (op.type === 'insert_node') {\n const index = result.inverse.type === 'remove_node' ? result.inverse.index : op.index;\n sel = {\n anchor: {\n offset: sel.anchor.offset,\n path: remapPathSibling(sel.anchor.path, op.path, index, 1),\n },\n focus: {\n offset: sel.focus.offset,\n path: remapPathSibling(sel.focus.path, op.path, index, 1),\n },\n };\n sel = clampSelection(current, sel);\n } else if (op.type === 'remove_node') {\n sel = {\n anchor: {\n offset: sel.anchor.offset,\n path: remapPathSibling(sel.anchor.path, op.path, op.index, -1),\n },\n focus: {\n offset: sel.focus.offset,\n path: remapPathSibling(sel.focus.path, op.path, op.index, -1),\n },\n };\n sel = clampSelection(current, sel);\n } else {\n sel = clampSelection(current, sel);\n }\n }\n return { doc: current, selection: clampSelection(current, sel), inverses: inverses.toReversed() };\n}\n\nfunction remapPathSibling(\n path: number[],\n parent: number[],\n index: number,\n delta: 1 | -1\n): number[] {\n const d = parent.length;\n if (path.length <= d) {\n return path;\n }\n for (let i = 0; i < d; i++) {\n if (path[i] !== parent[i]) {\n return path;\n }\n }\n const at = path[d];\n if (at === undefined) {\n return path;\n }\n if (delta < 0 && at === index) {\n return path;\n }\n if ((delta > 0 && at >= index) || (delta < 0 && at > index)) {\n const next = [...path];\n next[d] = at + delta;\n return next;\n }\n return path;\n}\n\nexport function selectionTextRange(\n sel: Selection\n): { path: number[]; from: number; to: number } | null {\n const { from, to } = orderedRange(sel);\n if (from.path.join('.') !== to.path.join('.')) {\n return null;\n }\n return { path: from.path, from: from.offset, to: to.offset };\n}\n\nexport function ensureParagraphPath(doc: DocNode, path: number[]): number[] {\n if (path.length > 0) {\n return path;\n }\n // default first paragraph\n if (doc.content?.[0]) {\n return [0];\n }\n return [0];\n}\n","import type { Operation } from './operations';\n\nfunction pathsEqual(a: number[], b: number[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\nfunction pathPrefix(longer: number[], shorter: number[]): boolean {\n if (longer.length < shorter.length) {\n return false;\n }\n for (let i = 0; i < shorter.length; i++) {\n if (longer[i] !== shorter[i]) {\n return false;\n }\n }\n return true;\n}\n\n/** Shift path index at `depth` by `delta` when the path is at/after `index`. */\nfunction shiftPath(path: number[], parentPath: number[], index: number, delta: number): number[] {\n if (!pathPrefix(path, parentPath) || path.length <= parentPath.length) {\n return path;\n }\n const at = parentPath.length;\n const cur = path[at];\n if (cur === undefined || cur < index) {\n return path;\n }\n const next = path.slice();\n next[at] = cur + delta;\n return next;\n}\n\nfunction mapPath(op: Operation, map: (path: number[]) => number[]): Operation {\n switch (op.type) {\n case 'set_selection':\n return op;\n case 'insert_text':\n case 'delete_text':\n case 'split_paragraph':\n case 'merge_paragraph':\n case 'set_mark':\n case 'remove_mark':\n case 'replace_slice':\n case 'set_attrs':\n case 'insert_node':\n case 'remove_node':\n return { ...op, path: map(op.path) };\n default: {\n const _exhaustive: never = op;\n return _exhaustive;\n }\n }\n}\n\nfunction mapOffset(op: Operation, path: number[], map: (offset: number) => number): Operation {\n if (!('path' in op) || !pathsEqual(op.path, path)) {\n return op;\n }\n switch (op.type) {\n case 'insert_text':\n return { ...op, offset: map(op.offset) };\n case 'delete_text': {\n const start = map(op.offset);\n const end = map(op.offset + op.length);\n return { ...op, offset: start, length: Math.max(0, end - start) };\n }\n case 'split_paragraph':\n return { ...op, offset: map(op.offset) };\n case 'set_mark':\n case 'remove_mark':\n case 'replace_slice': {\n const from = map(op.from);\n const to = map(op.to);\n return { ...op, from, to: Math.max(from, to) };\n }\n case 'merge_paragraph':\n case 'insert_node':\n case 'remove_node':\n case 'set_attrs':\n return op;\n default: {\n const _exhaustive: never = op;\n return _exhaustive;\n }\n }\n}\n\n/**\n * Transform `op` so it can be applied after `against` was already applied\n * (ProseMirror-style: rebase client op against server op).\n * Returns null if `op` becomes a no-op.\n */\nexport function transformOp(op: Operation, against: Operation): Operation | null {\n if (op.type === 'set_selection' || against.type === 'set_selection') {\n return op.type === 'set_selection' ? null : op;\n }\n\n // Node insert/remove shifts sibling paths\n if (against.type === 'insert_node') {\n let next = mapPath(op, (p) => shiftPath(p, against.path, against.index, 1));\n if (\n (next.type === 'insert_node' || next.type === 'remove_node') &&\n pathsEqual(next.path, against.path) &&\n next.index >= against.index\n ) {\n next = { ...next, index: next.index + 1 };\n }\n return next;\n }\n if (against.type === 'remove_node') {\n if (\n (op.type === 'insert_node' || op.type === 'remove_node') &&\n pathsEqual(op.path, against.path)\n ) {\n if (op.index === against.index && op.type === 'remove_node') {\n return null;\n }\n if (op.index > against.index) {\n return { ...op, index: op.index - 1 };\n }\n }\n const removedPath = [...against.path, against.index];\n if (\n 'path' in op &&\n pathPrefix(op.path, removedPath) &&\n op.path.length >= removedPath.length &&\n pathsEqual(op.path.slice(0, removedPath.length), removedPath)\n ) {\n return null;\n }\n let next = mapPath(op, (p) => shiftPath(p, against.path, against.index + 1, -1));\n if (\n (next.type === 'insert_node' || next.type === 'remove_node') &&\n pathsEqual(next.path, against.path) &&\n next.index > against.index\n ) {\n next = { ...next, index: next.index - 1 };\n }\n return next;\n }\n\n // split: index after split point +1 for paths under parent\n if (against.type === 'split_paragraph') {\n const parentPath = against.path.slice(0, -1);\n const index = against.path.at(-1);\n if (index === undefined) {\n return op;\n }\n // Ops on the left half (same path, offset <= split): keep path, maybe clamp offset\n if ('path' in op && pathsEqual(op.path, against.path)) {\n if (op.type === 'insert_text') {\n if (op.offset <= against.offset) {\n return op;\n }\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n if (op.type === 'delete_text') {\n if (op.offset + op.length <= against.offset) {\n return op;\n }\n if (op.offset >= against.offset) {\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n // Spans split: keep left portion only\n return { ...op, length: against.offset - op.offset };\n }\n if (op.type === 'split_paragraph') {\n if (op.offset <= against.offset) {\n return op;\n }\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n }\n return mapPath(op, (p) => shiftPath(p, parentPath, index + 1, 1));\n }\n\n if (against.type === 'merge_paragraph') {\n const parentPath = against.path.slice(0, -1);\n const index = against.path.at(-1);\n if (index === undefined || index <= 0) {\n return op;\n }\n const leftPath = [...parentPath, index - 1];\n const rightPath = against.path;\n // Approximate: paths after right shift down; ops on right move to left with offset bump unknown → keep & shift indices\n if ('path' in op && pathsEqual(op.path, rightPath)) {\n // Without join length we cannot fix offsets perfectly; shift path to left and leave offsets\n return mapPath(op, () => leftPath);\n }\n return mapPath(op, (p) => shiftPath(p, parentPath, index, -1));\n }\n\n // Text insert/delete on same path\n if (against.type === 'insert_text' && 'path' in op && pathsEqual(op.path, against.path)) {\n return mapOffset(op, against.path, (o) => (o >= against.offset ? o + against.text.length : o));\n }\n if (against.type === 'delete_text' && 'path' in op && pathsEqual(op.path, against.path)) {\n const delStart = against.offset;\n const delEnd = against.offset + against.length;\n return mapOffset(op, against.path, (o) => {\n if (o >= delEnd) {\n return o - against.length;\n }\n if (o >= delStart) {\n return delStart;\n }\n return o;\n });\n }\n\n if (against.type === 'replace_slice' && 'path' in op && pathsEqual(op.path, against.path)) {\n const removed = against.to - against.from;\n const inserted = against.runs.reduce((n, r) => n + r.text.length, 0);\n const delta = inserted - removed;\n return mapOffset(op, against.path, (o) => {\n if (o >= against.to) {\n return o + delta;\n }\n if (o >= against.from) {\n return against.from + inserted;\n }\n return o;\n });\n }\n\n return op;\n}\n\n/** Transform a sequence of ops against a single already-applied op. */\nexport function transformOps(ops: Operation[], against: Operation): Operation[] {\n const out: Operation[] = [];\n for (const op of ops) {\n const next = transformOp(op, against);\n if (next) {\n out.push(next);\n }\n }\n return out;\n}\n\n/**\n * Rebase client ops that were based on `baseVersion` against server ops\n * that landed since (in order). Returns ops safe to apply on the new tip.\n */\nexport function rebaseOps(clientOps: Operation[], serverOps: Operation[]): Operation[] {\n let pending: Operation[] = clientOps.filter((o) => o.type !== 'set_selection');\n for (const serverOp of serverOps) {\n if (serverOp.type === 'set_selection') {\n continue;\n }\n pending = transformOps(pending, serverOp);\n }\n return pending;\n}\n","import type { DocNode } from './types';\nimport type { Operation } from './operations';\nimport { createParagraph, createText, deepCloneNode, getNodeAt, textLength } from './document';\n\nconst TEXT_BLOCKS = new Set(['paragraph', 'heading', 'listItem', 'blockquote', 'codeBlock']);\nconst LIST_TYPES = new Set(['bulletList', 'orderedList']);\n\nexport function isTextBlock(type: string): boolean {\n return TEXT_BLOCKS.has(type);\n}\n\nexport function isListType(type: string): boolean {\n return LIST_TYPES.has(type);\n}\n\n/** Flatten text of a text-bearing node (paragraph / heading / listItem). */\nexport function plainText(node: DocNode): string {\n if (node.type === 'text') {\n return node.text ?? '';\n }\n let out = '';\n for (const child of node.content ?? []) {\n if (child.type === 'text') {\n out += child.text ?? '';\n } else if (child.content) {\n out += plainText(child);\n }\n }\n return out;\n}\n\n/**\n * Resolve selection path to a text-bearing leaf.\n * Lists → first/only item; listItem → nested paragraph; table → first cell paragraph.\n */\nexport function resolveTextPath(doc: DocNode, path: number[]): number[] {\n if (path.length === 0) {\n return [0];\n }\n let cur = getNodeAt(doc, path);\n const resolved = [...path];\n\n if (isListType(cur.type)) {\n if ((cur.content?.length ?? 0) === 0) {\n return resolved;\n }\n resolved.push(0);\n cur = cur.content![0];\n }\n\n if (cur.type === 'table') {\n const row = cur.content?.[0];\n const cell = row?.content?.[0];\n if (row && cell) {\n resolved.push(0, 0);\n cur = cell;\n }\n }\n\n if (cur.type === 'tableRow') {\n const cell = cur.content?.[0];\n if (cell) {\n resolved.push(0);\n cur = cell;\n }\n }\n\n if (cur.type === 'tableCell') {\n const para = cur.content?.[0];\n if (para && isTextBlock(para.type)) {\n resolved.push(0);\n cur = para;\n } else if (!para) {\n // empty cell — still point at cell; caller may create para\n return resolved;\n }\n }\n\n // listItem with nested paragraph (or other text block) → descend to leaf\n if (cur.type === 'listItem') {\n const first = cur.content?.[0];\n if (first && first.type !== 'text' && isTextBlock(first.type) && first.type !== 'listItem') {\n resolved.push(0);\n cur = first;\n }\n }\n\n // blockquote / codeBlock → descend into first nested text block\n if (cur.type === 'blockquote' || cur.type === 'codeBlock') {\n const first = cur.content?.[0];\n if (first && isTextBlock(first.type)) {\n resolved.push(0);\n // re-enter via recurse on extended path\n return resolveTextPath(doc, resolved);\n }\n }\n\n return resolved;\n}\n\nexport function createListItem(content: DocNode[] = [createText('')]): DocNode {\n return { type: 'listItem', content: [...content] };\n}\n\nexport function createList(listType: 'bulletList' | 'orderedList', items: DocNode[]): DocNode {\n return {\n type: listType,\n id: `list_${Date.now()}`,\n content: items.length > 0 ? items : [createListItem()],\n };\n}\n\n/** Extract a paragraph to lift out of a list item. */\nfunction liftedParagraphFromItem(item: DocNode): DocNode {\n const content = item.content ?? [];\n const first = content[0];\n if (first !== undefined && first.type === 'paragraph') {\n return deepCloneNode(first);\n }\n if (\n first !== undefined &&\n isTextBlock(first.type) &&\n first.type !== 'listItem' &&\n !isListType(first.type)\n ) {\n return deepCloneNode(first);\n }\n // Flat listItem with inline content (text / hardBreak)\n return createParagraph(content.length > 0 ? content.map(deepCloneNode) : [createText('')]);\n}\n\n/**\n * Lift list item `itemIndex` out of the list at `listPath` into the list's parent.\n * Removes the list, reinserts before-list (if any), lifted paragraph, after-list (if any).\n */\nexport function liftIntoParent(\n doc: DocNode,\n listPath: number[],\n itemIndex: number\n): { ops: Operation[]; selectionPath: number[]; liftedIndex: number } {\n const list = getNodeAt(doc, listPath);\n const items = list.content ?? [];\n const listIndex = listPath.at(-1);\n if (listIndex === undefined) {\n throw new Error('liftIntoParent: empty list path');\n }\n const parentPath = listPath.slice(0, -1);\n const item = items[itemIndex];\n if (item === undefined) {\n throw new Error('liftIntoParent: item out of bounds');\n }\n\n const before = items.slice(0, itemIndex);\n const after = items.slice(itemIndex + 1);\n const para = liftedParagraphFromItem(item);\n const ops: Operation[] = [];\n\n ops.push({ type: 'remove_node', path: parentPath, index: listIndex });\n\n let insertAt = listIndex;\n if (before.length > 0) {\n ops.push({\n type: 'insert_node',\n path: parentPath,\n index: insertAt,\n node: { ...list, content: before, id: `list_${Date.now()}_a` },\n });\n insertAt += 1;\n }\n ops.push({ type: 'insert_node', path: parentPath, index: insertAt, node: para });\n const liftedIndex = insertAt;\n const selectionPath = [...parentPath, insertAt];\n insertAt += 1;\n if (after.length > 0) {\n ops.push({\n type: 'insert_node',\n path: parentPath,\n index: insertAt,\n node: { ...list, content: after, id: `list_${Date.now()}_b` },\n });\n }\n\n return { ops, selectionPath, liftedIndex };\n}\n\n/** Exit empty list item: lift to paragraph in the list's parent (any depth). */\nexport function exitListItemOps(\n doc: DocNode,\n listPath: number[],\n itemIndex: number\n): { ops: Operation[]; selectionPath: number[] } {\n const { ops, selectionPath } = liftIntoParent(doc, listPath, itemIndex);\n return { ops, selectionPath };\n}\n\nexport function textBlockLength(doc: DocNode, path: number[]): number {\n try {\n return textLength(getNodeAt(doc, path));\n } catch {\n return 0;\n }\n}\n","import type { DocNode } from './types';\nimport { cloneNode, createText, nextId } from './document';\nimport { isListType, isTextBlock } from './structure';\n\n/** Idempotent normalize: ensure doc has content, text blocks have text leaves, coalesce adjacent same-mark texts. */\nexport function normalize(doc: DocNode): DocNode {\n if (doc.type !== 'doc') {\n throw new Error('normalize expects doc');\n }\n const next = cloneNode(doc);\n if (!next.content || next.content.length === 0) {\n next.content = [{ content: [createText('')], id: 'p_empty', type: 'paragraph' }];\n return next;\n }\n next.content = next.content.map(normalizeBlock);\n if (next.content.length === 0) {\n next.content = [{ content: [createText('')], id: 'p_empty', type: 'paragraph' }];\n }\n return next;\n}\n\nfunction normalizeBlock(node: DocNode): DocNode {\n if (node.type === 'text') {\n return node;\n }\n const cloned = cloneNode(node);\n if (!cloned.content || cloned.content.length === 0) {\n if (isListType(node.type)) {\n return {\n type: 'paragraph',\n id: nextId('p'),\n content: [createText('')],\n };\n }\n if (isTextBlock(node.type)) {\n cloned.content = [createText('')];\n }\n return cloned;\n }\n if (isTextBlock(node.type)) {\n cloned.content = coalesceText(cloned.content.map(normalizeBlock));\n if (cloned.content.length === 0) {\n cloned.content = [createText('')];\n }\n } else {\n cloned.content = cloned.content.map(normalizeBlock);\n if (isListType(node.type)) {\n cloned.content = cloned.content.filter((c) => {\n if (c.type !== 'listItem') {\n return true;\n }\n return (c.content?.length ?? 0) > 0;\n });\n if (cloned.content.length === 0) {\n return {\n type: 'paragraph',\n id: nextId('p'),\n content: [createText('')],\n };\n }\n }\n }\n return cloned;\n}\n\nfunction coalesceText(nodes: DocNode[]): DocNode[] {\n const out: DocNode[] = [];\n for (const n of nodes) {\n if (n.type !== 'text') {\n out.push(n);\n continue;\n }\n const prev = out.at(-1);\n if (\n prev?.type === 'text' &&\n JSON.stringify(prev.marks ?? []) === JSON.stringify(n.marks ?? [])\n ) {\n out[out.length - 1] = {\n ...prev,\n text: (prev.text ?? '') + (n.text ?? ''),\n };\n } else {\n out.push(n);\n }\n }\n return out;\n}\n\nexport function isNormalizeIdempotent(doc: DocNode): boolean {\n const a = normalize(doc),\n b = normalize(a);\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","import type { DocNode, Selection } from './types';\nimport { createDoc } from './document';\nimport { clampSelection, collapsedAt } from './selection';\nimport { applyOps } from './operations';\nimport type { Operation } from './operations';\nimport { normalize } from './normalize';\nimport type { Schema } from './schema';\n\nexport interface EditorState {\n doc: DocNode;\n selection: Selection;\n}\n\nexport interface Transaction {\n ops: Operation[];\n meta?: Record<string, unknown>;\n}\n\nexport function createState(doc: DocNode = createDoc(), selection?: Selection): EditorState {\n const normalized = normalize(doc);\n const sel = selection ?? collapsedAt([0], 0);\n return {\n doc: normalized,\n selection: clampSelection(normalized, sel),\n };\n}\n\nexport function applyTransaction(\n state: EditorState,\n tr: Transaction,\n schema?: Schema\n): { state: EditorState; inverses: Operation[] } {\n const { doc, selection, inverses } = applyOps(state.doc, tr.ops, state.selection, schema);\n return {\n inverses,\n state: { doc: normalize(doc), selection },\n };\n}\n\nexport function transaction(...ops: Operation[]): Transaction {\n return { ops };\n}\n","import type { Operation } from './operations';\nimport { applyTransaction, createState, transaction } from './transaction';\nimport type { EditorState, Transaction } from './transaction';\nimport type { Schema } from './schema';\n\nexport interface HistoryOptions {\n maxDepth?: number;\n /** Merge window in ms for consecutive typing */\n mergeWindowMs?: number;\n /** Cap merged typing entry size (insert+delete char counts); stop merging when exceeded. */\n maxEntryChars?: number;\n /** When set, applyTransaction validates ops against this schema. */\n schema?: Schema;\n}\n\nexport interface HistoryController {\n apply: (state: EditorState, tr: Transaction, now?: number) => EditorState;\n undo: (state: EditorState) => EditorState;\n redo: (state: EditorState) => EditorState;\n canUndo: () => boolean;\n canRedo: () => boolean;\n depth: () => number;\n /** Drop stacks after out-of-band full-document replace (setJSON / replaceDocument). */\n clear: () => void;\n}\n\ninterface Entry {\n inverses: Operation[];\n redo: Operation[];\n /** Final selection after the transaction (caret metadata; not replayed as ops). */\n selection: EditorState['selection'];\n at: number;\n chars: number;\n}\n\nexport function createHistory(options: HistoryOptions = {}): HistoryController {\n const maxDepth = options.maxDepth ?? 100,\n mergeWindowMs = options.mergeWindowMs ?? 500,\n maxEntryChars = options.maxEntryChars ?? 10_000,\n schema = options.schema,\n undoStack: Entry[] = [],\n redoStack: Entry[] = [];\n\n function push(entry: Entry): void {\n const last = undoStack.at(-1);\n if (\n last &&\n entry.at - last.at <= mergeWindowMs &&\n isTyping(entry.redo) &&\n isTyping(last.redo) &&\n last.chars + entry.chars <= maxEntryChars\n ) {\n last.redo = [...last.redo, ...entry.redo];\n last.inverses = [...entry.inverses, ...last.inverses];\n last.selection = entry.selection;\n last.at = entry.at;\n last.chars += entry.chars;\n } else {\n undoStack.push(entry);\n }\n while (undoStack.length > maxDepth) {\n undoStack.shift();\n }\n redoStack.length = 0;\n }\n\n return {\n apply(state, tr, now = Date.now()) {\n const { state: next, inverses } = applyTransaction(state, tr, schema);\n if (tr.ops.some((op) => op.type !== 'set_selection')) {\n const redo = tr.ops.filter((o) => o.type !== 'set_selection');\n push({\n inverses,\n redo,\n selection: next.selection,\n at: now,\n chars: entryCharCount(redo),\n });\n }\n return next;\n },\n canRedo: () => redoStack.length > 0,\n canUndo: () => undoStack.length > 0,\n clear() {\n undoStack.length = 0;\n redoStack.length = 0;\n },\n depth: () => undoStack.length,\n redo(state) {\n const entry = redoStack.pop();\n if (!entry) {\n return state;\n }\n const { state: next, inverses } = applyTransaction(state, transaction(...entry.redo), schema);\n undoStack.push({\n inverses,\n redo: entry.redo,\n selection: entry.selection,\n at: Date.now(),\n chars: entry.chars,\n });\n return { ...next, selection: entry.selection };\n },\n undo(state) {\n const entry = undoStack.pop();\n if (!entry) {\n return state;\n }\n const { state: next } = applyTransaction(state, transaction(...entry.inverses), schema);\n redoStack.push(entry);\n return next;\n },\n };\n}\n\nfunction isTyping(ops: Operation[]): boolean {\n return ops.length > 0 && ops.every((o) => o.type === 'insert_text' || o.type === 'delete_text');\n}\n\nfunction entryCharCount(ops: Operation[]): number {\n let n = 0;\n for (const op of ops) {\n if (op.type === 'insert_text') {\n n += op.text.length;\n } else if (op.type === 'delete_text') {\n n += op.length;\n }\n }\n return n;\n}\n\nexport function emptyState(): EditorState {\n return createState();\n}\n","import type { EditorState } from './transaction';\nimport { transaction } from './transaction';\nimport type { Operation } from './operations';\nimport { offsetHasMark, rangeHasMark, selectionTextRange } from './operations';\nimport { createParagraph, createText, getNodeAt, textLength } from './document';\nimport { collapsedAt, orderedRange } from './selection';\nimport type { DocNode, Mark, Point, Selection } from './types';\nimport {\n exitListItemOps,\n isListType,\n isTextBlock,\n liftIntoParent,\n plainText,\n resolveTextPath,\n} from './structure';\n\nexport type Command = (state: EditorState) => Operation[] | null;\n\nfunction textPath(state: EditorState): number[] {\n return resolveTextPath(state.doc, state.selection.anchor.path);\n}\n\nfunction samePath(a: number[], b: number[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\nfunction isLeafTextBlock(node: DocNode): boolean {\n return (\n isTextBlock(node.type) &&\n !(node.content ?? []).some(\n (c) =>\n c.type !== 'text' &&\n (isTextBlock(c.type) ||\n isListType(c.type) ||\n c.type === 'table' ||\n c.type === 'tableRow' ||\n c.type === 'tableCell')\n )\n );\n}\n\n/**\n * Ops to delete the current selection — same-path text or cross-block (siblings / root span).\n * Keeps selectAll → deleteBackward/insertText working.\n */\nexport function deleteSelectionRangeOps(doc: DocNode, sel: Selection): Operation[] | null {\n const { from, to } = orderedRange(sel);\n if (samePath(from.path, to.path)) {\n if (from.offset === to.offset) {\n return null;\n }\n const path = resolveTextPath(doc, from.path);\n return [\n {\n type: 'delete_text',\n path,\n offset: from.offset,\n length: to.offset - from.offset,\n },\n ];\n }\n\n // True siblings: same parent, same depth\n if (\n from.path.length === to.path.length &&\n from.path.length > 0 &&\n samePath(from.path.slice(0, -1), to.path.slice(0, -1))\n ) {\n return deleteSiblingSpan(doc, from, to);\n }\n\n return deleteRootSpan(doc, from, to);\n}\n\nfunction deleteSiblingSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const parent = from.path.slice(0, -1);\n const fromIdx = from.path.at(-1) ?? 0;\n const toIdx = to.path.at(-1) ?? 0;\n return deleteSpanUnderParent(doc, from, to, parent, fromIdx, toIdx);\n}\n\nfunction deleteSpanUnderParent(\n doc: DocNode,\n from: Point,\n to: Point,\n parent: number[],\n fromIdx: number,\n toIdx: number\n): Operation[] {\n const fromPath = resolveTextPath(doc, from.path);\n const toPath = resolveTextPath(doc, to.path);\n const ops: Operation[] = [];\n\n const fromLen = textLength(getNodeAt(doc, fromPath));\n if (from.offset < fromLen) {\n ops.push({\n type: 'delete_text',\n path: fromPath,\n offset: from.offset,\n length: fromLen - from.offset,\n });\n }\n\n const fromBlock = getNodeAt(doc, [...parent, fromIdx]);\n const toBlock = getNodeAt(doc, [...parent, toIdx]);\n const canMerge = isLeafTextBlock(fromBlock) && isLeafTextBlock(toBlock);\n\n if (canMerge && toIdx > fromIdx) {\n if (to.offset > 0) {\n const remappedTo = [...toPath];\n if (parent.length < remappedTo.length) {\n remappedTo[parent.length] = toIdx;\n }\n ops.push({ type: 'delete_text', path: remappedTo, offset: 0, length: to.offset });\n }\n for (let i = toIdx - 1; i > fromIdx; i--) {\n ops.push({ type: 'remove_node', path: parent, index: i });\n }\n ops.push({ type: 'merge_paragraph', path: [...parent, fromIdx + 1] });\n } else {\n // Non-leaf containers: leaf-walk so unselected end suffix is kept\n return deleteLeafSpan(doc, from, to);\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nfunction collectTextLeaves(node: DocNode, path: number[], out: number[][]): void {\n if (isLeafTextBlock(node)) {\n out.push([...path]);\n return;\n }\n (node.content ?? []).forEach((child, i) => {\n collectTextLeaves(child, [...path, i], out);\n });\n}\n\nfunction removableAncestor(doc: DocNode, leafPath: number[]): { parent: number[]; index: number } {\n if (leafPath.length >= 2) {\n const itemPath = leafPath.slice(0, -1);\n try {\n const item = getNodeAt(doc, itemPath);\n if (item.type === 'listItem' || item.type === 'tableCell') {\n return { parent: itemPath.slice(0, -1), index: itemPath.at(-1) ?? 0 };\n }\n } catch {\n /* fall through */\n }\n }\n return { parent: leafPath.slice(0, -1), index: leafPath.at(-1) ?? 0 };\n}\n\nfunction deleteLeafSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const fromPath = resolveTextPath(doc, from.path);\n const toPath = resolveTextPath(doc, to.path);\n let d = 0;\n while (d < fromPath.length && d < toPath.length && fromPath[d] === toPath[d]) {\n d++;\n }\n const rootPath = fromPath.slice(0, d);\n const rootNode = rootPath.length === 0 ? doc : getNodeAt(doc, rootPath);\n const leaves: number[][] = [];\n collectTextLeaves(rootNode, rootPath, leaves);\n const i0 = leaves.findIndex((p) => samePath(p, fromPath));\n const i1 = leaves.findIndex((p) => samePath(p, toPath));\n if (i0 === -1 || i1 === -1) {\n return [];\n }\n const start = Math.min(i0, i1);\n const end = Math.max(i0, i1);\n const ops: Operation[] = [];\n const first = leaves[start];\n if (first === undefined) {\n return [];\n }\n const firstLen = textLength(getNodeAt(doc, first));\n const firstFrom = samePath(first, fromPath) ? from.offset : 0;\n if (firstFrom < firstLen) {\n ops.push({\n type: 'delete_text',\n path: first,\n offset: firstFrom,\n length: firstLen - firstFrom,\n });\n }\n\n // Collect removable containers for fully covered start + middle + end (high → low)\n const removals: { parent: number[]; index: number; key: string }[] = [];\n const startFullyCovered = firstFrom === 0 && (end > start || to.offset >= firstLen);\n for (let i = end; i >= start; i--) {\n if (i === start && !startFullyCovered) {\n continue;\n }\n const leaf = leaves[i];\n if (leaf === undefined) {\n continue;\n }\n const fullyCovered =\n i === start ? startFullyCovered : i < end || to.offset >= textLength(getNodeAt(doc, leaf));\n if (!fullyCovered) {\n if (i === end && to.offset > 0) {\n ops.push({ type: 'delete_text', path: leaf, offset: 0, length: to.offset });\n }\n continue;\n }\n const rem = removableAncestor(doc, leaf);\n const key = `${rem.parent.join('.')}:${rem.index}`;\n if (!removals.some((r) => r.key === key)) {\n removals.push({ ...rem, key });\n }\n }\n removals.sort((a, b) => {\n if (a.parent.length !== b.parent.length) {\n return b.parent.length - a.parent.length;\n }\n for (let i = 0; i < a.parent.length; i++) {\n if (a.parent[i] !== b.parent[i]) {\n return (b.parent[i] ?? 0) - (a.parent[i] ?? 0);\n }\n }\n return b.index - a.index;\n });\n for (const rem of removals) {\n ops.push({ type: 'remove_node', path: rem.parent, index: rem.index });\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nfunction deleteRootSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const fromRoot = from.path[0] ?? 0;\n const toRoot = to.path[0] ?? 0;\n const fromPath = resolveTextPath(doc, from.path);\n const ops: Operation[] = [];\n\n if (fromRoot === toRoot) {\n let d = 0;\n while (d < from.path.length && d < to.path.length && from.path[d] === to.path[d]) {\n d++;\n }\n if (d < from.path.length && d < to.path.length && from.path.length === to.path.length) {\n return deleteSpanUnderParent(\n doc,\n from,\n to,\n from.path.slice(0, d),\n from.path[d] ?? 0,\n to.path[d] ?? 0\n );\n }\n return deleteLeafSpan(doc, from, to);\n }\n\n const fromLen = textLength(getNodeAt(doc, fromPath));\n if (from.offset < fromLen) {\n ops.push({\n type: 'delete_text',\n path: fromPath,\n offset: from.offset,\n length: fromLen - from.offset,\n });\n }\n\n const fromBlock = getNodeAt(doc, [fromRoot]);\n const toBlock = getNodeAt(doc, [toRoot]);\n const toPath = resolveTextPath(doc, to.path);\n const simple =\n from.path.length === 1 &&\n to.path.length === 1 &&\n isLeafTextBlock(fromBlock) &&\n isLeafTextBlock(toBlock);\n\n if (simple) {\n if (to.offset > 0) {\n ops.push({ type: 'delete_text', path: toPath, offset: 0, length: to.offset });\n }\n for (let i = toRoot - 1; i > fromRoot; i--) {\n ops.push({ type: 'remove_node', path: [], index: i });\n }\n ops.push({ type: 'merge_paragraph', path: [fromRoot + 1] });\n } else {\n // Mixed / nested roots: leaf-walk to preserve unselected end suffix\n return deleteLeafSpan(doc, from, to);\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nexport function insertText(text: string, marks?: Mark[]): Command {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range) {\n const cross = deleteSelectionRangeOps(state.doc, state.selection);\n if (cross && !isCollapsedSelection(state.selection)) {\n const path = resolveTextPath(state.doc, orderedRange(state.selection).from.path);\n const offset = orderedRange(state.selection).from.offset;\n const ops: Operation[] = cross.filter((op) => op.type !== 'set_selection');\n ops.push(\n marks && marks.length > 0\n ? { type: 'insert_text', path, offset, text, marks }\n : { type: 'insert_text', path, offset, text },\n { type: 'set_selection', selection: collapsedAt(path, offset + text.length) }\n );\n return ops;\n }\n }\n const path = resolveTextPath(state.doc, range?.path ?? state.selection.anchor.path);\n const offset = range ? range.from : state.selection.anchor.offset;\n const ops: Operation[] = [];\n if (range && range.from !== range.to) {\n ops.push({\n type: 'delete_text',\n path,\n offset: range.from,\n length: range.to - range.from,\n });\n }\n ops.push(\n marks && marks.length > 0\n ? { type: 'insert_text', path, offset, text, marks }\n : { type: 'insert_text', path, offset, text }\n );\n return ops;\n };\n}\n\nfunction isCollapsedSelection(sel: Selection): boolean {\n return samePath(sel.anchor.path, sel.focus.path) && sel.anchor.offset === sel.focus.offset;\n}\n\n/**\n * Track-changes style backspace: mark the previous char as deleted instead of\n * removing it. Hard-deletes own `insertion` marks and already-marked deletions.\n */\nexport function softDeleteBackward(deletionMark: Mark): Command {\n return (state) => {\n if (!isCollapsedSelection(state.selection)) {\n return deleteBackward(state);\n }\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n if (offset <= 0) {\n return deleteBackward(state);\n }\n\n const para = getNodeAt(state.doc, path);\n const { text, runs } = flattenTextForMarks(para);\n if (text.length === 0) {\n return deleteBackward(state);\n }\n const from = offset - 1;\n const existing = marksAtOffset(runs, from);\n if (existing.some((m) => m.type === 'insertion' || m.type === deletionMark.type)) {\n return [{ type: 'delete_text', path, offset: from, length: 1 }];\n }\n return [\n { type: 'set_mark', path, from, to: offset, mark: deletionMark },\n { type: 'set_selection', selection: collapsedAt(path, from) },\n ];\n };\n}\n\nfunction flattenTextForMarks(paragraph: DocNode): {\n text: string;\n runs: { start: number; end: number; marks: Mark[] }[];\n} {\n let text = '';\n const runs: { start: number; end: number; marks: Mark[] }[] = [];\n for (const child of paragraph.content ?? []) {\n if (child.type !== 'text') {\n continue;\n }\n const start = text.length;\n const chunk = child.text ?? '';\n text += chunk;\n runs.push({\n start,\n end: text.length,\n marks: (child.marks ?? []).map((m) => ({ ...m })),\n });\n }\n return { text, runs };\n}\n\nfunction marksAtOffset(\n runs: { start: number; end: number; marks: Mark[] }[],\n index: number\n): Mark[] {\n for (const run of runs) {\n if (index >= run.start && index < run.end) {\n return run.marks.map((m) => ({ ...m }));\n }\n }\n return [];\n}\n\n/** Resolve list-item path when caret is on the item or its first nested text block. */\nfunction listItemContext(\n doc: DocNode,\n path: number[]\n): { listItemPath: number[]; listPath: number[]; itemIndex: number } | null {\n let node: DocNode;\n try {\n node = getNodeAt(doc, path);\n } catch {\n return null;\n }\n if (node.type === 'listItem') {\n const itemIndex = path.at(-1) ?? 0;\n return { listItemPath: path, listPath: path.slice(0, -1), itemIndex };\n }\n if (path.length < 2) {\n return null;\n }\n const parentPath = path.slice(0, -1);\n try {\n const parent = getNodeAt(doc, parentPath);\n if (parent.type === 'listItem' && (path.at(-1) ?? 0) === 0) {\n const itemIndex = parentPath.at(-1) ?? 0;\n return { listItemPath: parentPath, listPath: parentPath.slice(0, -1), itemIndex };\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nexport const deleteBackward: Command = (state) => {\n const crossOrSame = deleteSelectionRangeOps(state.doc, state.selection);\n if (crossOrSame) {\n const range = selectionTextRange(state.selection);\n if (!range || range.from !== range.to) {\n return crossOrSame;\n }\n }\n\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n\n if (offset > 0) {\n return [{ type: 'delete_text', path, offset: offset - 1, length: 1 }];\n }\n\n const listCtx = listItemContext(state.doc, path);\n if (listCtx) {\n const { listItemPath, listPath, itemIndex } = listCtx;\n if (itemIndex > 0) {\n const prevItemPath = [...listPath, itemIndex - 1];\n const leftItem = getNodeAt(state.doc, prevItemPath);\n const rightItem = getNodeAt(state.doc, listItemPath);\n if (isLeafTextBlock(leftItem) && isLeafTextBlock(rightItem)) {\n return [{ type: 'merge_paragraph', path: listItemPath }];\n }\n // Nested listItem → block children: move right children into left, drop right, merge boundary leaves\n const ops: Operation[] = [];\n const leftCount = leftItem.content?.length ?? 0;\n const rightContent = rightItem.content ?? [];\n for (let i = 0; i < rightContent.length; i++) {\n const node = rightContent[i];\n if (node === undefined) {\n continue;\n }\n ops.push({\n type: 'insert_node',\n path: prevItemPath,\n index: leftCount + i,\n node,\n });\n }\n ops.push({ type: 'remove_node', path: listPath, index: itemIndex });\n const leftLast = leftCount > 0 ? leftItem.content?.[leftCount - 1] : undefined;\n const rightFirst = rightContent[0];\n if (\n leftLast !== undefined &&\n rightFirst !== undefined &&\n isLeafTextBlock(leftLast) &&\n isLeafTextBlock(rightFirst)\n ) {\n const joinAt = textLength(leftLast);\n ops.push(\n { type: 'merge_paragraph', path: [...prevItemPath, leftCount] },\n {\n type: 'set_selection',\n selection: collapsedAt([...prevItemPath, leftCount - 1], joinAt),\n }\n );\n } else {\n const selPath = resolveTextPath(state.doc, prevItemPath);\n ops.push({\n type: 'set_selection',\n selection: collapsedAt(selPath, textLength(getNodeAt(state.doc, selPath))),\n });\n }\n return ops;\n }\n // First list item at offset 0: lift into parent, optionally merge with prev sibling\n const parentPath = listPath.slice(0, -1);\n const { ops, selectionPath, liftedIndex } = liftIntoParent(state.doc, listPath, itemIndex);\n if (liftedIndex > 0) {\n try {\n const prev = getNodeAt(state.doc, [...parentPath, liftedIndex - 1]);\n if (isTextBlock(prev.type)) {\n const joinAt = textLength(prev);\n return [\n ...ops,\n { type: 'merge_paragraph', path: [...parentPath, liftedIndex] },\n {\n type: 'set_selection',\n selection: collapsedAt([...parentPath, liftedIndex - 1], joinAt),\n },\n ];\n }\n } catch {\n /* ignore */\n }\n }\n return [...ops, { type: 'set_selection', selection: collapsedAt(selectionPath, 0) }];\n }\n\n // Don't destroy table by merging out of first cell para\n if (path.length >= 4) {\n const cellPath = path.slice(0, 3);\n try {\n if (getNodeAt(state.doc, cellPath).type === 'tableCell' && (path.at(-1) ?? 0) === 0) {\n return null;\n }\n } catch {\n /* ignore */\n }\n }\n\n if (path.length === 1) {\n if (path[0] <= 0) {\n return null;\n }\n return [{ type: 'merge_paragraph', path }];\n }\n\n const index = path.at(-1);\n if (index === undefined || index <= 0) {\n return null;\n }\n return [{ type: 'merge_paragraph', path }];\n};\n\n/** Delete one character forward of the caret (range → delete selection, incl. cross-block). */\nexport const deleteForward: Command = (state) => {\n const crossOrSame = deleteSelectionRangeOps(state.doc, state.selection);\n if (crossOrSame) {\n const range = selectionTextRange(state.selection);\n if (!range || range.from !== range.to) {\n return crossOrSame;\n }\n }\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n let node: DocNode;\n try {\n node = getNodeAt(state.doc, path);\n } catch {\n return null;\n }\n if (offset < textLength(node)) {\n return [{ type: 'delete_text', path, offset, length: 1 }];\n }\n return null;\n};\n\nexport const splitBlock: Command = (state) => {\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n let node;\n try {\n node = getNodeAt(state.doc, path);\n } catch {\n return null;\n }\n\n if (\n isListType(node.type) ||\n node.type === 'table' ||\n node.type === 'tableRow' ||\n node.type === 'tableCell'\n ) {\n return null;\n }\n\n const parentPath = path.slice(0, -1);\n let parentIsList = false;\n if (path.length >= 2) {\n try {\n parentIsList = isListType(getNodeAt(state.doc, parentPath).type);\n } catch {\n parentIsList = false;\n }\n }\n\n // listItem, or text block nested under a list (e.g. after a bad split)\n const inList = node.type === 'listItem' || (parentIsList && isTextBlock(node.type));\n if (inList) {\n if (plainText(node).length === 0) {\n const listPath = parentIsList ? parentPath : path.slice(0, -1);\n const itemIndex = path.at(-1) ?? 0;\n const { ops, selectionPath } = exitListItemOps(state.doc, listPath, itemIndex);\n return [...ops, { type: 'set_selection', selection: collapsedAt(selectionPath, 0) }];\n }\n return [{ type: 'split_paragraph', path, offset }];\n }\n\n if (node.type === 'heading' && offset >= plainText(node).length) {\n const headingParentPath = path.slice(0, -1);\n const index = (path.at(-1) ?? 0) + 1;\n return [\n {\n type: 'insert_node',\n path: headingParentPath,\n index,\n node: createParagraph([createText('')]),\n },\n { type: 'set_selection', selection: collapsedAt([...headingParentPath, index], 0) },\n ];\n }\n\n if (isTextBlock(node.type)) {\n return [{ type: 'split_paragraph', path, offset }];\n }\n\n return null;\n};\n\nexport function toggleMark(markType: string): Command {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range || range.from === range.to) {\n return null;\n }\n const para = getNodeAt(state.doc, range.path);\n const fullyMarked = rangeHasMark(para, range.from, range.to, markType);\n if (fullyMarked) {\n return [\n {\n type: 'remove_mark',\n path: range.path,\n from: range.from,\n to: range.to,\n markType,\n },\n ];\n }\n return [\n {\n type: 'set_mark',\n path: range.path,\n from: range.from,\n to: range.to,\n mark: { type: markType },\n },\n ];\n };\n}\n\n/** Whether the current selection (or caret) carries `markType`. */\nexport function selectionHasMark(markType: string): (state: EditorState) => boolean {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range) {\n return false;\n }\n const para = getNodeAt(state.doc, range.path);\n if (range.from === range.to) {\n const probe = range.from > 0 ? range.from - 1 : range.from;\n return offsetHasMark(para, probe, markType);\n }\n return rangeHasMark(para, range.from, range.to, markType);\n };\n}\n\nexport const selectAll: Command = (state) => {\n const leaves: number[][] = [];\n collectTextLeaves(state.doc, [], leaves);\n if (leaves.length === 0) {\n return null;\n }\n const first = leaves[0];\n const last = leaves.at(-1);\n if (first === undefined || last === undefined) {\n return null;\n }\n const len = plainText(getNodeAt(state.doc, last)).length;\n return [\n {\n type: 'set_selection',\n selection: {\n anchor: { path: first, offset: 0 },\n focus: { path: last, offset: len },\n },\n },\n ];\n};\n\nexport function runCommand(state: EditorState, command: Command) {\n const ops = command(state);\n if (!ops) {\n return null;\n }\n return transaction(...ops);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/document.ts","../src/selection.ts","../src/schema.ts","../src/operations.ts","../src/transform.ts","../src/structure.ts","../src/normalize.ts","../src/transaction.ts","../src/history.ts","../src/commands.ts"],"sourcesContent":["import type { DocNode, JSONDoc, Mark } from './types';\n\nlet idCounter = 0;\n\nexport function resetIdCounter(n = 0): void {\n idCounter = n;\n}\n\nexport function nextId(prefix = 'n'): string {\n idCounter += 1;\n return `${prefix}${idCounter}`;\n}\n\nexport function createText(text: string, marks: Mark[] = []): DocNode {\n return marks.length > 0\n ? { marks: marks.map((m) => ({ ...m })), text, type: 'text' }\n : { text, type: 'text' };\n}\n\nexport function createParagraph(\n content: DocNode[] = [createText('')],\n attrs?: Record<string, unknown>\n): DocNode {\n const nextAttrs = copyAttrs(attrs);\n return {\n ...(nextAttrs ? { attrs: nextAttrs } : {}),\n content: [...content],\n id: nextId('p'),\n type: 'paragraph',\n };\n}\n\nexport function createDoc(content?: DocNode[]): DocNode {\n return {\n content: content !== undefined && content.length > 0 ? [...content] : [createParagraph()],\n id: nextId('doc'),\n type: 'doc',\n };\n}\n\nfunction isAttrsRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/** Null-prototype attrs bag (no __proto__ pollution). */\nexport function emptyAttrsRecord(): Record<string, unknown> {\n const raw: unknown = Object.create(null);\n if (!isAttrsRecord(raw)) {\n return {};\n }\n return raw;\n}\n\n/** Copy own enumerable attrs onto a null-prototype bag (no __proto__ pollution). */\nexport function copyAttrs(\n src?: Record<string, unknown> | null\n): Record<string, unknown> | undefined {\n if (!src) {\n return undefined;\n }\n const out = emptyAttrsRecord();\n for (const key of Object.keys(src)) {\n out[key] = src[key];\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/** Shallow clone node; children array is new, child refs shared (structural sharing). */\nexport function cloneNode(node: DocNode): DocNode {\n const out: DocNode = { type: node.type };\n if (node.id !== undefined) {\n out.id = node.id;\n }\n if (node.text !== undefined) {\n out.text = node.text;\n }\n const attrs = copyAttrs(node.attrs);\n if (attrs) {\n out.attrs = attrs;\n }\n if (node.content) {\n out.content = [...node.content];\n }\n if (node.marks) {\n out.marks = node.marks.map((m) => {\n const mark: Mark = { type: m.type };\n const markAttrs = copyAttrs(m.attrs);\n if (markAttrs) {\n mark.attrs = markAttrs;\n }\n return mark;\n });\n }\n return out;\n}\n\n/** Deep clone node tree (content recursively cloned). */\nexport function deepCloneNode(node: DocNode): DocNode {\n const cloned = cloneNode(node);\n if (cloned.content) {\n cloned.content = cloned.content.map(deepCloneNode);\n }\n return cloned;\n}\n\n/** Assign stable ids to every non-text node missing `id`. */\nexport function ensureNodeIds(node: DocNode): DocNode {\n const out: DocNode = { type: node.type };\n if (node.id !== undefined) {\n out.id = node.id;\n }\n if (node.text !== undefined) {\n out.text = node.text;\n }\n const attrs = copyAttrs(node.attrs);\n if (attrs) {\n out.attrs = attrs;\n }\n if (node.content) {\n out.content = node.content.map(ensureNodeIds);\n }\n if (node.marks) {\n out.marks = node.marks.map((m) => {\n const mark: Mark = { type: m.type };\n const markAttrs = copyAttrs(m.attrs);\n if (markAttrs) {\n mark.attrs = markAttrs;\n }\n return mark;\n });\n }\n if (out.type !== 'text' && !out.id) {\n const prefix =\n out.type === 'doc'\n ? 'doc'\n : out.type === 'paragraph'\n ? 'p'\n : out.type === 'listItem'\n ? 'li'\n : 'n';\n out.id = nextId(prefix);\n }\n return out;\n}\n\nfunction deepClone<T>(value: T): T {\n return structuredClone(value);\n}\n\n/** Document JSON format version — bump when the on-disk shape changes. */\nexport const JSON_DOC_VERSION = 1;\n\nexport function docToJSON(doc: DocNode): JSONDoc {\n return { doc: deepClone(doc), version: JSON_DOC_VERSION };\n}\n\nfunction isJSONDoc(value: object): value is JSONDoc {\n if (!('version' in value) || !('doc' in value)) {\n return false;\n }\n const doc = Reflect.get(value, 'doc');\n return typeof doc === 'object' && doc !== null;\n}\n\nfunction isDocNode(value: object): value is DocNode {\n return typeof Reflect.get(value, 'type') === 'string';\n}\n\nexport function docFromJSON(json: JSONDoc | DocNode | object): DocNode {\n if (isJSONDoc(json)) {\n if (json.version !== JSON_DOC_VERSION) {\n throw new Error(`Unsupported JSONDoc version: ${json.version}`);\n }\n if (json.doc.type !== 'doc') {\n throw new Error('Expected root type \"doc\"');\n }\n assertTreeDepth(json.doc);\n return ensureNodeIds(deepClone(json.doc));\n }\n if (isDocNode(json) && json.type === 'doc') {\n assertTreeDepth(json);\n return ensureNodeIds(deepClone(json));\n }\n throw new Error('Expected root type \"doc\"');\n}\n\nfunction assertTreeDepth(node: DocNode, max = 64): void {\n const stack: { n: DocNode; d: number }[] = [{ n: node, d: 0 }];\n while (stack.length > 0) {\n const { n, d } = stack.pop()!;\n if (d > max) {\n throw new Error(`Tree exceeds MAX_TREE_DEPTH (${max})`);\n }\n for (const child of n.content ?? []) {\n stack.push({ n: child, d: d + 1 });\n }\n }\n}\n\nexport function getNodeAt(doc: DocNode, path: number[]): DocNode {\n let cur = doc;\n for (const index of path) {\n if (!cur.content || index < 0 || index >= cur.content.length) {\n throw new Error(`Invalid path: ${path.join('.')}`);\n }\n cur = cur.content[index];\n }\n return cur;\n}\n\nexport function replaceAt(doc: DocNode, path: number[], next: DocNode): DocNode {\n if (path.length === 0) {\n return next;\n }\n const [head, ...rest] = path,\n cloned = cloneNode(doc);\n if (!cloned.content) {\n throw new Error('Cannot replace in leaf');\n }\n cloned.content[head] = replaceAt(cloned.content[head], rest, next);\n return cloned;\n}\n\nexport function textLength(node: DocNode): number {\n if (node.type === 'text') {\n return node.text?.length ?? 0;\n }\n if (!node.content) {\n return 0;\n }\n return node.content.reduce((sum, child) => sum + textLength(child), 0);\n}\n","import type { DocNode, Point, Selection } from './types';\nimport { getNodeAt, textLength } from './document';\n\nexport function createSelection(anchor: Point, focus: Point = anchor): Selection {\n return {\n anchor: { ...anchor, path: [...anchor.path] },\n focus: { ...focus, path: [...focus.path] },\n };\n}\n\nexport function collapsedAt(path: number[], offset: number): Selection {\n return createSelection({ offset, path: [...path] });\n}\n\nexport function isCollapsed(sel: Selection): boolean {\n return (\n sel.anchor.offset === sel.focus.offset &&\n sel.anchor.path.length === sel.focus.path.length &&\n sel.anchor.path.every((v, i) => v === sel.focus.path[i])\n );\n}\n\n/** Resolve a point inside a paragraph path to ensure offset is within text bounds. */\nexport function clampPoint(doc: DocNode, point: Point): Point {\n try {\n let path = [...point.path];\n let node = getNodeAt(doc, path);\n // Selection must address a text-bearing block, never a text leaf\n while (node.type === 'text' && path.length > 0) {\n path = path.slice(0, -1);\n node = path.length === 0 ? doc : getNodeAt(doc, path);\n }\n if (path.length === 0 || node.type === 'doc') {\n return { offset: 0, path: [0] };\n }\n const max = textLength(node);\n return { offset: Math.max(0, Math.min(point.offset, max)), path };\n } catch {\n // Path became invalid mid-transaction (structural edits) — fall back to doc start.\n return { offset: 0, path: [0] };\n }\n}\n\nexport function clampSelection(doc: DocNode, sel: Selection): Selection {\n return {\n anchor: clampPoint(doc, sel.anchor),\n focus: clampPoint(doc, sel.focus),\n };\n}\n\n/** Compare points: -1 if a < b, 0 equal, 1 if a > b (path then offset). */\nexport function comparePoints(a: Point, b: Point): number {\n const len = Math.max(a.path.length, b.path.length);\n for (let i = 0; i < len; i++) {\n const av = a.path[i] ?? -1,\n bv = b.path[i] ?? -1;\n if (av !== bv) {\n return av < bv ? -1 : 1;\n }\n }\n if (a.offset !== b.offset) {\n return a.offset < b.offset ? -1 : 1;\n }\n return 0;\n}\n\nexport function orderedRange(sel: Selection): { from: Point; to: Point } {\n return comparePoints(sel.anchor, sel.focus) <= 0\n ? { from: sel.anchor, to: sel.focus }\n : { from: sel.focus, to: sel.anchor };\n}\n","import type { Mark } from './types';\n\nexport interface NodeSpec {\n name: string;\n group?: 'block' | 'inline' | 'atom';\n atom?: boolean;\n attrs?: Record<string, unknown>;\n}\n\nexport interface MarkSpec {\n name: string;\n attrs?: Record<string, unknown>;\n}\n\nexport interface Schema {\n nodes: Map<string, NodeSpec>;\n marks: Map<string, MarkSpec>;\n sealed: boolean;\n}\n\nexport function createSchema(): Schema {\n const schema: Schema = {\n marks: new Map(),\n nodes: new Map(),\n sealed: false,\n };\n registerNode(schema, { group: 'block', name: 'doc' });\n registerNode(schema, { group: 'block', name: 'paragraph' });\n registerNode(schema, { group: 'inline', name: 'text' });\n registerNode(schema, { atom: true, group: 'inline', name: 'hardBreak' });\n registerMark(schema, { name: 'bold' });\n registerMark(schema, { name: 'italic' });\n registerMark(schema, { name: 'underline' });\n registerMark(schema, { name: 'strike' });\n return schema;\n}\n\nexport function registerNode(schema: Schema, spec: NodeSpec): void {\n if (schema.sealed) {\n throw new Error('Schema is sealed');\n }\n if (schema.nodes.has(spec.name)) {\n throw new Error(`Node already registered: ${spec.name}`);\n }\n schema.nodes.set(spec.name, spec);\n}\n\nexport function registerMark(schema: Schema, spec: MarkSpec): void {\n if (schema.sealed) {\n throw new Error('Schema is sealed');\n }\n if (schema.marks.has(spec.name)) {\n throw new Error(`Mark already registered: ${spec.name}`);\n }\n schema.marks.set(spec.name, spec);\n}\n\nexport function sealSchema(schema: Schema): void {\n schema.sealed = true;\n}\n\nexport function assertMark(schema: Schema, mark: Mark): void {\n if (!schema.marks.has(mark.type)) {\n throw new Error(`Unknown mark: ${mark.type}`);\n }\n}\n\nexport function assertNodeType(schema: Schema, type: string): void {\n if (!schema.nodes.has(type)) {\n throw new Error(`Unknown node type: ${type}`);\n }\n}\n","import type { DocNode, Mark, Selection } from './types';\nimport {\n cloneNode,\n copyAttrs,\n emptyAttrsRecord,\n createText,\n deepCloneNode,\n ensureNodeIds,\n getNodeAt,\n nextId,\n replaceAt,\n textLength,\n} from './document';\nimport { clampSelection, collapsedAt, orderedRange } from './selection';\nimport type { Schema } from './schema';\nimport { assertMark, assertNodeType } from './schema';\n\nexport { textLength };\n\nexport type TextRun = { text: string; marks: Mark[] };\n\n/** Inline keep (hardBreak etc.) relative to a slice start. */\nexport type SliceKeep = { at: number; node: DocNode };\n\nexport type Operation =\n | {\n type: 'insert_text';\n path: number[];\n offset: number;\n text: string;\n marks?: Mark[];\n marksByOffset?: Mark[][];\n }\n | { type: 'delete_text'; path: number[]; offset: number; length: number }\n | {\n type: 'split_paragraph';\n path: number[];\n offset: number;\n /** When set (merge inverse), restore this node as the right block. */\n rightNode?: DocNode;\n }\n | { type: 'merge_paragraph'; path: number[] }\n | { type: 'set_selection'; selection: Selection }\n | { type: 'set_mark'; path: number[]; from: number; to: number; mark: Mark }\n | { type: 'remove_mark'; path: number[]; from: number; to: number; markType: string }\n | {\n type: 'replace_slice';\n path: number[];\n from: number;\n to: number;\n runs: TextRun[];\n keeps?: SliceKeep[];\n }\n | { type: 'insert_node'; path: number[]; index: number; node: DocNode }\n | { type: 'remove_node'; path: number[]; index: number }\n | {\n type: 'set_attrs';\n path: number[];\n attrs: Record<string, unknown>;\n replace?: boolean;\n };\n\nexport type InvertibleOp = { op: Operation; inverse: Operation };\n\ntype FlatKeep = { at: number; node: DocNode };\ntype FlatRun = { start: number; end: number; node: DocNode };\n\nconst BLOCK_CHILD_TYPES = new Set([\n 'paragraph',\n 'heading',\n 'listItem',\n 'blockquote',\n 'codeBlock',\n 'bulletList',\n 'orderedList',\n 'table',\n 'tableRow',\n 'tableCell',\n]);\n\nfunction assertIntegerPath(path: number[]): void {\n for (const seg of path) {\n if (!Number.isInteger(seg)) {\n throw new TypeError(`Path segments must be integers: ${path.join('.')}`);\n }\n }\n}\n\nfunction assertLeafTextBlock(node: DocNode): void {\n if (node.type === 'text') {\n throw new Error('Text ops require a leaf text block');\n }\n if ((node.content ?? []).some((c) => BLOCK_CHILD_TYPES.has(c.type))) {\n throw new Error('Text ops require a leaf text block');\n }\n}\n\nfunction flattenText(paragraph: DocNode): {\n text: string;\n runs: FlatRun[];\n keeps: FlatKeep[];\n} {\n const runs: FlatRun[] = [];\n const keeps: FlatKeep[] = [];\n let text = '';\n for (const child of paragraph.content ?? []) {\n if (child.type === 'text') {\n const start = text.length;\n const chunk = child.text ?? '';\n text += chunk;\n runs.push({ start, end: text.length, node: child });\n } else {\n keeps.push({ at: text.length, node: deepCloneNode(child) });\n }\n }\n return { text, runs, keeps };\n}\n\nfunction rebuildParagraph(\n paragraph: DocNode,\n text: string,\n markAt: (i: number) => Mark[],\n keeps: FlatKeep[] = []\n): DocNode {\n const keepsSorted = [...keeps].toSorted((a, b) => a.at - b.at);\n if (text.length === 0) {\n if (keepsSorted.length === 0) {\n return { ...cloneNode(paragraph), content: [createText('')] };\n }\n return {\n ...cloneNode(paragraph),\n content: keepsSorted.map((k) => deepCloneNode(k.node)),\n };\n }\n\n const content: DocNode[] = [];\n let keepIdx = 0;\n let i = 0;\n\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at <= 0) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n\n while (i < text.length) {\n const marks = markAt(i);\n let j = i + 1;\n const nextKeepAt = keepsSorted[keepIdx]?.at ?? text.length + 1;\n while (j < text.length && j < nextKeepAt && sameMarks(markAt(j), marks)) {\n j++;\n }\n const end = Math.min(j, nextKeepAt, text.length);\n if (end > i) {\n content.push(createText(text.slice(i, end), marks));\n i = end;\n }\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at === i) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n }\n\n while (keepIdx < keepsSorted.length && keepsSorted[keepIdx].at >= text.length) {\n content.push(deepCloneNode(keepsSorted[keepIdx].node));\n keepIdx++;\n }\n\n if (content.length === 0) {\n content.push(createText(''));\n }\n return { ...cloneNode(paragraph), content };\n}\n\nfunction shiftKeeps(keeps: FlatKeep[], offset: number, delta: number): FlatKeep[] {\n return keeps.map((k) => (k.at >= offset ? { ...k, at: k.at + delta } : k));\n}\n\nfunction deleteKeepsInRange(keeps: FlatKeep[], offset: number, length: number): FlatKeep[] {\n const end = offset + length;\n return keeps\n .filter((k) => k.at <= offset || k.at >= end)\n .map((k) => (k.at >= end ? { ...k, at: k.at - length } : k));\n}\n\nfunction captureKeepsInRange(keeps: FlatKeep[], from: number, to: number): SliceKeep[] {\n return keeps\n .filter((k) => k.at > from && k.at < to)\n .map((k) => ({ at: k.at - from, node: deepCloneNode(k.node) }));\n}\n\nfunction mergeSliceKeeps(\n base: FlatKeep[],\n from: number,\n sliceKeeps: SliceKeep[] | undefined\n): FlatKeep[] {\n if (sliceKeeps === undefined || sliceKeeps.length === 0) {\n return base;\n }\n return [...base, ...sliceKeeps.map((k) => ({ at: from + k.at, node: deepCloneNode(k.node) }))];\n}\n\nfunction assertOpSchema(schema: Schema | undefined, op: Operation): void {\n if (!schema) {\n return;\n }\n if (op.type === 'set_mark') {\n assertMark(schema, op.mark);\n } else if (op.type === 'insert_text') {\n if (op.marks) {\n for (const m of op.marks) {\n assertMark(schema, m);\n }\n }\n if (op.marksByOffset) {\n for (const ms of op.marksByOffset) {\n for (const m of ms) {\n assertMark(schema, m);\n }\n }\n }\n } else if (op.type === 'replace_slice') {\n for (const run of op.runs) {\n for (const m of run.marks) {\n assertMark(schema, m);\n }\n }\n for (const k of op.keeps ?? []) {\n assertMaxTreeDepth(k.node);\n assertNodeTree(schema, k.node);\n }\n } else if (op.type === 'split_paragraph') {\n if (op.rightNode) {\n assertMaxTreeDepth(op.rightNode);\n assertNodeTree(schema, op.rightNode);\n }\n } else if (op.type === 'insert_node') {\n assertNodeTree(schema, op.node);\n }\n}\n\nfunction assertNodeTree(schema: Schema, node: DocNode, depthChecked = false): void {\n if (!depthChecked) {\n assertMaxTreeDepth(node);\n }\n assertNodeType(schema, node.type);\n if (node.marks) {\n for (const m of node.marks) {\n assertMark(schema, m);\n }\n }\n for (const child of node.content ?? []) {\n assertNodeTree(schema, child, true);\n }\n}\n\nfunction sameMarks(a: Mark[], b: Mark[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n return a.every(\n (m, i) =>\n m.type === b[i].type && JSON.stringify(m.attrs ?? {}) === JSON.stringify(b[i].attrs ?? {})\n );\n}\n\nfunction cloneMarks(marks: Mark[]): Mark[] {\n return marks.map((m) => ({ ...m, attrs: m.attrs ? { ...m.attrs } : undefined }));\n}\n\nfunction marksAt(runs: FlatRun[], index: number): Mark[] {\n for (const run of runs) {\n if (index >= run.start && index < run.end) {\n return run.node.marks ? cloneMarks(run.node.marks) : [];\n }\n }\n // caret at end — inherit last run marks\n const lastRun = runs.at(-1);\n if (lastRun && index === lastRun.end) {\n return lastRun.node.marks ? cloneMarks(lastRun.node.marks) : [];\n }\n return [];\n}\n\nfunction captureRuns(text: string, runs: FlatRun[], from: number, to: number): TextRun[] {\n const result: TextRun[] = [];\n let i = from;\n while (i < to) {\n const marks = marksAt(runs, i);\n let j = i + 1;\n while (j < to && sameMarks(marksAt(runs, j), marks)) {\n j++;\n }\n result.push({ text: text.slice(i, j), marks });\n i = j;\n }\n return result;\n}\n\n/** True when every offset in `[from, to)` carries `markType`. Empty range → false. */\nexport function rangeHasMark(\n paragraph: DocNode,\n from: number,\n to: number,\n markType: string\n): boolean {\n const { text, runs } = flattenText(paragraph);\n const start = Math.max(0, Math.min(from, text.length));\n const end = Math.max(start, Math.min(to, text.length));\n if (start >= end) {\n return false;\n }\n for (let i = start; i < end; i++) {\n if (!marksAt(runs, i).some((m) => m.type === markType)) {\n return false;\n }\n }\n return true;\n}\n\n/** Mark presence at a single offset (caret / left of caret). */\nexport function offsetHasMark(paragraph: DocNode, offset: number, markType: string): boolean {\n const { text, runs } = flattenText(paragraph);\n if (text.length === 0) {\n return false;\n }\n const i = Math.max(0, Math.min(offset, text.length - 1));\n return marksAt(runs, i).some((m) => m.type === markType);\n}\n\n/** Merge marks by type — `extra` wins on conflict. */\nexport function mergeMarksByType(base: Mark[], extra: Mark[]): Mark[] {\n const map = new Map<string, Mark>();\n for (const m of base) {\n map.set(m.type, { ...m, attrs: m.attrs ? { ...m.attrs } : undefined });\n }\n for (const m of extra) {\n map.set(m.type, { ...m, attrs: m.attrs ? { ...m.attrs } : undefined });\n }\n return [...map.values()];\n}\n\n/** Hard cap on a single insert_text / replace_slice payload (paste / programmatic flood). */\nexport const MAX_INSERT_CHARS = 100_000;\n/** Cap on keep nodes injected via replace_slice (hardBreak floods). */\nexport const MAX_SLICE_KEEPS = 10_000;\n/** Max nesting depth for op/JSON trees (empty structural bombs). */\nexport const MAX_TREE_DEPTH = 64;\n\n/** Iterative depth check — fail closed before recursive clone/walk. */\nexport function assertMaxTreeDepth(node: DocNode, max = MAX_TREE_DEPTH): void {\n const stack: { n: DocNode; d: number }[] = [{ n: node, d: 0 }];\n while (stack.length > 0) {\n const { n, d } = stack.pop()!;\n if (d > max) {\n throw new Error(`Tree exceeds MAX_TREE_DEPTH (${max})`);\n }\n for (const child of n.content ?? []) {\n stack.push({ n: child, d: d + 1 });\n }\n }\n}\n\nexport function applyOp(\n doc: DocNode,\n op: Operation,\n schema?: Schema\n): { doc: DocNode; inverse: Operation } {\n if ('path' in op) {\n assertIntegerPath(op.path);\n }\n assertOpSchema(schema, op);\n\n switch (op.type) {\n case 'insert_text': {\n if (op.text.length > MAX_INSERT_CHARS) {\n throw new Error(`insert_text exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const nextText = text.slice(0, offset) + op.text + text.slice(offset);\n const nextKeeps = shiftKeeps(keeps, offset, op.text.length);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n if (i >= offset && i < offset + op.text.length) {\n if (op.marksByOffset) {\n return cloneMarks(op.marksByOffset[i - offset] ?? []);\n }\n const inherited = marksAt(runs, Math.max(0, offset - 1));\n return op.marks && op.marks.length > 0\n ? mergeMarksByType(inherited, op.marks)\n : inherited;\n }\n const src = i < offset ? i : i - op.text.length;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: { type: 'delete_text', path: op.path, offset, length: op.text.length },\n };\n }\n case 'delete_text': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const length = Math.min(op.length, text.length - offset);\n const deletedKeeps = captureKeepsInRange(keeps, offset, offset + length);\n const captured = captureRuns(text, runs, offset, offset + length);\n const nextText = text.slice(0, offset) + text.slice(offset + length);\n const nextKeeps = deleteKeepsInRange(keeps, offset, length);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n const src = i < offset ? i : i + length;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from: offset,\n to: offset,\n runs: captured,\n keeps: deletedKeeps,\n },\n };\n }\n case 'split_paragraph': {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined) {\n throw new Error('split_paragraph path is empty');\n }\n assertIntegerPath(parentPath);\n const parent = parentPath.length > 0 ? getNodeAt(doc, parentPath) : doc;\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const offset = Math.max(0, Math.min(op.offset, text.length));\n const leftKeeps = keeps.filter((k) => k.at < offset);\n const left = rebuildParagraph(\n para,\n text.slice(0, offset),\n (i) => marksAt(runs, i),\n leftKeeps\n );\n let rightRebuilt: DocNode;\n if (op.rightNode) {\n rightRebuilt = deepCloneNode(op.rightNode);\n } else {\n const rightKeeps = keeps\n .filter((k) => k.at >= offset)\n .map((k) => ({ ...k, at: k.at - offset }));\n const rightSeed = {\n ...cloneNode(para),\n content: [createText('')],\n id: nextId(para.type === 'listItem' ? 'li' : 'p'),\n };\n rightRebuilt = rebuildParagraph(\n rightSeed,\n text.slice(offset),\n (i) => marksAt(runs, offset + i),\n rightKeeps\n );\n }\n const nextParent = cloneNode(parent);\n if (!nextParent.content) {\n throw new Error('split parent has no content');\n }\n nextParent.content.splice(index, 1, left, rightRebuilt);\n const nextDoc = parentPath.length > 0 ? replaceAt(doc, parentPath, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'merge_paragraph', path: [...parentPath, index + 1] },\n };\n }\n case 'merge_paragraph': {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined || index <= 0) {\n throw new Error('Cannot merge first paragraph');\n }\n assertIntegerPath(parentPath);\n const parent = parentPath.length > 0 ? getNodeAt(doc, parentPath) : doc;\n const left = getNodeAt(doc, [...parentPath, index - 1]);\n const right = getNodeAt(doc, op.path);\n assertLeafTextBlock(left);\n assertLeafTextBlock(right);\n const rightSnap = deepCloneNode(right);\n const leftFlat = flattenText(left);\n const rightFlat = flattenText(right);\n const mergedText = leftFlat.text + rightFlat.text;\n const joinAt = leftFlat.text.length;\n const mergedKeeps = [\n ...leftFlat.keeps,\n ...rightFlat.keeps.map((k) => ({ ...k, at: k.at + joinAt })),\n ];\n const merged = rebuildParagraph(\n left,\n mergedText,\n (i) => {\n if (i < joinAt) {\n return marksAt(leftFlat.runs, i);\n }\n return marksAt(rightFlat.runs, i - joinAt);\n },\n mergedKeeps\n );\n const nextParent = cloneNode(parent);\n if (!nextParent.content) {\n throw new Error('merge parent has no content');\n }\n nextParent.content.splice(index - 1, 2, merged);\n const nextDoc = parentPath.length > 0 ? replaceAt(doc, parentPath, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: {\n type: 'split_paragraph',\n path: [...parentPath, index - 1],\n offset: joinAt,\n rightNode: rightSnap,\n },\n };\n }\n case 'set_selection': {\n return { doc, inverse: op };\n }\n case 'set_attrs': {\n const node = getNodeAt(doc, op.path);\n const prevSnapshot = copyAttrs(node.attrs) ?? emptyAttrsRecord();\n let nextAttrs: Record<string, unknown>;\n if (op.replace) {\n nextAttrs = copyAttrs(op.attrs) ?? emptyAttrsRecord();\n } else {\n nextAttrs = copyAttrs(node.attrs) ?? emptyAttrsRecord();\n for (const [key, value] of Object.entries(op.attrs)) {\n if (value === null) {\n delete nextAttrs[key];\n } else {\n nextAttrs[key] = value;\n }\n }\n }\n const next = {\n ...cloneNode(node),\n attrs: Object.keys(nextAttrs).length > 0 ? nextAttrs : undefined,\n };\n return {\n doc: replaceAt(doc, op.path, next),\n inverse: { type: 'set_attrs', path: op.path, attrs: prevSnapshot, replace: true },\n };\n }\n case 'set_mark': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const nextPara = rebuildParagraph(\n para,\n text,\n (i) => {\n const base = marksAt(runs, i);\n if (i >= from && i < to) {\n const filtered = base.filter((m) => m.type !== op.mark.type);\n return [...filtered, { ...op.mark, attrs: copyAttrs(op.mark.attrs) }];\n }\n return base;\n },\n keeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'remove_mark': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const nextPara = rebuildParagraph(\n para,\n text,\n (i) => {\n const base = marksAt(runs, i);\n if (i >= from && i < to) {\n return base.filter((m) => m.type !== op.markType);\n }\n return base;\n },\n keeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'replace_slice': {\n const para = getNodeAt(doc, op.path);\n assertLeafTextBlock(para);\n const { text, runs, keeps } = flattenText(para);\n const from = Math.max(0, Math.min(op.from, text.length));\n const to = Math.max(from, Math.min(op.to, text.length));\n const captured = captureRuns(text, runs, from, to);\n const lostKeeps = captureKeepsInRange(keeps, from, to);\n const newText = op.runs.map((r) => r.text).join('');\n if (newText.length > MAX_INSERT_CHARS) {\n throw new Error(`replace_slice exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n if ((op.keeps?.length ?? 0) > MAX_SLICE_KEEPS) {\n throw new Error(`replace_slice exceeds MAX_SLICE_KEEPS (${MAX_SLICE_KEEPS})`);\n }\n const insertedMarks: Mark[][] = [];\n for (const run of op.runs) {\n const marks = cloneMarks(run.marks);\n for (const _ of run.text) {\n insertedMarks.push(cloneMarks(marks));\n }\n }\n const nextText = text.slice(0, from) + newText + text.slice(to);\n const delta = newText.length - (to - from);\n const shifted = keeps\n .filter((k) => k.at <= from || k.at >= to)\n .map((k) => (k.at >= to ? { ...k, at: k.at + delta } : k));\n const nextKeeps = mergeSliceKeeps(shifted, from, op.keeps);\n const nextPara = rebuildParagraph(\n para,\n nextText,\n (i) => {\n if (i >= from && i < from + newText.length) {\n return insertedMarks[i - from] ?? [];\n }\n const src = i < from ? i : i - delta;\n return marksAt(runs, src);\n },\n nextKeeps\n );\n return {\n doc: replaceAt(doc, op.path, nextPara),\n inverse: {\n type: 'replace_slice',\n path: op.path,\n from,\n to: from + newText.length,\n runs: captured,\n keeps: lostKeeps,\n },\n };\n }\n case 'insert_node': {\n assertMaxTreeDepth(op.node);\n if (textLength(op.node) > MAX_INSERT_CHARS) {\n throw new Error(`insert_node exceeds MAX_INSERT_CHARS (${MAX_INSERT_CHARS})`);\n }\n const parent = op.path.length > 0 ? getNodeAt(doc, op.path) : doc;\n const nextParent = cloneNode(parent);\n nextParent.content ??= [];\n const index = Math.max(0, Math.min(op.index, nextParent.content.length));\n nextParent.content.splice(index, 0, ensureNodeIds(deepCloneNode(op.node)));\n const nextDoc = op.path.length > 0 ? replaceAt(doc, op.path, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'remove_node', path: op.path, index },\n };\n }\n case 'remove_node': {\n const parent = op.path.length > 0 ? getNodeAt(doc, op.path) : doc;\n const nextParent = cloneNode(parent);\n if (!nextParent.content || op.index < 0 || op.index >= nextParent.content.length) {\n throw new Error('remove_node out of bounds');\n }\n const [removed] = nextParent.content.splice(op.index, 1);\n const nextDoc = op.path.length > 0 ? replaceAt(doc, op.path, nextParent) : nextParent;\n return {\n doc: nextDoc,\n inverse: { type: 'insert_node', path: op.path, index: op.index, node: removed },\n };\n }\n default: {\n const _exhaustive: never = op;\n throw new Error(`Unknown op: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\nexport function applyOps(\n doc: DocNode,\n ops: Operation[],\n selection: Selection,\n schema?: Schema\n): { doc: DocNode; selection: Selection; inverses: Operation[] } {\n let current = doc;\n let sel = selection;\n const inverses: Operation[] = [];\n for (const op of ops) {\n if (op.type === 'set_selection') {\n inverses.push({ type: 'set_selection', selection: sel });\n sel = clampSelection(current, op.selection);\n continue;\n }\n const result = applyOp(current, op, schema);\n current = result.doc;\n inverses.push(result.inverse);\n if (op.type === 'insert_text') {\n sel = collapsedAt(op.path, op.offset + op.text.length);\n } else if (op.type === 'delete_text') {\n sel = collapsedAt(op.path, op.offset);\n } else if (op.type === 'split_paragraph') {\n const parentPath = op.path.slice(0, -1);\n const index = op.path.at(-1);\n if (index === undefined) {\n throw new Error('split_paragraph path is empty');\n }\n sel = collapsedAt([...parentPath, index + 1], 0);\n } else if (op.type === 'merge_paragraph') {\n const inv = result.inverse;\n if (inv.type === 'split_paragraph') {\n sel = collapsedAt(inv.path, inv.offset);\n }\n } else if (op.type === 'insert_node') {\n const index = result.inverse.type === 'remove_node' ? result.inverse.index : op.index;\n sel = {\n anchor: {\n offset: sel.anchor.offset,\n path: remapPathSibling(sel.anchor.path, op.path, index, 1),\n },\n focus: {\n offset: sel.focus.offset,\n path: remapPathSibling(sel.focus.path, op.path, index, 1),\n },\n };\n sel = clampSelection(current, sel);\n } else if (op.type === 'remove_node') {\n sel = {\n anchor: {\n offset: sel.anchor.offset,\n path: remapPathSibling(sel.anchor.path, op.path, op.index, -1),\n },\n focus: {\n offset: sel.focus.offset,\n path: remapPathSibling(sel.focus.path, op.path, op.index, -1),\n },\n };\n sel = clampSelection(current, sel);\n } else {\n sel = clampSelection(current, sel);\n }\n }\n return { doc: current, selection: clampSelection(current, sel), inverses: inverses.toReversed() };\n}\n\nfunction remapPathSibling(\n path: number[],\n parent: number[],\n index: number,\n delta: 1 | -1\n): number[] {\n const d = parent.length;\n if (path.length <= d) {\n return path;\n }\n for (let i = 0; i < d; i++) {\n if (path[i] !== parent[i]) {\n return path;\n }\n }\n const at = path[d];\n if (at === undefined) {\n return path;\n }\n if (delta < 0 && at === index) {\n return path;\n }\n if ((delta > 0 && at >= index) || (delta < 0 && at > index)) {\n const next = [...path];\n next[d] = at + delta;\n return next;\n }\n return path;\n}\n\nexport function selectionTextRange(\n sel: Selection\n): { path: number[]; from: number; to: number } | null {\n const { from, to } = orderedRange(sel);\n if (from.path.join('.') !== to.path.join('.')) {\n return null;\n }\n return { path: from.path, from: from.offset, to: to.offset };\n}\n\nexport function ensureParagraphPath(doc: DocNode, path: number[]): number[] {\n if (path.length > 0) {\n return path;\n }\n // default first paragraph\n if (doc.content?.[0]) {\n return [0];\n }\n return [0];\n}\n","import type { Operation } from './operations';\n\nfunction pathsEqual(a: number[], b: number[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\nfunction pathPrefix(longer: number[], shorter: number[]): boolean {\n if (longer.length < shorter.length) {\n return false;\n }\n for (let i = 0; i < shorter.length; i++) {\n if (longer[i] !== shorter[i]) {\n return false;\n }\n }\n return true;\n}\n\n/** Shift path index at `depth` by `delta` when the path is at/after `index`. */\nfunction shiftPath(path: number[], parentPath: number[], index: number, delta: number): number[] {\n if (!pathPrefix(path, parentPath) || path.length <= parentPath.length) {\n return path;\n }\n const at = parentPath.length;\n const cur = path[at];\n if (cur === undefined || cur < index) {\n return path;\n }\n const next = path.slice();\n next[at] = cur + delta;\n return next;\n}\n\nfunction mapPath(op: Operation, map: (path: number[]) => number[]): Operation {\n switch (op.type) {\n case 'set_selection':\n return op;\n case 'insert_text':\n case 'delete_text':\n case 'split_paragraph':\n case 'merge_paragraph':\n case 'set_mark':\n case 'remove_mark':\n case 'replace_slice':\n case 'set_attrs':\n case 'insert_node':\n case 'remove_node':\n return { ...op, path: map(op.path) };\n default: {\n const _exhaustive: never = op;\n return _exhaustive;\n }\n }\n}\n\nfunction mapOffset(op: Operation, path: number[], map: (offset: number) => number): Operation {\n if (!('path' in op) || !pathsEqual(op.path, path)) {\n return op;\n }\n switch (op.type) {\n case 'insert_text':\n return { ...op, offset: map(op.offset) };\n case 'delete_text': {\n const start = map(op.offset);\n const end = map(op.offset + op.length);\n return { ...op, offset: start, length: Math.max(0, end - start) };\n }\n case 'split_paragraph':\n return { ...op, offset: map(op.offset) };\n case 'set_mark':\n case 'remove_mark':\n case 'replace_slice': {\n const from = map(op.from);\n const to = map(op.to);\n return { ...op, from, to: Math.max(from, to) };\n }\n case 'merge_paragraph':\n case 'insert_node':\n case 'remove_node':\n case 'set_attrs':\n return op;\n default: {\n const _exhaustive: never = op;\n return _exhaustive;\n }\n }\n}\n\n/**\n * Transform `op` so it can be applied after `against` was already applied\n * (ProseMirror-style: rebase client op against server op).\n * Returns null if `op` becomes a no-op.\n */\nexport function transformOp(op: Operation, against: Operation): Operation | null {\n if (op.type === 'set_selection' || against.type === 'set_selection') {\n return op.type === 'set_selection' ? null : op;\n }\n\n // Node insert/remove shifts sibling paths\n if (against.type === 'insert_node') {\n let next = mapPath(op, (p) => shiftPath(p, against.path, against.index, 1));\n if (\n (next.type === 'insert_node' || next.type === 'remove_node') &&\n pathsEqual(next.path, against.path) &&\n next.index >= against.index\n ) {\n next = { ...next, index: next.index + 1 };\n }\n return next;\n }\n if (against.type === 'remove_node') {\n if (\n (op.type === 'insert_node' || op.type === 'remove_node') &&\n pathsEqual(op.path, against.path)\n ) {\n if (op.index === against.index && op.type === 'remove_node') {\n return null;\n }\n if (op.index > against.index) {\n return { ...op, index: op.index - 1 };\n }\n }\n const removedPath = [...against.path, against.index];\n if (\n 'path' in op &&\n pathPrefix(op.path, removedPath) &&\n op.path.length >= removedPath.length &&\n pathsEqual(op.path.slice(0, removedPath.length), removedPath)\n ) {\n return null;\n }\n let next = mapPath(op, (p) => shiftPath(p, against.path, against.index + 1, -1));\n if (\n (next.type === 'insert_node' || next.type === 'remove_node') &&\n pathsEqual(next.path, against.path) &&\n next.index > against.index\n ) {\n next = { ...next, index: next.index - 1 };\n }\n return next;\n }\n\n // split: index after split point +1 for paths under parent\n if (against.type === 'split_paragraph') {\n const parentPath = against.path.slice(0, -1);\n const index = against.path.at(-1);\n if (index === undefined) {\n return op;\n }\n // Ops on the left half (same path, offset <= split): keep path, maybe clamp offset\n if ('path' in op && pathsEqual(op.path, against.path)) {\n if (op.type === 'insert_text') {\n if (op.offset <= against.offset) {\n return op;\n }\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n if (op.type === 'delete_text') {\n if (op.offset + op.length <= against.offset) {\n return op;\n }\n if (op.offset >= against.offset) {\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n // Spans split: keep left portion only\n return { ...op, length: against.offset - op.offset };\n }\n if (op.type === 'split_paragraph') {\n if (op.offset <= against.offset) {\n return op;\n }\n return {\n ...op,\n path: [...parentPath, index + 1],\n offset: op.offset - against.offset,\n };\n }\n }\n return mapPath(op, (p) => shiftPath(p, parentPath, index + 1, 1));\n }\n\n if (against.type === 'merge_paragraph') {\n const parentPath = against.path.slice(0, -1);\n const index = against.path.at(-1);\n if (index === undefined || index <= 0) {\n return op;\n }\n const leftPath = [...parentPath, index - 1];\n const rightPath = against.path;\n // Approximate: paths after right shift down; ops on right move to left with offset bump unknown → keep & shift indices\n if ('path' in op && pathsEqual(op.path, rightPath)) {\n // Without join length we cannot fix offsets perfectly; shift path to left and leave offsets\n return mapPath(op, () => leftPath);\n }\n return mapPath(op, (p) => shiftPath(p, parentPath, index, -1));\n }\n\n // Text insert/delete on same path\n if (against.type === 'insert_text' && 'path' in op && pathsEqual(op.path, against.path)) {\n return mapOffset(op, against.path, (o) => (o >= against.offset ? o + against.text.length : o));\n }\n if (against.type === 'delete_text' && 'path' in op && pathsEqual(op.path, against.path)) {\n const delStart = against.offset;\n const delEnd = against.offset + against.length;\n return mapOffset(op, against.path, (o) => {\n if (o >= delEnd) {\n return o - against.length;\n }\n if (o >= delStart) {\n return delStart;\n }\n return o;\n });\n }\n\n if (against.type === 'replace_slice' && 'path' in op && pathsEqual(op.path, against.path)) {\n const removed = against.to - against.from;\n const inserted = against.runs.reduce((n, r) => n + r.text.length, 0);\n const delta = inserted - removed;\n return mapOffset(op, against.path, (o) => {\n if (o >= against.to) {\n return o + delta;\n }\n if (o >= against.from) {\n return against.from + inserted;\n }\n return o;\n });\n }\n\n return op;\n}\n\n/** Transform a sequence of ops against a single already-applied op. */\nexport function transformOps(ops: Operation[], against: Operation): Operation[] {\n const out: Operation[] = [];\n for (const op of ops) {\n const next = transformOp(op, against);\n if (next) {\n out.push(next);\n }\n }\n return out;\n}\n\n/**\n * Rebase client ops that were based on `baseVersion` against server ops\n * that landed since (in order). Returns ops safe to apply on the new tip.\n */\nexport function rebaseOps(clientOps: Operation[], serverOps: Operation[]): Operation[] {\n let pending: Operation[] = clientOps.filter((o) => o.type !== 'set_selection');\n for (const serverOp of serverOps) {\n if (serverOp.type === 'set_selection') {\n continue;\n }\n pending = transformOps(pending, serverOp);\n }\n return pending;\n}\n","import type { DocNode } from './types';\nimport type { Operation } from './operations';\nimport { createParagraph, createText, deepCloneNode, getNodeAt, textLength } from './document';\n\nconst TEXT_BLOCKS = new Set(['paragraph', 'heading', 'listItem', 'blockquote', 'codeBlock']);\nconst LIST_TYPES = new Set(['bulletList', 'orderedList']);\n\nexport function isTextBlock(type: string): boolean {\n return TEXT_BLOCKS.has(type);\n}\n\nexport function isListType(type: string): boolean {\n return LIST_TYPES.has(type);\n}\n\n/** Flatten text of a text-bearing node (paragraph / heading / listItem). */\nexport function plainText(node: DocNode): string {\n if (node.type === 'text') {\n return node.text ?? '';\n }\n let out = '';\n for (const child of node.content ?? []) {\n if (child.type === 'text') {\n out += child.text ?? '';\n } else if (child.content) {\n out += plainText(child);\n }\n }\n return out;\n}\n\n/**\n * Resolve selection path to a text-bearing leaf.\n * Lists → first/only item; listItem → nested paragraph; table → first cell paragraph.\n */\nexport function resolveTextPath(doc: DocNode, path: number[]): number[] {\n if (path.length === 0) {\n return [0];\n }\n let cur = getNodeAt(doc, path);\n const resolved = [...path];\n\n if (isListType(cur.type)) {\n if ((cur.content?.length ?? 0) === 0) {\n return resolved;\n }\n resolved.push(0);\n cur = cur.content![0];\n }\n\n if (cur.type === 'table') {\n const row = cur.content?.[0];\n const cell = row?.content?.[0];\n if (row && cell) {\n resolved.push(0, 0);\n cur = cell;\n }\n }\n\n if (cur.type === 'tableRow') {\n const cell = cur.content?.[0];\n if (cell) {\n resolved.push(0);\n cur = cell;\n }\n }\n\n if (cur.type === 'tableCell') {\n const para = cur.content?.[0];\n if (para && isTextBlock(para.type)) {\n resolved.push(0);\n cur = para;\n } else if (!para) {\n // empty cell — still point at cell; caller may create para\n return resolved;\n }\n }\n\n // listItem with nested paragraph (or other text block) → descend to leaf\n if (cur.type === 'listItem') {\n const first = cur.content?.[0];\n if (first && first.type !== 'text' && isTextBlock(first.type) && first.type !== 'listItem') {\n resolved.push(0);\n cur = first;\n }\n }\n\n // blockquote / codeBlock → descend into first nested text block\n if (cur.type === 'blockquote' || cur.type === 'codeBlock') {\n const first = cur.content?.[0];\n if (first && isTextBlock(first.type)) {\n resolved.push(0);\n // re-enter via recurse on extended path\n return resolveTextPath(doc, resolved);\n }\n }\n\n return resolved;\n}\n\nexport function createListItem(content: DocNode[] = [createText('')]): DocNode {\n return { type: 'listItem', content: [...content] };\n}\n\nexport function createList(listType: 'bulletList' | 'orderedList', items: DocNode[]): DocNode {\n return {\n type: listType,\n id: `list_${Date.now()}`,\n content: items.length > 0 ? items : [createListItem()],\n };\n}\n\n/** Extract a paragraph to lift out of a list item. */\nfunction liftedParagraphFromItem(item: DocNode): DocNode {\n const content = item.content ?? [];\n const first = content[0];\n if (first !== undefined && first.type === 'paragraph') {\n return deepCloneNode(first);\n }\n if (\n first !== undefined &&\n isTextBlock(first.type) &&\n first.type !== 'listItem' &&\n !isListType(first.type)\n ) {\n return deepCloneNode(first);\n }\n // Flat listItem with inline content (text / hardBreak)\n return createParagraph(content.length > 0 ? content.map(deepCloneNode) : [createText('')]);\n}\n\n/**\n * Lift list item `itemIndex` out of the list at `listPath` into the list's parent.\n * Removes the list, reinserts before-list (if any), lifted paragraph, after-list (if any).\n */\nexport function liftIntoParent(\n doc: DocNode,\n listPath: number[],\n itemIndex: number\n): { ops: Operation[]; selectionPath: number[]; liftedIndex: number } {\n const list = getNodeAt(doc, listPath);\n const items = list.content ?? [];\n const listIndex = listPath.at(-1);\n if (listIndex === undefined) {\n throw new Error('liftIntoParent: empty list path');\n }\n const parentPath = listPath.slice(0, -1);\n const item = items[itemIndex];\n if (item === undefined) {\n throw new Error('liftIntoParent: item out of bounds');\n }\n\n const before = items.slice(0, itemIndex);\n const after = items.slice(itemIndex + 1);\n const para = liftedParagraphFromItem(item);\n const ops: Operation[] = [];\n\n ops.push({ type: 'remove_node', path: parentPath, index: listIndex });\n\n let insertAt = listIndex;\n if (before.length > 0) {\n ops.push({\n type: 'insert_node',\n path: parentPath,\n index: insertAt,\n node: { ...list, content: before, id: `list_${Date.now()}_a` },\n });\n insertAt += 1;\n }\n ops.push({ type: 'insert_node', path: parentPath, index: insertAt, node: para });\n const liftedIndex = insertAt;\n const selectionPath = [...parentPath, insertAt];\n insertAt += 1;\n if (after.length > 0) {\n ops.push({\n type: 'insert_node',\n path: parentPath,\n index: insertAt,\n node: { ...list, content: after, id: `list_${Date.now()}_b` },\n });\n }\n\n return { ops, selectionPath, liftedIndex };\n}\n\n/** Exit empty list item: lift to paragraph in the list's parent (any depth). */\nexport function exitListItemOps(\n doc: DocNode,\n listPath: number[],\n itemIndex: number\n): { ops: Operation[]; selectionPath: number[] } {\n const { ops, selectionPath } = liftIntoParent(doc, listPath, itemIndex);\n return { ops, selectionPath };\n}\n\nexport function textBlockLength(doc: DocNode, path: number[]): number {\n try {\n return textLength(getNodeAt(doc, path));\n } catch {\n return 0;\n }\n}\n","import type { DocNode } from './types';\nimport { cloneNode, createText, nextId } from './document';\nimport { isListType, isTextBlock } from './structure';\n\n/** Idempotent normalize: ensure doc has content, text blocks have text leaves, coalesce adjacent same-mark texts. */\nexport function normalize(doc: DocNode): DocNode {\n if (doc.type !== 'doc') {\n throw new Error('normalize expects doc');\n }\n const next = cloneNode(doc);\n if (!next.content || next.content.length === 0) {\n next.content = [{ content: [createText('')], id: 'p_empty', type: 'paragraph' }];\n return next;\n }\n next.content = next.content.map(normalizeBlock);\n if (next.content.length === 0) {\n next.content = [{ content: [createText('')], id: 'p_empty', type: 'paragraph' }];\n }\n return next;\n}\n\nfunction normalizeBlock(node: DocNode): DocNode {\n if (node.type === 'text') {\n return node;\n }\n const cloned = cloneNode(node);\n if (!cloned.content || cloned.content.length === 0) {\n if (isListType(node.type)) {\n return {\n type: 'paragraph',\n id: nextId('p'),\n content: [createText('')],\n };\n }\n if (isTextBlock(node.type)) {\n cloned.content = [createText('')];\n }\n return cloned;\n }\n if (isTextBlock(node.type)) {\n cloned.content = coalesceText(cloned.content.map(normalizeBlock));\n if (cloned.content.length === 0) {\n cloned.content = [createText('')];\n }\n } else {\n cloned.content = cloned.content.map(normalizeBlock);\n if (isListType(node.type)) {\n cloned.content = cloned.content.filter((c) => {\n if (c.type !== 'listItem') {\n return true;\n }\n return (c.content?.length ?? 0) > 0;\n });\n if (cloned.content.length === 0) {\n return {\n type: 'paragraph',\n id: nextId('p'),\n content: [createText('')],\n };\n }\n }\n }\n return cloned;\n}\n\nfunction coalesceText(nodes: DocNode[]): DocNode[] {\n const out: DocNode[] = [];\n for (const n of nodes) {\n if (n.type !== 'text') {\n out.push(n);\n continue;\n }\n const prev = out.at(-1);\n if (\n prev?.type === 'text' &&\n JSON.stringify(prev.marks ?? []) === JSON.stringify(n.marks ?? [])\n ) {\n out[out.length - 1] = {\n ...prev,\n text: (prev.text ?? '') + (n.text ?? ''),\n };\n } else {\n out.push(n);\n }\n }\n return out;\n}\n\nexport function isNormalizeIdempotent(doc: DocNode): boolean {\n const a = normalize(doc),\n b = normalize(a);\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","import type { DocNode, Selection } from './types';\nimport { createDoc } from './document';\nimport { clampSelection, collapsedAt } from './selection';\nimport { applyOps } from './operations';\nimport type { Operation } from './operations';\nimport { normalize } from './normalize';\nimport type { Schema } from './schema';\n\nexport interface EditorState {\n doc: DocNode;\n selection: Selection;\n}\n\nexport interface Transaction {\n ops: Operation[];\n meta?: Record<string, unknown>;\n}\n\nexport function createState(doc: DocNode = createDoc(), selection?: Selection): EditorState {\n const normalized = normalize(doc);\n const sel = selection ?? collapsedAt([0], 0);\n return {\n doc: normalized,\n selection: clampSelection(normalized, sel),\n };\n}\n\nexport function applyTransaction(\n state: EditorState,\n tr: Transaction,\n schema?: Schema\n): { state: EditorState; inverses: Operation[] } {\n const { doc, selection, inverses } = applyOps(state.doc, tr.ops, state.selection, schema);\n return {\n inverses,\n state: { doc: normalize(doc), selection },\n };\n}\n\nexport function transaction(...ops: Operation[]): Transaction {\n return { ops };\n}\n","import type { Operation } from './operations';\nimport { applyTransaction, createState, transaction } from './transaction';\nimport type { EditorState, Transaction } from './transaction';\nimport type { Schema } from './schema';\n\nexport interface HistoryOptions {\n maxDepth?: number;\n /** Merge window in ms for consecutive typing */\n mergeWindowMs?: number;\n /** Cap merged typing entry size (insert+delete char counts); stop merging when exceeded. */\n maxEntryChars?: number;\n /** When set, applyTransaction validates ops against this schema. */\n schema?: Schema;\n}\n\nexport interface HistoryController {\n apply: (state: EditorState, tr: Transaction, now?: number) => EditorState;\n undo: (state: EditorState) => EditorState;\n redo: (state: EditorState) => EditorState;\n canUndo: () => boolean;\n canRedo: () => boolean;\n depth: () => number;\n /** Drop stacks after out-of-band full-document replace (setJSON / replaceDocument). */\n clear: () => void;\n}\n\ninterface Entry {\n inverses: Operation[];\n redo: Operation[];\n /** Final selection after the transaction (caret metadata; not replayed as ops). */\n selection: EditorState['selection'];\n at: number;\n chars: number;\n}\n\nexport function createHistory(options: HistoryOptions = {}): HistoryController {\n const maxDepth = options.maxDepth ?? 100,\n mergeWindowMs = options.mergeWindowMs ?? 500,\n maxEntryChars = options.maxEntryChars ?? 10_000,\n schema = options.schema,\n undoStack: Entry[] = [],\n redoStack: Entry[] = [];\n\n function push(entry: Entry): void {\n const last = undoStack.at(-1);\n if (\n last &&\n entry.at - last.at <= mergeWindowMs &&\n isTyping(entry.redo) &&\n isTyping(last.redo) &&\n last.chars + entry.chars <= maxEntryChars\n ) {\n last.redo = [...last.redo, ...entry.redo];\n last.inverses = [...entry.inverses, ...last.inverses];\n last.selection = entry.selection;\n last.at = entry.at;\n last.chars += entry.chars;\n } else {\n undoStack.push(entry);\n }\n while (undoStack.length > maxDepth) {\n undoStack.shift();\n }\n redoStack.length = 0;\n }\n\n return {\n apply(state, tr, now = Date.now()) {\n const { state: next, inverses } = applyTransaction(state, tr, schema);\n if (tr.ops.some((op) => op.type !== 'set_selection')) {\n const redo = tr.ops.filter((o) => o.type !== 'set_selection');\n push({\n inverses,\n redo,\n selection: next.selection,\n at: now,\n chars: entryCharCount(redo),\n });\n }\n return next;\n },\n canRedo: () => redoStack.length > 0,\n canUndo: () => undoStack.length > 0,\n clear() {\n undoStack.length = 0;\n redoStack.length = 0;\n },\n depth: () => undoStack.length,\n redo(state) {\n const entry = redoStack.pop();\n if (!entry) {\n return state;\n }\n const { state: next, inverses } = applyTransaction(state, transaction(...entry.redo), schema);\n undoStack.push({\n inverses,\n redo: entry.redo,\n selection: entry.selection,\n at: Date.now(),\n chars: entry.chars,\n });\n return { ...next, selection: entry.selection };\n },\n undo(state) {\n const entry = undoStack.pop();\n if (!entry) {\n return state;\n }\n const { state: next } = applyTransaction(state, transaction(...entry.inverses), schema);\n redoStack.push(entry);\n return next;\n },\n };\n}\n\nfunction isTyping(ops: Operation[]): boolean {\n return ops.length > 0 && ops.every((o) => o.type === 'insert_text' || o.type === 'delete_text');\n}\n\nfunction entryCharCount(ops: Operation[]): number {\n let n = 0;\n for (const op of ops) {\n if (op.type === 'insert_text') {\n n += op.text.length;\n } else if (op.type === 'delete_text') {\n n += op.length;\n }\n }\n return n;\n}\n\nexport function emptyState(): EditorState {\n return createState();\n}\n","import type { EditorState } from './transaction';\nimport { transaction } from './transaction';\nimport type { Operation } from './operations';\nimport { offsetHasMark, rangeHasMark, selectionTextRange } from './operations';\nimport { createParagraph, createText, getNodeAt, textLength } from './document';\nimport { collapsedAt, orderedRange } from './selection';\nimport type { DocNode, Mark, Point, Selection } from './types';\nimport {\n exitListItemOps,\n isListType,\n isTextBlock,\n liftIntoParent,\n plainText,\n resolveTextPath,\n} from './structure';\n\nexport type Command = (state: EditorState) => Operation[] | null;\n\nfunction textPath(state: EditorState): number[] {\n return resolveTextPath(state.doc, state.selection.anchor.path);\n}\n\nfunction samePath(a: number[], b: number[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\nfunction isLeafTextBlock(node: DocNode): boolean {\n return (\n isTextBlock(node.type) &&\n !(node.content ?? []).some(\n (c) =>\n c.type !== 'text' &&\n (isTextBlock(c.type) ||\n isListType(c.type) ||\n c.type === 'table' ||\n c.type === 'tableRow' ||\n c.type === 'tableCell')\n )\n );\n}\n\n/**\n * Ops to delete the current selection — same-path text or cross-block (siblings / root span).\n * Keeps selectAll → deleteBackward/insertText working.\n */\nexport function deleteSelectionRangeOps(doc: DocNode, sel: Selection): Operation[] | null {\n const { from, to } = orderedRange(sel);\n if (samePath(from.path, to.path)) {\n if (from.offset === to.offset) {\n return null;\n }\n const path = resolveTextPath(doc, from.path);\n return [\n {\n type: 'delete_text',\n path,\n offset: from.offset,\n length: to.offset - from.offset,\n },\n ];\n }\n\n // True siblings: same parent, same depth\n if (\n from.path.length === to.path.length &&\n from.path.length > 0 &&\n samePath(from.path.slice(0, -1), to.path.slice(0, -1))\n ) {\n return deleteSiblingSpan(doc, from, to);\n }\n\n return deleteRootSpan(doc, from, to);\n}\n\nfunction deleteSiblingSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const parent = from.path.slice(0, -1);\n const fromIdx = from.path.at(-1) ?? 0;\n const toIdx = to.path.at(-1) ?? 0;\n return deleteSpanUnderParent(doc, from, to, parent, fromIdx, toIdx);\n}\n\nfunction deleteSpanUnderParent(\n doc: DocNode,\n from: Point,\n to: Point,\n parent: number[],\n fromIdx: number,\n toIdx: number\n): Operation[] {\n const fromPath = resolveTextPath(doc, from.path);\n const toPath = resolveTextPath(doc, to.path);\n const ops: Operation[] = [];\n\n const fromLen = textLength(getNodeAt(doc, fromPath));\n if (from.offset < fromLen) {\n ops.push({\n type: 'delete_text',\n path: fromPath,\n offset: from.offset,\n length: fromLen - from.offset,\n });\n }\n\n const fromBlock = getNodeAt(doc, [...parent, fromIdx]);\n const toBlock = getNodeAt(doc, [...parent, toIdx]);\n const canMerge = isLeafTextBlock(fromBlock) && isLeafTextBlock(toBlock);\n\n if (canMerge && toIdx > fromIdx) {\n if (to.offset > 0) {\n const remappedTo = [...toPath];\n if (parent.length < remappedTo.length) {\n remappedTo[parent.length] = toIdx;\n }\n ops.push({ type: 'delete_text', path: remappedTo, offset: 0, length: to.offset });\n }\n for (let i = toIdx - 1; i > fromIdx; i--) {\n ops.push({ type: 'remove_node', path: parent, index: i });\n }\n ops.push({ type: 'merge_paragraph', path: [...parent, fromIdx + 1] });\n } else {\n // Non-leaf containers: leaf-walk so unselected end suffix is kept\n return deleteLeafSpan(doc, from, to);\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nfunction collectTextLeaves(node: DocNode, path: number[], out: number[][]): void {\n if (isLeafTextBlock(node)) {\n out.push([...path]);\n return;\n }\n (node.content ?? []).forEach((child, i) => {\n collectTextLeaves(child, [...path, i], out);\n });\n}\n\nfunction removableAncestor(doc: DocNode, leafPath: number[]): { parent: number[]; index: number } {\n if (leafPath.length >= 2) {\n const itemPath = leafPath.slice(0, -1);\n try {\n const item = getNodeAt(doc, itemPath);\n if (item.type === 'listItem' || item.type === 'tableCell') {\n return { parent: itemPath.slice(0, -1), index: itemPath.at(-1) ?? 0 };\n }\n } catch {\n /* fall through */\n }\n }\n return { parent: leafPath.slice(0, -1), index: leafPath.at(-1) ?? 0 };\n}\n\nfunction deleteLeafSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const fromPath = resolveTextPath(doc, from.path);\n const toPath = resolveTextPath(doc, to.path);\n let d = 0;\n while (d < fromPath.length && d < toPath.length && fromPath[d] === toPath[d]) {\n d++;\n }\n const rootPath = fromPath.slice(0, d);\n const rootNode = rootPath.length === 0 ? doc : getNodeAt(doc, rootPath);\n const leaves: number[][] = [];\n collectTextLeaves(rootNode, rootPath, leaves);\n const i0 = leaves.findIndex((p) => samePath(p, fromPath));\n const i1 = leaves.findIndex((p) => samePath(p, toPath));\n if (i0 === -1 || i1 === -1) {\n return [];\n }\n const start = Math.min(i0, i1);\n const end = Math.max(i0, i1);\n const ops: Operation[] = [];\n const first = leaves[start];\n if (first === undefined) {\n return [];\n }\n const firstLen = textLength(getNodeAt(doc, first));\n const firstFrom = samePath(first, fromPath) ? from.offset : 0;\n if (firstFrom < firstLen) {\n ops.push({\n type: 'delete_text',\n path: first,\n offset: firstFrom,\n length: firstLen - firstFrom,\n });\n }\n\n // Collect removable containers for fully covered start + middle + end (high → low)\n const removals: { parent: number[]; index: number; key: string }[] = [];\n const startFullyCovered = firstFrom === 0 && (end > start || to.offset >= firstLen);\n for (let i = end; i >= start; i--) {\n if (i === start && !startFullyCovered) {\n continue;\n }\n const leaf = leaves[i];\n if (leaf === undefined) {\n continue;\n }\n const fullyCovered =\n i === start ? startFullyCovered : i < end || to.offset >= textLength(getNodeAt(doc, leaf));\n if (!fullyCovered) {\n if (i === end && to.offset > 0) {\n ops.push({ type: 'delete_text', path: leaf, offset: 0, length: to.offset });\n }\n continue;\n }\n const rem = removableAncestor(doc, leaf);\n const key = `${rem.parent.join('.')}:${rem.index}`;\n if (!removals.some((r) => r.key === key)) {\n removals.push({ ...rem, key });\n }\n }\n removals.sort((a, b) => {\n if (a.parent.length !== b.parent.length) {\n return b.parent.length - a.parent.length;\n }\n for (let i = 0; i < a.parent.length; i++) {\n if (a.parent[i] !== b.parent[i]) {\n return (b.parent[i] ?? 0) - (a.parent[i] ?? 0);\n }\n }\n return b.index - a.index;\n });\n for (const rem of removals) {\n ops.push({ type: 'remove_node', path: rem.parent, index: rem.index });\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nfunction deleteRootSpan(doc: DocNode, from: Point, to: Point): Operation[] {\n const fromRoot = from.path[0] ?? 0;\n const toRoot = to.path[0] ?? 0;\n const fromPath = resolveTextPath(doc, from.path);\n const ops: Operation[] = [];\n\n if (fromRoot === toRoot) {\n let d = 0;\n while (d < from.path.length && d < to.path.length && from.path[d] === to.path[d]) {\n d++;\n }\n if (d < from.path.length && d < to.path.length && from.path.length === to.path.length) {\n return deleteSpanUnderParent(\n doc,\n from,\n to,\n from.path.slice(0, d),\n from.path[d] ?? 0,\n to.path[d] ?? 0\n );\n }\n return deleteLeafSpan(doc, from, to);\n }\n\n const fromLen = textLength(getNodeAt(doc, fromPath));\n if (from.offset < fromLen) {\n ops.push({\n type: 'delete_text',\n path: fromPath,\n offset: from.offset,\n length: fromLen - from.offset,\n });\n }\n\n const fromBlock = getNodeAt(doc, [fromRoot]);\n const toBlock = getNodeAt(doc, [toRoot]);\n const toPath = resolveTextPath(doc, to.path);\n const simple =\n from.path.length === 1 &&\n to.path.length === 1 &&\n isLeafTextBlock(fromBlock) &&\n isLeafTextBlock(toBlock);\n\n if (simple) {\n if (to.offset > 0) {\n ops.push({ type: 'delete_text', path: toPath, offset: 0, length: to.offset });\n }\n for (let i = toRoot - 1; i > fromRoot; i--) {\n ops.push({ type: 'remove_node', path: [], index: i });\n }\n ops.push({ type: 'merge_paragraph', path: [fromRoot + 1] });\n } else {\n // Mixed / nested roots: leaf-walk to preserve unselected end suffix\n return deleteLeafSpan(doc, from, to);\n }\n\n ops.push({ type: 'set_selection', selection: collapsedAt(fromPath, from.offset) });\n return ops;\n}\n\nexport function insertText(text: string, marks?: Mark[]): Command {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range) {\n const cross = deleteSelectionRangeOps(state.doc, state.selection);\n if (cross && !isCollapsedSelection(state.selection)) {\n const path = resolveTextPath(state.doc, orderedRange(state.selection).from.path);\n const offset = orderedRange(state.selection).from.offset;\n const ops: Operation[] = cross.filter((op) => op.type !== 'set_selection');\n ops.push(\n marks && marks.length > 0\n ? { type: 'insert_text', path, offset, text, marks }\n : { type: 'insert_text', path, offset, text },\n { type: 'set_selection', selection: collapsedAt(path, offset + text.length) }\n );\n return ops;\n }\n }\n const path = resolveTextPath(state.doc, range?.path ?? state.selection.anchor.path);\n const offset = range ? range.from : state.selection.anchor.offset;\n const ops: Operation[] = [];\n if (range && range.from !== range.to) {\n ops.push({\n type: 'delete_text',\n path,\n offset: range.from,\n length: range.to - range.from,\n });\n }\n ops.push(\n marks && marks.length > 0\n ? { type: 'insert_text', path, offset, text, marks }\n : { type: 'insert_text', path, offset, text }\n );\n return ops;\n };\n}\n\nfunction isCollapsedSelection(sel: Selection): boolean {\n return samePath(sel.anchor.path, sel.focus.path) && sel.anchor.offset === sel.focus.offset;\n}\n\n/**\n * Track-changes style backspace: mark the previous char as deleted instead of\n * removing it. Hard-deletes own `insertion` marks and already-marked deletions.\n */\nexport function softDeleteBackward(deletionMark: Mark): Command {\n return (state) => {\n if (!isCollapsedSelection(state.selection)) {\n return deleteBackward(state);\n }\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n if (offset <= 0) {\n return deleteBackward(state);\n }\n\n const para = getNodeAt(state.doc, path);\n const { text, runs } = flattenTextForMarks(para);\n if (text.length === 0) {\n return deleteBackward(state);\n }\n const from = offset - 1;\n const existing = marksAtOffset(runs, from);\n if (existing.some((m) => m.type === 'insertion' || m.type === deletionMark.type)) {\n return [{ type: 'delete_text', path, offset: from, length: 1 }];\n }\n return [\n { type: 'set_mark', path, from, to: offset, mark: deletionMark },\n { type: 'set_selection', selection: collapsedAt(path, from) },\n ];\n };\n}\n\nfunction flattenTextForMarks(paragraph: DocNode): {\n text: string;\n runs: { start: number; end: number; marks: Mark[] }[];\n} {\n let text = '';\n const runs: { start: number; end: number; marks: Mark[] }[] = [];\n for (const child of paragraph.content ?? []) {\n if (child.type !== 'text') {\n continue;\n }\n const start = text.length;\n const chunk = child.text ?? '';\n text += chunk;\n runs.push({\n start,\n end: text.length,\n marks: (child.marks ?? []).map((m) => ({ ...m })),\n });\n }\n return { text, runs };\n}\n\nfunction marksAtOffset(\n runs: { start: number; end: number; marks: Mark[] }[],\n index: number\n): Mark[] {\n for (const run of runs) {\n if (index >= run.start && index < run.end) {\n return run.marks.map((m) => ({ ...m }));\n }\n }\n return [];\n}\n\n/** Resolve list-item path when caret is on the item or its first nested text block. */\nfunction listItemContext(\n doc: DocNode,\n path: number[]\n): { listItemPath: number[]; listPath: number[]; itemIndex: number } | null {\n let node: DocNode;\n try {\n node = getNodeAt(doc, path);\n } catch {\n return null;\n }\n if (node.type === 'listItem') {\n const itemIndex = path.at(-1) ?? 0;\n return { listItemPath: path, listPath: path.slice(0, -1), itemIndex };\n }\n if (path.length < 2) {\n return null;\n }\n const parentPath = path.slice(0, -1);\n try {\n const parent = getNodeAt(doc, parentPath);\n if (parent.type === 'listItem' && (path.at(-1) ?? 0) === 0) {\n const itemIndex = parentPath.at(-1) ?? 0;\n return { listItemPath: parentPath, listPath: parentPath.slice(0, -1), itemIndex };\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nexport const deleteBackward: Command = (state) => {\n const crossOrSame = deleteSelectionRangeOps(state.doc, state.selection);\n if (crossOrSame) {\n const range = selectionTextRange(state.selection);\n if (!range || range.from !== range.to) {\n return crossOrSame;\n }\n }\n\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n\n if (offset > 0) {\n return [{ type: 'delete_text', path, offset: offset - 1, length: 1 }];\n }\n\n const listCtx = listItemContext(state.doc, path);\n if (listCtx) {\n const { listItemPath, listPath, itemIndex } = listCtx;\n if (itemIndex > 0) {\n const prevItemPath = [...listPath, itemIndex - 1];\n const leftItem = getNodeAt(state.doc, prevItemPath);\n const rightItem = getNodeAt(state.doc, listItemPath);\n if (isLeafTextBlock(leftItem) && isLeafTextBlock(rightItem)) {\n return [{ type: 'merge_paragraph', path: listItemPath }];\n }\n // Nested listItem → block children: move right children into left, drop right, merge boundary leaves\n const ops: Operation[] = [];\n const leftCount = leftItem.content?.length ?? 0;\n const rightContent = rightItem.content ?? [];\n for (let i = 0; i < rightContent.length; i++) {\n const node = rightContent[i];\n if (node === undefined) {\n continue;\n }\n ops.push({\n type: 'insert_node',\n path: prevItemPath,\n index: leftCount + i,\n node,\n });\n }\n ops.push({ type: 'remove_node', path: listPath, index: itemIndex });\n const leftLast = leftCount > 0 ? leftItem.content?.[leftCount - 1] : undefined;\n const rightFirst = rightContent[0];\n if (\n leftLast !== undefined &&\n rightFirst !== undefined &&\n isLeafTextBlock(leftLast) &&\n isLeafTextBlock(rightFirst)\n ) {\n const joinAt = textLength(leftLast);\n ops.push(\n { type: 'merge_paragraph', path: [...prevItemPath, leftCount] },\n {\n type: 'set_selection',\n selection: collapsedAt([...prevItemPath, leftCount - 1], joinAt),\n }\n );\n } else {\n const selPath = resolveTextPath(state.doc, prevItemPath);\n ops.push({\n type: 'set_selection',\n selection: collapsedAt(selPath, textLength(getNodeAt(state.doc, selPath))),\n });\n }\n return ops;\n }\n // First list item at offset 0: lift into parent, optionally merge with prev sibling\n const parentPath = listPath.slice(0, -1);\n const { ops, selectionPath, liftedIndex } = liftIntoParent(state.doc, listPath, itemIndex);\n if (liftedIndex > 0) {\n try {\n const prev = getNodeAt(state.doc, [...parentPath, liftedIndex - 1]);\n if (isTextBlock(prev.type)) {\n const joinAt = textLength(prev);\n return [\n ...ops,\n { type: 'merge_paragraph', path: [...parentPath, liftedIndex] },\n {\n type: 'set_selection',\n selection: collapsedAt([...parentPath, liftedIndex - 1], joinAt),\n },\n ];\n }\n } catch {\n /* ignore */\n }\n }\n return [...ops, { type: 'set_selection', selection: collapsedAt(selectionPath, 0) }];\n }\n\n // Don't destroy table by merging out of first cell para\n if (path.length >= 4) {\n const cellPath = path.slice(0, 3);\n try {\n if (getNodeAt(state.doc, cellPath).type === 'tableCell' && (path.at(-1) ?? 0) === 0) {\n return null;\n }\n } catch {\n /* ignore */\n }\n }\n\n if (path.length === 1) {\n if (path[0] <= 0) {\n return null;\n }\n return [{ type: 'merge_paragraph', path }];\n }\n\n const index = path.at(-1);\n if (index === undefined || index <= 0) {\n return null;\n }\n return [{ type: 'merge_paragraph', path }];\n};\n\n/** Delete one character forward of the caret (range → delete selection, incl. cross-block). */\nexport const deleteForward: Command = (state) => {\n const crossOrSame = deleteSelectionRangeOps(state.doc, state.selection);\n if (crossOrSame) {\n const range = selectionTextRange(state.selection);\n if (!range || range.from !== range.to) {\n return crossOrSame;\n }\n }\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n let node: DocNode;\n try {\n node = getNodeAt(state.doc, path);\n } catch {\n return null;\n }\n if (offset < textLength(node)) {\n return [{ type: 'delete_text', path, offset, length: 1 }];\n }\n return null;\n};\n\nexport const splitBlock: Command = (state) => {\n const path = textPath(state);\n const offset = state.selection.anchor.offset;\n let node;\n try {\n node = getNodeAt(state.doc, path);\n } catch {\n return null;\n }\n\n if (\n isListType(node.type) ||\n node.type === 'table' ||\n node.type === 'tableRow' ||\n node.type === 'tableCell'\n ) {\n return null;\n }\n\n const parentPath = path.slice(0, -1);\n let parentIsList = false;\n if (path.length >= 2) {\n try {\n parentIsList = isListType(getNodeAt(state.doc, parentPath).type);\n } catch {\n parentIsList = false;\n }\n }\n\n // listItem, or text block nested under a list (e.g. after a bad split)\n const inList = node.type === 'listItem' || (parentIsList && isTextBlock(node.type));\n if (inList) {\n if (plainText(node).length === 0) {\n const listPath = parentIsList ? parentPath : path.slice(0, -1);\n const itemIndex = path.at(-1) ?? 0;\n const { ops, selectionPath } = exitListItemOps(state.doc, listPath, itemIndex);\n return [...ops, { type: 'set_selection', selection: collapsedAt(selectionPath, 0) }];\n }\n return [{ type: 'split_paragraph', path, offset }];\n }\n\n if (node.type === 'heading' && offset >= plainText(node).length) {\n const headingParentPath = path.slice(0, -1);\n const index = (path.at(-1) ?? 0) + 1;\n return [\n {\n type: 'insert_node',\n path: headingParentPath,\n index,\n node: createParagraph([createText('')]),\n },\n { type: 'set_selection', selection: collapsedAt([...headingParentPath, index], 0) },\n ];\n }\n\n if (isTextBlock(node.type)) {\n return [{ type: 'split_paragraph', path, offset }];\n }\n\n return null;\n};\n\nexport function toggleMark(markType: string): Command {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range || range.from === range.to) {\n return null;\n }\n const para = getNodeAt(state.doc, range.path);\n const fullyMarked = rangeHasMark(para, range.from, range.to, markType);\n if (fullyMarked) {\n return [\n {\n type: 'remove_mark',\n path: range.path,\n from: range.from,\n to: range.to,\n markType,\n },\n ];\n }\n return [\n {\n type: 'set_mark',\n path: range.path,\n from: range.from,\n to: range.to,\n mark: { type: markType },\n },\n ];\n };\n}\n\n/** Whether the current selection (or caret) carries `markType`. */\nexport function selectionHasMark(markType: string): (state: EditorState) => boolean {\n return (state) => {\n const range = selectionTextRange(state.selection);\n if (!range) {\n return false;\n }\n const para = getNodeAt(state.doc, range.path);\n if (range.from === range.to) {\n const probe = range.from > 0 ? range.from - 1 : range.from;\n return offsetHasMark(para, probe, markType);\n }\n return rangeHasMark(para, range.from, range.to, markType);\n };\n}\n\nexport const selectAll: Command = (state) => {\n const leaves: number[][] = [];\n collectTextLeaves(state.doc, [], leaves);\n if (leaves.length === 0) {\n return null;\n }\n const first = leaves[0];\n const last = leaves.at(-1);\n if (first === undefined || last === undefined) {\n return null;\n }\n const len = plainText(getNodeAt(state.doc, last)).length;\n return [\n {\n type: 'set_selection',\n selection: {\n anchor: { path: first, offset: 0 },\n focus: { path: last, offset: len },\n },\n },\n ];\n};\n\nexport function runCommand(state: EditorState, command: Command) {\n const ops = command(state);\n if (!ops) {\n return null;\n }\n return transaction(...ops);\n}\n"],"mappings":"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"}
|