@sofereditor/core 0.1.0 → 0.2.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/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +26 -14
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/schema.ts","../src/page-settings.ts","../src/document.ts","../src/selection.ts","../src/marks.ts","../src/commands.ts","../src/history.ts"],"sourcesContent":["/**\n * Public type definitions for the document model.\n * The runtime representation lives in Y.js (see document.ts);\n * these types describe its shape for consumers.\n */\n\nexport type BlockType =\n | \"paragraph\"\n | \"heading\"\n | \"blockquote\"\n | \"codeBlock\"\n | \"listItem\"\n | \"table\";\n\nexport type AlignValue = \"left\" | \"center\" | \"right\" | \"justify\";\nexport type DirValue = \"ltr\" | \"rtl\";\nexport type ListKind = \"bullet\" | \"ordered\";\n\n/** Maximum supported list nesting (0 = top level). */\nexport const MAX_LIST_LEVEL = 5;\n\nexport interface BlockAttrs {\n align?: AlignValue;\n dir?: DirValue;\n /** Only meaningful when `type === \"heading\"`. 1..6. */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Only meaningful when `type === \"codeBlock\"`. Free-form (CSS-style language hint). */\n language?: string;\n /** Only meaningful when `type === \"listItem\"`. */\n listKind?: ListKind;\n /** Only meaningful when `type === \"listItem\"`. 0..MAX_LIST_LEVEL. */\n listLevel?: number;\n /** Only meaningful when `type === \"table\"`. */\n rows?: number;\n /** Only meaningful when `type === \"table\"`. */\n cols?: number;\n /**\n * Only meaningful when `type === \"table\"`. Per-column widths in CSS px.\n * Length should equal `cols` when set; missing or short arrays fall back to\n * an auto distribution at render time.\n */\n colWidths?: number[];\n}\n\nexport interface CellAttrs {\n /**\n * Number of rows this cell spans, starting at its row. Default 1.\n * Only meaningful on REAL cells (not covered).\n */\n rowspan?: number;\n /** Default 1. Only meaningful on REAL cells. */\n colspan?: number;\n /**\n * `true` iff this cell is occluded by an owning cell with a `rowspan`/`colspan`\n * spanning into this position. Covered cells do not render their own `<td>`,\n * never accept input, and are skipped by Tab navigation.\n *\n * The cells array keeps `rows * cols` entries to preserve the row-major index\n * scheme — covered cells are placeholders, not gaps.\n */\n covered?: true;\n}\n\nexport interface Position {\n blockIndex: number;\n /**\n * When the caret is inside a table cell, identifies which cell within the\n * table at `blockIndex`. Flat row-major index: `row * cols + col`.\n * `undefined` means the position addresses the block's own text (or the block\n * itself, for atomic blocks). Tables have no own text — every caret position\n * inside a table block carries a defined `cellIndex`.\n */\n cellIndex?: number;\n offset: number;\n}\n\nexport interface Selection {\n anchor: Position;\n focus: Position;\n}\n\nexport type MarkName =\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strike\"\n | \"color\"\n | \"fontFamily\"\n | \"fontSize\"\n | \"link\"\n | \"comment\";\n\nexport interface LinkAttr {\n href: string;\n title?: string;\n}\n\nexport interface CommentAttr {\n /** Identificador estável compartilhado com o backend (ProvaDocumentoComentario.markId). */\n markId: string;\n}\n\nexport interface MarkAttrs {\n bold?: true;\n italic?: true;\n underline?: true;\n strike?: true;\n color?: string;\n fontFamily?: string;\n fontSize?: string;\n link?: LinkAttr;\n comment?: CommentAttr;\n}\n\nexport type MarkValue<K extends MarkName = MarkName> = NonNullable<MarkAttrs[K]>;\n\n/**\n * Visual layout mode for an image embed.\n *\n * - `inline` (default): part of the text run, flows like a character.\n * - `wrap-left` / `wrap-right`: image floats to the named side of the anchor\n * paragraph (Word-style \"wrap square\"). Text in the paragraph wraps around it.\n * - `behind`: image is absolutely positioned beneath the text (z-index < text).\n * - `front`: image is absolutely positioned above the text (z-index > text).\n *\n * In every non-inline mode the embed remains in the Y.Text run at its offset —\n * the offset is its **anchor** (it follows the paragraph during pagination\n * and re-flows). Visual position is offset from the anchor block's content box.\n */\nexport type ImageLayout = \"inline\" | \"wrap-left\" | \"wrap-right\" | \"behind\" | \"front\";\n\nexport interface ImageEmbed {\n type: \"image\";\n /** Data URL (base64) — self-contained so the embed travels with the Y.Doc. */\n src: string;\n /** Rendered CSS px (display size — may differ from intrinsic dimensions). */\n width: number;\n height: number;\n /** When set (inline mode only), the image renders `display: block` with the matching margin auto. */\n align?: \"left\" | \"center\" | \"right\";\n /** Visual layout. Defaults to \"inline\" when omitted. */\n layout?: ImageLayout;\n /**\n * Horizontal offset in CSS px from the anchor block's content box.\n * - wrap-left: extra left margin from the paragraph's start edge.\n * - wrap-right: extra right margin from the paragraph's end edge.\n * - behind / front: `left` relative to the anchor block's padding-box.\n * Ignored for `inline`.\n */\n offsetX?: number;\n /**\n * Vertical offset in CSS px from the anchor block's content box.\n * - wrap-left / wrap-right: extra top margin pushing the float down inside\n * the paragraph.\n * - behind / front: `top` relative to the anchor block's padding-box.\n * Ignored for `inline`.\n */\n offsetY?: number;\n /**\n * Optional plain-text caption. Renders inside a `<figcaption>` beneath the\n * image in any layout — the figure wraps the image so the caption travels\n * with floats/anchors. Plain text only; rich marks are out of scope (we\n * never want a sub-editor inside an inline embed).\n */\n caption?: string;\n /**\n * Text alignment for the caption. Defaults to \"center\" (Word/Google Docs\n * default for figure captions). Only meaningful when `caption` is set.\n * Note: DOCX export emits captions inside the host paragraph, so this\n * setting only affects the editor and HTML/PDF exports — Word displays the\n * caption using the paragraph's own alignment.\n */\n captionAlign?: \"left\" | \"center\" | \"right\";\n}\n\nexport type InsertContent = string | ImageEmbed;\n\nexport function isImageEmbed(v: unknown): v is ImageEmbed {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as { type?: unknown }).type === \"image\" &&\n typeof (v as { src?: unknown }).src === \"string\"\n );\n}\n\nexport interface DeltaOp {\n insert: InsertContent;\n attributes?: MarkAttrs;\n}\n\nexport interface SerializedCell {\n /** Plain concatenated text. */\n text: string;\n /** Delta with marks. */\n delta: DeltaOp[];\n attrs: CellAttrs;\n}\n\nexport interface SerializedBlock {\n type: BlockType;\n /** Plain concatenated text (no marks). Kept for ergonomic equality checks. */\n text: string;\n /** Yjs delta — used by the renderer to draw mark-aware spans. */\n delta: DeltaOp[];\n /** Block-level attributes (align, dir, heading level, code language…). */\n attrs: BlockAttrs;\n /** Only present when `type === \"table\"`. Flat row-major list, length = rows * cols. */\n cells?: SerializedCell[];\n}\n\nimport type { PageSettings } from \"./page-settings\";\n\n/**\n * Document JSON shape used by `EditorDocument.toJSON` / `fromJSON`, the\n * exporters and the importer. Until Fase 9.5 this was a bare `SerializedBlock[]`;\n * Fase 9.6 promoted it to an object so per-document settings (page size,\n * margins) can travel with the content.\n *\n * `fromJSON` still accepts a legacy array for backwards compatibility — see\n * `isLegacySerializedDocument`.\n */\nexport interface SerializedDocument {\n blocks: SerializedBlock[];\n /** Page settings. Optional; omitted means default A4 + 1\" margins. */\n pageSettings?: PageSettings;\n}\n\n/** A `SerializedDocument` produced before Fase 9.6 — just an array of blocks. */\nexport type LegacySerializedDocument = SerializedBlock[];\n\nexport function isLegacySerializedDocument(\n v: SerializedDocument | LegacySerializedDocument,\n): v is LegacySerializedDocument {\n return Array.isArray(v);\n}\n","import type { BlockAttrs, BlockType } from \"./types\";\n\ninterface BlockSpec {\n type: BlockType;\n defaultAttrs: BlockAttrs;\n}\n\nexport const BLOCK_SPECS: Record<BlockType, BlockSpec> = {\n paragraph: {\n type: \"paragraph\",\n defaultAttrs: {},\n },\n heading: {\n type: \"heading\",\n defaultAttrs: { level: 1 },\n },\n blockquote: {\n type: \"blockquote\",\n defaultAttrs: {},\n },\n codeBlock: {\n type: \"codeBlock\",\n defaultAttrs: {},\n },\n listItem: {\n type: \"listItem\",\n defaultAttrs: { listKind: \"bullet\", listLevel: 0 },\n },\n table: {\n type: \"table\",\n defaultAttrs: { rows: 1, cols: 1 },\n },\n};\n\nexport function isKnownBlockType(t: string): t is BlockType {\n return t in BLOCK_SPECS;\n}\n\nexport function defaultAttrsFor(type: BlockType): BlockAttrs {\n return { ...BLOCK_SPECS[type].defaultAttrs };\n}\n","/**\n * Document-level page configuration: physical size and margins.\n *\n * Everything is stored in **CSS pixels @ 96dpi** for consistency with the\n * pagination engine (`packages/react/src/usePagination.ts` reads these\n * directly). Conversion helpers (`mmToPx`, `pxToMm`) round-trip with millimeter\n * inputs from the UI and the OOXML twip values used by docx import/export.\n */\n\nexport type PagePreset = \"a4\" | \"letter\" | \"oficio\" | \"custom\";\n\nexport interface PageSettings {\n /** Page width in CSS px. */\n width: number;\n /** Page height in CSS px. */\n height: number;\n marginTop: number;\n marginBottom: number;\n marginLeft: number;\n marginRight: number;\n /**\n * The preset whose size the geometry matches, with the ±0.5mm tolerance used\n * by `detectPreset`. \"custom\" when the dimensions don't match any preset.\n * This is purely a UI hint — it's recomputed from width/height when needed.\n */\n preset?: PagePreset;\n}\n\n/** Page sizes in CSS px @ 96dpi. */\nexport const PAGE_PRESETS = {\n a4: { width: 794, height: 1123 }, // 210×297 mm\n letter: { width: 816, height: 1056 }, // 8.5×11 in\n oficio: { width: 816, height: 1248 }, // 216×330 mm (BR Ofício)\n} as const;\n\n/** Margin presets in CSS px. Match common Word defaults. */\nexport const MARGIN_PRESETS = {\n normal: 96, // 25.4 mm = 1 in\n narrow: 48, // 12.7 mm = 0.5 in\n wide: 192, // 50.8 mm = 2 in\n} as const;\n\nexport const DEFAULT_PAGE_SETTINGS: PageSettings = {\n ...PAGE_PRESETS.a4,\n marginTop: MARGIN_PRESETS.normal,\n marginBottom: MARGIN_PRESETS.normal,\n marginLeft: MARGIN_PRESETS.normal,\n marginRight: MARGIN_PRESETS.normal,\n preset: \"a4\",\n};\n\nconst PX_PER_MM = 96 / 25.4;\n\nexport function mmToPx(mm: number): number {\n return mm * PX_PER_MM;\n}\n\nexport function pxToMm(px: number): number {\n return px / PX_PER_MM;\n}\n\n/**\n * Detect which preset a (width, height) pair matches. Tolerance is ±0.5mm to\n * absorb rounding from the twips↔px conversion used by docx round-trip.\n */\nexport function detectPreset(width: number, height: number): PagePreset {\n const TOL = mmToPx(0.5);\n for (const [name, size] of Object.entries(PAGE_PRESETS) as Array<[PagePreset, { width: number; height: number }]>) {\n if (Math.abs(width - size.width) <= TOL && Math.abs(height - size.height) <= TOL) {\n return name;\n }\n }\n return \"custom\";\n}\n\n/** Fill missing fields with the default. Useful when reading from a Y.Map that may be partially populated. */\nexport function withDefaults(partial: Partial<PageSettings> | undefined): PageSettings {\n const merged = { ...DEFAULT_PAGE_SETTINGS, ...(partial ?? {}) };\n return { ...merged, preset: detectPreset(merged.width, merged.height) };\n}\n","import * as Y from \"yjs\";\nimport { defaultAttrsFor } from \"./schema\";\nimport {\n DEFAULT_PAGE_SETTINGS,\n detectPreset,\n type PageSettings,\n} from \"./page-settings\";\nimport {\n isLegacySerializedDocument,\n type BlockAttrs,\n type BlockType,\n type CellAttrs,\n type DeltaOp,\n type LegacySerializedDocument,\n type SerializedBlock,\n type SerializedCell,\n type SerializedDocument,\n} from \"./types\";\n\n/**\n * Y.js-backed document.\n *\n * Storage layout:\n * ydoc.getArray(\"blocks\") : Y.Array<Y.Map>\n * each Y.Map (\"block\"):\n * - type: string (\"paragraph\" | \"heading\" | \"blockquote\" | \"codeBlock\" | \"listItem\" | \"table\")\n * - text: Y.Text (NOT present on tables)\n * - attrs: Y.Map<unknown> (align, dir, level, language… plus rows/cols for tables)\n * - cells: Y.Array<Y.Map> (only on tables, length = rows * cols, row-major)\n * each cell map: { text: Y.Text, attrs: Y.Map<unknown> }\n *\n * Block-level attrs live inside a nested Y.Map so concurrent edits (e.g. two users\n * changing alignment at once) reconcile through Yjs' last-write-wins per key.\n */\nexport class EditorDocument {\n readonly ydoc: Y.Doc;\n readonly blocks: Y.Array<Y.Map<unknown>>;\n /** Document-level settings (page size, margins). See `getPageSettings`. */\n readonly docSettings: Y.Map<unknown>;\n\n constructor(ydoc?: Y.Doc) {\n this.ydoc = ydoc ?? new Y.Doc();\n this.blocks = this.ydoc.getArray<Y.Map<unknown>>(\"blocks\");\n this.docSettings = this.ydoc.getMap<unknown>(\"docSettings\");\n\n if (this.blocks.length === 0) {\n this.ydoc.transact(() => {\n this.blocks.push([createBlock(\"paragraph\")]);\n }, \"init\");\n }\n }\n\n /**\n * Returns the current page settings. Missing fields fall back to\n * `DEFAULT_PAGE_SETTINGS`. The returned object is a fresh snapshot — mutating\n * it does not write back to the Y.Doc. Use `setPageSettings` for that.\n */\n getPageSettings(): PageSettings {\n const m = this.docSettings;\n const pick = <K extends keyof PageSettings>(key: K): PageSettings[K] | undefined => {\n const v = m.get(key as string);\n return typeof v === \"number\" || typeof v === \"string\" ? (v as PageSettings[K]) : undefined;\n };\n const merged: PageSettings = {\n width: pick(\"width\") ?? DEFAULT_PAGE_SETTINGS.width,\n height: pick(\"height\") ?? DEFAULT_PAGE_SETTINGS.height,\n marginTop: pick(\"marginTop\") ?? DEFAULT_PAGE_SETTINGS.marginTop,\n marginBottom: pick(\"marginBottom\") ?? DEFAULT_PAGE_SETTINGS.marginBottom,\n marginLeft: pick(\"marginLeft\") ?? DEFAULT_PAGE_SETTINGS.marginLeft,\n marginRight: pick(\"marginRight\") ?? DEFAULT_PAGE_SETTINGS.marginRight,\n };\n merged.preset = detectPreset(merged.width, merged.height);\n return merged;\n }\n\n /**\n * Merge `partial` into the docSettings Y.Map. Runs in a `ydoc.transact` with\n * origin `\"pageSettings\"` (NOT tracked by the UndoManager, mirroring the\n * `\"import\"` convention from Fase 9.5).\n */\n setPageSettings(partial: Partial<PageSettings>): void {\n this.ydoc.transact(() => {\n for (const [k, v] of Object.entries(partial)) {\n if (k === \"preset\") continue; // derived, never stored\n if (v === undefined) continue;\n this.docSettings.set(k, v);\n }\n }, \"pageSettings\");\n }\n\n /** Listen for page-settings changes. Returns an unsubscribe function. */\n observePageSettings(cb: () => void): () => void {\n const handler = () => cb();\n this.docSettings.observe(handler);\n return () => this.docSettings.unobserve(handler);\n }\n\n getBlock(index: number): Y.Map<unknown> | undefined {\n if (index < 0 || index >= this.blocks.length) return undefined;\n return this.blocks.get(index);\n }\n\n getBlockText(index: number): Y.Text | undefined {\n const b = this.getBlock(index);\n return b?.get(\"text\") as Y.Text | undefined;\n }\n\n getBlockType(index: number): BlockType | undefined {\n const b = this.getBlock(index);\n return b?.get(\"type\") as BlockType | undefined;\n }\n\n getBlockAttrsMap(index: number): Y.Map<unknown> | undefined {\n const b = this.getBlock(index);\n return b?.get(\"attrs\") as Y.Map<unknown> | undefined;\n }\n\n getBlockAttrs(index: number): BlockAttrs {\n const m = this.getBlockAttrsMap(index);\n if (!m) return {};\n return Object.fromEntries(m.entries()) as BlockAttrs;\n }\n\n blockCount(): number {\n return this.blocks.length;\n }\n\n // ---------- Table helpers ----------\n\n isTable(index: number): boolean {\n return this.getBlockType(index) === \"table\";\n }\n\n /** Returns rows/cols read from the block's attrs map. `{0,0}` for non-table blocks. */\n getTableSize(index: number): { rows: number; cols: number } {\n const attrs = this.getBlockAttrs(index);\n const rows = typeof attrs.rows === \"number\" ? attrs.rows : 0;\n const cols = typeof attrs.cols === \"number\" ? attrs.cols : 0;\n return { rows, cols };\n }\n\n getCells(index: number): Y.Array<Y.Map<unknown>> | undefined {\n const b = this.getBlock(index);\n return b?.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n }\n\n getCell(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined {\n const cells = this.getCells(blockIndex);\n if (!cells) return undefined;\n if (cellIndex < 0 || cellIndex >= cells.length) return undefined;\n return cells.get(cellIndex);\n }\n\n getCellText(blockIndex: number, cellIndex: number): Y.Text | undefined {\n const cell = this.getCell(blockIndex, cellIndex);\n return cell?.get(\"text\") as Y.Text | undefined;\n }\n\n getCellAttrsMap(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined {\n const cell = this.getCell(blockIndex, cellIndex);\n return cell?.get(\"attrs\") as Y.Map<unknown> | undefined;\n }\n\n getCellAttrs(blockIndex: number, cellIndex: number): CellAttrs {\n const m = this.getCellAttrsMap(blockIndex, cellIndex);\n if (!m) return {};\n return Object.fromEntries(m.entries()) as CellAttrs;\n }\n\n /**\n * Returns the editable Y.Text targeted by a position:\n * - When `cellIndex` is set: the cell's text (or the owner's text if the\n * target cell is covered by a span — we treat the covered position as\n * addressing the owner).\n * - Otherwise: the block's own text.\n */\n textAt(blockIndex: number, cellIndex: number | undefined): Y.Text | undefined {\n if (cellIndex == null) return this.getBlockText(blockIndex);\n const real = this.realCellIndex(blockIndex, cellIndex);\n if (real == null) return undefined;\n return this.getCellText(blockIndex, real);\n }\n\n /**\n * Returns the \"real\" (non-covered) cell index for a target cell. When the\n * target is already a real cell, returns it unchanged. When covered, walks\n * up-and-left to find the owner.\n *\n * The walk is robust to oversized or non-rectangular spans by skipping\n * candidates whose declared span doesn't actually cover the target.\n */\n realCellIndex(blockIndex: number, cellIndex: number): number | undefined {\n if (!this.isTable(blockIndex)) return undefined;\n const { rows, cols } = this.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return undefined;\n if (cellIndex < 0 || cellIndex >= rows * cols) return undefined;\n const targetAttrs = this.getCellAttrs(blockIndex, cellIndex);\n if (targetAttrs.covered !== true) return cellIndex;\n\n const tRow = Math.floor(cellIndex / cols);\n const tCol = cellIndex - tRow * cols;\n // Scan candidate owners — any real cell (or, oc) with or <= tRow, oc <= tCol,\n // spanning into (tRow, tCol). Walk from (tRow, tCol) up-and-left.\n for (let or = tRow; or >= 0; or--) {\n for (let oc = tCol; oc >= 0; oc--) {\n const idx = or * cols + oc;\n if (idx === cellIndex) continue;\n const a = this.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (or + rs - 1 >= tRow && oc + cs - 1 >= tCol) return idx;\n }\n }\n return undefined;\n }\n\n /**\n * Replace the document contents with a `SerializedDocument`. Runs in a single\n * `ydoc.transact` with origin `\"import\"` so the UndoManager can group or skip\n * the operation as one step.\n *\n * Reuses `createBlock` / `createTableBlock` so every block ends up with the\n * exact same Y.js shape produced by the rest of the editor.\n */\n loadFromJSON(serialized: SerializedDocument | LegacySerializedDocument): void {\n const { blocks: sourceBlocks, pageSettings } = normalizeSerialized(serialized);\n this.ydoc.transact(() => {\n if (this.blocks.length > 0) {\n this.blocks.delete(0, this.blocks.length);\n }\n // Build the Y structure in two passes: first create empty blocks (with\n // correct type/attrs/cells shape) and push them so their inner Y.Texts\n // get integrated into the document; only then apply each delta. Y.Text\n // requires an active transaction context that exists for integrated\n // instances — `applyDelta` on a detached Y.Text throws.\n const sources = sourceBlocks.length > 0 ? sourceBlocks : [makeEmptyParagraphSource()];\n const fresh: Y.Map<unknown>[] = sources.map((b) => buildEmptyBlockFromSerialized(b));\n this.blocks.push(fresh);\n\n for (let i = 0; i < sources.length; i++) {\n const src = sources[i];\n const yBlock = this.blocks.get(i);\n applyDeltaIntoBlock(yBlock, src);\n }\n\n if (pageSettings) {\n for (const [k, v] of Object.entries(pageSettings)) {\n if (k === \"preset\") continue;\n if (v === undefined) continue;\n this.docSettings.set(k, v);\n }\n }\n }, \"import\");\n }\n\n /** Build a fresh `EditorDocument` from a `SerializedDocument`. */\n static fromJSON(serialized: SerializedDocument | LegacySerializedDocument): EditorDocument {\n const ydoc = new Y.Doc();\n // Touch the shared array before loadFromJSON so the constructor doesn't\n // insert its default paragraph — we replace the contents anyway.\n ydoc.getArray<Y.Map<unknown>>(\"blocks\");\n const doc = new EditorDocument(ydoc);\n doc.loadFromJSON(serialized);\n return doc;\n }\n\n toJSON(): SerializedDocument {\n const blocks = this.blocks.toArray().map<SerializedBlock>((b) => {\n const type = (b.get(\"type\") as BlockType) ?? \"paragraph\";\n const attrsMap = b.get(\"attrs\") as Y.Map<unknown> | undefined;\n const attrs = attrsMap ? (Object.fromEntries(attrsMap.entries()) as BlockAttrs) : {};\n\n if (type === \"table\") {\n const cellsArray = b.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n const cells: SerializedCell[] = cellsArray\n ? cellsArray.toArray().map((c) => serializeCell(c))\n : [];\n return {\n type,\n text: \"\",\n delta: [],\n attrs,\n cells,\n };\n }\n\n const yText = b.get(\"text\") as Y.Text | undefined;\n return {\n type,\n text: yText?.toString() ?? \"\",\n delta: (yText?.toDelta() as DeltaOp[] | undefined) ?? [],\n attrs,\n };\n });\n return { blocks, pageSettings: this.getPageSettings() };\n }\n}\n\nfunction normalizeSerialized(\n v: SerializedDocument | LegacySerializedDocument,\n): { blocks: SerializedBlock[]; pageSettings?: PageSettings } {\n if (isLegacySerializedDocument(v)) {\n return { blocks: v };\n }\n return { blocks: v.blocks, pageSettings: v.pageSettings };\n}\n\nfunction serializeCell(c: Y.Map<unknown>): SerializedCell {\n const yText = c.get(\"text\") as Y.Text | undefined;\n const attrsMap = c.get(\"attrs\") as Y.Map<unknown> | undefined;\n return {\n text: yText?.toString() ?? \"\",\n delta: (yText?.toDelta() as DeltaOp[] | undefined) ?? [],\n attrs: attrsMap ? (Object.fromEntries(attrsMap.entries()) as Record<string, unknown>) : {},\n };\n}\n\nexport function createBlock(\n type: BlockType,\n initialText = \"\",\n attrs?: BlockAttrs,\n): Y.Map<unknown> {\n if (type === \"table\") {\n // Callers that need a table should use createTableBlock(rows, cols).\n // We honor any rows/cols passed via attrs but default to 1x1 to keep the\n // invariant `cells.length === rows * cols` non-zero.\n const merged = { ...defaultAttrsFor(\"table\"), ...(attrs ?? {}) };\n const rows = typeof merged.rows === \"number\" && merged.rows > 0 ? Math.trunc(merged.rows) : 1;\n const cols = typeof merged.cols === \"number\" && merged.cols > 0 ? Math.trunc(merged.cols) : 1;\n return createTableBlock(rows, cols);\n }\n\n const block = new Y.Map<unknown>();\n block.set(\"type\", type);\n const yText = new Y.Text();\n if (initialText.length > 0) yText.insert(0, initialText);\n block.set(\"text\", yText);\n const attrsMap = new Y.Map<unknown>();\n const merged = { ...defaultAttrsFor(type), ...(attrs ?? {}) };\n for (const [k, v] of Object.entries(merged)) {\n if (v !== undefined) attrsMap.set(k, v);\n }\n block.set(\"attrs\", attrsMap);\n return block;\n}\n\n/**\n * Build a table block with `rows × cols` empty cells.\n * Cells are stored in row-major order: `cell[row * cols + col]`.\n */\nexport function createTableBlock(rows: number, cols: number): Y.Map<unknown> {\n const r = Math.max(1, Math.trunc(rows));\n const c = Math.max(1, Math.trunc(cols));\n const block = new Y.Map<unknown>();\n block.set(\"type\", \"table\");\n const attrsMap = new Y.Map<unknown>();\n attrsMap.set(\"rows\", r);\n attrsMap.set(\"cols\", c);\n block.set(\"attrs\", attrsMap);\n const cells = new Y.Array<Y.Map<unknown>>();\n const total = r * c;\n const fresh: Y.Map<unknown>[] = [];\n for (let i = 0; i < total; i++) fresh.push(createCell());\n cells.push(fresh);\n block.set(\"cells\", cells);\n return block;\n}\n\nexport function createCell(attrs?: CellAttrs): Y.Map<unknown> {\n const m = new Y.Map<unknown>();\n m.set(\"text\", new Y.Text());\n const attrsMap = new Y.Map<unknown>();\n if (attrs) {\n for (const [k, v] of Object.entries(attrs)) {\n if (v === undefined) continue;\n attrsMap.set(k, v);\n }\n }\n m.set(\"attrs\", attrsMap);\n return m;\n}\n\nfunction makeEmptyParagraphSource(): SerializedBlock {\n return { type: \"paragraph\", text: \"\", delta: [], attrs: {} };\n}\n\nfunction buildEmptyBlockFromSerialized(block: SerializedBlock): Y.Map<unknown> {\n if (block.type === \"table\") {\n const rows =\n typeof block.attrs.rows === \"number\" ? Math.max(1, Math.trunc(block.attrs.rows)) : 1;\n const cols =\n typeof block.attrs.cols === \"number\" ? Math.max(1, Math.trunc(block.attrs.cols)) : 1;\n const yBlock = new Y.Map<unknown>();\n yBlock.set(\"type\", \"table\");\n const attrsMap = new Y.Map<unknown>();\n attrsMap.set(\"rows\", rows);\n attrsMap.set(\"cols\", cols);\n for (const [k, v] of Object.entries(block.attrs)) {\n if (k === \"rows\" || k === \"cols\") continue;\n if (v === undefined) continue;\n attrsMap.set(k, v);\n }\n yBlock.set(\"attrs\", attrsMap);\n const cellsArr = new Y.Array<Y.Map<unknown>>();\n const total = rows * cols;\n const fresh: Y.Map<unknown>[] = [];\n const cells = block.cells ?? [];\n for (let i = 0; i < total; i++) {\n const src = cells[i];\n fresh.push(createCell((src?.attrs ?? undefined) as CellAttrs | undefined));\n }\n cellsArr.push(fresh);\n yBlock.set(\"cells\", cellsArr);\n return yBlock;\n }\n return createBlock(block.type, \"\", block.attrs);\n}\n\nfunction applyDeltaIntoBlock(yBlock: Y.Map<unknown> | undefined, src: SerializedBlock): void {\n if (!yBlock) return;\n if (src.type === \"table\") {\n const cellsArr = yBlock.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n if (!cellsArr) return;\n const cells = src.cells ?? [];\n for (let i = 0; i < cellsArr.length; i++) {\n const cellSrc = cells[i];\n if (!cellSrc || !cellSrc.delta || cellSrc.delta.length === 0) continue;\n const cell = cellsArr.get(i);\n const yText = cell.get(\"text\") as Y.Text | undefined;\n if (!yText) continue;\n yText.applyDelta(cellSrc.delta as unknown as Array<{ insert: unknown; attributes?: unknown }>);\n }\n return;\n }\n if (!src.delta || src.delta.length === 0) return;\n const yText = yBlock.get(\"text\") as Y.Text | undefined;\n if (!yText) return;\n yText.applyDelta(src.delta as unknown as Array<{ insert: unknown; attributes?: unknown }>);\n}\n\n/** Coerce a `rowspan`/`colspan` attribute value into a positive integer. */\nexport function spanOf(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1;\n return Math.max(1, Math.trunc(value));\n}\n","import type { Position, Selection } from \"./types\";\n\nexport function isCollapsed(sel: Selection): boolean {\n return positionsEqual(sel.anchor, sel.focus);\n}\n\nexport function positionsEqual(a: Position, b: Position): boolean {\n return (\n a.blockIndex === b.blockIndex &&\n (a.cellIndex ?? -1) === (b.cellIndex ?? -1) &&\n a.offset === b.offset\n );\n}\n\nexport function comparePositions(a: Position, b: Position): number {\n if (a.blockIndex !== b.blockIndex) return a.blockIndex - b.blockIndex;\n const ac = a.cellIndex ?? -1;\n const bc = b.cellIndex ?? -1;\n if (ac !== bc) return ac - bc;\n return a.offset - b.offset;\n}\n\nexport function orderedRange(sel: Selection): { start: Position; end: Position } {\n if (comparePositions(sel.anchor, sel.focus) <= 0) {\n return { start: sel.anchor, end: sel.focus };\n }\n return { start: sel.focus, end: sel.anchor };\n}\n\nexport function collapsedSelection(pos: Position): Selection {\n return { anchor: pos, focus: pos };\n}\n\n/**\n * Two positions are in the same \"editable run\" (same Y.Text) when they share\n * the block index AND the cellIndex (treating absent and present-with-undefined\n * the same way: a non-table position has cellIndex === undefined for both).\n */\nexport function sameTextRun(a: Position, b: Position): boolean {\n return a.blockIndex === b.blockIndex && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);\n}\n","import type * as Y from \"yjs\";\nimport type { DeltaOp, MarkAttrs, MarkName } from \"./types\";\n\n/**\n * Helpers for reading mark attributes off a Y.Text by inspecting its delta.\n * Writing is done with `yText.format(...)` directly in commands.ts.\n */\n\nfunction iterateRunsInRange(\n yText: Y.Text,\n start: number,\n end: number,\n visit: (run: DeltaOp, runStart: number, runEnd: number) => void,\n): void {\n if (start >= end) return;\n const delta = yText.toDelta() as DeltaOp[];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert !== \"string\") {\n // Embed: advance cursor (counts as 1 char) but don't visit — mark queries\n // are about text runs, not embed attributes.\n if (op.insert == null) continue;\n cursor += 1;\n if (cursor > end) break;\n continue;\n }\n const opStart = cursor;\n const opEnd = cursor + op.insert.length;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n const runStart = Math.max(opStart, start);\n const runEnd = Math.min(opEnd, end);\n visit(op, runStart, runEnd);\n }\n}\n\n/**\n * Returns the marks observed across `[start, end)`. For each mark name encountered:\n * - if every covered character has the same value, returns that value\n * - if values differ OR some characters lack the mark, returns \"mixed\"\n */\nexport function getMarksInRange(\n yText: Y.Text,\n start: number,\n end: number,\n): Partial<Record<MarkName, MarkAttrs[MarkName] | \"mixed\">> {\n const result: Partial<Record<MarkName, MarkAttrs[MarkName] | \"mixed\">> = {};\n if (start >= end) return result;\n\n // Track total covered length and per-mark covered length to detect \"some chars lacked it\".\n const total = end - start;\n const coveredByName: Partial<Record<MarkName, number>> = {};\n\n iterateRunsInRange(yText, start, end, (run, runStart, runEnd) => {\n const len = runEnd - runStart;\n const attrs = (run.attributes ?? {}) as MarkAttrs;\n (Object.keys(attrs) as MarkName[]).forEach((name) => {\n const value = attrs[name];\n if (value === undefined || value === null) return;\n const prev = result[name];\n if (prev === undefined) {\n result[name] = value;\n } else if (prev !== \"mixed\" && !sameMarkValue(prev, value)) {\n result[name] = \"mixed\";\n }\n coveredByName[name] = (coveredByName[name] ?? 0) + len;\n });\n });\n\n (Object.keys(result) as MarkName[]).forEach((name) => {\n if ((coveredByName[name] ?? 0) < total) {\n result[name] = \"mixed\";\n }\n });\n\n return result;\n}\n\nexport function isMarkUniformInRange(\n yText: Y.Text,\n start: number,\n end: number,\n name: MarkName,\n value?: MarkAttrs[MarkName],\n): boolean {\n if (start >= end) return false;\n const total = end - start;\n let covered = 0;\n let observed: MarkAttrs[MarkName] | undefined;\n let ok = true;\n iterateRunsInRange(yText, start, end, (run, runStart, runEnd) => {\n if (!ok) return;\n const len = runEnd - runStart;\n const attr = (run.attributes ?? {})[name];\n if (attr === undefined || attr === null) {\n ok = false;\n return;\n }\n if (value !== undefined && !sameMarkValue(value, attr)) {\n ok = false;\n return;\n }\n if (observed === undefined) {\n observed = attr;\n } else if (!sameMarkValue(observed, attr)) {\n ok = false;\n return;\n }\n covered += len;\n });\n return ok && covered === total;\n}\n\n/** Total number of inserted characters. Embeds (non-string inserts) count as 1. */\nexport function deltaLength(delta: DeltaOp[]): number {\n let sum = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") sum += op.insert.length;\n else if (op.insert != null) sum += 1;\n }\n return sum;\n}\n\n/**\n * Return the subset of `delta` covering `[start, end)` characters.\n * Embeds are atomic length-1 ops: included whole if their slot intersects the range.\n */\nexport function sliceDelta(delta: DeltaOp[], start: number, end: number): DeltaOp[] {\n if (end <= start) return [];\n const out: DeltaOp[] = [];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n const opStart = cursor;\n const opEnd = cursor + op.insert.length;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n const sliceFrom = Math.max(opStart, start) - opStart;\n const sliceTo = Math.min(opEnd, end) - opStart;\n out.push({\n insert: op.insert.slice(sliceFrom, sliceTo),\n attributes: op.attributes,\n });\n } else if (op.insert != null) {\n const opStart = cursor;\n const opEnd = cursor + 1;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n out.push({ insert: op.insert, attributes: op.attributes });\n }\n }\n return out;\n}\n\nfunction sameMarkValue(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === \"object\" && typeof b === \"object\" && a && b) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k) => (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]);\n }\n return false;\n}\n","import * as Y from \"yjs\";\nimport { EditorDocument, createBlock, createCell, createTableBlock, spanOf } from \"./document\";\nimport { isMarkUniformInRange, sliceDelta } from \"./marks\";\nimport { defaultAttrsFor } from \"./schema\";\nimport { collapsedSelection, isCollapsed, orderedRange, sameTextRun } from \"./selection\";\nimport type {\n BlockAttrs,\n BlockType,\n DeltaOp,\n ImageEmbed,\n ListKind,\n MarkAttrs,\n MarkName,\n Position,\n Selection,\n} from \"./types\";\nimport { isImageEmbed, MAX_LIST_LEVEL } from \"./types\";\n\nexport const COMMAND_ORIGIN: unique symbol = Symbol(\"editor-command\");\n\nexport interface CommandContext {\n doc: EditorDocument;\n getSelection: () => Selection;\n setSelection: (sel: Selection) => void;\n}\n\nfunction transact(doc: EditorDocument, fn: () => void): void {\n doc.ydoc.transact(fn, COMMAND_ORIGIN);\n}\n\n/**\n * Insert text at the current selection.\n *\n * `marks` is an explicit override map applied to the freshly inserted range.\n * - Entry value: apply that mark value.\n * - Entry value `null`: clear that mark (used when the UI just toggled it off\n * with a collapsed caret and the next typed char must NOT inherit the\n * surrounding run's attribute).\n * - When `marks` is undefined, Y.Text's default inheritance applies (good for\n * normal typing inside a marked run).\n */\nexport function insertText(\n ctx: CommandContext,\n text: string,\n marks?: Partial<Record<MarkName, MarkAttrs[MarkName] | null>>,\n): void {\n if (text.length === 0) return;\n // Rectangular cell selection: clear all selected cells, collapse to top-left,\n // then insert into the owner like a normal call.\n const collapsedFromRect = clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel = collapsedFromRect ?? ctx.getSelection();\n let cursor = sel;\n if (!isCollapsed(sel)) {\n cursor = deleteRange(ctx.doc, sel);\n }\n const pos = cursor.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.insert(pos.offset, text);\n if (marks && Object.keys(marks).length > 0) {\n yText.format(pos.offset, text.length, marks as Record<string, unknown>);\n }\n const newPos: Position = {\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + text.length,\n };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\nexport function insertParagraph(ctx: CommandContext): void {\n // Rectangular selection: collapse + clear first.\n clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n let cursor = sel;\n if (!isCollapsed(sel)) {\n cursor = deleteRange(ctx.doc, sel);\n }\n const pos = cursor.focus;\n // Inside a table cell, Enter inserts a literal newline rather than splitting\n // the cell into two paragraphs. Cells in 4.1 are single-text containers; we\n // rely on `white-space: pre-wrap` in CSS to render the line break visibly.\n if (pos.cellIndex != null) {\n const yText = ctx.doc.getCellText(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.insert(pos.offset, \"\\n\");\n ctx.setSelection(\n collapsedSelection({\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + 1,\n }),\n );\n return;\n }\n const yText = ctx.doc.getBlockText(pos.blockIndex);\n if (!yText) return;\n\n const totalLen = yText.length;\n // Read the tail's delta (preserves marks) before mutating yText.\n const tailDelta = totalLen > pos.offset\n ? sliceDelta(yText.toDelta() as DeltaOp[], pos.offset, totalLen)\n : [];\n\n if (totalLen > pos.offset) {\n yText.delete(pos.offset, totalLen - pos.offset);\n }\n\n const newBlock = createBlock(\"paragraph\");\n ctx.doc.blocks.insert(pos.blockIndex + 1, [newBlock]);\n if (tailDelta.length > 0) {\n const newYText = newBlock.get(\"text\") as Y.Text;\n writeDeltaInto(newYText, 0, tailDelta);\n }\n\n const newPos: Position = { blockIndex: pos.blockIndex + 1, offset: 0 };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\nexport function deleteBackward(ctx: CommandContext): void {\n // Rectangular selection: clear text of every selected cell and collapse to\n // the rect's top-left, then return — no further character delete needed.\n if (clearRectCells(ctx)) return;\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) {\n const cursor = deleteRange(ctx.doc, sel);\n ctx.setSelection(cursor);\n return;\n }\n const pos = sel.focus;\n if (pos.offset > 0) {\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.delete(pos.offset - 1, 1);\n ctx.setSelection(\n collapsedSelection({\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset - 1,\n }),\n );\n return;\n }\n // offset === 0\n // Inside a table cell, backspace at the cell start is a no-op — the user\n // cannot escape the table by pressing backspace.\n if (pos.cellIndex != null) return;\n // At offset 0: if it's a listItem, dedent (or convert to paragraph at level 0)\n // before falling back to merging with the previous block.\n const blockType = ctx.doc.getBlockType(pos.blockIndex);\n if (blockType === \"listItem\") {\n const block = ctx.doc.getBlock(pos.blockIndex);\n const attrsMap = block?.get(\"attrs\") as Y.Map<unknown> | undefined;\n const rawLevel = attrsMap?.get(\"listLevel\") as number | undefined;\n const level = typeof rawLevel === \"number\" && Number.isFinite(rawLevel)\n ? Math.max(0, Math.min(MAX_LIST_LEVEL, Math.trunc(rawLevel)))\n : 0;\n if (level > 0) {\n attrsMap!.set(\"listLevel\", level - 1);\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n // Level 0 listItem → convert to paragraph (escape the list).\n setBlockTypeAtIndex(ctx.doc, pos.blockIndex, \"paragraph\", {});\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n if (pos.blockIndex > 0) {\n const prevType = ctx.doc.getBlockType(pos.blockIndex - 1);\n if (prevType === \"table\") {\n // Can't merge with a table; move caret to the table's last cell instead.\n const tableIdx = pos.blockIndex - 1;\n const { rows, cols } = ctx.doc.getTableSize(tableIdx);\n const lastCell = rows * cols - 1;\n const cellText = ctx.doc.getCellText(tableIdx, lastCell);\n const off = cellText?.length ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex: tableIdx, cellIndex: lastCell, offset: off }),\n );\n return;\n }\n mergeWithPrevious(ctx, pos.blockIndex);\n }\n });\n}\n\nexport function deleteForward(ctx: CommandContext): void {\n if (clearRectCells(ctx)) return;\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) {\n const cursor = deleteRange(ctx.doc, sel);\n ctx.setSelection(cursor);\n return;\n }\n const pos = sel.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n if (pos.offset < yText.length) {\n yText.delete(pos.offset, 1);\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n // at end of editable run\n // Inside a table cell, forward-delete at the cell end is a no-op.\n if (pos.cellIndex != null) return;\n // at end of block: merge next into current (but tables are atomic)\n if (pos.blockIndex + 1 < ctx.doc.blockCount()) {\n const nextType = ctx.doc.getBlockType(pos.blockIndex + 1);\n if (nextType === \"table\") {\n // Jump caret into the table's first cell.\n const tableIdx = pos.blockIndex + 1;\n ctx.setSelection(collapsedSelection({ blockIndex: tableIdx, cellIndex: 0, offset: 0 }));\n return;\n }\n const nextText = ctx.doc.getBlockText(pos.blockIndex + 1);\n if (!nextText) return;\n const tail = nextText.toString();\n if (tail.length > 0) yText.insert(yText.length, tail);\n ctx.doc.blocks.delete(pos.blockIndex + 1, 1);\n ctx.setSelection(collapsedSelection(pos));\n }\n });\n}\n\n// ---------- Marks ----------\n\nconst booleanMarks: Set<MarkName> = new Set([\"bold\", \"italic\", \"underline\", \"strike\"]);\n\n/**\n * Toggle a mark across the current selection.\n * - If the selection is collapsed: no-op (the UI layer handles pendingMarks).\n * - Boolean marks (bold/italic/underline/strike): if every character already has\n * the mark, remove it; otherwise apply.\n * - Parametric marks (color, fontFamily, fontSize, link): require `value` to apply;\n * when uniform with that value across the range, remove instead (acts like toggle).\n */\nexport function toggleMark(\n ctx: CommandContext,\n name: MarkName,\n value?: MarkAttrs[MarkName],\n): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n const uniform = isMarkUniformInRange(yText, localStart, localEnd, name, value);\n const attrs: Record<string, unknown> = {};\n if (uniform) {\n attrs[name] = null;\n } else {\n attrs[name] = value ?? (booleanMarks.has(name) ? true : null);\n }\n if (attrs[name] === null && !uniform) return;\n yText.format(localStart, localEnd - localStart, attrs);\n });\n ctx.setSelection(sel);\n });\n}\n\nexport function setMark(\n ctx: CommandContext,\n name: MarkName,\n value: MarkAttrs[MarkName],\n): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n yText.format(localStart, localEnd - localStart, { [name]: value });\n });\n ctx.setSelection(sel);\n });\n}\n\nexport function removeMark(ctx: CommandContext, name: MarkName): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n yText.format(localStart, localEnd - localStart, { [name]: null });\n });\n ctx.setSelection(sel);\n });\n}\n\n// ---------- Block-level commands (Sub-phase 2.2) ----------\n\n/**\n * Change the type of every block covered by the current selection.\n * When `attrs` is provided, merges those on top of the new type's defaults.\n * Preserves `Y.Text` content (and therefore all inline marks) and the selection.\n */\nexport function setBlockType(\n ctx: CommandContext,\n type: BlockType,\n attrs?: BlockAttrs,\n): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n // Inert when the caret is inside a cell — block-level operations only\n // apply to top-level blocks (the table itself), and changing a table's\n // block type is not exposed in 4.1.\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block) continue;\n block.set(\"type\", type);\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n // Reset attrs to the new type's defaults, then layer caller overrides.\n // Strategy: clear keys that aren't in either map, then write new ones.\n const next = { ...defaultAttrsFor(type), ...(attrs ?? {}) };\n const keep = new Set(Object.keys(next));\n for (const k of Array.from(attrsMap.keys())) {\n if (!keep.has(k)) attrsMap.delete(k);\n }\n for (const [k, v] of Object.entries(next)) {\n if (v === undefined) continue;\n if (attrsMap.get(k) !== v) attrsMap.set(k, v);\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Set a single attribute on every block covered by the selection.\n * Passing `value === null` deletes the key.\n */\nexport function setBlockAttr<K extends keyof BlockAttrs>(\n ctx: CommandContext,\n key: K,\n value: BlockAttrs[K] | null,\n): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block) continue;\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n if (value === null || value === undefined) {\n attrsMap.delete(key as string);\n } else {\n attrsMap.set(key as string, value);\n }\n }\n ctx.setSelection(sel);\n });\n}\n\nfunction selectedBlockIndices(sel: Selection, blockCount: number): number[] {\n const { start, end } = orderedRange(sel);\n const out: number[] = [];\n const last = Math.min(end.blockIndex, blockCount - 1);\n for (let i = Math.max(start.blockIndex, 0); i <= last; i++) out.push(i);\n return out;\n}\n\nfunction forEachBlockTextInRange(\n doc: EditorDocument,\n start: Position,\n end: Position,\n visit: (yText: Y.Text, localStart: number, localEnd: number) => void,\n): void {\n // Same text-run (block or cell): straightforward.\n if (sameTextRun(start, end)) {\n const yText = doc.textAt(start.blockIndex, start.cellIndex);\n if (!yText) return;\n if (start.offset < end.offset) visit(yText, start.offset, end.offset);\n return;\n }\n // Cross-run selections involving a cell are currently treated as inert for\n // mark application; the UI surfaces them as \"no-op\" rather than partially\n // applying marks across mismatched runs.\n if (start.cellIndex != null || end.cellIndex != null) return;\n\n for (let i = start.blockIndex; i <= end.blockIndex; i++) {\n const yText = doc.getBlockText(i);\n if (!yText) continue;\n const localStart = i === start.blockIndex ? start.offset : 0;\n const localEnd = i === end.blockIndex ? end.offset : yText.length;\n if (localStart < localEnd) visit(yText, localStart, localEnd);\n }\n}\n\n/**\n * Deletes the content of a non-collapsed selection.\n * Returns the new collapsed selection at the deletion point.\n * Must be called inside a Y.Doc transaction.\n *\n * Selections that span DIFFERENT text-runs (different blocks, or two cells of\n * the same table) are bridged conservatively:\n * - Same text-run (block+cell): delete the range normally.\n * - Different runs but both outside tables (i.e. cellIndex undefined on both):\n * delete and merge blocks as before.\n * - Otherwise (one endpoint is in a table cell): no destructive cross-cell\n * delete in 4.1; collapse to `start` instead.\n */\nfunction deleteRange(doc: EditorDocument, sel: Selection): Selection {\n const { start, end } = orderedRange(sel);\n\n if (sameTextRun(start, end)) {\n const yText = doc.textAt(start.blockIndex, start.cellIndex);\n if (yText) yText.delete(start.offset, end.offset - start.offset);\n return collapsedSelection(start);\n }\n\n // Reject cross-cell / cross-table-to-paragraph multi-run deletions for now.\n if (start.cellIndex != null || end.cellIndex != null) {\n return collapsedSelection(start);\n }\n\n const startText = doc.getBlockText(start.blockIndex);\n const endText = doc.getBlockText(end.blockIndex);\n if (!startText || !endText) return collapsedSelection(start);\n\n // Trim tail of start block\n startText.delete(start.offset, startText.length - start.offset);\n // Read remaining tail from end block, after the deleted prefix\n const remainingTail = endText.toString().slice(end.offset);\n if (remainingTail.length > 0) {\n startText.insert(startText.length, remainingTail);\n }\n // Remove all blocks between start (exclusive) and end (inclusive)\n doc.blocks.delete(start.blockIndex + 1, end.blockIndex - start.blockIndex);\n return collapsedSelection(start);\n}\n\nfunction mergeWithPrevious(ctx: CommandContext, blockIndex: number): void {\n const prevText = ctx.doc.getBlockText(blockIndex - 1);\n const currText = ctx.doc.getBlockText(blockIndex);\n if (!prevText || !currText) return;\n const prevLen = prevText.length;\n const tail = currText.toString();\n if (tail.length > 0) prevText.insert(prevLen, tail);\n ctx.doc.blocks.delete(blockIndex, 1);\n ctx.setSelection(collapsedSelection({ blockIndex: blockIndex - 1, offset: prevLen }));\n}\n\n// ---------- List commands (Sub-phase 2.3) ----------\n\n/**\n * Convert every block in the selection to/from a `listItem` of `kind`.\n * If every covered block is already a `listItem` of `kind` → convert them all to paragraphs.\n * Otherwise → convert them all to `listItem` (keeping existing `listLevel` when already\n * a listItem, defaulting to 0 otherwise).\n */\nexport function toggleList(ctx: CommandContext, kind: ListKind): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n const allMatching = indices.every((i) => {\n const block = ctx.doc.getBlock(i);\n if (!block) return false;\n if (block.get(\"type\") !== \"listItem\") return false;\n const attrs = ctx.doc.getBlockAttrs(i);\n return attrs.listKind === kind;\n });\n for (const i of indices) {\n if (allMatching) {\n // Strip list → paragraph (defaults reset).\n setBlockTypeAtIndex(ctx.doc, i, \"paragraph\", {});\n } else {\n const prev = ctx.doc.getBlockAttrs(i);\n const level = clampLevel(prev.listLevel);\n setBlockTypeAtIndex(ctx.doc, i, \"listItem\", { listKind: kind, listLevel: level });\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/** Increase nesting of every listItem in the selection (clamped to MAX_LIST_LEVEL). */\nexport function indentList(ctx: CommandContext): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block || block.get(\"type\") !== \"listItem\") continue;\n const attrsMap = block.get(\"attrs\") as Y.Map<unknown>;\n const current = clampLevel((attrsMap.get(\"listLevel\") as number | undefined) ?? 0);\n const next = Math.min(current + 1, MAX_LIST_LEVEL);\n if (next !== current) attrsMap.set(\"listLevel\", next);\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Decrease nesting of every listItem in the selection.\n * When level was 0, demote to paragraph (escape from the list).\n */\nexport function dedentList(ctx: CommandContext): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block || block.get(\"type\") !== \"listItem\") continue;\n const attrsMap = block.get(\"attrs\") as Y.Map<unknown>;\n const current = clampLevel((attrsMap.get(\"listLevel\") as number | undefined) ?? 0);\n if (current > 0) {\n attrsMap.set(\"listLevel\", current - 1);\n } else {\n // Escape from the list at level 0.\n setBlockTypeAtIndex(ctx.doc, i, \"paragraph\", {});\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Enter behavior inside a listItem.\n * - Empty listItem at level > 0 → dedent (stays a listItem, one level out).\n * - Empty listItem at level 0 → convert to paragraph (exit the list).\n * - Non-empty → split: tail moves to a new listItem with same kind/level.\n *\n * Returns `true` when it handled the event; `false` to let the default `insertParagraph` run.\n */\nexport function splitListItem(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) return false;\n const pos = sel.focus;\n // Inside a table cell, Enter is handled by insertParagraph (newline within cell).\n if (pos.cellIndex != null) return false;\n const block = ctx.doc.getBlock(pos.blockIndex);\n if (!block || block.get(\"type\") !== \"listItem\") return false;\n const yText = ctx.doc.getBlockText(pos.blockIndex);\n if (!yText) return false;\n\n const attrs = ctx.doc.getBlockAttrs(pos.blockIndex);\n const kind = (attrs.listKind ?? \"bullet\") as ListKind;\n const level = clampLevel(attrs.listLevel ?? 0);\n\n transact(ctx.doc, () => {\n if (yText.length === 0) {\n if (level > 0) {\n const m = block.get(\"attrs\") as Y.Map<unknown>;\n m.set(\"listLevel\", level - 1);\n } else {\n setBlockTypeAtIndex(ctx.doc, pos.blockIndex, \"paragraph\", {});\n }\n ctx.setSelection(collapsedSelection({ blockIndex: pos.blockIndex, offset: 0 }));\n return;\n }\n const tail = yText.toString().slice(pos.offset);\n if (tail.length > 0) yText.delete(pos.offset, tail.length);\n ctx.doc.blocks.insert(pos.blockIndex + 1, [\n createBlock(\"listItem\", tail, { listKind: kind, listLevel: level }),\n ]);\n ctx.setSelection(collapsedSelection({ blockIndex: pos.blockIndex + 1, offset: 0 }));\n });\n return true;\n}\n\n/**\n * Internal: reset a single block's type + attrs (used by list commands).\n * Same merge rules as the public `setBlockType` but scoped to one block and\n * intended to run already inside a transaction.\n */\nfunction setBlockTypeAtIndex(\n doc: EditorDocument,\n index: number,\n type: BlockType,\n attrs: BlockAttrs,\n): void {\n const block = doc.getBlock(index);\n if (!block) return;\n block.set(\"type\", type);\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n const next = { ...defaultAttrsFor(type), ...attrs };\n const keep = new Set(Object.keys(next));\n for (const k of Array.from(attrsMap.keys())) {\n if (!keep.has(k)) attrsMap.delete(k);\n }\n for (const [k, v] of Object.entries(next)) {\n if (v === undefined) continue;\n if (attrsMap.get(k) !== v) attrsMap.set(k, v);\n }\n}\n\nfunction clampLevel(l: number | undefined): number {\n if (typeof l !== \"number\" || !Number.isFinite(l)) return 0;\n return Math.max(0, Math.min(MAX_LIST_LEVEL, Math.trunc(l)));\n}\n\n// ---------- Table commands (Sub-phase 4.1 / 4.2) ----------\n\n/**\n * Insert a fresh `rows × cols` table after the block currently holding the\n * caret (or at the end of the document if the selection is somehow invalid),\n * and place the caret in the table's first cell.\n *\n * Sub-phase 4.1 doesn't try to be clever: it does NOT replace an empty\n * preceding paragraph. Callers can clean that up themselves; an extra empty\n * paragraph above a table is a small price for predictable behavior.\n */\nexport function insertTable(ctx: CommandContext, rows: number, cols: number): void {\n const r = Math.max(1, Math.trunc(rows));\n const c = Math.max(1, Math.trunc(cols));\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n // Anchor point: the block holding the focus. If focus is inside a cell of\n // an existing table, insert AFTER that table.\n const focusBlock = Math.max(0, Math.min(sel.focus.blockIndex, ctx.doc.blockCount() - 1));\n const insertAt = focusBlock + 1;\n ctx.doc.blocks.insert(insertAt, [createTableBlock(r, c)]);\n ctx.setSelection(\n collapsedSelection({ blockIndex: insertAt, cellIndex: 0, offset: 0 }),\n );\n });\n}\n\n/** Remove the entire table at `blockIndex` and place the caret at the start of the next block (or the previous one if removal would leave the doc empty). */\nexport function deleteTable(ctx: CommandContext, blockIndex: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n transact(ctx.doc, () => {\n ctx.doc.blocks.delete(blockIndex, 1);\n if (ctx.doc.blocks.length === 0) {\n ctx.doc.blocks.push([createBlock(\"paragraph\")]);\n ctx.setSelection(collapsedSelection({ blockIndex: 0, offset: 0 }));\n return;\n }\n const targetIdx = Math.max(0, Math.min(blockIndex, ctx.doc.blockCount() - 1));\n const targetType = ctx.doc.getBlockType(targetIdx);\n if (targetType === \"table\") {\n ctx.setSelection(collapsedSelection({ blockIndex: targetIdx, cellIndex: 0, offset: 0 }));\n } else {\n ctx.setSelection(collapsedSelection({ blockIndex: targetIdx, offset: 0 }));\n }\n });\n}\n\n/**\n * Sub-phase 4.1 has no rowspan/colspan, so row/col operations are pure splice\n * on the flat `cells` array. The flat index of `(r, c)` is `r * cols + c`.\n */\n\nexport interface TableLocation {\n blockIndex: number;\n row: number;\n col: number;\n}\n\n/**\n * Derive `{row, col}` from a position inside a table — always pointing at the\n * owner of the targeted cell (covered cells redirect to their owner). Returns\n * null when the position isn't inside a table cell.\n */\nexport function tableLocationOf(\n doc: EditorDocument,\n pos: Position,\n): TableLocation | null {\n if (pos.cellIndex == null) return null;\n if (!doc.isTable(pos.blockIndex)) return null;\n const { cols } = doc.getTableSize(pos.blockIndex);\n if (cols <= 0) return null;\n const real = doc.realCellIndex(pos.blockIndex, pos.cellIndex);\n if (real == null) return null;\n const row = Math.floor(real / cols);\n const col = real - row * cols;\n return { blockIndex: pos.blockIndex, row, col };\n}\n\n/**\n * Insert a fresh row above (`where === \"before\"`) or below (`\"after\"`) the\n * given row. Spans that previously crossed the insertion boundary are extended\n * by 1; the corresponding columns of the new row become `covered: true`.\n */\nexport function insertTableRow(\n ctx: CommandContext,\n blockIndex: number,\n row: number,\n where: \"before\" | \"after\",\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n const targetRow = Math.max(0, Math.min(row, rows - 1));\n const P = where === \"before\" ? targetRow : targetRow + 1;\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Snapshot: for each column, does a span crossing the [P-1, P] boundary\n // cover this column at row P? Compute BEFORE mutating spans.\n const newRowCovered: boolean[] = new Array(cols).fill(false);\n if (P > 0 && P < rows) {\n // Walk row P-1 to find spans crossing into row P (i.e., or < P and or+rs > P).\n for (let r = 0; r < P; r++) {\n for (let c = 0; c < cols; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (r < P && r + rs > P) {\n for (let cc = c; cc < c + cs && cc < cols; cc++) newRowCovered[cc] = true;\n }\n }\n }\n // Now extend those spans' rowspan by 1.\n for (let r = 0; r < P; r++) {\n for (let c = 0; c < cols; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n if (r < P && r + rs > P) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"rowspan\", rs + 1);\n }\n }\n }\n }\n\n const fresh: Y.Map<unknown>[] = [];\n for (let c = 0; c < cols; c++) {\n fresh.push(createCell(newRowCovered[c] ? { covered: true } : undefined));\n }\n cells.insert(P * cols, fresh);\n attrs.set(\"rows\", rows + 1);\n // Caret on the first non-covered cell of the new row (falls back to flat-0\n // if every column is covered — pathologically possible only with bad data).\n const firstReal = newRowCovered.findIndex((v) => !v);\n const targetCellIdx = P * cols + (firstReal < 0 ? 0 : firstReal);\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: targetCellIdx, offset: 0 }),\n );\n });\n}\n\n/**\n * Remove `row` from the table. Spans that pass through the row are shortened\n * by one; spans that START at the row are removed AND the cell at row R+1 (in\n * each affected column) is promoted to be the new owner with `rowspan - 1`.\n * When it was the last row, deletes the whole table.\n */\nexport function deleteTableRow(ctx: CommandContext, blockIndex: number, row: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n if (rows === 1) {\n deleteTable(ctx, blockIndex);\n return;\n }\n const R = Math.max(0, Math.min(row, rows - 1));\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Phase 1: spans crossing R (started above, end at or after R): shorten by 1.\n for (let r = 0; r < R; r++) {\n for (let c = 0; c < cols; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n if (r < R && r + rs > R) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"rowspan\", rs - 1);\n if (rs - 1 === 1) m?.delete(\"rowspan\");\n }\n }\n }\n\n // Phase 2: spans starting AT row R with rowspan > 1: promote the cell at\n // (R+1, c) to be the new owner. Capture the promotion list FIRST so we\n // can apply changes after the row delete (since indices shift).\n interface Promotion {\n // Flat index AFTER the row delete.\n flatNew: number;\n rowspan: number;\n colspan: number;\n }\n const promotions: Promotion[] = [];\n for (let c = 0; c < cols; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, R * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (rs > 1 && R + 1 < rows) {\n // After delete, what was (R+1, c) becomes (R, c).\n promotions.push({ flatNew: R * cols + c, rowspan: rs - 1, colspan: cs });\n }\n }\n\n cells.delete(R * cols, cols);\n attrs.set(\"rows\", rows - 1);\n\n for (const p of promotions) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, p.flatNew);\n if (!m) continue;\n m.delete(\"covered\");\n if (p.rowspan > 1) m.set(\"rowspan\", p.rowspan); else m.delete(\"rowspan\");\n if (p.colspan > 1) m.set(\"colspan\", p.colspan); else m.delete(\"colspan\");\n }\n\n const newRow = Math.min(R, rows - 2);\n const target = findNextRealCell(ctx.doc, blockIndex, newRow * cols, (rows - 1) * cols) ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: target, offset: 0 }),\n );\n });\n}\n\n/**\n * Insert a fresh column to the left (`\"before\"`) or right (`\"after\"`) of `col`.\n * Spans crossing the insertion column have `colspan += 1`; the new column's\n * cells in covered rows are themselves `covered: true`.\n *\n * Also resizes `colWidths` (if defined) by inserting a default width.\n */\nexport function insertTableColumn(\n ctx: CommandContext,\n blockIndex: number,\n col: number,\n where: \"before\" | \"after\",\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n const targetCol = Math.max(0, Math.min(col, cols - 1));\n const C = where === \"before\" ? targetCol : targetCol + 1;\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Snapshot covered rows BEFORE mutating spans.\n const newColCovered: boolean[] = new Array(rows).fill(false);\n if (C > 0 && C < cols) {\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n for (let rr = r; rr < r + rs && rr < rows; rr++) newColCovered[rr] = true;\n }\n }\n }\n // Extend colspans.\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"colspan\", cs + 1);\n }\n }\n }\n }\n\n // Walk rows LAST→FIRST so insert indices stay correct.\n for (let r = rows - 1; r >= 0; r--) {\n const at = r * cols + C;\n cells.insert(at, [createCell(newColCovered[r] ? { covered: true } : undefined)]);\n }\n attrs.set(\"cols\", cols + 1);\n\n // Resize colWidths if present — insert a 100px placeholder for the new col.\n const widths = attrs.get(\"colWidths\") as number[] | undefined;\n if (Array.isArray(widths) && widths.length === cols) {\n const next = widths.slice();\n next.splice(C, 0, 100);\n attrs.set(\"colWidths\", next);\n }\n\n const newCols = cols + 1;\n const focusRow = 0;\n const firstReal = newColCovered.findIndex((_, r) => r === focusRow && !newColCovered[r]);\n ctx.setSelection(\n collapsedSelection({\n blockIndex,\n cellIndex: focusRow * newCols + C + (firstReal < 0 ? 0 : 0),\n offset: 0,\n }),\n );\n });\n}\n\n/**\n * Remove `col` from the table. Spans that pass through the column are\n * shortened by one; spans that START at the column with `colspan > 1` get\n * their owner promoted from (r, C+1) to take over with `colspan - 1`.\n *\n * Also shrinks `colWidths` (if defined). When it was the last column, deletes\n * the whole table.\n */\nexport function deleteTableColumn(ctx: CommandContext, blockIndex: number, col: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n if (cols === 1) {\n deleteTable(ctx, blockIndex);\n return;\n }\n const C = Math.max(0, Math.min(col, cols - 1));\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Phase 1: spans crossing C — colspan -= 1.\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"colspan\", cs - 1);\n if (cs - 1 === 1) m?.delete(\"colspan\");\n }\n }\n }\n\n // Phase 2: capture promotions for spans starting at column C with colspan > 1.\n // After deletion, what was (r, C+1) becomes (r, C). Capture both the\n // FUTURE flat index in the post-delete (rows x (cols-1)) grid and the\n // attrs to apply.\n interface Promotion {\n flatNew: number;\n rowspan: number;\n colspan: number;\n }\n const promotions: Promotion[] = [];\n const newCols = cols - 1;\n for (let r = 0; r < rows; r++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + C);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (cs > 1 && C + 1 < cols) {\n promotions.push({\n flatNew: r * newCols + C,\n rowspan: rs,\n colspan: cs - 1,\n });\n }\n }\n\n // Walk rows LAST→FIRST so deletions don't perturb indices we still need.\n for (let r = rows - 1; r >= 0; r--) {\n const at = r * cols + C;\n cells.delete(at, 1);\n }\n attrs.set(\"cols\", newCols);\n\n for (const p of promotions) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, p.flatNew);\n if (!m) continue;\n m.delete(\"covered\");\n if (p.rowspan > 1) m.set(\"rowspan\", p.rowspan); else m.delete(\"rowspan\");\n if (p.colspan > 1) m.set(\"colspan\", p.colspan); else m.delete(\"colspan\");\n }\n\n // Trim colWidths.\n const widths = attrs.get(\"colWidths\") as number[] | undefined;\n if (Array.isArray(widths) && widths.length === cols) {\n const next = widths.slice();\n next.splice(C, 1);\n attrs.set(\"colWidths\", next);\n }\n\n const newCol = Math.min(C, newCols - 1);\n const target = findNextRealCell(ctx.doc, blockIndex, newCol, rows * newCols) ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: target, offset: 0 }),\n );\n });\n}\n\n// ---------- Rectangular cell selection (Sub-phase 4.5) ----------\n\nexport interface TableRect {\n blockIndex: number;\n /** Inclusive bounds in OWNER coordinates. */\n top: number;\n left: number;\n bottom: number;\n right: number;\n}\n\n/**\n * Interpret a `Selection` as a rectangular cell range when:\n * - Both endpoints carry `cellIndex`.\n * - They live in the same table block.\n * - They point to DIFFERENT owner cells.\n *\n * The naive bounds are then EXPANDED until every span fully fits inside —\n * essential so that operations like `mergeSelection` can never produce a\n * non-rectangular shape, and so visual highlights always cover whole spans.\n */\nexport function tableRectSelection(\n doc: EditorDocument,\n sel: Selection,\n): TableRect | null {\n if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;\n if (sel.anchor.cellIndex == null || sel.focus.cellIndex == null) return null;\n const blockIndex = sel.anchor.blockIndex;\n if (!doc.isTable(blockIndex)) return null;\n const aLoc = tableLocationOf(doc, sel.anchor);\n const fLoc = tableLocationOf(doc, sel.focus);\n if (!aLoc || !fLoc) return null;\n // After redirection to owners, anchor and focus may collapse to the same\n // owner cell (e.g. anchor in an owner, focus in one of its covered cells).\n if (aLoc.row === fLoc.row && aLoc.col === fLoc.col) return null;\n return expandTableRect(\n doc,\n blockIndex,\n Math.min(aLoc.row, fLoc.row),\n Math.min(aLoc.col, fLoc.col),\n Math.max(aLoc.row, fLoc.row),\n Math.max(aLoc.col, fLoc.col),\n );\n}\n\n/**\n * Grow a candidate rect until every owner whose span starts within the rect\n * fits entirely, and every covered cell inside it has its owner inside too.\n * Converges in O(rows × cols) iterations in the worst case (each pass either\n * grows a bound or terminates).\n */\nexport function expandTableRect(\n doc: EditorDocument,\n blockIndex: number,\n initTop: number,\n initLeft: number,\n initBottom: number,\n initRight: number,\n): TableRect {\n const { rows, cols } = doc.getTableSize(blockIndex);\n let top = Math.max(0, initTop);\n let left = Math.max(0, initLeft);\n let bottom = Math.min(rows - 1, initBottom);\n let right = Math.min(cols - 1, initRight);\n\n let changed = true;\n let guard = rows * cols + 1;\n while (changed && guard-- > 0) {\n changed = false;\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n const a = doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) {\n const owner = doc.realCellIndex(blockIndex, idx);\n if (owner == null) continue;\n const oRow = Math.floor(owner / cols);\n const oCol = owner - oRow * cols;\n if (oRow < top) { top = oRow; changed = true; }\n if (oCol < left) { left = oCol; changed = true; }\n // Owner's far edge:\n const oAttrs = doc.getCellAttrs(blockIndex, owner);\n const oRs = spanOf(oAttrs.rowspan);\n const oCs = spanOf(oAttrs.colspan);\n if (oRow + oRs - 1 > bottom) { bottom = oRow + oRs - 1; changed = true; }\n if (oCol + oCs - 1 > right) { right = oCol + oCs - 1; changed = true; }\n } else {\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (r + rs - 1 > bottom) { bottom = r + rs - 1; changed = true; }\n if (c + cs - 1 > right) { right = c + cs - 1; changed = true; }\n }\n }\n }\n }\n return { blockIndex, top, left, bottom, right };\n}\n\n/** Enumerate every cell-index (real or covered) contained in `rect`. */\nexport function cellsInRect(doc: EditorDocument, rect: TableRect): number[] {\n const { cols } = doc.getTableSize(rect.blockIndex);\n const out: number[] = [];\n for (let r = rect.top; r <= rect.bottom; r++) {\n for (let c = rect.left; c <= rect.right; c++) out.push(r * cols + c);\n }\n return out;\n}\n\n/**\n * Merge every cell in the current rectangular selection into one owner at the\n * rect's top-left. The owner's text is the concatenation of all non-empty\n * inner texts (space-separated, mark-preserving). Returns true on success, false\n * when there is no rect selection.\n */\nexport function mergeSelection(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const rect = tableRectSelection(ctx.doc, sel);\n if (!rect) return false;\n const { blockIndex, top, left, bottom, right } = rect;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n const ownerIdx = top * cols + left;\n\n transact(ctx.doc, () => {\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n if (!ownerText) return;\n\n // Walk every cell in the rect (skip the owner itself). For real cells with\n // non-empty text, append to owner.\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n if (idx === ownerIdx) continue;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered !== true) {\n const t = ctx.doc.getCellText(blockIndex, idx);\n if (t && t.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n const delta = t.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n t.delete(0, t.length);\n }\n }\n // Reset attrs to \"covered\" — drops any prior rowspan/colspan.\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n if (m) {\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n }\n // Update owner spans.\n const oMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (oMap) {\n const newRs = bottom - top + 1;\n const newCs = right - left + 1;\n if (newRs > 1) oMap.set(\"rowspan\", newRs); else oMap.delete(\"rowspan\");\n if (newCs > 1) oMap.set(\"colspan\", newCs); else oMap.delete(\"colspan\");\n oMap.delete(\"covered\");\n }\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }),\n );\n });\n return true;\n}\n\n/**\n * Clears the text of every cell in the current rectangular selection (no\n * structural mutation — spans stay intact). Returns the collapsed selection\n * at the rect's top-left when something was cleared, otherwise null.\n */\nexport function clearRectCells(ctx: CommandContext): Selection | null {\n const sel = ctx.getSelection();\n const rect = tableRectSelection(ctx.doc, sel);\n if (!rect) return null;\n const { blockIndex, top, left, bottom, right } = rect;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n const ownerIdx = top * cols + left;\n let result: Selection | null = null;\n transact(ctx.doc, () => {\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const t = ctx.doc.getCellText(blockIndex, idx);\n if (t && t.length > 0) t.delete(0, t.length);\n }\n }\n result = collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 });\n ctx.setSelection(result);\n });\n return result;\n}\n\n// ---------- Merge / split ----------\n\n/**\n * Merge the cell at `(row, col)` with its immediate right neighbor. The right\n * neighbor must be a real cell with matching `rowspan` (otherwise the merge\n * would form a non-rectangle). Returns true on success, false on shape\n * mismatch or when there is no neighbor.\n *\n * After: the owner's `colspan` grows by the neighbor's `colspan`; the\n * neighbor and all its formerly-covered cells in the merged rectangle are\n * marked `covered: true`. The neighbor's text is appended to the owner with a\n * single space delimiter (when both sides had content).\n */\nexport function mergeRight(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const ownerIdx = row * cols + col;\n const ownerAttrs = ctx.doc.getCellAttrs(blockIndex, ownerIdx);\n if (ownerAttrs.covered === true) return false;\n const ownerRs = spanOf(ownerAttrs.rowspan);\n const ownerCs = spanOf(ownerAttrs.colspan);\n const nbCol = col + ownerCs;\n if (nbCol >= cols) return false;\n const nbIdx = row * cols + nbCol;\n const nbAttrs = ctx.doc.getCellAttrs(blockIndex, nbIdx);\n if (nbAttrs.covered === true) return false;\n const nbRs = spanOf(nbAttrs.rowspan);\n const nbCs = spanOf(nbAttrs.colspan);\n if (nbRs !== ownerRs) return false;\n\n transact(ctx.doc, () => {\n // Append neighbor's text into the owner.\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n const nbText = ctx.doc.getCellText(blockIndex, nbIdx);\n if (ownerText && nbText && nbText.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n // Re-apply delta with marks and embeds preserved.\n const delta = nbText.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n }\n // Clear neighbor text.\n if (nbText && nbText.length > 0) nbText.delete(0, nbText.length);\n\n // Owner gets the widened colspan.\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (ownerMap) ownerMap.set(\"colspan\", ownerCs + nbCs);\n\n // Mark all cells in the neighbor's old rectangle as covered (in case nbCs > 1,\n // they were already covered — flag still applies).\n for (let r = row; r < row + ownerRs; r++) {\n for (let c = nbCol; c < nbCol + nbCs; c++) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }));\n });\n return true;\n}\n\n/** Merge with the immediate bottom neighbor. Mirror of `mergeRight`. */\nexport function mergeDown(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const ownerIdx = row * cols + col;\n const ownerAttrs = ctx.doc.getCellAttrs(blockIndex, ownerIdx);\n if (ownerAttrs.covered === true) return false;\n const ownerRs = spanOf(ownerAttrs.rowspan);\n const ownerCs = spanOf(ownerAttrs.colspan);\n const nbRow = row + ownerRs;\n if (nbRow >= rows) return false;\n const nbIdx = nbRow * cols + col;\n const nbAttrs = ctx.doc.getCellAttrs(blockIndex, nbIdx);\n if (nbAttrs.covered === true) return false;\n const nbRs = spanOf(nbAttrs.rowspan);\n const nbCs = spanOf(nbAttrs.colspan);\n if (nbCs !== ownerCs) return false;\n\n transact(ctx.doc, () => {\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n const nbText = ctx.doc.getCellText(blockIndex, nbIdx);\n if (ownerText && nbText && nbText.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n const delta = nbText.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n }\n if (nbText && nbText.length > 0) nbText.delete(0, nbText.length);\n\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (ownerMap) ownerMap.set(\"rowspan\", ownerRs + nbRs);\n\n for (let r = nbRow; r < nbRow + nbRs; r++) {\n for (let c = col; c < col + ownerCs; c++) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }));\n });\n return true;\n}\n\n/**\n * Split a merged cell back into a `rowspan × colspan` grid of independent real\n * cells. Each formerly-covered cell becomes empty and real. Returns true when\n * something was split. No-op (returns false) on a cell with no spans.\n */\nexport function splitCell(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const idx = row * cols + col;\n const attrs = ctx.doc.getCellAttrs(blockIndex, idx);\n if (attrs.covered === true) return false;\n const rs = spanOf(attrs.rowspan);\n const cs = spanOf(attrs.colspan);\n if (rs === 1 && cs === 1) return false;\n\n transact(ctx.doc, () => {\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, idx);\n if (ownerMap) {\n ownerMap.delete(\"rowspan\");\n ownerMap.delete(\"colspan\");\n }\n for (let r = row; r < row + rs; r++) {\n for (let c = col; c < col + cs; c++) {\n if (r === row && c === col) continue;\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"covered\");\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: idx, offset: 0 }));\n });\n return true;\n}\n\n// ---------- Column widths (Sub-phase 4.4) ----------\n\n/** Set the width (in CSS px) of a specific column. Auto-initializes `colWidths`. */\nexport function setColumnWidth(\n ctx: CommandContext,\n blockIndex: number,\n col: number,\n widthPx: number,\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n if (col < 0 || col >= cols) return;\n const w = Math.max(20, Math.round(widthPx));\n transact(ctx.doc, () => {\n const attrsMap = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!attrsMap) return;\n const current = attrsMap.get(\"colWidths\") as number[] | undefined;\n const next = Array.isArray(current) && current.length === cols\n ? current.slice()\n : new Array<number>(cols).fill(120);\n next[col] = w;\n attrsMap.set(\"colWidths\", next);\n });\n}\n\n/**\n * Move the caret to the next cell of the same table (Tab). At the last cell of\n * the last row, creates a new row and lands in its first cell. Returns true\n * when handled. Caret must be inside a table for this to act.\n */\nexport function moveToNextCell(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const loc = tableLocationOf(ctx.doc, sel.focus);\n if (!loc) return false;\n const { rows, cols } = ctx.doc.getTableSize(loc.blockIndex);\n if (rows <= 0 || cols <= 0) return false;\n\n // Walk forward starting at the cell immediately following the owner's bottom-right.\n // For a non-spanning cell that's `flat + 1`; for a span, it's `(loc.row, loc.col + colspan)`\n // — but conceptually the owner's \"next\" sibling is simply the next real cell in row-major\n // order after the owner's flat index, since covered cells get skipped by the loop below.\n const startFlat = loc.row * cols + loc.col + 1;\n const next = findNextRealCell(ctx.doc, loc.blockIndex, startFlat, rows * cols);\n if (next == null) {\n // No more cells in the table — append a new row and land in its first cell.\n insertTableRow(ctx, loc.blockIndex, rows - 1, \"after\");\n return true;\n }\n ctx.setSelection(\n collapsedSelection({ blockIndex: loc.blockIndex, cellIndex: next, offset: 0 }),\n );\n return true;\n}\n\n/** Move the caret to the previous cell (Shift+Tab). At the first cell, no-op (returns true). */\nexport function moveToPrevCell(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const loc = tableLocationOf(ctx.doc, sel.focus);\n if (!loc) return false;\n const { rows, cols } = ctx.doc.getTableSize(loc.blockIndex);\n if (rows <= 0 || cols <= 0) return false;\n const startFlat = loc.row * cols + loc.col - 1;\n if (startFlat < 0) return true; // at (0,0) — handled but no-op\n const prev = findPrevRealCell(ctx.doc, loc.blockIndex, startFlat);\n if (prev == null) return true;\n const cellText = ctx.doc.getCellText(loc.blockIndex, prev);\n const off = cellText?.length ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex: loc.blockIndex, cellIndex: prev, offset: off }),\n );\n return true;\n}\n\nfunction findNextRealCell(\n doc: EditorDocument,\n blockIndex: number,\n startFlat: number,\n total: number,\n): number | null {\n for (let i = startFlat; i < total; i++) {\n if (doc.getCellAttrs(blockIndex, i).covered !== true) return i;\n }\n return null;\n}\n\nfunction findPrevRealCell(\n doc: EditorDocument,\n blockIndex: number,\n startFlat: number,\n): number | null {\n for (let i = startFlat; i >= 0; i--) {\n if (doc.getCellAttrs(blockIndex, i).covered !== true) return i;\n }\n return null;\n}\n\n/**\n * Append/write a delta's ops into `yText` starting at `pos`, preserving marks\n * AND image embeds. Returns the position right after the last write.\n */\nfunction writeDeltaInto(yText: Y.Text, pos: number, delta: DeltaOp[]): number {\n let cursor = pos;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n if (op.insert.length === 0) continue;\n if (op.attributes && Object.keys(op.attributes).length > 0) {\n yText.insert(cursor, op.insert, op.attributes as Record<string, unknown>);\n } else {\n yText.insert(cursor, op.insert);\n }\n cursor += op.insert.length;\n } else if (op.insert != null) {\n // Embed (e.g. ImageEmbed). Y.Text accepts arbitrary JSON-serializable\n // objects as length-1 inserts.\n if (op.attributes && Object.keys(op.attributes).length > 0) {\n yText.insert(\n cursor,\n op.insert as unknown as string,\n op.attributes as Record<string, unknown>,\n );\n } else {\n yText.insert(cursor, op.insert as unknown as string);\n }\n cursor += 1;\n }\n }\n return cursor;\n}\n\n// ---------- Inline embeds (Fase 5: imagens) ----------\n\n/**\n * Insert an inline image embed at the current selection. Embeds occupy 1 char\n * in offset arithmetic (Y.Text treats them as length-1 inserts).\n */\nexport function insertImage(ctx: CommandContext, embed: ImageEmbed): void {\n clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel0 = ctx.getSelection();\n let cursor = sel0;\n if (!isCollapsed(sel0)) cursor = deleteRange(ctx.doc, sel0);\n const pos = cursor.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n // Y.Text accepts non-string inserts natively.\n yText.insert(pos.offset, embed as unknown as string);\n const newPos: Position = {\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + 1,\n };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\n/**\n * Update attributes of an existing image embed at `(blockIndex, embedOffset)`.\n * Implementation: delete the 1-char slot and re-insert the merged embed in the\n * SAME transaction — Y.UndoManager coalesces delete+insert in one transact, so\n * undo treats it as a single step.\n *\n * If `newOffset` is provided and differs from `embedOffset`, the embed is moved\n * to that offset within the same block/cell. Used by wrap-left/wrap-right\n * layouts which must anchor the image at the block start so floated text wraps\n * around it (CSS float only flows text that comes AFTER the float in DOM order).\n */\nexport function setImageAttrs(\n ctx: CommandContext,\n blockIndex: number,\n embedOffset: number,\n partial: Partial<ImageEmbed>,\n cellIndex?: number,\n newOffset?: number,\n): void {\n transact(ctx.doc, () => {\n const yText = ctx.doc.textAt(blockIndex, cellIndex);\n if (!yText) return;\n const delta = yText.toDelta() as DeltaOp[];\n let cursor = 0;\n let prev: ImageEmbed | null = null;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n cursor += op.insert.length;\n continue;\n }\n if (cursor === embedOffset && isImageEmbed(op.insert)) {\n prev = op.insert;\n break;\n }\n cursor += 1;\n }\n if (!prev) return;\n const merged: ImageEmbed = { ...prev, ...partial };\n yText.delete(embedOffset, 1);\n const insertAt =\n newOffset != null && newOffset !== embedOffset\n ? Math.max(0, Math.min(newOffset, yText.length))\n : embedOffset;\n yText.insert(insertAt, merged as unknown as string);\n });\n}\n\n// Expose the Y origin so consumers (e.g. UndoManager) can filter on it.\nexport function isCommandOrigin(origin: unknown): boolean {\n return origin === COMMAND_ORIGIN;\n}\n\n// Allow Y.UndoManager.trackedOrigins to include the symbol.\nexport const TRACKED_ORIGINS: Set<unknown> = new Set([COMMAND_ORIGIN]);\n\n// Re-export Y for downstream type checks if needed.\nexport { Y };\n","import * as Y from \"yjs\";\nimport type { EditorDocument } from \"./document\";\nimport { TRACKED_ORIGINS } from \"./commands\";\n\nexport class EditorHistory {\n readonly undoManager: Y.UndoManager;\n\n constructor(doc: EditorDocument) {\n this.undoManager = new Y.UndoManager(doc.blocks, {\n trackedOrigins: TRACKED_ORIGINS,\n captureTimeout: 400,\n });\n }\n\n undo(): boolean {\n return this.undoManager.undo() != null;\n }\n\n redo(): boolean {\n return this.undoManager.redo() != null;\n }\n\n destroy(): void {\n this.undoManager.destroy();\n }\n}\n"],"mappings":"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","names":["merged","yText","Y","yText","Y"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/schema.ts","../src/page-settings.ts","../src/document.ts","../src/selection.ts","../src/marks.ts","../src/commands.ts","../src/history.ts"],"sourcesContent":["/**\n * Public type definitions for the document model.\n * The runtime representation lives in Y.js (see document.ts);\n * these types describe its shape for consumers.\n */\n\nexport type BlockType =\n | \"paragraph\"\n | \"heading\"\n | \"blockquote\"\n | \"codeBlock\"\n | \"listItem\"\n | \"table\";\n\nexport type AlignValue = \"left\" | \"center\" | \"right\" | \"justify\";\nexport type DirValue = \"ltr\" | \"rtl\";\nexport type ListKind = \"bullet\" | \"ordered\";\n\nexport type ListStyleType =\n | \"decimal\"\n | \"lower-alpha\"\n | \"upper-alpha\"\n | \"lower-roman\"\n | \"upper-roman\";\n\n/** Maximum supported list nesting (0 = top level). */\nexport const MAX_LIST_LEVEL = 5;\n\nexport interface BlockAttrs {\n align?: AlignValue;\n dir?: DirValue;\n /** Only meaningful when `type === \"heading\"`. 1..6. */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Only meaningful when `type === \"codeBlock\"`. Free-form (CSS-style language hint). */\n language?: string;\n /** Only meaningful when `type === \"listItem\"`. */\n listKind?: ListKind;\n /** Only meaningful when `type === \"listItem\"`. 0..MAX_LIST_LEVEL. */\n listLevel?: number;\n /**\n * Only meaningful when `type === \"listItem\"` and `listKind === \"ordered\"`.\n * When set on a listItem, that item starts a NEW list group whose first\n * `<ol>` carries `start={listStart}`. Used to renumerate questions or pick\n * up an interrupted sequence.\n */\n listStart?: number;\n /**\n * Only meaningful when `type === \"listItem\"`. Overrides the default per-level\n * CSS cycle (decimal → lower-alpha → lower-roman) with an explicit style.\n * Like `listStart`, setting this on a listItem breaks the group so the new\n * `<ol>` carries the requested `list-style-type`.\n */\n listStyle?: ListStyleType;\n /** Only meaningful when `type === \"table\"`. */\n rows?: number;\n /** Only meaningful when `type === \"table\"`. */\n cols?: number;\n /**\n * Only meaningful when `type === \"table\"`. Per-column widths in CSS px.\n * Length should equal `cols` when set; missing or short arrays fall back to\n * an auto distribution at render time.\n */\n colWidths?: number[];\n}\n\nexport interface CellAttrs {\n /**\n * Number of rows this cell spans, starting at its row. Default 1.\n * Only meaningful on REAL cells (not covered).\n */\n rowspan?: number;\n /** Default 1. Only meaningful on REAL cells. */\n colspan?: number;\n /**\n * `true` iff this cell is occluded by an owning cell with a `rowspan`/`colspan`\n * spanning into this position. Covered cells do not render their own `<td>`,\n * never accept input, and are skipped by Tab navigation.\n *\n * The cells array keeps `rows * cols` entries to preserve the row-major index\n * scheme — covered cells are placeholders, not gaps.\n */\n covered?: true;\n}\n\nexport interface Position {\n blockIndex: number;\n /**\n * When the caret is inside a table cell, identifies which cell within the\n * table at `blockIndex`. Flat row-major index: `row * cols + col`.\n * `undefined` means the position addresses the block's own text (or the block\n * itself, for atomic blocks). Tables have no own text — every caret position\n * inside a table block carries a defined `cellIndex`.\n */\n cellIndex?: number;\n offset: number;\n}\n\nexport interface Selection {\n anchor: Position;\n focus: Position;\n}\n\nexport type MarkName =\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strike\"\n | \"color\"\n | \"fontFamily\"\n | \"fontSize\"\n | \"link\"\n | \"comment\";\n\nexport interface LinkAttr {\n href: string;\n title?: string;\n}\n\nexport interface CommentAttr {\n /** Identificador estável compartilhado com o backend (ProvaDocumentoComentario.markId). */\n markId: string;\n}\n\nexport interface MarkAttrs {\n bold?: true;\n italic?: true;\n underline?: true;\n strike?: true;\n color?: string;\n fontFamily?: string;\n fontSize?: string;\n link?: LinkAttr;\n comment?: CommentAttr;\n}\n\nexport type MarkValue<K extends MarkName = MarkName> = NonNullable<MarkAttrs[K]>;\n\n/**\n * Visual layout mode for an image embed.\n *\n * - `inline` (default): part of the text run, flows like a character.\n * - `wrap-left` / `wrap-right`: image floats to the named side of the anchor\n * paragraph (Word-style \"wrap square\"). Text in the paragraph wraps around it.\n * - `behind`: image is absolutely positioned beneath the text (z-index < text).\n * - `front`: image is absolutely positioned above the text (z-index > text).\n *\n * In every non-inline mode the embed remains in the Y.Text run at its offset —\n * the offset is its **anchor** (it follows the paragraph during pagination\n * and re-flows). Visual position is offset from the anchor block's content box.\n */\nexport type ImageLayout = \"inline\" | \"wrap-left\" | \"wrap-right\" | \"behind\" | \"front\";\n\nexport interface ImageEmbed {\n type: \"image\";\n /** Data URL (base64) — self-contained so the embed travels with the Y.Doc. */\n src: string;\n /** Rendered CSS px (display size — may differ from intrinsic dimensions). */\n width: number;\n height: number;\n /** When set (inline mode only), the image renders `display: block` with the matching margin auto. */\n align?: \"left\" | \"center\" | \"right\";\n /** Visual layout. Defaults to \"inline\" when omitted. */\n layout?: ImageLayout;\n /**\n * Horizontal offset in CSS px from the anchor block's content box.\n * - wrap-left: extra left margin from the paragraph's start edge.\n * - wrap-right: extra right margin from the paragraph's end edge.\n * - behind / front: `left` relative to the anchor block's padding-box.\n * Ignored for `inline`.\n */\n offsetX?: number;\n /**\n * Vertical offset in CSS px from the anchor block's content box.\n * - wrap-left / wrap-right: extra top margin pushing the float down inside\n * the paragraph.\n * - behind / front: `top` relative to the anchor block's padding-box.\n * Ignored for `inline`.\n */\n offsetY?: number;\n /**\n * Optional plain-text caption. Renders inside a `<figcaption>` beneath the\n * image in any layout — the figure wraps the image so the caption travels\n * with floats/anchors. Plain text only; rich marks are out of scope (we\n * never want a sub-editor inside an inline embed).\n */\n caption?: string;\n /**\n * Text alignment for the caption. Defaults to \"center\" (Word/Google Docs\n * default for figure captions). Only meaningful when `caption` is set.\n * Note: DOCX export emits captions inside the host paragraph, so this\n * setting only affects the editor and HTML/PDF exports — Word displays the\n * caption using the paragraph's own alignment.\n */\n captionAlign?: \"left\" | \"center\" | \"right\";\n}\n\nexport type InsertContent = string | ImageEmbed;\n\nexport function isImageEmbed(v: unknown): v is ImageEmbed {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as { type?: unknown }).type === \"image\" &&\n typeof (v as { src?: unknown }).src === \"string\"\n );\n}\n\nexport interface DeltaOp {\n insert: InsertContent;\n attributes?: MarkAttrs;\n}\n\nexport interface SerializedCell {\n /** Plain concatenated text. */\n text: string;\n /** Delta with marks. */\n delta: DeltaOp[];\n attrs: CellAttrs;\n}\n\nexport interface SerializedBlock {\n type: BlockType;\n /** Plain concatenated text (no marks). Kept for ergonomic equality checks. */\n text: string;\n /** Yjs delta — used by the renderer to draw mark-aware spans. */\n delta: DeltaOp[];\n /** Block-level attributes (align, dir, heading level, code language…). */\n attrs: BlockAttrs;\n /** Only present when `type === \"table\"`. Flat row-major list, length = rows * cols. */\n cells?: SerializedCell[];\n}\n\nimport type { PageSettings } from \"./page-settings\";\n\n/**\n * Document JSON shape used by `EditorDocument.toJSON` / `fromJSON`, the\n * exporters and the importer. Until Fase 9.5 this was a bare `SerializedBlock[]`;\n * Fase 9.6 promoted it to an object so per-document settings (page size,\n * margins) can travel with the content.\n *\n * `fromJSON` still accepts a legacy array for backwards compatibility — see\n * `isLegacySerializedDocument`.\n */\nexport interface SerializedDocument {\n blocks: SerializedBlock[];\n /** Page settings. Optional; omitted means default A4 + 1\" margins. */\n pageSettings?: PageSettings;\n}\n\n/** A `SerializedDocument` produced before Fase 9.6 — just an array of blocks. */\nexport type LegacySerializedDocument = SerializedBlock[];\n\nexport function isLegacySerializedDocument(\n v: SerializedDocument | LegacySerializedDocument,\n): v is LegacySerializedDocument {\n return Array.isArray(v);\n}\n","import type { BlockAttrs, BlockType } from \"./types\";\n\ninterface BlockSpec {\n type: BlockType;\n defaultAttrs: BlockAttrs;\n}\n\nexport const BLOCK_SPECS: Record<BlockType, BlockSpec> = {\n paragraph: {\n type: \"paragraph\",\n defaultAttrs: {},\n },\n heading: {\n type: \"heading\",\n defaultAttrs: { level: 1 },\n },\n blockquote: {\n type: \"blockquote\",\n defaultAttrs: {},\n },\n codeBlock: {\n type: \"codeBlock\",\n defaultAttrs: {},\n },\n listItem: {\n type: \"listItem\",\n defaultAttrs: { listKind: \"bullet\", listLevel: 0 },\n },\n table: {\n type: \"table\",\n defaultAttrs: { rows: 1, cols: 1 },\n },\n};\n\nexport function isKnownBlockType(t: string): t is BlockType {\n return t in BLOCK_SPECS;\n}\n\nexport function defaultAttrsFor(type: BlockType): BlockAttrs {\n return { ...BLOCK_SPECS[type].defaultAttrs };\n}\n","/**\n * Document-level page configuration: physical size and margins.\n *\n * Everything is stored in **CSS pixels @ 96dpi** for consistency with the\n * pagination engine (`packages/react/src/usePagination.ts` reads these\n * directly). Conversion helpers (`mmToPx`, `pxToMm`) round-trip with millimeter\n * inputs from the UI and the OOXML twip values used by docx import/export.\n */\n\nexport type PagePreset = \"a4\" | \"letter\" | \"oficio\" | \"custom\";\n\nexport interface PageSettings {\n /** Page width in CSS px. */\n width: number;\n /** Page height in CSS px. */\n height: number;\n marginTop: number;\n marginBottom: number;\n marginLeft: number;\n marginRight: number;\n /**\n * The preset whose size the geometry matches, with the ±0.5mm tolerance used\n * by `detectPreset`. \"custom\" when the dimensions don't match any preset.\n * This is purely a UI hint — it's recomputed from width/height when needed.\n */\n preset?: PagePreset;\n /**\n * Free-form title persisted on the document for a consumer-rendered\n * \"system header\" (e.g. a non-editable letterhead/identification block\n * drawn on page 1 via `renderPageHeader`). Stored in `docSettings` so it\n * survives serialization and is visible to every client/consumer of the\n * `SerializedDocument`, including headless exports.\n *\n * The renderer is application-defined — this field just transports the\n * title string. Use it when the header content is part of the document\n * (and therefore must round-trip through exports), not a UI chrome\n * decoration.\n */\n systemHeaderTitle?: string;\n /**\n * Owner/author display name for the same consumer-rendered system\n * header (see [[systemHeaderTitle]]). Useful when the header should\n * show the document's CREATOR, not the current viewer (e.g. an author\n * name on a doc viewed by a third party). Persisted in `docSettings`\n * for consistent rendering across clients and headless renderers.\n */\n systemHeaderAuthor?: string;\n}\n\n/** Page sizes in CSS px @ 96dpi. */\nexport const PAGE_PRESETS = {\n a4: { width: 794, height: 1123 }, // 210×297 mm\n letter: { width: 816, height: 1056 }, // 8.5×11 in\n oficio: { width: 816, height: 1248 }, // 216×330 mm (BR Ofício)\n} as const;\n\n/** Margin presets in CSS px. Match common Word defaults. */\nexport const MARGIN_PRESETS = {\n normal: 96, // 25.4 mm = 1 in\n narrow: 48, // 12.7 mm = 0.5 in\n wide: 192, // 50.8 mm = 2 in\n} as const;\n\nexport const DEFAULT_PAGE_SETTINGS: PageSettings = {\n ...PAGE_PRESETS.a4,\n marginTop: MARGIN_PRESETS.normal,\n marginBottom: MARGIN_PRESETS.normal,\n marginLeft: MARGIN_PRESETS.normal,\n marginRight: MARGIN_PRESETS.normal,\n preset: \"a4\",\n};\n\nconst PX_PER_MM = 96 / 25.4;\n\nexport function mmToPx(mm: number): number {\n return mm * PX_PER_MM;\n}\n\nexport function pxToMm(px: number): number {\n return px / PX_PER_MM;\n}\n\n/**\n * Detect which preset a (width, height) pair matches. Tolerance is ±0.5mm to\n * absorb rounding from the twips↔px conversion used by docx round-trip.\n */\nexport function detectPreset(width: number, height: number): PagePreset {\n const TOL = mmToPx(0.5);\n for (const [name, size] of Object.entries(PAGE_PRESETS) as Array<[PagePreset, { width: number; height: number }]>) {\n if (Math.abs(width - size.width) <= TOL && Math.abs(height - size.height) <= TOL) {\n return name;\n }\n }\n return \"custom\";\n}\n\n/** Fill missing fields with the default. Useful when reading from a Y.Map that may be partially populated. */\nexport function withDefaults(partial: Partial<PageSettings> | undefined): PageSettings {\n const merged = { ...DEFAULT_PAGE_SETTINGS, ...(partial ?? {}) };\n return { ...merged, preset: detectPreset(merged.width, merged.height) };\n}\n","import * as Y from \"yjs\";\nimport { defaultAttrsFor } from \"./schema\";\nimport {\n DEFAULT_PAGE_SETTINGS,\n detectPreset,\n type PageSettings,\n} from \"./page-settings\";\nimport {\n isLegacySerializedDocument,\n type BlockAttrs,\n type BlockType,\n type CellAttrs,\n type DeltaOp,\n type LegacySerializedDocument,\n type SerializedBlock,\n type SerializedCell,\n type SerializedDocument,\n} from \"./types\";\n\n/**\n * Y.js-backed document.\n *\n * Storage layout:\n * ydoc.getArray(\"blocks\") : Y.Array<Y.Map>\n * each Y.Map (\"block\"):\n * - type: string (\"paragraph\" | \"heading\" | \"blockquote\" | \"codeBlock\" | \"listItem\" | \"table\")\n * - text: Y.Text (NOT present on tables)\n * - attrs: Y.Map<unknown> (align, dir, level, language… plus rows/cols for tables)\n * - cells: Y.Array<Y.Map> (only on tables, length = rows * cols, row-major)\n * each cell map: { text: Y.Text, attrs: Y.Map<unknown> }\n *\n * Block-level attrs live inside a nested Y.Map so concurrent edits (e.g. two users\n * changing alignment at once) reconcile through Yjs' last-write-wins per key.\n */\nexport class EditorDocument {\n readonly ydoc: Y.Doc;\n readonly blocks: Y.Array<Y.Map<unknown>>;\n /** Document-level settings (page size, margins). See `getPageSettings`. */\n readonly docSettings: Y.Map<unknown>;\n\n constructor(ydoc?: Y.Doc) {\n this.ydoc = ydoc ?? new Y.Doc();\n this.blocks = this.ydoc.getArray<Y.Map<unknown>>(\"blocks\");\n this.docSettings = this.ydoc.getMap<unknown>(\"docSettings\");\n\n if (this.blocks.length === 0) {\n this.ydoc.transact(() => {\n this.blocks.push([createBlock(\"paragraph\")]);\n }, \"init\");\n }\n }\n\n /**\n * Returns the current page settings. Missing fields fall back to\n * `DEFAULT_PAGE_SETTINGS`. The returned object is a fresh snapshot — mutating\n * it does not write back to the Y.Doc. Use `setPageSettings` for that.\n */\n getPageSettings(): PageSettings {\n const m = this.docSettings;\n const pick = <K extends keyof PageSettings>(key: K): PageSettings[K] | undefined => {\n const v = m.get(key as string);\n return typeof v === \"number\" || typeof v === \"string\" ? (v as PageSettings[K]) : undefined;\n };\n const merged: PageSettings = {\n width: pick(\"width\") ?? DEFAULT_PAGE_SETTINGS.width,\n height: pick(\"height\") ?? DEFAULT_PAGE_SETTINGS.height,\n marginTop: pick(\"marginTop\") ?? DEFAULT_PAGE_SETTINGS.marginTop,\n marginBottom: pick(\"marginBottom\") ?? DEFAULT_PAGE_SETTINGS.marginBottom,\n marginLeft: pick(\"marginLeft\") ?? DEFAULT_PAGE_SETTINGS.marginLeft,\n marginRight: pick(\"marginRight\") ?? DEFAULT_PAGE_SETTINGS.marginRight,\n systemHeaderTitle: pick(\"systemHeaderTitle\"),\n systemHeaderAuthor: pick(\"systemHeaderAuthor\"),\n };\n merged.preset = detectPreset(merged.width, merged.height);\n return merged;\n }\n\n /**\n * Merge `partial` into the docSettings Y.Map. Runs in a `ydoc.transact` with\n * origin `\"pageSettings\"` (NOT tracked by the UndoManager, mirroring the\n * `\"import\"` convention from Fase 9.5).\n */\n setPageSettings(partial: Partial<PageSettings>): void {\n this.ydoc.transact(() => {\n for (const [k, v] of Object.entries(partial)) {\n if (k === \"preset\") continue; // derived, never stored\n if (v === undefined) continue;\n this.docSettings.set(k, v);\n }\n }, \"pageSettings\");\n }\n\n /** Listen for page-settings changes. Returns an unsubscribe function. */\n observePageSettings(cb: () => void): () => void {\n const handler = () => cb();\n this.docSettings.observe(handler);\n return () => this.docSettings.unobserve(handler);\n }\n\n getBlock(index: number): Y.Map<unknown> | undefined {\n if (index < 0 || index >= this.blocks.length) return undefined;\n return this.blocks.get(index);\n }\n\n getBlockText(index: number): Y.Text | undefined {\n const b = this.getBlock(index);\n return b?.get(\"text\") as Y.Text | undefined;\n }\n\n getBlockType(index: number): BlockType | undefined {\n const b = this.getBlock(index);\n return b?.get(\"type\") as BlockType | undefined;\n }\n\n getBlockAttrsMap(index: number): Y.Map<unknown> | undefined {\n const b = this.getBlock(index);\n return b?.get(\"attrs\") as Y.Map<unknown> | undefined;\n }\n\n getBlockAttrs(index: number): BlockAttrs {\n const m = this.getBlockAttrsMap(index);\n if (!m) return {};\n return Object.fromEntries(m.entries()) as BlockAttrs;\n }\n\n blockCount(): number {\n return this.blocks.length;\n }\n\n // ---------- Table helpers ----------\n\n isTable(index: number): boolean {\n return this.getBlockType(index) === \"table\";\n }\n\n /** Returns rows/cols read from the block's attrs map. `{0,0}` for non-table blocks. */\n getTableSize(index: number): { rows: number; cols: number } {\n const attrs = this.getBlockAttrs(index);\n const rows = typeof attrs.rows === \"number\" ? attrs.rows : 0;\n const cols = typeof attrs.cols === \"number\" ? attrs.cols : 0;\n return { rows, cols };\n }\n\n getCells(index: number): Y.Array<Y.Map<unknown>> | undefined {\n const b = this.getBlock(index);\n return b?.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n }\n\n getCell(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined {\n const cells = this.getCells(blockIndex);\n if (!cells) return undefined;\n if (cellIndex < 0 || cellIndex >= cells.length) return undefined;\n return cells.get(cellIndex);\n }\n\n getCellText(blockIndex: number, cellIndex: number): Y.Text | undefined {\n const cell = this.getCell(blockIndex, cellIndex);\n return cell?.get(\"text\") as Y.Text | undefined;\n }\n\n getCellAttrsMap(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined {\n const cell = this.getCell(blockIndex, cellIndex);\n return cell?.get(\"attrs\") as Y.Map<unknown> | undefined;\n }\n\n getCellAttrs(blockIndex: number, cellIndex: number): CellAttrs {\n const m = this.getCellAttrsMap(blockIndex, cellIndex);\n if (!m) return {};\n return Object.fromEntries(m.entries()) as CellAttrs;\n }\n\n /**\n * Returns the editable Y.Text targeted by a position:\n * - When `cellIndex` is set: the cell's text (or the owner's text if the\n * target cell is covered by a span — we treat the covered position as\n * addressing the owner).\n * - Otherwise: the block's own text.\n */\n textAt(blockIndex: number, cellIndex: number | undefined): Y.Text | undefined {\n if (cellIndex == null) return this.getBlockText(blockIndex);\n const real = this.realCellIndex(blockIndex, cellIndex);\n if (real == null) return undefined;\n return this.getCellText(blockIndex, real);\n }\n\n /**\n * Returns the \"real\" (non-covered) cell index for a target cell. When the\n * target is already a real cell, returns it unchanged. When covered, walks\n * up-and-left to find the owner.\n *\n * The walk is robust to oversized or non-rectangular spans by skipping\n * candidates whose declared span doesn't actually cover the target.\n */\n realCellIndex(blockIndex: number, cellIndex: number): number | undefined {\n if (!this.isTable(blockIndex)) return undefined;\n const { rows, cols } = this.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return undefined;\n if (cellIndex < 0 || cellIndex >= rows * cols) return undefined;\n const targetAttrs = this.getCellAttrs(blockIndex, cellIndex);\n if (targetAttrs.covered !== true) return cellIndex;\n\n const tRow = Math.floor(cellIndex / cols);\n const tCol = cellIndex - tRow * cols;\n // Scan candidate owners — any real cell (or, oc) with or <= tRow, oc <= tCol,\n // spanning into (tRow, tCol). Walk from (tRow, tCol) up-and-left.\n for (let or = tRow; or >= 0; or--) {\n for (let oc = tCol; oc >= 0; oc--) {\n const idx = or * cols + oc;\n if (idx === cellIndex) continue;\n const a = this.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (or + rs - 1 >= tRow && oc + cs - 1 >= tCol) return idx;\n }\n }\n return undefined;\n }\n\n /**\n * Replace the document contents with a `SerializedDocument`. Runs in a single\n * `ydoc.transact` with origin `\"import\"` so the UndoManager can group or skip\n * the operation as one step.\n *\n * Reuses `createBlock` / `createTableBlock` so every block ends up with the\n * exact same Y.js shape produced by the rest of the editor.\n */\n loadFromJSON(serialized: SerializedDocument | LegacySerializedDocument): void {\n const { blocks: sourceBlocks, pageSettings } = normalizeSerialized(serialized);\n // Lock anti-concorrência: `loadFromJSON` é destrutivo (clear+push) e\n // dois imports concorrentes (especialmente entre clientes via CRDT)\n // historicamente produziram blocks duplicados em massa (caso 172k).\n // Marker em `docSettings.__importLock` com TTL 5s — se outro import\n // foi iniciado < 5s atrás, este aborta com warning ao invés de\n // sobrescrever. A janela de 5s cobre a latência de rede do Hocuspocus\n // entre clients durante imports humanos típicos.\n const LOCK_KEY = \"__importLock\";\n const LOCK_TTL_MS = 5_000;\n const existing = this.docSettings.get(LOCK_KEY);\n if (typeof existing === \"number\" && Date.now() - existing < LOCK_TTL_MS) {\n const ageMs = Date.now() - existing;\n console.warn(\n `[EditorDocument.loadFromJSON] import já em andamento (${ageMs}ms atrás, TTL ${LOCK_TTL_MS}ms) — ignorando esta chamada para evitar duplicação de blocks.`,\n );\n return;\n }\n this.docSettings.set(LOCK_KEY, Date.now());\n this.ydoc.transact(() => {\n if (this.blocks.length > 0) {\n this.blocks.delete(0, this.blocks.length);\n }\n // Build the Y structure in two passes: first create empty blocks (with\n // correct type/attrs/cells shape) and push them so their inner Y.Texts\n // get integrated into the document; only then apply each delta. Y.Text\n // requires an active transaction context that exists for integrated\n // instances — `applyDelta` on a detached Y.Text throws.\n const sources = sourceBlocks.length > 0 ? sourceBlocks : [makeEmptyParagraphSource()];\n const fresh: Y.Map<unknown>[] = sources.map((b) => buildEmptyBlockFromSerialized(b));\n this.blocks.push(fresh);\n\n for (let i = 0; i < sources.length; i++) {\n const src = sources[i];\n const yBlock = this.blocks.get(i);\n applyDeltaIntoBlock(yBlock, src);\n }\n\n if (pageSettings) {\n for (const [k, v] of Object.entries(pageSettings)) {\n if (k === \"preset\") continue;\n if (v === undefined) continue;\n this.docSettings.set(k, v);\n }\n }\n // Limpa o lock no fim do import (mesma transaction \"import\"). Se\n // crashar antes daqui, o TTL de 5s expira a entrada e o doc volta a\n // aceitar imports.\n this.docSettings.delete(LOCK_KEY);\n }, \"import\");\n }\n\n /** Build a fresh `EditorDocument` from a `SerializedDocument`. */\n static fromJSON(serialized: SerializedDocument | LegacySerializedDocument): EditorDocument {\n const ydoc = new Y.Doc();\n // Touch the shared array before loadFromJSON so the constructor doesn't\n // insert its default paragraph — we replace the contents anyway.\n ydoc.getArray<Y.Map<unknown>>(\"blocks\");\n const doc = new EditorDocument(ydoc);\n doc.loadFromJSON(serialized);\n return doc;\n }\n\n toJSON(): SerializedDocument {\n const blocks = this.blocks.toArray().map<SerializedBlock>((b) => {\n const type = (b.get(\"type\") as BlockType) ?? \"paragraph\";\n const attrsMap = b.get(\"attrs\") as Y.Map<unknown> | undefined;\n const attrs = attrsMap ? (Object.fromEntries(attrsMap.entries()) as BlockAttrs) : {};\n\n if (type === \"table\") {\n const cellsArray = b.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n const cells: SerializedCell[] = cellsArray\n ? cellsArray.toArray().map((c) => serializeCell(c))\n : [];\n return {\n type,\n text: \"\",\n delta: [],\n attrs,\n cells,\n };\n }\n\n const yText = b.get(\"text\") as Y.Text | undefined;\n return {\n type,\n text: yText?.toString() ?? \"\",\n delta: (yText?.toDelta() as DeltaOp[] | undefined) ?? [],\n attrs,\n };\n });\n return { blocks, pageSettings: this.getPageSettings() };\n }\n}\n\nfunction normalizeSerialized(\n v: SerializedDocument | LegacySerializedDocument,\n): { blocks: SerializedBlock[]; pageSettings?: PageSettings } {\n if (isLegacySerializedDocument(v)) {\n return { blocks: v };\n }\n return { blocks: v.blocks, pageSettings: v.pageSettings };\n}\n\nfunction serializeCell(c: Y.Map<unknown>): SerializedCell {\n const yText = c.get(\"text\") as Y.Text | undefined;\n const attrsMap = c.get(\"attrs\") as Y.Map<unknown> | undefined;\n return {\n text: yText?.toString() ?? \"\",\n delta: (yText?.toDelta() as DeltaOp[] | undefined) ?? [],\n attrs: attrsMap ? (Object.fromEntries(attrsMap.entries()) as Record<string, unknown>) : {},\n };\n}\n\nexport function createBlock(\n type: BlockType,\n initialText = \"\",\n attrs?: BlockAttrs,\n): Y.Map<unknown> {\n if (type === \"table\") {\n // Callers that need a table should use createTableBlock(rows, cols).\n // We honor any rows/cols passed via attrs but default to 1x1 to keep the\n // invariant `cells.length === rows * cols` non-zero.\n const merged = { ...defaultAttrsFor(\"table\"), ...(attrs ?? {}) };\n const rows = typeof merged.rows === \"number\" && merged.rows > 0 ? Math.trunc(merged.rows) : 1;\n const cols = typeof merged.cols === \"number\" && merged.cols > 0 ? Math.trunc(merged.cols) : 1;\n return createTableBlock(rows, cols);\n }\n\n const block = new Y.Map<unknown>();\n block.set(\"type\", type);\n const yText = new Y.Text();\n if (initialText.length > 0) yText.insert(0, initialText);\n block.set(\"text\", yText);\n const attrsMap = new Y.Map<unknown>();\n const merged = { ...defaultAttrsFor(type), ...(attrs ?? {}) };\n for (const [k, v] of Object.entries(merged)) {\n if (v !== undefined) attrsMap.set(k, v);\n }\n block.set(\"attrs\", attrsMap);\n return block;\n}\n\n/**\n * Build a table block with `rows × cols` empty cells.\n * Cells are stored in row-major order: `cell[row * cols + col]`.\n */\nexport function createTableBlock(rows: number, cols: number): Y.Map<unknown> {\n const r = Math.max(1, Math.trunc(rows));\n const c = Math.max(1, Math.trunc(cols));\n const block = new Y.Map<unknown>();\n block.set(\"type\", \"table\");\n const attrsMap = new Y.Map<unknown>();\n attrsMap.set(\"rows\", r);\n attrsMap.set(\"cols\", c);\n block.set(\"attrs\", attrsMap);\n const cells = new Y.Array<Y.Map<unknown>>();\n const total = r * c;\n const fresh: Y.Map<unknown>[] = [];\n for (let i = 0; i < total; i++) fresh.push(createCell());\n cells.push(fresh);\n block.set(\"cells\", cells);\n return block;\n}\n\nexport function createCell(attrs?: CellAttrs): Y.Map<unknown> {\n const m = new Y.Map<unknown>();\n m.set(\"text\", new Y.Text());\n const attrsMap = new Y.Map<unknown>();\n if (attrs) {\n for (const [k, v] of Object.entries(attrs)) {\n if (v === undefined) continue;\n attrsMap.set(k, v);\n }\n }\n m.set(\"attrs\", attrsMap);\n return m;\n}\n\nfunction makeEmptyParagraphSource(): SerializedBlock {\n return { type: \"paragraph\", text: \"\", delta: [], attrs: {} };\n}\n\nfunction buildEmptyBlockFromSerialized(block: SerializedBlock): Y.Map<unknown> {\n if (block.type === \"table\") {\n const rows =\n typeof block.attrs.rows === \"number\" ? Math.max(1, Math.trunc(block.attrs.rows)) : 1;\n const cols =\n typeof block.attrs.cols === \"number\" ? Math.max(1, Math.trunc(block.attrs.cols)) : 1;\n const yBlock = new Y.Map<unknown>();\n yBlock.set(\"type\", \"table\");\n const attrsMap = new Y.Map<unknown>();\n attrsMap.set(\"rows\", rows);\n attrsMap.set(\"cols\", cols);\n for (const [k, v] of Object.entries(block.attrs)) {\n if (k === \"rows\" || k === \"cols\") continue;\n if (v === undefined) continue;\n attrsMap.set(k, v);\n }\n yBlock.set(\"attrs\", attrsMap);\n const cellsArr = new Y.Array<Y.Map<unknown>>();\n const total = rows * cols;\n const fresh: Y.Map<unknown>[] = [];\n const cells = block.cells ?? [];\n for (let i = 0; i < total; i++) {\n const src = cells[i];\n fresh.push(createCell((src?.attrs ?? undefined) as CellAttrs | undefined));\n }\n cellsArr.push(fresh);\n yBlock.set(\"cells\", cellsArr);\n return yBlock;\n }\n return createBlock(block.type, \"\", block.attrs);\n}\n\nfunction applyDeltaIntoBlock(yBlock: Y.Map<unknown> | undefined, src: SerializedBlock): void {\n if (!yBlock) return;\n if (src.type === \"table\") {\n const cellsArr = yBlock.get(\"cells\") as Y.Array<Y.Map<unknown>> | undefined;\n if (!cellsArr) return;\n const cells = src.cells ?? [];\n for (let i = 0; i < cellsArr.length; i++) {\n const cellSrc = cells[i];\n if (!cellSrc || !cellSrc.delta || cellSrc.delta.length === 0) continue;\n const cell = cellsArr.get(i);\n const yText = cell.get(\"text\") as Y.Text | undefined;\n if (!yText) continue;\n yText.applyDelta(cellSrc.delta as unknown as Array<{ insert: unknown; attributes?: unknown }>);\n }\n return;\n }\n if (!src.delta || src.delta.length === 0) return;\n const yText = yBlock.get(\"text\") as Y.Text | undefined;\n if (!yText) return;\n yText.applyDelta(src.delta as unknown as Array<{ insert: unknown; attributes?: unknown }>);\n}\n\n/** Coerce a `rowspan`/`colspan` attribute value into a positive integer. */\nexport function spanOf(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1;\n return Math.max(1, Math.trunc(value));\n}\n","import type { Position, Selection } from \"./types\";\n\nexport function isCollapsed(sel: Selection): boolean {\n return positionsEqual(sel.anchor, sel.focus);\n}\n\nexport function positionsEqual(a: Position, b: Position): boolean {\n return (\n a.blockIndex === b.blockIndex &&\n (a.cellIndex ?? -1) === (b.cellIndex ?? -1) &&\n a.offset === b.offset\n );\n}\n\nexport function comparePositions(a: Position, b: Position): number {\n if (a.blockIndex !== b.blockIndex) return a.blockIndex - b.blockIndex;\n const ac = a.cellIndex ?? -1;\n const bc = b.cellIndex ?? -1;\n if (ac !== bc) return ac - bc;\n return a.offset - b.offset;\n}\n\nexport function orderedRange(sel: Selection): { start: Position; end: Position } {\n if (comparePositions(sel.anchor, sel.focus) <= 0) {\n return { start: sel.anchor, end: sel.focus };\n }\n return { start: sel.focus, end: sel.anchor };\n}\n\nexport function collapsedSelection(pos: Position): Selection {\n return { anchor: pos, focus: pos };\n}\n\n/**\n * Two positions are in the same \"editable run\" (same Y.Text) when they share\n * the block index AND the cellIndex (treating absent and present-with-undefined\n * the same way: a non-table position has cellIndex === undefined for both).\n */\nexport function sameTextRun(a: Position, b: Position): boolean {\n return a.blockIndex === b.blockIndex && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);\n}\n","import type * as Y from \"yjs\";\nimport type { DeltaOp, MarkAttrs, MarkName } from \"./types\";\n\n/**\n * Helpers for reading mark attributes off a Y.Text by inspecting its delta.\n * Writing is done with `yText.format(...)` directly in commands.ts.\n */\n\nfunction iterateRunsInRange(\n yText: Y.Text,\n start: number,\n end: number,\n visit: (run: DeltaOp, runStart: number, runEnd: number) => void,\n): void {\n if (start >= end) return;\n const delta = yText.toDelta() as DeltaOp[];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert !== \"string\") {\n // Embed: advance cursor (counts as 1 char) but don't visit — mark queries\n // are about text runs, not embed attributes.\n if (op.insert == null) continue;\n cursor += 1;\n if (cursor > end) break;\n continue;\n }\n const opStart = cursor;\n const opEnd = cursor + op.insert.length;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n const runStart = Math.max(opStart, start);\n const runEnd = Math.min(opEnd, end);\n visit(op, runStart, runEnd);\n }\n}\n\n/**\n * Returns the marks observed across `[start, end)`. For each mark name encountered:\n * - if every covered character has the same value, returns that value\n * - if values differ OR some characters lack the mark, returns \"mixed\"\n */\nexport function getMarksInRange(\n yText: Y.Text,\n start: number,\n end: number,\n): Partial<Record<MarkName, MarkAttrs[MarkName] | \"mixed\">> {\n const result: Partial<Record<MarkName, MarkAttrs[MarkName] | \"mixed\">> = {};\n if (start >= end) return result;\n\n // Track total covered length and per-mark covered length to detect \"some chars lacked it\".\n const total = end - start;\n const coveredByName: Partial<Record<MarkName, number>> = {};\n\n iterateRunsInRange(yText, start, end, (run, runStart, runEnd) => {\n const len = runEnd - runStart;\n const attrs = (run.attributes ?? {}) as MarkAttrs;\n (Object.keys(attrs) as MarkName[]).forEach((name) => {\n const value = attrs[name];\n if (value === undefined || value === null) return;\n const prev = result[name];\n if (prev === undefined) {\n result[name] = value;\n } else if (prev !== \"mixed\" && !sameMarkValue(prev, value)) {\n result[name] = \"mixed\";\n }\n coveredByName[name] = (coveredByName[name] ?? 0) + len;\n });\n });\n\n (Object.keys(result) as MarkName[]).forEach((name) => {\n if ((coveredByName[name] ?? 0) < total) {\n result[name] = \"mixed\";\n }\n });\n\n return result;\n}\n\nexport function isMarkUniformInRange(\n yText: Y.Text,\n start: number,\n end: number,\n name: MarkName,\n value?: MarkAttrs[MarkName],\n): boolean {\n if (start >= end) return false;\n const total = end - start;\n let covered = 0;\n let observed: MarkAttrs[MarkName] | undefined;\n let ok = true;\n iterateRunsInRange(yText, start, end, (run, runStart, runEnd) => {\n if (!ok) return;\n const len = runEnd - runStart;\n const attr = (run.attributes ?? {})[name];\n if (attr === undefined || attr === null) {\n ok = false;\n return;\n }\n if (value !== undefined && !sameMarkValue(value, attr)) {\n ok = false;\n return;\n }\n if (observed === undefined) {\n observed = attr;\n } else if (!sameMarkValue(observed, attr)) {\n ok = false;\n return;\n }\n covered += len;\n });\n return ok && covered === total;\n}\n\n/** Total number of inserted characters. Embeds (non-string inserts) count as 1. */\nexport function deltaLength(delta: DeltaOp[]): number {\n let sum = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") sum += op.insert.length;\n else if (op.insert != null) sum += 1;\n }\n return sum;\n}\n\n/**\n * Return the subset of `delta` covering `[start, end)` characters.\n * Embeds are atomic length-1 ops: included whole if their slot intersects the range.\n */\nexport function sliceDelta(delta: DeltaOp[], start: number, end: number): DeltaOp[] {\n if (end <= start) return [];\n const out: DeltaOp[] = [];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n const opStart = cursor;\n const opEnd = cursor + op.insert.length;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n const sliceFrom = Math.max(opStart, start) - opStart;\n const sliceTo = Math.min(opEnd, end) - opStart;\n out.push({\n insert: op.insert.slice(sliceFrom, sliceTo),\n attributes: op.attributes,\n });\n } else if (op.insert != null) {\n const opStart = cursor;\n const opEnd = cursor + 1;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n out.push({ insert: op.insert, attributes: op.attributes });\n }\n }\n return out;\n}\n\nfunction sameMarkValue(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === \"object\" && typeof b === \"object\" && a && b) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k) => (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]);\n }\n return false;\n}\n","import * as Y from \"yjs\";\nimport { EditorDocument, createBlock, createCell, createTableBlock, spanOf } from \"./document\";\nimport { isMarkUniformInRange, sliceDelta } from \"./marks\";\nimport { defaultAttrsFor } from \"./schema\";\nimport { collapsedSelection, isCollapsed, orderedRange, sameTextRun } from \"./selection\";\nimport type {\n BlockAttrs,\n BlockType,\n DeltaOp,\n ImageEmbed,\n ListKind,\n MarkAttrs,\n MarkName,\n Position,\n Selection,\n} from \"./types\";\nimport { isImageEmbed, MAX_LIST_LEVEL } from \"./types\";\n\nexport const COMMAND_ORIGIN: unique symbol = Symbol(\"editor-command\");\n\nexport interface CommandContext {\n doc: EditorDocument;\n getSelection: () => Selection;\n setSelection: (sel: Selection) => void;\n}\n\nfunction transact(doc: EditorDocument, fn: () => void): void {\n doc.ydoc.transact(fn, COMMAND_ORIGIN);\n}\n\n/**\n * Insert text at the current selection.\n *\n * `marks` is an explicit override map applied to the freshly inserted range.\n * - Entry value: apply that mark value.\n * - Entry value `null`: clear that mark (used when the UI just toggled it off\n * with a collapsed caret and the next typed char must NOT inherit the\n * surrounding run's attribute).\n * - When `marks` is undefined, Y.Text's default inheritance applies (good for\n * normal typing inside a marked run).\n */\nexport function insertText(\n ctx: CommandContext,\n text: string,\n marks?: Partial<Record<MarkName, MarkAttrs[MarkName] | null>>,\n): void {\n if (text.length === 0) return;\n // Rectangular cell selection: clear all selected cells, collapse to top-left,\n // then insert into the owner like a normal call.\n const collapsedFromRect = clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel = collapsedFromRect ?? ctx.getSelection();\n let cursor = sel;\n if (!isCollapsed(sel)) {\n cursor = deleteRange(ctx.doc, sel);\n }\n const pos = cursor.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.insert(pos.offset, text);\n if (marks && Object.keys(marks).length > 0) {\n yText.format(pos.offset, text.length, marks as Record<string, unknown>);\n }\n const newPos: Position = {\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + text.length,\n };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\nexport function insertParagraph(ctx: CommandContext): void {\n // Rectangular selection: collapse + clear first.\n clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n let cursor = sel;\n if (!isCollapsed(sel)) {\n cursor = deleteRange(ctx.doc, sel);\n }\n const pos = cursor.focus;\n // Inside a table cell, Enter inserts a literal newline rather than splitting\n // the cell into two paragraphs. Cells in 4.1 are single-text containers; we\n // rely on `white-space: pre-wrap` in CSS to render the line break visibly.\n if (pos.cellIndex != null) {\n const yText = ctx.doc.getCellText(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.insert(pos.offset, \"\\n\");\n ctx.setSelection(\n collapsedSelection({\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + 1,\n }),\n );\n return;\n }\n const yText = ctx.doc.getBlockText(pos.blockIndex);\n if (!yText) return;\n\n const totalLen = yText.length;\n // Read the tail's delta (preserves marks) before mutating yText.\n const tailDelta = totalLen > pos.offset\n ? sliceDelta(yText.toDelta() as DeltaOp[], pos.offset, totalLen)\n : [];\n\n if (totalLen > pos.offset) {\n yText.delete(pos.offset, totalLen - pos.offset);\n }\n\n const newBlock = createBlock(\"paragraph\");\n ctx.doc.blocks.insert(pos.blockIndex + 1, [newBlock]);\n if (tailDelta.length > 0) {\n const newYText = newBlock.get(\"text\") as Y.Text;\n writeDeltaInto(newYText, 0, tailDelta);\n }\n\n const newPos: Position = { blockIndex: pos.blockIndex + 1, offset: 0 };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\nexport function deleteBackward(ctx: CommandContext): void {\n // Rectangular selection: clear text of every selected cell and collapse to\n // the rect's top-left, then return — no further character delete needed.\n if (clearRectCells(ctx)) return;\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) {\n const cursor = deleteRange(ctx.doc, sel);\n ctx.setSelection(cursor);\n return;\n }\n const pos = sel.focus;\n if (pos.offset > 0) {\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n yText.delete(pos.offset - 1, 1);\n ctx.setSelection(\n collapsedSelection({\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset - 1,\n }),\n );\n return;\n }\n // offset === 0\n // Inside a table cell, backspace at the cell start is a no-op — the user\n // cannot escape the table by pressing backspace.\n if (pos.cellIndex != null) return;\n // At offset 0: if it's a listItem, dedent (or convert to paragraph at level 0)\n // before falling back to merging with the previous block.\n const blockType = ctx.doc.getBlockType(pos.blockIndex);\n if (blockType === \"listItem\") {\n const block = ctx.doc.getBlock(pos.blockIndex);\n const attrsMap = block?.get(\"attrs\") as Y.Map<unknown> | undefined;\n const rawLevel = attrsMap?.get(\"listLevel\") as number | undefined;\n const level = typeof rawLevel === \"number\" && Number.isFinite(rawLevel)\n ? Math.max(0, Math.min(MAX_LIST_LEVEL, Math.trunc(rawLevel)))\n : 0;\n if (level > 0) {\n attrsMap!.set(\"listLevel\", level - 1);\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n // Level 0 listItem → convert to paragraph (escape the list).\n setBlockTypeAtIndex(ctx.doc, pos.blockIndex, \"paragraph\", {});\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n if (pos.blockIndex > 0) {\n const prevType = ctx.doc.getBlockType(pos.blockIndex - 1);\n if (prevType === \"table\") {\n // Can't merge with a table; move caret to the table's last cell instead.\n const tableIdx = pos.blockIndex - 1;\n const { rows, cols } = ctx.doc.getTableSize(tableIdx);\n const lastCell = rows * cols - 1;\n const cellText = ctx.doc.getCellText(tableIdx, lastCell);\n const off = cellText?.length ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex: tableIdx, cellIndex: lastCell, offset: off }),\n );\n return;\n }\n mergeWithPrevious(ctx, pos.blockIndex);\n }\n });\n}\n\nexport function deleteForward(ctx: CommandContext): void {\n if (clearRectCells(ctx)) return;\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) {\n const cursor = deleteRange(ctx.doc, sel);\n ctx.setSelection(cursor);\n return;\n }\n const pos = sel.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n if (pos.offset < yText.length) {\n yText.delete(pos.offset, 1);\n ctx.setSelection(collapsedSelection(pos));\n return;\n }\n // at end of editable run\n // Inside a table cell, forward-delete at the cell end is a no-op.\n if (pos.cellIndex != null) return;\n // at end of block: merge next into current (but tables are atomic)\n if (pos.blockIndex + 1 < ctx.doc.blockCount()) {\n const nextType = ctx.doc.getBlockType(pos.blockIndex + 1);\n if (nextType === \"table\") {\n // Jump caret into the table's first cell.\n const tableIdx = pos.blockIndex + 1;\n ctx.setSelection(collapsedSelection({ blockIndex: tableIdx, cellIndex: 0, offset: 0 }));\n return;\n }\n const nextText = ctx.doc.getBlockText(pos.blockIndex + 1);\n if (!nextText) return;\n const tail = nextText.toString();\n if (tail.length > 0) yText.insert(yText.length, tail);\n ctx.doc.blocks.delete(pos.blockIndex + 1, 1);\n ctx.setSelection(collapsedSelection(pos));\n }\n });\n}\n\n// ---------- Marks ----------\n\nconst booleanMarks: Set<MarkName> = new Set([\"bold\", \"italic\", \"underline\", \"strike\"]);\n\n/**\n * Toggle a mark across the current selection.\n * - If the selection is collapsed: no-op (the UI layer handles pendingMarks).\n * - Boolean marks (bold/italic/underline/strike): if every character already has\n * the mark, remove it; otherwise apply.\n * - Parametric marks (color, fontFamily, fontSize, link): require `value` to apply;\n * when uniform with that value across the range, remove instead (acts like toggle).\n */\nexport function toggleMark(\n ctx: CommandContext,\n name: MarkName,\n value?: MarkAttrs[MarkName],\n): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n const uniform = isMarkUniformInRange(yText, localStart, localEnd, name, value);\n const attrs: Record<string, unknown> = {};\n if (uniform) {\n attrs[name] = null;\n } else {\n attrs[name] = value ?? (booleanMarks.has(name) ? true : null);\n }\n if (attrs[name] === null && !uniform) return;\n yText.format(localStart, localEnd - localStart, attrs);\n });\n ctx.setSelection(sel);\n });\n}\n\nexport function setMark(\n ctx: CommandContext,\n name: MarkName,\n value: MarkAttrs[MarkName],\n): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n yText.format(localStart, localEnd - localStart, { [name]: value });\n });\n ctx.setSelection(sel);\n });\n}\n\nexport function removeMark(ctx: CommandContext, name: MarkName): void {\n const sel = ctx.getSelection();\n if (isCollapsed(sel)) return;\n transact(ctx.doc, () => {\n const { start, end } = orderedRange(sel);\n forEachBlockTextInRange(ctx.doc, start, end, (yText, localStart, localEnd) => {\n yText.format(localStart, localEnd - localStart, { [name]: null });\n });\n ctx.setSelection(sel);\n });\n}\n\n// ---------- Block-level commands (Sub-phase 2.2) ----------\n\n/**\n * Change the type of every block covered by the current selection.\n * When `attrs` is provided, merges those on top of the new type's defaults.\n * Preserves `Y.Text` content (and therefore all inline marks) and the selection.\n */\nexport function setBlockType(\n ctx: CommandContext,\n type: BlockType,\n attrs?: BlockAttrs,\n): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n // Inert when the caret is inside a cell — block-level operations only\n // apply to top-level blocks (the table itself), and changing a table's\n // block type is not exposed in 4.1.\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block) continue;\n block.set(\"type\", type);\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n // Reset attrs to the new type's defaults, then layer caller overrides.\n // Strategy: clear keys that aren't in either map, then write new ones.\n const next = { ...defaultAttrsFor(type), ...(attrs ?? {}) };\n const keep = new Set(Object.keys(next));\n for (const k of Array.from(attrsMap.keys())) {\n if (!keep.has(k)) attrsMap.delete(k);\n }\n for (const [k, v] of Object.entries(next)) {\n if (v === undefined) continue;\n if (attrsMap.get(k) !== v) attrsMap.set(k, v);\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Set a single attribute on every block covered by the selection.\n * Passing `value === null` deletes the key.\n */\nexport function setBlockAttr<K extends keyof BlockAttrs>(\n ctx: CommandContext,\n key: K,\n value: BlockAttrs[K] | null,\n): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block) continue;\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n if (value === null || value === undefined) {\n attrsMap.delete(key as string);\n } else {\n attrsMap.set(key as string, value);\n }\n }\n ctx.setSelection(sel);\n });\n}\n\nfunction selectedBlockIndices(sel: Selection, blockCount: number): number[] {\n const { start, end } = orderedRange(sel);\n const out: number[] = [];\n const last = Math.min(end.blockIndex, blockCount - 1);\n for (let i = Math.max(start.blockIndex, 0); i <= last; i++) out.push(i);\n return out;\n}\n\nfunction forEachBlockTextInRange(\n doc: EditorDocument,\n start: Position,\n end: Position,\n visit: (yText: Y.Text, localStart: number, localEnd: number) => void,\n): void {\n // Same text-run (block or cell): straightforward.\n if (sameTextRun(start, end)) {\n const yText = doc.textAt(start.blockIndex, start.cellIndex);\n if (!yText) return;\n if (start.offset < end.offset) visit(yText, start.offset, end.offset);\n return;\n }\n // Cross-run selections involving a cell are currently treated as inert for\n // mark application; the UI surfaces them as \"no-op\" rather than partially\n // applying marks across mismatched runs.\n if (start.cellIndex != null || end.cellIndex != null) return;\n\n for (let i = start.blockIndex; i <= end.blockIndex; i++) {\n const yText = doc.getBlockText(i);\n if (!yText) continue;\n const localStart = i === start.blockIndex ? start.offset : 0;\n const localEnd = i === end.blockIndex ? end.offset : yText.length;\n if (localStart < localEnd) visit(yText, localStart, localEnd);\n }\n}\n\n/**\n * Deletes the content of a non-collapsed selection.\n * Returns the new collapsed selection at the deletion point.\n * Must be called inside a Y.Doc transaction.\n *\n * Selections that span DIFFERENT text-runs (different blocks, or two cells of\n * the same table) are bridged conservatively:\n * - Same text-run (block+cell): delete the range normally.\n * - Different runs but both outside tables (i.e. cellIndex undefined on both):\n * delete and merge blocks as before.\n * - Otherwise (one endpoint is in a table cell): no destructive cross-cell\n * delete in 4.1; collapse to `start` instead.\n */\nfunction deleteRange(doc: EditorDocument, sel: Selection): Selection {\n const { start, end } = orderedRange(sel);\n\n if (sameTextRun(start, end)) {\n const yText = doc.textAt(start.blockIndex, start.cellIndex);\n if (yText) yText.delete(start.offset, end.offset - start.offset);\n return collapsedSelection(start);\n }\n\n // Reject cross-cell / cross-table-to-paragraph multi-run deletions for now.\n if (start.cellIndex != null || end.cellIndex != null) {\n return collapsedSelection(start);\n }\n\n const startText = doc.getBlockText(start.blockIndex);\n const endText = doc.getBlockText(end.blockIndex);\n if (!startText || !endText) return collapsedSelection(start);\n\n // Trim tail of start block\n startText.delete(start.offset, startText.length - start.offset);\n // Read remaining tail from end block, after the deleted prefix\n const remainingTail = endText.toString().slice(end.offset);\n if (remainingTail.length > 0) {\n startText.insert(startText.length, remainingTail);\n }\n // Remove all blocks between start (exclusive) and end (inclusive)\n doc.blocks.delete(start.blockIndex + 1, end.blockIndex - start.blockIndex);\n return collapsedSelection(start);\n}\n\nfunction mergeWithPrevious(ctx: CommandContext, blockIndex: number): void {\n const prevText = ctx.doc.getBlockText(blockIndex - 1);\n const currText = ctx.doc.getBlockText(blockIndex);\n if (!prevText || !currText) return;\n const prevLen = prevText.length;\n const tail = currText.toString();\n if (tail.length > 0) prevText.insert(prevLen, tail);\n ctx.doc.blocks.delete(blockIndex, 1);\n ctx.setSelection(collapsedSelection({ blockIndex: blockIndex - 1, offset: prevLen }));\n}\n\n// ---------- List commands (Sub-phase 2.3) ----------\n\n/**\n * Convert every block in the selection to/from a `listItem` of `kind`.\n * If every covered block is already a `listItem` of `kind` → convert them all to paragraphs.\n * Otherwise → convert them all to `listItem` (keeping existing `listLevel` when already\n * a listItem, defaulting to 0 otherwise).\n */\nexport function toggleList(ctx: CommandContext, kind: ListKind): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n const allMatching = indices.every((i) => {\n const block = ctx.doc.getBlock(i);\n if (!block) return false;\n if (block.get(\"type\") !== \"listItem\") return false;\n const attrs = ctx.doc.getBlockAttrs(i);\n return attrs.listKind === kind;\n });\n for (const i of indices) {\n if (allMatching) {\n // Strip list → paragraph (defaults reset).\n setBlockTypeAtIndex(ctx.doc, i, \"paragraph\", {});\n } else {\n const prev = ctx.doc.getBlockAttrs(i);\n const level = clampLevel(prev.listLevel);\n setBlockTypeAtIndex(ctx.doc, i, \"listItem\", { listKind: kind, listLevel: level });\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/** Increase nesting of every listItem in the selection (clamped to MAX_LIST_LEVEL). */\nexport function indentList(ctx: CommandContext): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block || block.get(\"type\") !== \"listItem\") continue;\n const attrsMap = block.get(\"attrs\") as Y.Map<unknown>;\n const current = clampLevel((attrsMap.get(\"listLevel\") as number | undefined) ?? 0);\n const next = Math.min(current + 1, MAX_LIST_LEVEL);\n if (next !== current) attrsMap.set(\"listLevel\", next);\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Decrease nesting of every listItem in the selection.\n * When level was 0, demote to paragraph (escape from the list).\n */\nexport function dedentList(ctx: CommandContext): void {\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n if (sel.anchor.cellIndex != null || sel.focus.cellIndex != null) return;\n const indices = selectedBlockIndices(sel, ctx.doc.blockCount());\n for (const i of indices) {\n const block = ctx.doc.getBlock(i);\n if (!block || block.get(\"type\") !== \"listItem\") continue;\n const attrsMap = block.get(\"attrs\") as Y.Map<unknown>;\n const current = clampLevel((attrsMap.get(\"listLevel\") as number | undefined) ?? 0);\n if (current > 0) {\n attrsMap.set(\"listLevel\", current - 1);\n } else {\n // Escape from the list at level 0.\n setBlockTypeAtIndex(ctx.doc, i, \"paragraph\", {});\n }\n }\n ctx.setSelection(sel);\n });\n}\n\n/**\n * Enter behavior inside a listItem.\n * - Empty listItem at level > 0 → dedent (stays a listItem, one level out).\n * - Empty listItem at level 0 → convert to paragraph (exit the list).\n * - Non-empty → split: tail moves to a new listItem with same kind/level.\n *\n * Returns `true` when it handled the event; `false` to let the default `insertParagraph` run.\n */\nexport function splitListItem(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n if (!isCollapsed(sel)) return false;\n const pos = sel.focus;\n // Inside a table cell, Enter is handled by insertParagraph (newline within cell).\n if (pos.cellIndex != null) return false;\n const block = ctx.doc.getBlock(pos.blockIndex);\n if (!block || block.get(\"type\") !== \"listItem\") return false;\n const yText = ctx.doc.getBlockText(pos.blockIndex);\n if (!yText) return false;\n\n const attrs = ctx.doc.getBlockAttrs(pos.blockIndex);\n const kind = (attrs.listKind ?? \"bullet\") as ListKind;\n const level = clampLevel(attrs.listLevel ?? 0);\n\n transact(ctx.doc, () => {\n if (yText.length === 0) {\n if (level > 0) {\n const m = block.get(\"attrs\") as Y.Map<unknown>;\n m.set(\"listLevel\", level - 1);\n } else {\n setBlockTypeAtIndex(ctx.doc, pos.blockIndex, \"paragraph\", {});\n }\n ctx.setSelection(collapsedSelection({ blockIndex: pos.blockIndex, offset: 0 }));\n return;\n }\n const tail = yText.toString().slice(pos.offset);\n if (tail.length > 0) yText.delete(pos.offset, tail.length);\n ctx.doc.blocks.insert(pos.blockIndex + 1, [\n createBlock(\"listItem\", tail, { listKind: kind, listLevel: level }),\n ]);\n ctx.setSelection(collapsedSelection({ blockIndex: pos.blockIndex + 1, offset: 0 }));\n });\n return true;\n}\n\n/**\n * Internal: reset a single block's type + attrs (used by list commands).\n * Same merge rules as the public `setBlockType` but scoped to one block and\n * intended to run already inside a transaction.\n */\nfunction setBlockTypeAtIndex(\n doc: EditorDocument,\n index: number,\n type: BlockType,\n attrs: BlockAttrs,\n): void {\n const block = doc.getBlock(index);\n if (!block) return;\n block.set(\"type\", type);\n const attrsMap = (block.get(\"attrs\") as Y.Map<unknown> | undefined) ?? new Y.Map<unknown>();\n if (!block.get(\"attrs\")) block.set(\"attrs\", attrsMap);\n const next = { ...defaultAttrsFor(type), ...attrs };\n const keep = new Set(Object.keys(next));\n for (const k of Array.from(attrsMap.keys())) {\n if (!keep.has(k)) attrsMap.delete(k);\n }\n for (const [k, v] of Object.entries(next)) {\n if (v === undefined) continue;\n if (attrsMap.get(k) !== v) attrsMap.set(k, v);\n }\n}\n\nfunction clampLevel(l: number | undefined): number {\n if (typeof l !== \"number\" || !Number.isFinite(l)) return 0;\n return Math.max(0, Math.min(MAX_LIST_LEVEL, Math.trunc(l)));\n}\n\n// ---------- Table commands (Sub-phase 4.1 / 4.2) ----------\n\n/**\n * Insert a fresh `rows × cols` table after the block currently holding the\n * caret (or at the end of the document if the selection is somehow invalid),\n * and place the caret in the table's first cell.\n *\n * Sub-phase 4.1 doesn't try to be clever: it does NOT replace an empty\n * preceding paragraph. Callers can clean that up themselves; an extra empty\n * paragraph above a table is a small price for predictable behavior.\n */\nexport function insertTable(ctx: CommandContext, rows: number, cols: number): void {\n const r = Math.max(1, Math.trunc(rows));\n const c = Math.max(1, Math.trunc(cols));\n transact(ctx.doc, () => {\n const sel = ctx.getSelection();\n // Anchor point: the block holding the focus. If focus is inside a cell of\n // an existing table, insert AFTER that table.\n const focusBlock = Math.max(0, Math.min(sel.focus.blockIndex, ctx.doc.blockCount() - 1));\n const insertAt = focusBlock + 1;\n ctx.doc.blocks.insert(insertAt, [createTableBlock(r, c)]);\n ctx.setSelection(\n collapsedSelection({ blockIndex: insertAt, cellIndex: 0, offset: 0 }),\n );\n });\n}\n\n/** Remove the entire table at `blockIndex` and place the caret at the start of the next block (or the previous one if removal would leave the doc empty). */\nexport function deleteTable(ctx: CommandContext, blockIndex: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n transact(ctx.doc, () => {\n ctx.doc.blocks.delete(blockIndex, 1);\n if (ctx.doc.blocks.length === 0) {\n ctx.doc.blocks.push([createBlock(\"paragraph\")]);\n ctx.setSelection(collapsedSelection({ blockIndex: 0, offset: 0 }));\n return;\n }\n const targetIdx = Math.max(0, Math.min(blockIndex, ctx.doc.blockCount() - 1));\n const targetType = ctx.doc.getBlockType(targetIdx);\n if (targetType === \"table\") {\n ctx.setSelection(collapsedSelection({ blockIndex: targetIdx, cellIndex: 0, offset: 0 }));\n } else {\n ctx.setSelection(collapsedSelection({ blockIndex: targetIdx, offset: 0 }));\n }\n });\n}\n\n/**\n * Sub-phase 4.1 has no rowspan/colspan, so row/col operations are pure splice\n * on the flat `cells` array. The flat index of `(r, c)` is `r * cols + c`.\n */\n\nexport interface TableLocation {\n blockIndex: number;\n row: number;\n col: number;\n}\n\n/**\n * Derive `{row, col}` from a position inside a table — always pointing at the\n * owner of the targeted cell (covered cells redirect to their owner). Returns\n * null when the position isn't inside a table cell.\n */\nexport function tableLocationOf(\n doc: EditorDocument,\n pos: Position,\n): TableLocation | null {\n if (pos.cellIndex == null) return null;\n if (!doc.isTable(pos.blockIndex)) return null;\n const { cols } = doc.getTableSize(pos.blockIndex);\n if (cols <= 0) return null;\n const real = doc.realCellIndex(pos.blockIndex, pos.cellIndex);\n if (real == null) return null;\n const row = Math.floor(real / cols);\n const col = real - row * cols;\n return { blockIndex: pos.blockIndex, row, col };\n}\n\n/**\n * Insert a fresh row above (`where === \"before\"`) or below (`\"after\"`) the\n * given row. Spans that previously crossed the insertion boundary are extended\n * by 1; the corresponding columns of the new row become `covered: true`.\n */\nexport function insertTableRow(\n ctx: CommandContext,\n blockIndex: number,\n row: number,\n where: \"before\" | \"after\",\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n const targetRow = Math.max(0, Math.min(row, rows - 1));\n const P = where === \"before\" ? targetRow : targetRow + 1;\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Snapshot: for each column, does a span crossing the [P-1, P] boundary\n // cover this column at row P? Compute BEFORE mutating spans.\n const newRowCovered: boolean[] = new Array(cols).fill(false);\n if (P > 0 && P < rows) {\n // Walk row P-1 to find spans crossing into row P (i.e., or < P and or+rs > P).\n for (let r = 0; r < P; r++) {\n for (let c = 0; c < cols; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (r < P && r + rs > P) {\n for (let cc = c; cc < c + cs && cc < cols; cc++) newRowCovered[cc] = true;\n }\n }\n }\n // Now extend those spans' rowspan by 1.\n for (let r = 0; r < P; r++) {\n for (let c = 0; c < cols; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n if (r < P && r + rs > P) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"rowspan\", rs + 1);\n }\n }\n }\n }\n\n const fresh: Y.Map<unknown>[] = [];\n for (let c = 0; c < cols; c++) {\n fresh.push(createCell(newRowCovered[c] ? { covered: true } : undefined));\n }\n cells.insert(P * cols, fresh);\n attrs.set(\"rows\", rows + 1);\n // Caret on the first non-covered cell of the new row (falls back to flat-0\n // if every column is covered — pathologically possible only with bad data).\n const firstReal = newRowCovered.findIndex((v) => !v);\n const targetCellIdx = P * cols + (firstReal < 0 ? 0 : firstReal);\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: targetCellIdx, offset: 0 }),\n );\n });\n}\n\n/**\n * Remove `row` from the table. Spans that pass through the row are shortened\n * by one; spans that START at the row are removed AND the cell at row R+1 (in\n * each affected column) is promoted to be the new owner with `rowspan - 1`.\n * When it was the last row, deletes the whole table.\n */\nexport function deleteTableRow(ctx: CommandContext, blockIndex: number, row: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n if (rows === 1) {\n deleteTable(ctx, blockIndex);\n return;\n }\n const R = Math.max(0, Math.min(row, rows - 1));\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Phase 1: spans crossing R (started above, end at or after R): shorten by 1.\n for (let r = 0; r < R; r++) {\n for (let c = 0; c < cols; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n if (r < R && r + rs > R) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"rowspan\", rs - 1);\n if (rs - 1 === 1) m?.delete(\"rowspan\");\n }\n }\n }\n\n // Phase 2: spans starting AT row R with rowspan > 1: promote the cell at\n // (R+1, c) to be the new owner. Capture the promotion list FIRST so we\n // can apply changes after the row delete (since indices shift).\n interface Promotion {\n // Flat index AFTER the row delete.\n flatNew: number;\n rowspan: number;\n colspan: number;\n }\n const promotions: Promotion[] = [];\n for (let c = 0; c < cols; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, R * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (rs > 1 && R + 1 < rows) {\n // After delete, what was (R+1, c) becomes (R, c).\n promotions.push({ flatNew: R * cols + c, rowspan: rs - 1, colspan: cs });\n }\n }\n\n cells.delete(R * cols, cols);\n attrs.set(\"rows\", rows - 1);\n\n for (const p of promotions) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, p.flatNew);\n if (!m) continue;\n m.delete(\"covered\");\n if (p.rowspan > 1) m.set(\"rowspan\", p.rowspan); else m.delete(\"rowspan\");\n if (p.colspan > 1) m.set(\"colspan\", p.colspan); else m.delete(\"colspan\");\n }\n\n const newRow = Math.min(R, rows - 2);\n const target = findNextRealCell(ctx.doc, blockIndex, newRow * cols, (rows - 1) * cols) ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: target, offset: 0 }),\n );\n });\n}\n\n/**\n * Insert a fresh column to the left (`\"before\"`) or right (`\"after\"`) of `col`.\n * Spans crossing the insertion column have `colspan += 1`; the new column's\n * cells in covered rows are themselves `covered: true`.\n *\n * Also resizes `colWidths` (if defined) by inserting a default width.\n */\nexport function insertTableColumn(\n ctx: CommandContext,\n blockIndex: number,\n col: number,\n where: \"before\" | \"after\",\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n const targetCol = Math.max(0, Math.min(col, cols - 1));\n const C = where === \"before\" ? targetCol : targetCol + 1;\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Snapshot covered rows BEFORE mutating spans.\n const newColCovered: boolean[] = new Array(rows).fill(false);\n if (C > 0 && C < cols) {\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + c);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n for (let rr = r; rr < r + rs && rr < rows; rr++) newColCovered[rr] = true;\n }\n }\n }\n // Extend colspans.\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"colspan\", cs + 1);\n }\n }\n }\n }\n\n // Walk rows LAST→FIRST so insert indices stay correct.\n for (let r = rows - 1; r >= 0; r--) {\n const at = r * cols + C;\n cells.insert(at, [createCell(newColCovered[r] ? { covered: true } : undefined)]);\n }\n attrs.set(\"cols\", cols + 1);\n\n // Resize colWidths if present — insert a 100px placeholder for the new col.\n const widths = attrs.get(\"colWidths\") as number[] | undefined;\n if (Array.isArray(widths) && widths.length === cols) {\n const next = widths.slice();\n next.splice(C, 0, 100);\n attrs.set(\"colWidths\", next);\n }\n\n const newCols = cols + 1;\n const focusRow = 0;\n const firstReal = newColCovered.findIndex((_, r) => r === focusRow && !newColCovered[r]);\n ctx.setSelection(\n collapsedSelection({\n blockIndex,\n cellIndex: focusRow * newCols + C + (firstReal < 0 ? 0 : 0),\n offset: 0,\n }),\n );\n });\n}\n\n/**\n * Remove `col` from the table. Spans that pass through the column are\n * shortened by one; spans that START at the column with `colspan > 1` get\n * their owner promoted from (r, C+1) to take over with `colspan - 1`.\n *\n * Also shrinks `colWidths` (if defined). When it was the last column, deletes\n * the whole table.\n */\nexport function deleteTableColumn(ctx: CommandContext, blockIndex: number, col: number): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (rows <= 0 || cols <= 0) return;\n if (cols === 1) {\n deleteTable(ctx, blockIndex);\n return;\n }\n const C = Math.max(0, Math.min(col, cols - 1));\n transact(ctx.doc, () => {\n const cells = ctx.doc.getCells(blockIndex);\n const attrs = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!cells || !attrs) return;\n\n // Phase 1: spans crossing C — colspan -= 1.\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < C; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const cs = spanOf(a.colspan);\n if (c < C && c + cs > C) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n m?.set(\"colspan\", cs - 1);\n if (cs - 1 === 1) m?.delete(\"colspan\");\n }\n }\n }\n\n // Phase 2: capture promotions for spans starting at column C with colspan > 1.\n // After deletion, what was (r, C+1) becomes (r, C). Capture both the\n // FUTURE flat index in the post-delete (rows x (cols-1)) grid and the\n // attrs to apply.\n interface Promotion {\n flatNew: number;\n rowspan: number;\n colspan: number;\n }\n const promotions: Promotion[] = [];\n const newCols = cols - 1;\n for (let r = 0; r < rows; r++) {\n const a = ctx.doc.getCellAttrs(blockIndex, r * cols + C);\n if (a.covered === true) continue;\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (cs > 1 && C + 1 < cols) {\n promotions.push({\n flatNew: r * newCols + C,\n rowspan: rs,\n colspan: cs - 1,\n });\n }\n }\n\n // Walk rows LAST→FIRST so deletions don't perturb indices we still need.\n for (let r = rows - 1; r >= 0; r--) {\n const at = r * cols + C;\n cells.delete(at, 1);\n }\n attrs.set(\"cols\", newCols);\n\n for (const p of promotions) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, p.flatNew);\n if (!m) continue;\n m.delete(\"covered\");\n if (p.rowspan > 1) m.set(\"rowspan\", p.rowspan); else m.delete(\"rowspan\");\n if (p.colspan > 1) m.set(\"colspan\", p.colspan); else m.delete(\"colspan\");\n }\n\n // Trim colWidths.\n const widths = attrs.get(\"colWidths\") as number[] | undefined;\n if (Array.isArray(widths) && widths.length === cols) {\n const next = widths.slice();\n next.splice(C, 1);\n attrs.set(\"colWidths\", next);\n }\n\n const newCol = Math.min(C, newCols - 1);\n const target = findNextRealCell(ctx.doc, blockIndex, newCol, rows * newCols) ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: target, offset: 0 }),\n );\n });\n}\n\n// ---------- Rectangular cell selection (Sub-phase 4.5) ----------\n\nexport interface TableRect {\n blockIndex: number;\n /** Inclusive bounds in OWNER coordinates. */\n top: number;\n left: number;\n bottom: number;\n right: number;\n}\n\n/**\n * Interpret a `Selection` as a rectangular cell range when:\n * - Both endpoints carry `cellIndex`.\n * - They live in the same table block.\n * - They point to DIFFERENT owner cells.\n *\n * The naive bounds are then EXPANDED until every span fully fits inside —\n * essential so that operations like `mergeSelection` can never produce a\n * non-rectangular shape, and so visual highlights always cover whole spans.\n */\nexport function tableRectSelection(\n doc: EditorDocument,\n sel: Selection,\n): TableRect | null {\n if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;\n if (sel.anchor.cellIndex == null || sel.focus.cellIndex == null) return null;\n const blockIndex = sel.anchor.blockIndex;\n if (!doc.isTable(blockIndex)) return null;\n const aLoc = tableLocationOf(doc, sel.anchor);\n const fLoc = tableLocationOf(doc, sel.focus);\n if (!aLoc || !fLoc) return null;\n // After redirection to owners, anchor and focus may collapse to the same\n // owner cell (e.g. anchor in an owner, focus in one of its covered cells).\n if (aLoc.row === fLoc.row && aLoc.col === fLoc.col) return null;\n return expandTableRect(\n doc,\n blockIndex,\n Math.min(aLoc.row, fLoc.row),\n Math.min(aLoc.col, fLoc.col),\n Math.max(aLoc.row, fLoc.row),\n Math.max(aLoc.col, fLoc.col),\n );\n}\n\n/**\n * Grow a candidate rect until every owner whose span starts within the rect\n * fits entirely, and every covered cell inside it has its owner inside too.\n * Converges in O(rows × cols) iterations in the worst case (each pass either\n * grows a bound or terminates).\n */\nexport function expandTableRect(\n doc: EditorDocument,\n blockIndex: number,\n initTop: number,\n initLeft: number,\n initBottom: number,\n initRight: number,\n): TableRect {\n const { rows, cols } = doc.getTableSize(blockIndex);\n let top = Math.max(0, initTop);\n let left = Math.max(0, initLeft);\n let bottom = Math.min(rows - 1, initBottom);\n let right = Math.min(cols - 1, initRight);\n\n let changed = true;\n let guard = rows * cols + 1;\n while (changed && guard-- > 0) {\n changed = false;\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n const a = doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) {\n const owner = doc.realCellIndex(blockIndex, idx);\n if (owner == null) continue;\n const oRow = Math.floor(owner / cols);\n const oCol = owner - oRow * cols;\n if (oRow < top) { top = oRow; changed = true; }\n if (oCol < left) { left = oCol; changed = true; }\n // Owner's far edge:\n const oAttrs = doc.getCellAttrs(blockIndex, owner);\n const oRs = spanOf(oAttrs.rowspan);\n const oCs = spanOf(oAttrs.colspan);\n if (oRow + oRs - 1 > bottom) { bottom = oRow + oRs - 1; changed = true; }\n if (oCol + oCs - 1 > right) { right = oCol + oCs - 1; changed = true; }\n } else {\n const rs = spanOf(a.rowspan);\n const cs = spanOf(a.colspan);\n if (r + rs - 1 > bottom) { bottom = r + rs - 1; changed = true; }\n if (c + cs - 1 > right) { right = c + cs - 1; changed = true; }\n }\n }\n }\n }\n return { blockIndex, top, left, bottom, right };\n}\n\n/** Enumerate every cell-index (real or covered) contained in `rect`. */\nexport function cellsInRect(doc: EditorDocument, rect: TableRect): number[] {\n const { cols } = doc.getTableSize(rect.blockIndex);\n const out: number[] = [];\n for (let r = rect.top; r <= rect.bottom; r++) {\n for (let c = rect.left; c <= rect.right; c++) out.push(r * cols + c);\n }\n return out;\n}\n\n/**\n * Merge every cell in the current rectangular selection into one owner at the\n * rect's top-left. The owner's text is the concatenation of all non-empty\n * inner texts (space-separated, mark-preserving). Returns true on success, false\n * when there is no rect selection.\n */\nexport function mergeSelection(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const rect = tableRectSelection(ctx.doc, sel);\n if (!rect) return false;\n const { blockIndex, top, left, bottom, right } = rect;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n const ownerIdx = top * cols + left;\n\n transact(ctx.doc, () => {\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n if (!ownerText) return;\n\n // Walk every cell in the rect (skip the owner itself). For real cells with\n // non-empty text, append to owner.\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n if (idx === ownerIdx) continue;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered !== true) {\n const t = ctx.doc.getCellText(blockIndex, idx);\n if (t && t.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n const delta = t.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n t.delete(0, t.length);\n }\n }\n // Reset attrs to \"covered\" — drops any prior rowspan/colspan.\n const m = ctx.doc.getCellAttrsMap(blockIndex, idx);\n if (m) {\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n }\n // Update owner spans.\n const oMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (oMap) {\n const newRs = bottom - top + 1;\n const newCs = right - left + 1;\n if (newRs > 1) oMap.set(\"rowspan\", newRs); else oMap.delete(\"rowspan\");\n if (newCs > 1) oMap.set(\"colspan\", newCs); else oMap.delete(\"colspan\");\n oMap.delete(\"covered\");\n }\n ctx.setSelection(\n collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }),\n );\n });\n return true;\n}\n\n/**\n * Clears the text of every cell in the current rectangular selection (no\n * structural mutation — spans stay intact). Returns the collapsed selection\n * at the rect's top-left when something was cleared, otherwise null.\n */\nexport function clearRectCells(ctx: CommandContext): Selection | null {\n const sel = ctx.getSelection();\n const rect = tableRectSelection(ctx.doc, sel);\n if (!rect) return null;\n const { blockIndex, top, left, bottom, right } = rect;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n const ownerIdx = top * cols + left;\n let result: Selection | null = null;\n transact(ctx.doc, () => {\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n const idx = r * cols + c;\n const a = ctx.doc.getCellAttrs(blockIndex, idx);\n if (a.covered === true) continue;\n const t = ctx.doc.getCellText(blockIndex, idx);\n if (t && t.length > 0) t.delete(0, t.length);\n }\n }\n result = collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 });\n ctx.setSelection(result);\n });\n return result;\n}\n\n// ---------- Merge / split ----------\n\n/**\n * Merge the cell at `(row, col)` with its immediate right neighbor. The right\n * neighbor must be a real cell with matching `rowspan` (otherwise the merge\n * would form a non-rectangle). Returns true on success, false on shape\n * mismatch or when there is no neighbor.\n *\n * After: the owner's `colspan` grows by the neighbor's `colspan`; the\n * neighbor and all its formerly-covered cells in the merged rectangle are\n * marked `covered: true`. The neighbor's text is appended to the owner with a\n * single space delimiter (when both sides had content).\n */\nexport function mergeRight(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const ownerIdx = row * cols + col;\n const ownerAttrs = ctx.doc.getCellAttrs(blockIndex, ownerIdx);\n if (ownerAttrs.covered === true) return false;\n const ownerRs = spanOf(ownerAttrs.rowspan);\n const ownerCs = spanOf(ownerAttrs.colspan);\n const nbCol = col + ownerCs;\n if (nbCol >= cols) return false;\n const nbIdx = row * cols + nbCol;\n const nbAttrs = ctx.doc.getCellAttrs(blockIndex, nbIdx);\n if (nbAttrs.covered === true) return false;\n const nbRs = spanOf(nbAttrs.rowspan);\n const nbCs = spanOf(nbAttrs.colspan);\n if (nbRs !== ownerRs) return false;\n\n transact(ctx.doc, () => {\n // Append neighbor's text into the owner.\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n const nbText = ctx.doc.getCellText(blockIndex, nbIdx);\n if (ownerText && nbText && nbText.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n // Re-apply delta with marks and embeds preserved.\n const delta = nbText.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n }\n // Clear neighbor text.\n if (nbText && nbText.length > 0) nbText.delete(0, nbText.length);\n\n // Owner gets the widened colspan.\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (ownerMap) ownerMap.set(\"colspan\", ownerCs + nbCs);\n\n // Mark all cells in the neighbor's old rectangle as covered (in case nbCs > 1,\n // they were already covered — flag still applies).\n for (let r = row; r < row + ownerRs; r++) {\n for (let c = nbCol; c < nbCol + nbCs; c++) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }));\n });\n return true;\n}\n\n/** Merge with the immediate bottom neighbor. Mirror of `mergeRight`. */\nexport function mergeDown(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const ownerIdx = row * cols + col;\n const ownerAttrs = ctx.doc.getCellAttrs(blockIndex, ownerIdx);\n if (ownerAttrs.covered === true) return false;\n const ownerRs = spanOf(ownerAttrs.rowspan);\n const ownerCs = spanOf(ownerAttrs.colspan);\n const nbRow = row + ownerRs;\n if (nbRow >= rows) return false;\n const nbIdx = nbRow * cols + col;\n const nbAttrs = ctx.doc.getCellAttrs(blockIndex, nbIdx);\n if (nbAttrs.covered === true) return false;\n const nbRs = spanOf(nbAttrs.rowspan);\n const nbCs = spanOf(nbAttrs.colspan);\n if (nbCs !== ownerCs) return false;\n\n transact(ctx.doc, () => {\n const ownerText = ctx.doc.getCellText(blockIndex, ownerIdx);\n const nbText = ctx.doc.getCellText(blockIndex, nbIdx);\n if (ownerText && nbText && nbText.length > 0) {\n const sep = ownerText.length > 0 ? \" \" : \"\";\n const delta = nbText.toDelta() as DeltaOp[];\n let pos = ownerText.length;\n if (sep) {\n ownerText.insert(pos, sep);\n pos += 1;\n }\n writeDeltaInto(ownerText, pos, delta);\n }\n if (nbText && nbText.length > 0) nbText.delete(0, nbText.length);\n\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, ownerIdx);\n if (ownerMap) ownerMap.set(\"rowspan\", ownerRs + nbRs);\n\n for (let r = nbRow; r < nbRow + nbRs; r++) {\n for (let c = col; c < col + ownerCs; c++) {\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n m.set(\"covered\", true);\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: ownerIdx, offset: 0 }));\n });\n return true;\n}\n\n/**\n * Split a merged cell back into a `rowspan × colspan` grid of independent real\n * cells. Each formerly-covered cell becomes empty and real. Returns true when\n * something was split. No-op (returns false) on a cell with no spans.\n */\nexport function splitCell(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean {\n if (!ctx.doc.isTable(blockIndex)) return false;\n const { rows, cols } = ctx.doc.getTableSize(blockIndex);\n if (row < 0 || row >= rows || col < 0 || col >= cols) return false;\n const idx = row * cols + col;\n const attrs = ctx.doc.getCellAttrs(blockIndex, idx);\n if (attrs.covered === true) return false;\n const rs = spanOf(attrs.rowspan);\n const cs = spanOf(attrs.colspan);\n if (rs === 1 && cs === 1) return false;\n\n transact(ctx.doc, () => {\n const ownerMap = ctx.doc.getCellAttrsMap(blockIndex, idx);\n if (ownerMap) {\n ownerMap.delete(\"rowspan\");\n ownerMap.delete(\"colspan\");\n }\n for (let r = row; r < row + rs; r++) {\n for (let c = col; c < col + cs; c++) {\n if (r === row && c === col) continue;\n const m = ctx.doc.getCellAttrsMap(blockIndex, r * cols + c);\n if (!m) continue;\n m.delete(\"covered\");\n m.delete(\"rowspan\");\n m.delete(\"colspan\");\n }\n }\n ctx.setSelection(collapsedSelection({ blockIndex, cellIndex: idx, offset: 0 }));\n });\n return true;\n}\n\n// ---------- Column widths (Sub-phase 4.4) ----------\n\n/** Set the width (in CSS px) of a specific column. Auto-initializes `colWidths`. */\nexport function setColumnWidth(\n ctx: CommandContext,\n blockIndex: number,\n col: number,\n widthPx: number,\n): void {\n if (!ctx.doc.isTable(blockIndex)) return;\n const { cols } = ctx.doc.getTableSize(blockIndex);\n if (col < 0 || col >= cols) return;\n const w = Math.max(20, Math.round(widthPx));\n transact(ctx.doc, () => {\n const attrsMap = ctx.doc.getBlockAttrsMap(blockIndex);\n if (!attrsMap) return;\n const current = attrsMap.get(\"colWidths\") as number[] | undefined;\n const next = Array.isArray(current) && current.length === cols\n ? current.slice()\n : new Array<number>(cols).fill(120);\n next[col] = w;\n attrsMap.set(\"colWidths\", next);\n });\n}\n\n/**\n * Move the caret to the next cell of the same table (Tab). At the last cell of\n * the last row, creates a new row and lands in its first cell. Returns true\n * when handled. Caret must be inside a table for this to act.\n */\nexport function moveToNextCell(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const loc = tableLocationOf(ctx.doc, sel.focus);\n if (!loc) return false;\n const { rows, cols } = ctx.doc.getTableSize(loc.blockIndex);\n if (rows <= 0 || cols <= 0) return false;\n\n // Walk forward starting at the cell immediately following the owner's bottom-right.\n // For a non-spanning cell that's `flat + 1`; for a span, it's `(loc.row, loc.col + colspan)`\n // — but conceptually the owner's \"next\" sibling is simply the next real cell in row-major\n // order after the owner's flat index, since covered cells get skipped by the loop below.\n const startFlat = loc.row * cols + loc.col + 1;\n const next = findNextRealCell(ctx.doc, loc.blockIndex, startFlat, rows * cols);\n if (next == null) {\n // No more cells in the table — append a new row and land in its first cell.\n insertTableRow(ctx, loc.blockIndex, rows - 1, \"after\");\n return true;\n }\n ctx.setSelection(\n collapsedSelection({ blockIndex: loc.blockIndex, cellIndex: next, offset: 0 }),\n );\n return true;\n}\n\n/** Move the caret to the previous cell (Shift+Tab). At the first cell, no-op (returns true). */\nexport function moveToPrevCell(ctx: CommandContext): boolean {\n const sel = ctx.getSelection();\n const loc = tableLocationOf(ctx.doc, sel.focus);\n if (!loc) return false;\n const { rows, cols } = ctx.doc.getTableSize(loc.blockIndex);\n if (rows <= 0 || cols <= 0) return false;\n const startFlat = loc.row * cols + loc.col - 1;\n if (startFlat < 0) return true; // at (0,0) — handled but no-op\n const prev = findPrevRealCell(ctx.doc, loc.blockIndex, startFlat);\n if (prev == null) return true;\n const cellText = ctx.doc.getCellText(loc.blockIndex, prev);\n const off = cellText?.length ?? 0;\n ctx.setSelection(\n collapsedSelection({ blockIndex: loc.blockIndex, cellIndex: prev, offset: off }),\n );\n return true;\n}\n\nfunction findNextRealCell(\n doc: EditorDocument,\n blockIndex: number,\n startFlat: number,\n total: number,\n): number | null {\n for (let i = startFlat; i < total; i++) {\n if (doc.getCellAttrs(blockIndex, i).covered !== true) return i;\n }\n return null;\n}\n\nfunction findPrevRealCell(\n doc: EditorDocument,\n blockIndex: number,\n startFlat: number,\n): number | null {\n for (let i = startFlat; i >= 0; i--) {\n if (doc.getCellAttrs(blockIndex, i).covered !== true) return i;\n }\n return null;\n}\n\n/**\n * Append/write a delta's ops into `yText` starting at `pos`, preserving marks\n * AND image embeds. Returns the position right after the last write.\n */\nfunction writeDeltaInto(yText: Y.Text, pos: number, delta: DeltaOp[]): number {\n let cursor = pos;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n if (op.insert.length === 0) continue;\n if (op.attributes && Object.keys(op.attributes).length > 0) {\n yText.insert(cursor, op.insert, op.attributes as Record<string, unknown>);\n } else {\n yText.insert(cursor, op.insert);\n }\n cursor += op.insert.length;\n } else if (op.insert != null) {\n // Embed (e.g. ImageEmbed). Y.Text accepts arbitrary JSON-serializable\n // objects as length-1 inserts.\n if (op.attributes && Object.keys(op.attributes).length > 0) {\n yText.insert(\n cursor,\n op.insert as unknown as string,\n op.attributes as Record<string, unknown>,\n );\n } else {\n yText.insert(cursor, op.insert as unknown as string);\n }\n cursor += 1;\n }\n }\n return cursor;\n}\n\n// ---------- Inline embeds (Fase 5: imagens) ----------\n\n/**\n * Insert an inline image embed at the current selection. Embeds occupy 1 char\n * in offset arithmetic (Y.Text treats them as length-1 inserts).\n */\nexport function insertImage(ctx: CommandContext, embed: ImageEmbed): void {\n clearRectCells(ctx);\n transact(ctx.doc, () => {\n const sel0 = ctx.getSelection();\n let cursor = sel0;\n if (!isCollapsed(sel0)) cursor = deleteRange(ctx.doc, sel0);\n const pos = cursor.focus;\n const yText = ctx.doc.textAt(pos.blockIndex, pos.cellIndex);\n if (!yText) return;\n // Y.Text accepts non-string inserts natively.\n yText.insert(pos.offset, embed as unknown as string);\n const newPos: Position = {\n blockIndex: pos.blockIndex,\n cellIndex: pos.cellIndex,\n offset: pos.offset + 1,\n };\n ctx.setSelection(collapsedSelection(newPos));\n });\n}\n\n/**\n * Update attributes of an existing image embed at `(blockIndex, embedOffset)`.\n * Implementation: delete the 1-char slot and re-insert the merged embed in the\n * SAME transaction — Y.UndoManager coalesces delete+insert in one transact, so\n * undo treats it as a single step.\n *\n * If `newOffset` is provided and differs from `embedOffset`, the embed is moved\n * to that offset within the same block/cell. Used by wrap-left/wrap-right\n * layouts which must anchor the image at the block start so floated text wraps\n * around it (CSS float only flows text that comes AFTER the float in DOM order).\n */\nexport function setImageAttrs(\n ctx: CommandContext,\n blockIndex: number,\n embedOffset: number,\n partial: Partial<ImageEmbed>,\n cellIndex?: number,\n newOffset?: number,\n): void {\n transact(ctx.doc, () => {\n const yText = ctx.doc.textAt(blockIndex, cellIndex);\n if (!yText) return;\n const delta = yText.toDelta() as DeltaOp[];\n let cursor = 0;\n let prev: ImageEmbed | null = null;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n cursor += op.insert.length;\n continue;\n }\n if (cursor === embedOffset && isImageEmbed(op.insert)) {\n prev = op.insert;\n break;\n }\n cursor += 1;\n }\n if (!prev) return;\n const merged: ImageEmbed = { ...prev, ...partial };\n yText.delete(embedOffset, 1);\n const insertAt =\n newOffset != null && newOffset !== embedOffset\n ? Math.max(0, Math.min(newOffset, yText.length))\n : embedOffset;\n yText.insert(insertAt, merged as unknown as string);\n });\n}\n\n// Expose the Y origin so consumers (e.g. UndoManager) can filter on it.\nexport function isCommandOrigin(origin: unknown): boolean {\n return origin === COMMAND_ORIGIN;\n}\n\n// Allow Y.UndoManager.trackedOrigins to include the symbol.\nexport const TRACKED_ORIGINS: Set<unknown> = new Set([COMMAND_ORIGIN]);\n\n// Re-export Y for downstream type checks if needed.\nexport { Y };\n","import * as Y from \"yjs\";\nimport type { EditorDocument } from \"./document\";\nimport { TRACKED_ORIGINS } from \"./commands\";\n\nexport class EditorHistory {\n readonly undoManager: Y.UndoManager;\n\n constructor(doc: EditorDocument) {\n this.undoManager = new Y.UndoManager(doc.blocks, {\n trackedOrigins: TRACKED_ORIGINS,\n captureTimeout: 400,\n });\n }\n\n undo(): boolean {\n return this.undoManager.undo() != null;\n }\n\n redo(): boolean {\n return this.undoManager.redo() != null;\n }\n\n destroy(): void {\n this.undoManager.destroy();\n }\n}\n"],"mappings":"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","names":["merged","yText","Y","yText","Y"]}
|