@voithos-labs/aragonite 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -21
- package/THIRD-PARTY-NOTICES.md +25 -0
- package/dist/a11y-strings.d.ts +18 -0
- package/dist/a11y-strings.js +18 -0
- package/dist/action-contracts.d.ts +7 -1
- package/dist/ambient/ambient-dom.js +5 -1
- package/dist/block-component.d.ts +14 -0
- package/dist/components/BlockDragHandle.svelte +35 -24
- package/dist/components/BlockHost.svelte +16 -9
- package/dist/components/Editor.svelte +381 -198
- package/dist/components/Editor.svelte.d.ts +1 -1
- package/dist/components/SelectionOverlay.svelte +17 -3
- package/dist/components/TailInsert.svelte +107 -0
- package/dist/components/TailInsert.svelte.d.ts +17 -0
- package/dist/components/block-content-selector.d.ts +6 -2
- package/dist/components/block-content-selector.js +6 -2
- package/dist/components/blocks/ThematicBreakBlock.svelte +19 -6
- package/dist/components/blocks/ThematicBreakBlock.svelte.d.ts +1 -0
- package/dist/components/blocks/code/CodeBlock.svelte +211 -30
- package/dist/components/blocks/code/CodeBlockRail.svelte +686 -0
- package/dist/components/blocks/code/CodeBlockRail.svelte.d.ts +26 -0
- package/dist/components/blocks/code/code-bootstrap.js +4 -0
- package/dist/components/blocks/code/code-context-actions.d.ts +1 -0
- package/dist/components/blocks/code/code-context-actions.js +24 -0
- package/dist/components/blocks/code/code-fence-exit.d.ts +15 -0
- package/dist/components/blocks/code/code-fence-exit.js +26 -0
- package/dist/components/blocks/code/code-languages.d.ts +6 -0
- package/dist/components/blocks/code/code-languages.js +11 -0
- package/dist/components/blocks/code/code-renderer.js +11 -0
- package/dist/components/blocks/directive/DirectiveContainerBlock.svelte +1 -1
- package/dist/components/blocks/editable-leaf.d.ts +37 -6
- package/dist/components/blocks/editable-leaf.js +243 -29
- package/dist/components/blocks/editable-surface.d.ts +9 -0
- package/dist/components/blocks/editable-surface.js +22 -3
- package/dist/components/blocks/list/ListItemBlock.svelte +3 -3
- package/dist/components/blocks/list/task-checkbox.d.ts +2 -0
- package/dist/components/blocks/list/task-checkbox.js +11 -2
- package/dist/components/blocks/surface-wiring.svelte.d.ts +4 -0
- package/dist/components/blocks/surface-wiring.svelte.js +8 -1
- package/dist/components/blocks/table/TableActionMenu.svelte +210 -86
- package/dist/components/blocks/table/TableActionMenu.svelte.d.ts +5 -0
- package/dist/components/blocks/table/TableBlock.svelte +205 -186
- package/dist/components/blocks/table/TableBlock.svelte.d.ts +1 -0
- package/dist/components/blocks/table/TableCellBlock.svelte +87 -22
- package/dist/components/blocks/table/TableRowBlock.svelte +4 -18
- package/dist/components/blocks/table/TableRowBlock.svelte.d.ts +0 -5
- package/dist/components/blocks/table/cell-clipboard.d.ts +10 -0
- package/dist/components/blocks/table/cell-clipboard.js +34 -1
- package/dist/components/blocks/table/cell-keydown-plan.d.ts +1 -1
- package/dist/components/blocks/table/cell-keydown-plan.js +3 -1
- package/dist/components/blocks/table/table-cell-paste.js +2 -1
- package/dist/components/blocks/table/table-menu-model.d.ts +35 -8
- package/dist/components/blocks/table/table-menu-model.js +36 -17
- package/dist/components/blocks/text/TextEditableBlock.svelte +58 -11
- package/dist/components/blocks/text/delimiter-autopair.d.ts +71 -0
- package/dist/components/blocks/text/delimiter-autopair.js +216 -0
- package/dist/components/blocks/text/edge-policy-dispatch.d.ts +4 -0
- package/dist/components/blocks/text/edge-policy-dispatch.js +56 -2
- package/dist/components/blocks/text/live-selection-edit.js +27 -0
- package/dist/components/blocks/text/text-keydown.d.ts +7 -1
- package/dist/components/blocks/text/text-keydown.js +11 -1
- package/dist/components/blocks/text/text-render.d.ts +1 -1
- package/dist/components/blocks/text/text-render.js +3 -1
- package/dist/components/blocks/text/widget-interaction.d.ts +3 -0
- package/dist/components/blocks/text/widget-interaction.js +144 -22
- package/dist/components/drag-handle.d.ts +35 -0
- package/dist/components/drag-handle.js +126 -0
- package/dist/components/editor-root-focus.d.ts +19 -0
- package/dist/components/editor-root-focus.js +67 -0
- package/dist/components/editor-root-geometry.d.ts +39 -0
- package/dist/components/editor-root-geometry.js +91 -0
- package/dist/components/editor-root-keydown.d.ts +1 -1
- package/dist/components/editor-root-keydown.js +12 -3
- package/dist/components/editor-root-listeners.d.ts +10 -6
- package/dist/components/editor-root-listeners.js +23 -22
- package/dist/components/editor-root-mode-flip.d.ts +36 -0
- package/dist/components/editor-root-mode-flip.js +92 -0
- package/dist/components/image/ImageOverlayHost.svelte +14 -6
- package/dist/components/image/ImageProperties.svelte +512 -70
- package/dist/components/image/ImageProperties.svelte.d.ts +6 -1
- package/dist/components/image/ImageResizeHandles.svelte +59 -34
- package/dist/components/image/image-crop.d.ts +39 -0
- package/dist/components/image/image-crop.js +74 -0
- package/dist/components/image/image-edit-commit.d.ts +1 -0
- package/dist/components/image/image-edit-commit.js +21 -5
- package/dist/components/image/image-source-bytes.js +10 -3
- package/dist/components/image/image-widget-editing.js +1 -0
- package/dist/components/image/widget-dom.js +5 -1
- package/dist/components/link-card/link-card-commit.js +1 -1
- package/dist/components/lrd-map-gate.js +1 -1
- package/dist/components/menu/BlockMenu.svelte +315 -0
- package/dist/components/menu/BlockMenu.svelte.d.ts +34 -0
- package/dist/components/menu/MenuIcon.svelte +153 -0
- package/dist/components/menu/MenuIcon.svelte.d.ts +51 -0
- package/dist/components/menu/clipboard-actions.d.ts +12 -0
- package/dist/components/menu/clipboard-actions.js +42 -0
- package/dist/components/menu/default-context-actions.d.ts +15 -0
- package/dist/components/menu/default-context-actions.js +76 -0
- package/dist/components/menu/flyout-placement.d.ts +6 -0
- package/dist/components/menu/flyout-placement.js +25 -0
- package/dist/core/inline/format-toggle.d.ts +12 -4
- package/dist/core/inline/format-toggle.js +94 -40
- package/dist/core/inline/image-dimensions.d.ts +3 -0
- package/dist/core/inline/image-dimensions.js +46 -10
- package/dist/core/inline/inline-widgets.d.ts +11 -0
- package/dist/core/inline/scan/brackets.js +1 -0
- package/dist/core/inline/scan/plugin-syntax.d.ts +8 -0
- package/dist/core/inline/scan/plugin-syntax.js +15 -1
- package/dist/core/inline-render.d.ts +6 -0
- package/dist/core/inline-render.js +32 -0
- package/dist/core/nodes.d.ts +14 -0
- package/dist/cursor/edge-affinity.js +2 -1
- package/dist/cursor/overlay-remeasure.js +8 -0
- package/dist/cursor/reveal-source.js +7 -2
- package/dist/cursor/widget-offset.d.ts +6 -0
- package/dist/cursor/widget-offset.js +61 -4
- package/dist/debug/interaction-trace.d.ts +4 -0
- package/dist/debug/interaction-trace.js +15 -0
- package/dist/decorations/decoration-state.svelte.js +1 -1
- package/dist/editor-actions/ancestry-folds.d.ts +2 -2
- package/dist/editor-actions/ancestry-folds.js +1 -1
- package/dist/editor-actions/block-edit-scope.js +1 -1
- package/dist/editor-actions/commit/text-batch.d.ts +3 -2
- package/dist/editor-actions/commit/text-batch.js +1 -1
- package/dist/editor-actions/commit/undo-controller.js +4 -2
- package/dist/editor-actions/container-edit.js +2 -1
- package/dist/editor-actions/enter-completion.d.ts +2 -0
- package/dist/editor-actions/enter-completion.js +23 -2
- package/dist/editor-actions/inline-range-commit.js +1 -1
- package/dist/editor-actions/reorder-action.js +19 -10
- package/dist/editor-actions/reorder-drag.js +29 -1
- package/dist/editor-actions/replacement-focus.d.ts +1 -1
- package/dist/editor-actions/replacement-focus.js +1 -1
- package/dist/editor-actions/search-replace.js +1 -1
- package/dist/editor-actions/table-context.d.ts +4 -1
- package/dist/editor-actions/table-context.js +57 -1
- package/dist/editor-events.d.ts +3 -0
- package/dist/editor-keys.d.ts +33 -0
- package/dist/editor-props.d.ts +21 -12
- package/dist/index.d.ts +1 -1
- package/dist/plugin.d.ts +6 -0
- package/dist/plugin.js +11 -0
- package/dist/plugins/latex/BlockMath.svelte +264 -29
- package/dist/plugins/latex/BlockMath.svelte.d.ts +2 -0
- package/dist/plugins/latex/index.d.ts +2 -1
- package/dist/plugins/latex/latex-kind.js +36 -3
- package/dist/plugins/latex/math-completion.js +4 -1
- package/dist/plugins/latex/math-layout.d.ts +15 -0
- package/dist/plugins/latex/math-layout.js +13 -0
- package/dist/plugins/latex/math-source.d.ts +19 -0
- package/dist/plugins/latex/math-source.js +97 -0
- package/dist/plugins/latex/register.d.ts +11 -2
- package/dist/plugins/latex/register.js +3 -1
- package/dist/plugins/latex/renderer.d.ts +3 -3
- package/dist/plugins/latex/renderer.js +13 -6
- package/dist/reactivity/list-windowing.svelte.d.ts +8 -8
- package/dist/reactivity/list-windowing.svelte.js +49 -24
- package/dist/schema/block-completions.d.ts +8 -0
- package/dist/schema/block-completions.js +11 -0
- package/dist/schema/context-actions.d.ts +31 -0
- package/dist/schema/context-actions.js +23 -0
- package/dist/schema/fenced-code-raw.js +31 -1
- package/dist/schema/operations.d.ts +8 -1
- package/dist/schema/reserved-chords.js +25 -4
- package/dist/schema/table-cell-raw.d.ts +1 -1
- package/dist/schema/table-cell-raw.js +1 -1
- package/dist/selection/block-hit-test.js +3 -2
- package/dist/selection/char-endpoint-snap.js +1 -1
- package/dist/selection/clipboard-text.js +6 -1
- package/dist/selection/covered-block.d.ts +10 -0
- package/dist/selection/covered-block.js +24 -0
- package/dist/selection/cross-block/dispatch.d.ts +3 -0
- package/dist/selection/cross-block/dispatch.js +13 -1
- package/dist/selection/cross-block/format-range.d.ts +1 -1
- package/dist/selection/cross-block/format-range.js +4 -15
- package/dist/selection/cross-block/format-toggle.js +1 -1
- package/dist/selection/cross-block/keydown.js +1 -1
- package/dist/selection/cross-block/ops.js +1 -1
- package/dist/selection/cross-block/paste.js +32 -30
- package/dist/selection/cross-block/type-replace.d.ts +3 -2
- package/dist/selection/cross-block/type-replace.js +62 -13
- package/dist/selection/dead-space-caret.d.ts +10 -0
- package/dist/selection/dead-space-caret.js +47 -1
- package/dist/selection/double-click-trim.d.ts +17 -0
- package/dist/selection/double-click-trim.js +57 -0
- package/dist/selection/drag-pointer.d.ts +7 -2
- package/dist/selection/drag-pointer.js +61 -2
- package/dist/selection/gap-caret.js +1 -1
- package/dist/selection/keyboard-extend.js +1 -1
- package/dist/selection/path-lookup.js +1 -1
- package/dist/selection/range-delete-ceremony.js +4 -2
- package/dist/selection/range-delete-chrome.js +2 -1
- package/dist/selection/range-delete-table-coverage.js +2 -1
- package/dist/selection/range-delete-table.js +3 -2
- package/dist/selection/range-delete.js +30 -2
- package/dist/selection/selection-restore.js +1 -1
- package/dist/selection/selection-state.svelte.d.ts +6 -0
- package/dist/selection/selection-state.svelte.js +36 -1
- package/dist/selection/table-endpoint-snap.js +1 -1
- package/dist/selection/table-rect-extend.js +1 -1
- package/dist/styles/editor-theme.css +57 -28
- package/dist/styles/editor.css +217 -18
- package/dist/testing/container-conformance.js +2 -2
- package/dist/testing/inline-conformance.js +2 -1
- package/dist/tree-operations/blockquote.js +1 -1
- package/dist/tree-operations/chain-rebuild.d.ts +63 -0
- package/dist/tree-operations/chain-rebuild.js +142 -0
- package/dist/tree-operations/children.d.ts +1 -1
- package/dist/tree-operations/children.js +1 -1
- package/dist/tree-operations/cleanup.js +1 -1
- package/dist/tree-operations/content-write.d.ts +50 -0
- package/dist/tree-operations/content-write.js +263 -0
- package/dist/tree-operations/index.d.ts +8 -3
- package/dist/tree-operations/index.js +6 -2
- package/dist/tree-operations/list/exit-replacement.js +1 -1
- package/dist/tree-operations/list/unwrap-merge.js +3 -3
- package/dist/tree-operations/node-ops.d.ts +17 -234
- package/dist/tree-operations/node-ops.js +47 -1113
- package/dist/tree-operations/node-primitives.d.ts +75 -0
- package/dist/tree-operations/node-primitives.js +117 -0
- package/dist/tree-operations/paste/apply.js +1 -1
- package/dist/tree-operations/paste/body-write.d.ts +1 -1
- package/dist/tree-operations/paste/body-write.js +2 -2
- package/dist/tree-operations/paste/container-match.js +4 -2
- package/dist/tree-operations/paste/dispatch.js +2 -1
- package/dist/tree-operations/paste/find-enclosing-list.js +1 -1
- package/dist/tree-operations/paste/focus-target.d.ts +1 -1
- package/dist/tree-operations/paste/list-absorb.js +1 -1
- package/dist/tree-operations/paste/list-break-out.js +1 -1
- package/dist/tree-operations/paste/parent-scope.js +1 -1
- package/dist/tree-operations/paste/paste-replacement.js +1 -1
- package/dist/tree-operations/paste/replace-block-at-parent.js +1 -1
- package/dist/tree-operations/path-mutate.d.ts +1 -1
- package/dist/tree-operations/path-mutate.js +2 -1
- package/dist/tree-operations/reorder-unit.js +1 -1
- package/dist/tree-operations/reorder.d.ts +5 -2
- package/dist/tree-operations/reorder.js +55 -2
- package/dist/tree-operations/settle.d.ts +105 -0
- package/dist/tree-operations/settle.js +660 -0
- package/dist/tree-operations/table-grid-clipboard.d.ts +21 -0
- package/dist/tree-operations/table-grid-clipboard.js +90 -0
- package/dist/tree-operations/unshare.d.ts +15 -77
- package/dist/tree-operations/unshare.js +15 -166
- package/docs/guide/consumer-guide.md +126 -96
- package/docs/guide/plugin-api.md +31 -3
- package/docs/guide/plugin-guide.md +26 -3
- package/package.json +4 -2
- package/dist/components/blocks/code/CodeLanguageChip.svelte +0 -127
- package/dist/components/blocks/code/CodeLanguageChip.svelte.d.ts +0 -14
- package/dist/components/blocks/table/TableGrip.svelte +0 -91
- package/dist/components/blocks/table/TableGrip.svelte.d.ts +0 -8
- package/dist/components/blocks/table/table-drop-target.d.ts +0 -1
- package/dist/components/blocks/table/table-drop-target.js +0 -16
- package/dist/components/blocks/table/table-reorder-drag.d.ts +0 -78
- package/dist/components/blocks/table/table-reorder-drag.js +0 -97
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grid a clipboard payload holds, for a spreadsheet-like paste into a table: tab-separated
|
|
3
|
+
* rows (what Excel and Sheets write to text/plain) or a GFM table (what this editor's own
|
|
4
|
+
* rectangle copy writes). Anything else is not a grid and takes the ordinary paste route. The
|
|
5
|
+
* inverse, an HTML table for the spreadsheets that read text/html, lives here too.
|
|
6
|
+
*/
|
|
7
|
+
/** Rows of cell texts, rectangular: every row padded to the widest. Null for a non-grid payload. */
|
|
8
|
+
export function parseClipboardGrid(text) {
|
|
9
|
+
const lines = text.replace(/\r\n?/g, '\n').split('\n');
|
|
10
|
+
while (lines.length && lines[lines.length - 1].trim() === '')
|
|
11
|
+
lines.pop();
|
|
12
|
+
if (lines.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
const rows = parseGfmRows(lines) ?? parseTsvRows(lines);
|
|
15
|
+
if (!rows || rows.length === 0)
|
|
16
|
+
return null;
|
|
17
|
+
let width = 0;
|
|
18
|
+
for (const row of rows)
|
|
19
|
+
width = Math.max(width, row.length);
|
|
20
|
+
if (width < 2 && rows.length < 2)
|
|
21
|
+
return null;
|
|
22
|
+
return rows.map((row) => [...row, ...Array(width - row.length).fill('')]);
|
|
23
|
+
}
|
|
24
|
+
// Every line a pipe row; the delimiter line (second, all dashes and colons) is dropped.
|
|
25
|
+
function parseGfmRows(lines) {
|
|
26
|
+
if (!lines.every((line) => /^\s*\|.*\|\s*$/.test(line)))
|
|
27
|
+
return null;
|
|
28
|
+
const rows = lines.map(splitPipeRow);
|
|
29
|
+
if (rows.length >= 2 && rows[1].every((cell) => /^:?-+:?$/.test(cell)))
|
|
30
|
+
rows.splice(1, 1);
|
|
31
|
+
return rows;
|
|
32
|
+
}
|
|
33
|
+
function splitPipeRow(line) {
|
|
34
|
+
const inner = line.trim().slice(1, -1);
|
|
35
|
+
const cells = [];
|
|
36
|
+
let cell = '';
|
|
37
|
+
for (let i = 0; i < inner.length; i++) {
|
|
38
|
+
const ch = inner[i];
|
|
39
|
+
if (ch === '\\' && inner[i + 1] === '|') {
|
|
40
|
+
cell += '|';
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
else if (ch === '|') {
|
|
44
|
+
cells.push(cell.trim());
|
|
45
|
+
cell = '';
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
cell += ch;
|
|
49
|
+
}
|
|
50
|
+
cells.push(cell.trim());
|
|
51
|
+
return cells;
|
|
52
|
+
}
|
|
53
|
+
function parseTsvRows(lines) {
|
|
54
|
+
if (!lines.some((line) => line.includes('\t')))
|
|
55
|
+
return null;
|
|
56
|
+
return lines.map((line) => line.split('\t'));
|
|
57
|
+
}
|
|
58
|
+
/** A rectangle's cell texts, pipes unescaped, as the clipboard's grid. */
|
|
59
|
+
export function rectangleGrid(table, a, b) {
|
|
60
|
+
const rows = table.children ?? [];
|
|
61
|
+
const grid = [];
|
|
62
|
+
for (let r = Math.min(a.rowIdx, b.rowIdx); r <= Math.max(a.rowIdx, b.rowIdx); r++) {
|
|
63
|
+
const cells = rows[r]?.children ?? [];
|
|
64
|
+
const line = [];
|
|
65
|
+
for (let c = Math.min(a.colIdx, b.colIdx); c <= Math.max(a.colIdx, b.colIdx); c++) {
|
|
66
|
+
line.push((cells[c]?.raw ?? '').replace(/\\\|/g, '|'));
|
|
67
|
+
}
|
|
68
|
+
grid.push(line);
|
|
69
|
+
}
|
|
70
|
+
return grid;
|
|
71
|
+
}
|
|
72
|
+
/** The grid repeated to fill a selection whose sides are multiples of it (a spreadsheet's
|
|
73
|
+
* tiling); any other selection takes the grid once from its top-left corner. */
|
|
74
|
+
export function tileGridTo(grid, rows, cols) {
|
|
75
|
+
const height = grid.length;
|
|
76
|
+
const width = grid[0]?.length ?? 0;
|
|
77
|
+
if (height === 0 || width === 0)
|
|
78
|
+
return grid;
|
|
79
|
+
if (rows % height !== 0 || cols % width !== 0 || (rows === height && cols === width)) {
|
|
80
|
+
return grid;
|
|
81
|
+
}
|
|
82
|
+
return Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => grid[r % height][c % width]));
|
|
83
|
+
}
|
|
84
|
+
export function gridToHtmlTable(grid) {
|
|
85
|
+
const escape = (text) => text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
86
|
+
const rows = grid
|
|
87
|
+
.map((row) => `<tr>${row.map((cell) => `<td>${escape(cell)}</td>`).join('')}</tr>`)
|
|
88
|
+
.join('');
|
|
89
|
+
return `<table>${rows}</table>`;
|
|
90
|
+
}
|
|
@@ -8,94 +8,32 @@
|
|
|
8
8
|
import type { CstNode } from '../core/nodes';
|
|
9
9
|
import type { NodeParentView, NodeView } from '../core/node-views';
|
|
10
10
|
import type { SharingState } from './sharing';
|
|
11
|
-
import type { NodeParent
|
|
12
|
-
import type {
|
|
13
|
-
import { type ChildRawChange } from '../schema/child-spans';
|
|
14
|
-
import type { GrammarView } from '../schema/block-openers';
|
|
11
|
+
import type { NodeParent } from './node-primitives';
|
|
12
|
+
import type { ChildRawChange } from '../schema/child-spans';
|
|
15
13
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* which
|
|
14
|
+
* The copy-on-write spine walk, returning the owned chain outermost-first. `assertInRange`
|
|
15
|
+
* fires G1.22 for the strict `ensureUnsharedPath` caller and stays silent for tolerant rebuild
|
|
16
|
+
* passes, which legitimately hand short paths; the walk stops at the first gap either way.
|
|
19
17
|
*/
|
|
20
|
-
export declare function
|
|
18
|
+
export declare function walkUnsharing(root: NodeParentView, path: number[], sharing: SharingState, assertInRange: boolean): CstNode[];
|
|
21
19
|
/**
|
|
22
|
-
* Unshare
|
|
23
|
-
*
|
|
20
|
+
* Unshare every node along `path` from `root`; returns the chain outermost-first. The caller
|
|
21
|
+
* owns `root.children` (live document, or a commit ceremony's array copy).
|
|
24
22
|
*/
|
|
23
|
+
export declare function ensureUnsharedPath(root: NodeParentView, path: number[], sharing: SharingState): CstNode[];
|
|
24
|
+
/** Unshare one direct child of an already-unshared parent, or of a caller-owned `{ children }`. */
|
|
25
25
|
export declare function ensureUnsharedChild(parent: CstNode | NodeParent, index: number, sharing: SharingState): CstNode;
|
|
26
26
|
/**
|
|
27
|
-
* Standalone copy for a node being MOVED out of a parent the snapshot keeps: the caller
|
|
28
|
-
*
|
|
29
|
-
* unshared input passes through — unshared already means live-tree-owned.
|
|
27
|
+
* Standalone copy for a node being MOVED out of a parent the snapshot keeps: the caller attaches
|
|
28
|
+
* the copy, the original stays put. An unshared input passes through as live-tree-owned.
|
|
30
29
|
*/
|
|
31
30
|
export declare function ensureUnsharedNode(node: NodeView, sharing: SharingState): CstNode;
|
|
32
31
|
/** Unshare every direct child of an owned parent (e.g. table rows before a whole-table rebuild). */
|
|
33
32
|
export declare function ensureUnsharedChildren(parent: CstNode, sharing: SharingState): void;
|
|
34
|
-
/**
|
|
35
|
-
* Deep-unshare an owned node's subtree. Intended for small bounded subtrees
|
|
36
|
-
* (tables: rows + cells) ahead of ops that write at arbitrary depth.
|
|
37
|
-
*/
|
|
33
|
+
/** Deep-unshare an owned node's subtree, for small bounded subtrees written at arbitrary depth. */
|
|
38
34
|
export declare function ensureUnsharedSubtree(node: CstNode, sharing: SharingState): void;
|
|
39
35
|
/**
|
|
40
|
-
* Rebuild one owned container's raw. A grid rebuild rewrites its children's raw, so a
|
|
41
|
-
*
|
|
42
|
-
* test, or a plugin grid writes through shared children.
|
|
36
|
+
* Rebuild one owned container's raw. A grid rebuild rewrites its children's raw, so a grid's
|
|
37
|
+
* children are unshared first, keyed off `containerContract` rather than a `table` kind test.
|
|
43
38
|
*/
|
|
44
39
|
export declare function rebuildOwnedContainer(node: CstNode, sharing: SharingState, changed?: ChildRawChange): void;
|
|
45
|
-
/**
|
|
46
|
-
* Longest prefix of `chain` still attached under `root`, identity-checked level by level.
|
|
47
|
-
* A commit mutation can splice a node out mid-ceremony; rebuilding the detached node's
|
|
48
|
-
* raw against its emptied children writes `raw: ''` and trips the commit-time staleness
|
|
49
|
-
* check. Ancestors above the detachment still need their rebuild — hence prefix.
|
|
50
|
-
*/
|
|
51
|
-
export declare function attachedChainPrefix(root: NodeParent, chain: CstNode[]): CstNode[];
|
|
52
|
-
/**
|
|
53
|
-
* One container slot a rebuild re-kinded. `previous` is the rollback register: a commit
|
|
54
|
-
* unwinding after the swap has already published `replacement` into a live children
|
|
55
|
-
* array, which no other rollback register reaches.
|
|
56
|
-
*/
|
|
57
|
-
export interface ContainerReclassification {
|
|
58
|
-
siblings: CstNode[];
|
|
59
|
-
index: number;
|
|
60
|
-
previous: CstNode;
|
|
61
|
-
replacement: CstNode;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* A fold the rebuilt container's own slot owed: its bytes stopped interrupting a neighbour, so
|
|
65
|
-
* the parent's array reloads as fewer blocks and no scope-local settle reaches that join
|
|
66
|
-
* `before` is the pre-splice array — the rollback register, since the splice lands in
|
|
67
|
-
* an array no commit descriptor covers. `landing` is where the container's first byte ended up.
|
|
68
|
-
*/
|
|
69
|
-
export interface AncestrySeamFold {
|
|
70
|
-
/** Chain level of the folded container, so a caller composes the owner's path from its own. */
|
|
71
|
-
depth: number;
|
|
72
|
-
siblings: CstNode[];
|
|
73
|
-
/** The chain node owning `siblings`, or null when they are the rebuild root's children. */
|
|
74
|
-
owner: CstNode | null;
|
|
75
|
-
change: StructuralChange;
|
|
76
|
-
before: CstNode[];
|
|
77
|
-
landing: TrackedPosition;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* What the typing door knows and a bare chain does not: where the chain sits in the document,
|
|
81
|
-
* and the bytes its leaf carried before the write. Both are guesses the rebuild identity-checks.
|
|
82
|
-
*/
|
|
83
|
-
export interface ChainWriteHint {
|
|
84
|
-
path: number[];
|
|
85
|
-
leafPreviousRaw: string;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Rebuild raws along an owned spine chain innermost-first, re-deriving each container's kind and
|
|
89
|
-
* settling the seams at its own slot; chain- rather than path-based so it survives index shifts.
|
|
90
|
-
* Both passes gate on a boundary line of the rebuilt raw moving; the re-derive additionally needs
|
|
91
|
-
* `lineOpensAs` not to name the current kind, a positive identification so a declining opener
|
|
92
|
-
* parses rather than eliding a real kind change. `folds` is required-nullable: a fold splices the
|
|
93
|
-
* PARENT's array, so only a caller that reconciles that scope's ids/refs passes a sink.
|
|
94
|
-
*/
|
|
95
|
-
export declare function rebuildUnsharedChain(root: NodeParent | CstNode, chain: CstNode[], sharing: SharingState, folds: AncestrySeamFold[] | null, grammar: GrammarView | undefined, hint?: ChainWriteHint): ContainerReclassification[];
|
|
96
|
-
/**
|
|
97
|
-
* Unshare the spine to `path` and rebuild it innermost-first, tolerating paths that ran
|
|
98
|
-
* out of range mid-walk (post-delete rebuild passes). Prefer `rebuildUnsharedChain` when
|
|
99
|
-
* indices may have shifted since the unshare.
|
|
100
|
-
*/
|
|
101
|
-
export declare function rebuildUnsharedAncestry(root: NodeParent, path: number[], sharing: SharingState, folds: AncestrySeamFold[] | null, grammar: GrammarView | undefined): ContainerReclassification[];
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { assertInvariant } from '../assert';
|
|
2
2
|
import { checkCloneSafeMetadata } from '../invariants/node-shape';
|
|
3
3
|
import { rebuildContainerRawIfContainer } from '../schema/container-raw';
|
|
4
|
-
import { dropChildSpans } from '../schema/child-spans';
|
|
5
4
|
import { getBlockKindDescriptor } from '../schema/block-kind-descriptor';
|
|
6
|
-
import { trimTrailingLineEnding } from '../core/lines';
|
|
7
|
-
import { perfEnabled, recordRebuildDepth } from '../perf/instruments';
|
|
8
5
|
import { cloneMetadata } from './clone';
|
|
9
|
-
import { absorbWindowSeams, lineOpensAs, reclassifyContainer } from './node-ops';
|
|
10
|
-
import { settleSublistSeparator } from './list/sublist-separator';
|
|
11
6
|
function copyNode(node, sharing) {
|
|
12
7
|
const copy = { ...node };
|
|
13
8
|
if (node.children)
|
|
@@ -25,12 +20,11 @@ function copyNode(node, sharing) {
|
|
|
25
20
|
return copy;
|
|
26
21
|
}
|
|
27
22
|
/**
|
|
28
|
-
* The copy-on-write spine walk, returning the owned chain outermost-first.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* stops at the first gap either way.
|
|
23
|
+
* The copy-on-write spine walk, returning the owned chain outermost-first. `assertInRange`
|
|
24
|
+
* fires G1.22 for the strict `ensureUnsharedPath` caller and stays silent for tolerant rebuild
|
|
25
|
+
* passes, which legitimately hand short paths; the walk stops at the first gap either way.
|
|
32
26
|
*/
|
|
33
|
-
function walkUnsharing(root, path, sharing, assertInRange) {
|
|
27
|
+
export function walkUnsharing(root, path, sharing, assertInRange) {
|
|
34
28
|
const chain = [];
|
|
35
29
|
// Root is the live document or a ceremony-owned array — writable by contract (file header).
|
|
36
30
|
let parentChildren = root.children;
|
|
@@ -52,21 +46,17 @@ function walkUnsharing(root, path, sharing, assertInRange) {
|
|
|
52
46
|
return chain;
|
|
53
47
|
}
|
|
54
48
|
/**
|
|
55
|
-
* Unshare every node along `path` from `root`; returns the chain outermost-first.
|
|
56
|
-
*
|
|
57
|
-
* which is what makes the splice safe.
|
|
49
|
+
* Unshare every node along `path` from `root`; returns the chain outermost-first. The caller
|
|
50
|
+
* owns `root.children` (live document, or a commit ceremony's array copy).
|
|
58
51
|
*/
|
|
59
52
|
export function ensureUnsharedPath(root, path, sharing) {
|
|
60
53
|
return walkUnsharing(root, path, sharing, true);
|
|
61
54
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Unshare one direct child of an already-unshared parent — a node, or a
|
|
64
|
-
* caller-owned `{ children }` view (e.g. a commit ceremony's array copy).
|
|
65
|
-
*/
|
|
55
|
+
/** Unshare one direct child of an already-unshared parent, or of a caller-owned `{ children }`. */
|
|
66
56
|
export function ensureUnsharedChild(parent, index, sharing) {
|
|
67
57
|
const child = parent.children[index];
|
|
68
|
-
// G1.22
|
|
69
|
-
//
|
|
58
|
+
// G1.22: an index off the end is a caller bug, failed here rather than epoch-dependently
|
|
59
|
+
// inside `isShared`.
|
|
70
60
|
assertInvariant('unshare-path-in-range', () => child ? null : { code: 'unshare-path', message: `child index ${index} out of range` });
|
|
71
61
|
if (!child || !sharing.isShared(child))
|
|
72
62
|
return child;
|
|
@@ -75,9 +65,8 @@ export function ensureUnsharedChild(parent, index, sharing) {
|
|
|
75
65
|
return parent.children[index];
|
|
76
66
|
}
|
|
77
67
|
/**
|
|
78
|
-
* Standalone copy for a node being MOVED out of a parent the snapshot keeps: the caller
|
|
79
|
-
*
|
|
80
|
-
* unshared input passes through — unshared already means live-tree-owned.
|
|
68
|
+
* Standalone copy for a node being MOVED out of a parent the snapshot keeps: the caller attaches
|
|
69
|
+
* the copy, the original stays put. An unshared input passes through as live-tree-owned.
|
|
81
70
|
*/
|
|
82
71
|
export function ensureUnsharedNode(node, sharing) {
|
|
83
72
|
return sharing.isShared(node) ? copyNode(node, sharing) : node;
|
|
@@ -88,21 +77,17 @@ export function ensureUnsharedChildren(parent, sharing) {
|
|
|
88
77
|
for (let i = 0; i < count; i++)
|
|
89
78
|
ensureUnsharedChild(parent, i, sharing);
|
|
90
79
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Deep-unshare an owned node's subtree. Intended for small bounded subtrees
|
|
93
|
-
* (tables: rows + cells) ahead of ops that write at arbitrary depth.
|
|
94
|
-
*/
|
|
80
|
+
/** Deep-unshare an owned node's subtree, for small bounded subtrees written at arbitrary depth. */
|
|
95
81
|
export function ensureUnsharedSubtree(node, sharing) {
|
|
96
82
|
const count = node.children?.length ?? 0;
|
|
97
83
|
for (let i = 0; i < count; i++) {
|
|
98
84
|
ensureUnsharedSubtree(ensureUnsharedChild(node, i, sharing), sharing);
|
|
99
85
|
}
|
|
100
86
|
}
|
|
101
|
-
// ── Sharing-aware raw
|
|
87
|
+
// ── Sharing-aware raw rebuild ───────────────────────────────────────────────
|
|
102
88
|
/**
|
|
103
|
-
* Rebuild one owned container's raw. A grid rebuild rewrites its children's raw, so a
|
|
104
|
-
*
|
|
105
|
-
* test, or a plugin grid writes through shared children.
|
|
89
|
+
* Rebuild one owned container's raw. A grid rebuild rewrites its children's raw, so a grid's
|
|
90
|
+
* children are unshared first, keyed off `containerContract` rather than a `table` kind test.
|
|
106
91
|
*/
|
|
107
92
|
export function rebuildOwnedContainer(node, sharing, changed) {
|
|
108
93
|
if (getBlockKindDescriptor(node.kind).containerContract === 'grid') {
|
|
@@ -110,139 +95,3 @@ export function rebuildOwnedContainer(node, sharing, changed) {
|
|
|
110
95
|
}
|
|
111
96
|
rebuildContainerRawIfContainer(node, changed);
|
|
112
97
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Longest prefix of `chain` still attached under `root`, identity-checked level by level.
|
|
115
|
-
* A commit mutation can splice a node out mid-ceremony; rebuilding the detached node's
|
|
116
|
-
* raw against its emptied children writes `raw: ''` and trips the commit-time staleness
|
|
117
|
-
* check. Ancestors above the detachment still need their rebuild — hence prefix.
|
|
118
|
-
*/
|
|
119
|
-
export function attachedChainPrefix(root, chain) {
|
|
120
|
-
let parentChildren = root.children;
|
|
121
|
-
for (let i = 0; i < chain.length; i++) {
|
|
122
|
-
if (!parentChildren.includes(chain[i]))
|
|
123
|
-
return chain.slice(0, i);
|
|
124
|
-
parentChildren = chain[i].children ?? [];
|
|
125
|
-
}
|
|
126
|
-
return chain;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Rebuild raws along an owned spine chain innermost-first, re-deriving each container's kind and
|
|
130
|
-
* settling the seams at its own slot; chain- rather than path-based so it survives index shifts.
|
|
131
|
-
* Both passes gate on a boundary line of the rebuilt raw moving; the re-derive additionally needs
|
|
132
|
-
* `lineOpensAs` not to name the current kind, a positive identification so a declining opener
|
|
133
|
-
* parses rather than eliding a real kind change. `folds` is required-nullable: a fold splices the
|
|
134
|
-
* PARENT's array, so only a caller that reconciles that scope's ids/refs passes a sink.
|
|
135
|
-
*/
|
|
136
|
-
export function rebuildUnsharedChain(root, chain, sharing, folds, grammar, hint) {
|
|
137
|
-
const reclassified = [];
|
|
138
|
-
// The bytes chain[i + 1] held before this pass, which is what its own level captures on the
|
|
139
|
-
// way past. It rides up only from a door that named the leaf's own: a caller passing no hint
|
|
140
|
-
// re-derives at every level, which is what makes the structural paths a reseed (editor.md § 9).
|
|
141
|
-
let childPreviousRaw;
|
|
142
|
-
for (let i = chain.length - 1; i >= 0; i--) {
|
|
143
|
-
const node = chain[i];
|
|
144
|
-
const rawBefore = node.raw;
|
|
145
|
-
const child = chain[i + 1];
|
|
146
|
-
rebuildOwnedContainer(node, sharing, child && childPreviousRaw !== undefined
|
|
147
|
-
? childRawChange(node, child, childPreviousRaw, hint?.path[i + 1])
|
|
148
|
-
: undefined);
|
|
149
|
-
if (hint)
|
|
150
|
-
childPreviousRaw = i === chain.length - 1 ? hint.leafPreviousRaw : rawBefore;
|
|
151
|
-
const openerMoved = firstLine(rawBefore) !== firstLine(node.raw);
|
|
152
|
-
const closerMoved = lastLine(rawBefore) !== lastLine(node.raw);
|
|
153
|
-
if (!openerMoved && !closerMoved)
|
|
154
|
-
continue;
|
|
155
|
-
const owner = i === 0 ? null : chain[i - 1];
|
|
156
|
-
const siblings = (owner ?? root).children;
|
|
157
|
-
const index = siblings ? childIndexOf(siblings, node, hint?.path[i]) : -1;
|
|
158
|
-
if (!siblings || index < 0)
|
|
159
|
-
continue;
|
|
160
|
-
if (openerMoved && lineOpensAs(firstLine(node.raw), grammar) !== node.kind) {
|
|
161
|
-
const replacement = reclassifyContainer({ children: siblings }, index, grammar);
|
|
162
|
-
if (replacement) {
|
|
163
|
-
sharing.stamp(replacement);
|
|
164
|
-
reclassified.push({ siblings, index, previous: node, replacement });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// Ahead of the seam ask, which then reads the settled bytes: a list rebuilt down to an
|
|
168
|
-
// empty marker owes the paragraph above it a separating line.
|
|
169
|
-
if (openerMoved)
|
|
170
|
-
settleSublistSeparator(siblings, index);
|
|
171
|
-
// After the re-derive: the seam reads whatever occupies the slot now.
|
|
172
|
-
if (folds) {
|
|
173
|
-
const before = folds.length;
|
|
174
|
-
settleSlotSeams({ siblings, owner, depth: i, index, openerMoved, closerMoved }, sharing, folds);
|
|
175
|
-
// A fold re-tiled the owner's children, so its spans describe a shape that is gone.
|
|
176
|
-
if (folds.length > before && owner)
|
|
177
|
-
dropChildSpans(owner);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
if (perfEnabled())
|
|
181
|
-
recordRebuildDepth(chain.length);
|
|
182
|
-
return reclassified;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* The changed-child hint for `node`, or undefined when `child` cannot be placed in it. The
|
|
186
|
-
* path index is a guess: an identity match is what makes it an answer, and a splice since the
|
|
187
|
-
* unshare falls back to the scan.
|
|
188
|
-
*/
|
|
189
|
-
function childRawChange(node, child, previousRaw, guess) {
|
|
190
|
-
const siblings = node.children;
|
|
191
|
-
if (!siblings)
|
|
192
|
-
return undefined;
|
|
193
|
-
const index = childIndexOf(siblings, child, guess);
|
|
194
|
-
return index < 0 ? undefined : { index, previousRaw };
|
|
195
|
-
}
|
|
196
|
-
/** `indexOf` with a guess first: the scan is O(children) through the `$state` proxy. */
|
|
197
|
-
function childIndexOf(siblings, child, guess) {
|
|
198
|
-
if (guess !== undefined && siblings[guess] === child)
|
|
199
|
-
return guess;
|
|
200
|
-
return siblings.indexOf(child);
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Ask the joins at a rebuilt container's slot, since its new bytes can stop interrupting a
|
|
204
|
-
* neighbour, which the reload then reads as one block with it. Byte-identical by construction,
|
|
205
|
-
* like every other seam absorb. `absorbWindowSeams` walks `at - 1 … at + added - 1`, so the two
|
|
206
|
-
* arguments below name exactly the sides whose line moved.
|
|
207
|
-
*/
|
|
208
|
-
function settleSlotSeams(slot, sharing, folds) {
|
|
209
|
-
const { siblings, index, openerMoved, closerMoved } = slot;
|
|
210
|
-
// The rollback snapshot is captured only once a fold is certain: an eager copy here cost
|
|
211
|
-
// O(children) reactive reads on every keystroke inside a large container.
|
|
212
|
-
let before = null;
|
|
213
|
-
const landing = { index, offset: 0 };
|
|
214
|
-
const settled = absorbWindowSeams({ children: siblings }, openerMoved ? index : index + 1, openerMoved && closerMoved ? 1 : 0, index, { op: 'noop' }, sharing, landing, index, () => {
|
|
215
|
-
before ??= siblings.slice();
|
|
216
|
-
});
|
|
217
|
-
if (settled.change.op === 'noop')
|
|
218
|
-
return;
|
|
219
|
-
folds.push({
|
|
220
|
-
depth: slot.depth,
|
|
221
|
-
siblings,
|
|
222
|
-
owner: slot.owner,
|
|
223
|
-
change: settled.change,
|
|
224
|
-
// A non-noop change means a splice ran, so the capture ran first.
|
|
225
|
-
before: before,
|
|
226
|
-
landing
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
/** The container's opener line. */
|
|
230
|
-
function firstLine(raw) {
|
|
231
|
-
const nl = raw.indexOf('\n');
|
|
232
|
-
return nl < 0 ? raw : raw.slice(0, nl);
|
|
233
|
-
}
|
|
234
|
-
/** The container's closing line: its last line carrying bytes, without the ending. */
|
|
235
|
-
function lastLine(raw) {
|
|
236
|
-
const body = trimTrailingLineEnding(raw);
|
|
237
|
-
const nl = body.lastIndexOf('\n');
|
|
238
|
-
return nl < 0 ? body : body.slice(nl + 1);
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Unshare the spine to `path` and rebuild it innermost-first, tolerating paths that ran
|
|
242
|
-
* out of range mid-walk (post-delete rebuild passes). Prefer `rebuildUnsharedChain` when
|
|
243
|
-
* indices may have shifted since the unshare.
|
|
244
|
-
*/
|
|
245
|
-
export function rebuildUnsharedAncestry(root, path, sharing, folds, grammar) {
|
|
246
|
-
const chain = walkUnsharing(root, path, sharing, false);
|
|
247
|
-
return rebuildUnsharedChain(root, chain, sharing, folds, grammar);
|
|
248
|
-
}
|