smartrte-core 0.2.1 → 1.0.0-beta.2
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/CHANGELOG.md +16 -0
- package/README.md +23 -0
- package/dist/command.d.ts +8 -8
- package/dist/editor.d.ts +32 -0
- package/dist/editor.js +121 -0
- package/dist/foundation/annotations/index.d.ts +2 -0
- package/dist/foundation/annotations/index.js +2 -0
- package/dist/foundation/annotations/range.d.ts +54 -0
- package/dist/foundation/annotations/range.js +158 -0
- package/dist/foundation/annotations/types.d.ts +33 -0
- package/dist/foundation/annotations/types.js +1 -0
- package/dist/foundation/atom/commands.d.ts +11 -0
- package/dist/foundation/atom/commands.js +118 -0
- package/dist/foundation/atom/composition.d.ts +8 -0
- package/dist/foundation/atom/composition.js +22 -0
- package/dist/foundation/atom/declarations.d.ts +2 -0
- package/dist/foundation/atom/declarations.js +17 -0
- package/dist/foundation/atom/formats.d.ts +24 -0
- package/dist/foundation/atom/formats.js +105 -0
- package/dist/foundation/atom/index.d.ts +10 -0
- package/dist/foundation/atom/index.js +10 -0
- package/dist/foundation/atom/lifecycle.d.ts +12 -0
- package/dist/foundation/atom/lifecycle.js +41 -0
- package/dist/foundation/atom/persistence.d.ts +3 -0
- package/dist/foundation/atom/persistence.js +20 -0
- package/dist/foundation/atom/plugin.d.ts +20 -0
- package/dist/foundation/atom/plugin.js +55 -0
- package/dist/foundation/atom/schema.d.ts +3 -0
- package/dist/foundation/atom/schema.js +29 -0
- package/dist/foundation/atom/security.d.ts +10 -0
- package/dist/foundation/atom/security.js +20 -0
- package/dist/foundation/atom/selection.d.ts +3 -0
- package/dist/foundation/atom/selection.js +4 -0
- package/dist/foundation/atom/types.d.ts +47 -0
- package/dist/foundation/atom/types.js +1 -0
- package/dist/foundation/block/commands.d.ts +17 -0
- package/dist/foundation/block/commands.js +197 -0
- package/dist/foundation/block/formats.d.ts +33 -0
- package/dist/foundation/block/formats.js +57 -0
- package/dist/foundation/block/index.d.ts +5 -0
- package/dist/foundation/block/index.js +5 -0
- package/dist/foundation/block/input.d.ts +19 -0
- package/dist/foundation/block/input.js +67 -0
- package/dist/foundation/block/plugin.d.ts +26 -0
- package/dist/foundation/block/plugin.js +79 -0
- package/dist/foundation/block/schema.d.ts +49 -0
- package/dist/foundation/block/schema.js +27 -0
- package/dist/foundation/block/types.d.ts +40 -0
- package/dist/foundation/block/types.js +1 -0
- package/dist/foundation/boundaries.d.ts +11 -0
- package/dist/foundation/boundaries.js +117 -0
- package/dist/foundation/clipboard/detection.d.ts +3 -0
- package/dist/foundation/clipboard/detection.js +29 -0
- package/dist/foundation/clipboard/diagnostics.d.ts +24 -0
- package/dist/foundation/clipboard/diagnostics.js +59 -0
- package/dist/foundation/clipboard/index.d.ts +8 -0
- package/dist/foundation/clipboard/index.js +8 -0
- package/dist/foundation/clipboard/insertion.d.ts +22 -0
- package/dist/foundation/clipboard/insertion.js +210 -0
- package/dist/foundation/clipboard/normalizers.d.ts +8 -0
- package/dist/foundation/clipboard/normalizers.js +229 -0
- package/dist/foundation/clipboard/pipeline.d.ts +13 -0
- package/dist/foundation/clipboard/pipeline.js +58 -0
- package/dist/foundation/clipboard/sanitizer.d.ts +3 -0
- package/dist/foundation/clipboard/sanitizer.js +58 -0
- package/dist/foundation/clipboard/serialization.d.ts +5 -0
- package/dist/foundation/clipboard/serialization.js +33 -0
- package/dist/foundation/clipboard/transfer.d.ts +11 -0
- package/dist/foundation/clipboard/transfer.js +108 -0
- package/dist/foundation/clipboard/types.d.ts +65 -0
- package/dist/foundation/clipboard/types.js +1 -0
- package/dist/foundation/collab/index.d.ts +3 -0
- package/dist/foundation/collab/index.js +3 -0
- package/dist/foundation/collab/rebase.d.ts +28 -0
- package/dist/foundation/collab/rebase.js +82 -0
- package/dist/foundation/collab/transform.d.ts +73 -0
- package/dist/foundation/collab/transform.js +251 -0
- package/dist/foundation/collab/types.d.ts +52 -0
- package/dist/foundation/collab/types.js +1 -0
- package/dist/foundation/comments/fromSelection.d.ts +16 -0
- package/dist/foundation/comments/fromSelection.js +24 -0
- package/dist/foundation/comments/index.d.ts +3 -0
- package/dist/foundation/comments/index.js +3 -0
- package/dist/foundation/comments/rebase.d.ts +31 -0
- package/dist/foundation/comments/rebase.js +43 -0
- package/dist/foundation/comments/types.d.ts +37 -0
- package/dist/foundation/comments/types.js +1 -0
- package/dist/foundation/diff/documentDiff.d.ts +12 -0
- package/dist/foundation/diff/documentDiff.js +148 -0
- package/dist/foundation/diff/index.d.ts +3 -0
- package/dist/foundation/diff/index.js +3 -0
- package/dist/foundation/diff/textDiff.d.ts +12 -0
- package/dist/foundation/diff/textDiff.js +114 -0
- package/dist/foundation/diff/types.d.ts +74 -0
- package/dist/foundation/diff/types.js +1 -0
- package/dist/foundation/editor.d.ts +138 -0
- package/dist/foundation/editor.js +398 -0
- package/dist/foundation/formats/codec.d.ts +45 -0
- package/dist/foundation/formats/codec.js +1 -0
- package/dist/foundation/formats/docx/export.d.ts +4 -0
- package/dist/foundation/formats/docx/export.js +285 -0
- package/dist/foundation/formats/docx/import.d.ts +9 -0
- package/dist/foundation/formats/docx/import.js +37 -0
- package/dist/foundation/formats/docx/nestingGuard.d.ts +40 -0
- package/dist/foundation/formats/docx/nestingGuard.js +66 -0
- package/dist/foundation/formats/docx/portableAtoms.d.ts +4 -0
- package/dist/foundation/formats/docx/portableAtoms.js +66 -0
- package/dist/foundation/formats/docx/styledImport.d.ts +10 -0
- package/dist/foundation/formats/docx/styledImport.js +205 -0
- package/dist/foundation/formats/featureCodecs.d.ts +37 -0
- package/dist/foundation/formats/featureCodecs.js +69 -0
- package/dist/foundation/formats/fidelity.d.ts +31 -0
- package/dist/foundation/formats/fidelity.js +123 -0
- package/dist/foundation/formats/index.d.ts +7 -0
- package/dist/foundation/formats/index.js +7 -0
- package/dist/foundation/formats/pdf/format.d.ts +29 -0
- package/dist/foundation/formats/pdf/format.js +190 -0
- package/dist/foundation/history.d.ts +20 -0
- package/dist/foundation/history.js +121 -0
- package/dist/foundation/identity.d.ts +8 -0
- package/dist/foundation/identity.js +30 -0
- package/dist/foundation/index.d.ts +30 -0
- package/dist/foundation/index.js +30 -0
- package/dist/foundation/list/commands.d.ts +28 -0
- package/dist/foundation/list/commands.js +422 -0
- package/dist/foundation/list/formats.d.ts +21 -0
- package/dist/foundation/list/formats.js +813 -0
- package/dist/foundation/list/index.d.ts +8 -0
- package/dist/foundation/list/index.js +8 -0
- package/dist/foundation/list/input.d.ts +35 -0
- package/dist/foundation/list/input.js +320 -0
- package/dist/foundation/list/plugin.d.ts +21 -0
- package/dist/foundation/list/plugin.js +71 -0
- package/dist/foundation/list/presets.d.ts +16 -0
- package/dist/foundation/list/presets.js +21 -0
- package/dist/foundation/list/schema.d.ts +35 -0
- package/dist/foundation/list/schema.js +29 -0
- package/dist/foundation/list/shadow.d.ts +54 -0
- package/dist/foundation/list/shadow.js +75 -0
- package/dist/foundation/list/shadowCorpus.d.ts +10 -0
- package/dist/foundation/list/shadowCorpus.js +41 -0
- package/dist/foundation/list/types.d.ts +50 -0
- package/dist/foundation/list/types.js +1 -0
- package/dist/foundation/mapping.d.ts +11 -0
- package/dist/foundation/mapping.js +40 -0
- package/dist/foundation/marks/canonical.d.ts +9 -0
- package/dist/foundation/marks/canonical.js +72 -0
- package/dist/foundation/marks/commands.d.ts +21 -0
- package/dist/foundation/marks/commands.js +136 -0
- package/dist/foundation/marks/dom.d.ts +2 -0
- package/dist/foundation/marks/dom.js +46 -0
- package/dist/foundation/marks/editor.d.ts +8 -0
- package/dist/foundation/marks/editor.js +50 -0
- package/dist/foundation/marks/formats.d.ts +37 -0
- package/dist/foundation/marks/formats.js +49 -0
- package/dist/foundation/marks/hardBreak.d.ts +8 -0
- package/dist/foundation/marks/hardBreak.js +80 -0
- package/dist/foundation/marks/index.d.ts +11 -0
- package/dist/foundation/marks/index.js +11 -0
- package/dist/foundation/marks/normalization.d.ts +2 -0
- package/dist/foundation/marks/normalization.js +49 -0
- package/dist/foundation/marks/plugin.d.ts +14 -0
- package/dist/foundation/marks/plugin.js +63 -0
- package/dist/foundation/marks/resolveMarkRun.d.ts +8 -0
- package/dist/foundation/marks/resolveMarkRun.js +47 -0
- package/dist/foundation/marks/schema.d.ts +167 -0
- package/dist/foundation/marks/schema.js +50 -0
- package/dist/foundation/marks/stored.d.ts +2 -0
- package/dist/foundation/marks/stored.js +31 -0
- package/dist/foundation/marks/types.d.ts +40 -0
- package/dist/foundation/marks/types.js +1 -0
- package/dist/foundation/modelDom.d.ts +38 -0
- package/dist/foundation/modelDom.js +327 -0
- package/dist/foundation/normalization.d.ts +22 -0
- package/dist/foundation/normalization.js +132 -0
- package/dist/foundation/operations.d.ts +28 -0
- package/dist/foundation/operations.js +568 -0
- package/dist/foundation/plugin/builtins.d.ts +10 -0
- package/dist/foundation/plugin/builtins.js +27 -0
- package/dist/foundation/plugin/dispatch.d.ts +33 -0
- package/dist/foundation/plugin/dispatch.js +34 -0
- package/dist/foundation/plugin/index.d.ts +4 -0
- package/dist/foundation/plugin/index.js +4 -0
- package/dist/foundation/plugin/registry.d.ts +36 -0
- package/dist/foundation/plugin/registry.js +115 -0
- package/dist/foundation/plugin/types.d.ts +141 -0
- package/dist/foundation/plugin/types.js +13 -0
- package/dist/foundation/positions.d.ts +20 -0
- package/dist/foundation/positions.js +121 -0
- package/dist/foundation/schema.d.ts +57 -0
- package/dist/foundation/schema.js +371 -0
- package/dist/foundation/schemaBuilder.d.ts +41 -0
- package/dist/foundation/schemaBuilder.js +96 -0
- package/dist/foundation/scope/index.d.ts +2 -0
- package/dist/foundation/scope/index.js +2 -0
- package/dist/foundation/scope/resolveScope.d.ts +13 -0
- package/dist/foundation/scope/resolveScope.js +860 -0
- package/dist/foundation/scope/types.d.ts +122 -0
- package/dist/foundation/scope/types.js +1 -0
- package/dist/foundation/security/urlPolicy.d.ts +21 -0
- package/dist/foundation/security/urlPolicy.js +75 -0
- package/dist/foundation/structural/contentTarget.d.ts +21 -0
- package/dist/foundation/structural/contentTarget.js +51 -0
- package/dist/foundation/structural/index.d.ts +2 -0
- package/dist/foundation/structural/index.js +2 -0
- package/dist/foundation/structural/move.d.ts +7 -0
- package/dist/foundation/structural/move.js +35 -0
- package/dist/foundation/suggestions/index.d.ts +3 -0
- package/dist/foundation/suggestions/index.js +3 -0
- package/dist/foundation/suggestions/inline.d.ts +64 -0
- package/dist/foundation/suggestions/inline.js +116 -0
- package/dist/foundation/suggestions/structural.d.ts +40 -0
- package/dist/foundation/suggestions/structural.js +47 -0
- package/dist/foundation/suggestions/types.d.ts +19 -0
- package/dist/foundation/suggestions/types.js +1 -0
- package/dist/foundation/surface/index.d.ts +3 -0
- package/dist/foundation/surface/index.js +3 -0
- package/dist/foundation/surface/input.d.ts +127 -0
- package/dist/foundation/surface/input.js +1761 -0
- package/dist/foundation/surface/renderer.d.ts +84 -0
- package/dist/foundation/surface/renderer.js +974 -0
- package/dist/foundation/surface/types.d.ts +48 -0
- package/dist/foundation/surface/types.js +1 -0
- package/dist/foundation/table/commands.d.ts +31 -0
- package/dist/foundation/table/commands.js +470 -0
- package/dist/foundation/table/formats.d.ts +27 -0
- package/dist/foundation/table/formats.js +40 -0
- package/dist/foundation/table/grid.d.ts +8 -0
- package/dist/foundation/table/grid.js +178 -0
- package/dist/foundation/table/index.d.ts +6 -0
- package/dist/foundation/table/index.js +6 -0
- package/dist/foundation/table/plugin.d.ts +23 -0
- package/dist/foundation/table/plugin.js +119 -0
- package/dist/foundation/table/schema.d.ts +2 -0
- package/dist/foundation/table/schema.js +38 -0
- package/dist/foundation/table/selection.d.ts +7 -0
- package/dist/foundation/table/selection.js +35 -0
- package/dist/foundation/table/types.d.ts +109 -0
- package/dist/foundation/table/types.js +1 -0
- package/dist/foundation/transactions.d.ts +41 -0
- package/dist/foundation/transactions.js +90 -0
- package/dist/foundation/types.d.ts +261 -0
- package/dist/foundation/types.js +1 -0
- package/dist/foundation/versioning/diffVersions.d.ts +5 -0
- package/dist/foundation/versioning/diffVersions.js +3 -0
- package/dist/foundation/versioning/index.d.ts +2 -0
- package/dist/foundation/versioning/index.js +2 -0
- package/dist/foundation/versioning/types.d.ts +17 -0
- package/dist/foundation/versioning/types.js +1 -0
- package/dist/history.d.ts +20 -0
- package/dist/history.js +165 -0
- package/dist/html/compatibility.js +7 -1
- package/dist/index.d.ts +1 -14
- package/dist/index.js +9 -14
- package/dist/legacy/index.d.ts +45 -0
- package/dist/legacy/index.js +45 -0
- package/dist/legacyCommands/alignment.d.ts +20 -0
- package/dist/{commands → legacyCommands}/alignment.js +17 -0
- package/dist/legacyCommands/blocks.d.ts +14 -0
- package/dist/legacyCommands/blocks.js +105 -0
- package/dist/legacyCommands/checklist.d.ts +11 -0
- package/dist/legacyCommands/checklist.js +45 -0
- package/dist/legacyCommands/code.d.ts +15 -0
- package/dist/{commands → legacyCommands}/code.js +25 -1
- package/dist/legacyCommands/formula.d.ts +7 -0
- package/dist/legacyCommands/formula.js +67 -0
- package/dist/legacyCommands/inlineAtoms.d.ts +7 -0
- package/dist/legacyCommands/inlineAtoms.js +58 -0
- package/dist/legacyCommands/list.d.ts +38 -0
- package/dist/legacyCommands/list.js +477 -0
- package/dist/{commands → legacyCommands}/marks.d.ts +3 -0
- package/dist/{commands → legacyCommands}/marks.js +28 -11
- package/dist/legacyCommands/media.d.ts +31 -0
- package/dist/legacyCommands/media.js +205 -0
- package/dist/legacyCommands/move.d.ts +14 -0
- package/dist/legacyCommands/move.js +91 -0
- package/dist/legacyCommands/table.d.ts +91 -0
- package/dist/legacyCommands/table.js +547 -0
- package/dist/listPresets.d.ts +12 -0
- package/dist/listPresets.js +6 -0
- package/dist/listScope.d.ts +27 -0
- package/dist/listScope.js +104 -0
- package/dist/markdown/compatibility.d.ts +2 -0
- package/dist/markdown/compatibility.js +94 -2
- package/dist/marks.d.ts +5 -5
- package/dist/model.d.ts +65 -9
- package/dist/plugin.d.ts +15 -0
- package/dist/plugin.js +31 -0
- package/dist/plugins/alignment.d.ts +3 -0
- package/dist/plugins/alignment.js +6 -0
- package/dist/plugins/basicFormatting.d.ts +9 -0
- package/dist/plugins/basicFormatting.js +24 -0
- package/dist/plugins/blockType.d.ts +3 -0
- package/dist/plugins/blockType.js +6 -0
- package/dist/plugins/blockquote.d.ts +3 -0
- package/dist/plugins/blockquote.js +6 -0
- package/dist/plugins/checklist.d.ts +3 -0
- package/dist/plugins/checklist.js +10 -0
- package/dist/plugins/codeBlock.d.ts +3 -0
- package/dist/plugins/codeBlock.js +6 -0
- package/dist/plugins/formula.d.ts +3 -0
- package/dist/plugins/formula.js +9 -0
- package/dist/plugins/list.d.ts +3 -0
- package/dist/plugins/list.js +10 -0
- package/dist/plugins/media.d.ts +3 -0
- package/dist/plugins/media.js +12 -0
- package/dist/plugins/move.d.ts +3 -0
- package/dist/plugins/move.js +9 -0
- package/dist/plugins/table.d.ts +3 -0
- package/dist/plugins/table.js +22 -0
- package/dist/preset.d.ts +12 -0
- package/dist/preset.js +40 -0
- package/dist/schema.d.ts +22 -0
- package/dist/schema.js +333 -0
- package/dist/security/urlPolicy.d.ts +1 -17
- package/dist/security/urlPolicy.js +3 -69
- package/dist/selection.d.ts +1 -1
- package/dist/selectionMapping.d.ts +4 -0
- package/dist/selectionMapping.js +222 -0
- package/dist/table.d.ts +3 -3
- package/dist/transaction.d.ts +35 -12
- package/dist/transaction.js +174 -28
- package/dist/tree.d.ts +8 -2
- package/dist/tree.js +44 -0
- package/package.json +27 -8
- package/dist/commands/alignment.d.ts +0 -18
- package/dist/commands/code.d.ts +0 -13
- package/dist/commands/list.d.ts +0 -20
- package/dist/commands/list.js +0 -52
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { isTextNode } from "../identity.js";
|
|
2
|
+
import { diffTextRuns } from "./textDiff.js";
|
|
3
|
+
const indexById = (document) => {
|
|
4
|
+
const index = new Map();
|
|
5
|
+
const visit = (node, parentId, path) => {
|
|
6
|
+
index.set(node.id, { node, parentId, path });
|
|
7
|
+
(node.children || []).forEach((child, childIndex) => {
|
|
8
|
+
if (!isTextNode(child))
|
|
9
|
+
visit(child, node.id, [...path, childIndex]);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
visit(document, null, []);
|
|
13
|
+
return index;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Every `SmartElementNode` keeps a stable id across split/merge/move/type-
|
|
17
|
+
* change/undo (Phase 8c collab-readiness gate, assertion 1). That turns the
|
|
18
|
+
* structural half of a document diff into a hash-map join - id present in
|
|
19
|
+
* both/only-before/only-after - instead of a generic tree-alignment problem
|
|
20
|
+
* a Myers/patience-style algorithm would otherwise be needed to solve.
|
|
21
|
+
* `SmartTextNode` has no id, so text content is the one place a real
|
|
22
|
+
* (word-level, see textDiff.ts) diff algorithm is still needed.
|
|
23
|
+
*/
|
|
24
|
+
export const diffDocuments = (before, after, schema) => {
|
|
25
|
+
const beforeIndex = indexById(before);
|
|
26
|
+
const afterIndex = indexById(after);
|
|
27
|
+
const removed = [];
|
|
28
|
+
beforeIndex.forEach((entry, id) => {
|
|
29
|
+
if (afterIndex.has(id))
|
|
30
|
+
return;
|
|
31
|
+
// Only the topmost removed root is reported - a removed id whose
|
|
32
|
+
// parent id is itself removed is part of that parent's own subtree.
|
|
33
|
+
if (entry.parentId && !afterIndex.has(entry.parentId))
|
|
34
|
+
return;
|
|
35
|
+
removed.push({ kind: "removed", nodeId: id, node: entry.node, parentId: entry.parentId, path: [...entry.path] });
|
|
36
|
+
});
|
|
37
|
+
const added = [];
|
|
38
|
+
afterIndex.forEach((entry, id) => {
|
|
39
|
+
if (beforeIndex.has(id))
|
|
40
|
+
return;
|
|
41
|
+
if (entry.parentId && !beforeIndex.has(entry.parentId))
|
|
42
|
+
return;
|
|
43
|
+
added.push({ kind: "added", nodeId: id, node: entry.node, parentId: entry.parentId, path: [...entry.path] });
|
|
44
|
+
});
|
|
45
|
+
const changed = [];
|
|
46
|
+
beforeIndex.forEach((beforeEntry, id) => {
|
|
47
|
+
const afterEntry = afterIndex.get(id);
|
|
48
|
+
if (!afterEntry)
|
|
49
|
+
return;
|
|
50
|
+
const entry = {};
|
|
51
|
+
if (beforeEntry.parentId !== afterEntry.parentId) {
|
|
52
|
+
entry.move = {
|
|
53
|
+
fromParentId: beforeEntry.parentId, toParentId: afterEntry.parentId,
|
|
54
|
+
fromPath: [...beforeEntry.path], toPath: [...afterEntry.path],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
else if (beforeEntry.parentId) {
|
|
58
|
+
const move = sameParentMove(beforeEntry.parentId, beforeIndex, afterIndex, id);
|
|
59
|
+
if (move)
|
|
60
|
+
entry.move = move;
|
|
61
|
+
}
|
|
62
|
+
if (beforeEntry.node.type !== afterEntry.node.type) {
|
|
63
|
+
entry.typeChange = { before: beforeEntry.node.type, after: afterEntry.node.type };
|
|
64
|
+
}
|
|
65
|
+
const attrsDiff = diffAttrs(beforeEntry.node.attrs || {}, afterEntry.node.attrs || {});
|
|
66
|
+
if (attrsDiff.length) {
|
|
67
|
+
entry.attrsChange = { before: beforeEntry.node.attrs || {}, after: afterEntry.node.attrs || {}, changedKeys: attrsDiff };
|
|
68
|
+
}
|
|
69
|
+
if (isInlineOwner(beforeEntry.node, schema) && isInlineOwner(afterEntry.node, schema)) {
|
|
70
|
+
const segments = diffTextRuns(textRunsOf(beforeEntry.node), textRunsOf(afterEntry.node));
|
|
71
|
+
if (segments.some((segment) => segment.op !== "equal"))
|
|
72
|
+
entry.contentChange = segments;
|
|
73
|
+
}
|
|
74
|
+
if (entry.move || entry.typeChange || entry.attrsChange || entry.contentChange) {
|
|
75
|
+
changed.push({ kind: "changed", nodeId: id, ...entry });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return { added, removed, changed };
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Detects a same-parent reorder without false-positives from mere sibling
|
|
82
|
+
* insertion/removal: only ids that were - and still are - direct children
|
|
83
|
+
* of this exact parent on both sides are considered, and their retained-
|
|
84
|
+
* only order is compared via LCS. A retained id inside that LCS kept its
|
|
85
|
+
* relative order (even if its numeric index shifted because siblings were
|
|
86
|
+
* added/removed around it) and is not reported as moved.
|
|
87
|
+
*/
|
|
88
|
+
const sameParentMove = (parentId, beforeIndex, afterIndex, nodeId) => {
|
|
89
|
+
const beforeParent = beforeIndex.get(parentId);
|
|
90
|
+
const afterParent = afterIndex.get(parentId);
|
|
91
|
+
if (!beforeParent || !afterParent)
|
|
92
|
+
return undefined;
|
|
93
|
+
const beforeChildIds = (beforeParent.node.children || []).filter((child) => !isTextNode(child)).map((child) => child.id);
|
|
94
|
+
const afterChildIds = (afterParent.node.children || []).filter((child) => !isTextNode(child)).map((child) => child.id);
|
|
95
|
+
const oldOrder = beforeChildIds.filter((id) => afterIndex.get(id)?.parentId === parentId);
|
|
96
|
+
const newOrder = afterChildIds.filter((id) => beforeIndex.get(id)?.parentId === parentId);
|
|
97
|
+
const lcs = lcsIds(oldOrder, newOrder);
|
|
98
|
+
if (lcs.has(nodeId))
|
|
99
|
+
return undefined;
|
|
100
|
+
const before = beforeIndex.get(nodeId);
|
|
101
|
+
const after = afterIndex.get(nodeId);
|
|
102
|
+
return { fromParentId: parentId, toParentId: parentId, fromPath: [...before.path], toPath: [...after.path] };
|
|
103
|
+
};
|
|
104
|
+
const lcsIds = (before, after) => {
|
|
105
|
+
const n = before.length;
|
|
106
|
+
const m = after.length;
|
|
107
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
108
|
+
for (let i = n - 1; i >= 0; i -= 1) {
|
|
109
|
+
for (let j = m - 1; j >= 0; j -= 1) {
|
|
110
|
+
dp[i][j] = before[i] === after[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const kept = new Set();
|
|
114
|
+
let i = 0;
|
|
115
|
+
let j = 0;
|
|
116
|
+
while (i < n && j < m) {
|
|
117
|
+
if (before[i] === after[j] && dp[i][j] === dp[i + 1][j + 1] + 1) {
|
|
118
|
+
kept.add(before[i]);
|
|
119
|
+
i += 1;
|
|
120
|
+
j += 1;
|
|
121
|
+
}
|
|
122
|
+
else if (dp[i + 1][j] >= dp[i][j + 1])
|
|
123
|
+
i += 1;
|
|
124
|
+
else
|
|
125
|
+
j += 1;
|
|
126
|
+
}
|
|
127
|
+
return kept;
|
|
128
|
+
};
|
|
129
|
+
const diffAttrs = (before, after) => {
|
|
130
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
131
|
+
return [...keys].filter((key) => JSON.stringify(before[key]) !== JSON.stringify(after[key]));
|
|
132
|
+
};
|
|
133
|
+
/** Mirrors the inline-content-owner predicate in canonicalEditorRuntime.ts's firstTextSelection, reused here for consistency rather than a second definition of the same concept. */
|
|
134
|
+
const isInlineOwner = (node, schema) => {
|
|
135
|
+
const children = node.children || [];
|
|
136
|
+
return children.every((child) => isTextNode(child) || schema.nodes[child.type]?.group === "inline");
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Flattens an inline owner's children into `{text, marks}` runs for word-
|
|
140
|
+
* level diffing. Inline atomic children (e.g. inline images/formulas) are
|
|
141
|
+
* intentionally not represented here - only text is word-diffed; a change
|
|
142
|
+
* limited entirely to an inline atom within otherwise-unchanged text will
|
|
143
|
+
* not surface as a `contentChange`. Documented scope limit, not a silent
|
|
144
|
+
* gap: such a change is still visible via the atom's own `added`/`removed`
|
|
145
|
+
* entry if it's inserted/removed outright.
|
|
146
|
+
*/
|
|
147
|
+
const textRunsOf = (node) => (node.children || []).filter((child) => isTextNode(child))
|
|
148
|
+
.map((child) => ({ text: child.text, marks: (child.marks || []) }));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SmartMark } from "../types.js";
|
|
2
|
+
import type { TextDiffSegment } from "./types.js";
|
|
3
|
+
export interface TextRun {
|
|
4
|
+
readonly text: string;
|
|
5
|
+
readonly marks: readonly SmartMark[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Diffs two sequences of `{text, marks}` runs (the flattened inline content
|
|
9
|
+
* of one node) at word granularity. A token never spans a run boundary, so
|
|
10
|
+
* it can never straddle two different mark sets by construction.
|
|
11
|
+
*/
|
|
12
|
+
export declare const diffTextRuns: (before: readonly TextRun[], after: readonly TextRun[]) => TextDiffSegment[];
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { canonicalMarkOrder, markKey } from "../marks/canonical.js";
|
|
2
|
+
/**
|
|
3
|
+
* Word-boundary tokenizer: each token is a run of non-whitespace plus its
|
|
4
|
+
* own trailing whitespace (leading whitespace with no preceding word, e.g.
|
|
5
|
+
* at the very start of a run, becomes its own token). Deliberately not
|
|
6
|
+
* further split on punctuation - this project's diff is word-granularity,
|
|
7
|
+
* not a linguistic tokenizer. Gluing whitespace onto its word rather than
|
|
8
|
+
* treating every space as an independent token matters for LCS matching
|
|
9
|
+
* below: an isolated whitespace token can spuriously "match" between two
|
|
10
|
+
* otherwise-unrelated words (e.g. "alpha beta" -> "gamma delta" sharing
|
|
11
|
+
* nothing but a space), fragmenting what should read as one clean
|
|
12
|
+
* delete+insert into delete/insert/equal(" ")/delete/insert.
|
|
13
|
+
*/
|
|
14
|
+
const tokenize = (text) => text.length ? text.match(/\S+\s*|^\s+/g) || [] : [];
|
|
15
|
+
const tokensOf = (runs) => runs.flatMap((run) => tokenize(run.text).map((text) => ({ text, marks: run.marks })));
|
|
16
|
+
const marksSignature = (marks) => canonicalMarkOrder(marks).map(markKey).join("|");
|
|
17
|
+
const sameMarks = (left, right) => marksSignature(left) === marksSignature(right);
|
|
18
|
+
/**
|
|
19
|
+
* A token's trailing whitespace is glued on for *display* (see `tokenize`
|
|
20
|
+
* above) but must not affect whether two tokens count as "the same word"
|
|
21
|
+
* for matching - the very same word carries different trailing whitespace
|
|
22
|
+
* depending only on whether another word happens to follow it in that
|
|
23
|
+
* particular text (a word at the end of "before" has no trailing space;
|
|
24
|
+
* the identical word gains one the moment "after" adds a word behind it).
|
|
25
|
+
* Comparing raw `.text` would make that purely incidental difference
|
|
26
|
+
* block an otherwise-correct match.
|
|
27
|
+
*/
|
|
28
|
+
const matchKey = (token) => token.text.trimEnd();
|
|
29
|
+
/**
|
|
30
|
+
* Longest common subsequence over token match-keys (marks are compared
|
|
31
|
+
* separately, after alignment - see `sameMarks` below) via plain O(n*m)
|
|
32
|
+
* dynamic programming. Inputs here are bounded to one inline-content
|
|
33
|
+
* owner's word count (a paragraph/heading/cell), not a whole document, so
|
|
34
|
+
* Myers' O(ND) is unneeded complexity for this project's actual scale;
|
|
35
|
+
* revisit only if a real profile shows otherwise.
|
|
36
|
+
*/
|
|
37
|
+
const lcsSteps = (before, after) => {
|
|
38
|
+
const n = before.length;
|
|
39
|
+
const m = after.length;
|
|
40
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
41
|
+
for (let i = n - 1; i >= 0; i -= 1) {
|
|
42
|
+
for (let j = m - 1; j >= 0; j -= 1) {
|
|
43
|
+
dp[i][j] = matchKey(before[i]) === matchKey(after[j])
|
|
44
|
+
? dp[i + 1][j + 1] + 1
|
|
45
|
+
: Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const steps = [];
|
|
49
|
+
let i = 0;
|
|
50
|
+
let j = 0;
|
|
51
|
+
while (i < n && j < m) {
|
|
52
|
+
if (matchKey(before[i]) === matchKey(after[j]) && dp[i][j] === dp[i + 1][j + 1] + 1) {
|
|
53
|
+
steps.push({ op: "match", before: before[i], after: after[j] });
|
|
54
|
+
i += 1;
|
|
55
|
+
j += 1;
|
|
56
|
+
}
|
|
57
|
+
else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
58
|
+
steps.push({ op: "delete", token: before[i] });
|
|
59
|
+
i += 1;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
steps.push({ op: "insert", token: after[j] });
|
|
63
|
+
j += 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
while (i < n) {
|
|
67
|
+
steps.push({ op: "delete", token: before[i] });
|
|
68
|
+
i += 1;
|
|
69
|
+
}
|
|
70
|
+
while (j < m) {
|
|
71
|
+
steps.push({ op: "insert", token: after[j] });
|
|
72
|
+
j += 1;
|
|
73
|
+
}
|
|
74
|
+
return steps;
|
|
75
|
+
};
|
|
76
|
+
/** Coalesces adjacent steps of the same kind (and, for match/markChange, the same mark signature) into one segment - one token per LCS step would be needlessly fragmented for a UI. */
|
|
77
|
+
const coalesce = (steps) => {
|
|
78
|
+
const segments = [];
|
|
79
|
+
for (const step of steps) {
|
|
80
|
+
if (step.op === "match") {
|
|
81
|
+
const changed = !sameMarks(step.before.marks, step.after.marks);
|
|
82
|
+
const last = segments[segments.length - 1];
|
|
83
|
+
if (changed) {
|
|
84
|
+
if (last?.op === "markChange" && sameMarks(last.before, step.before.marks) && sameMarks(last.after, step.after.marks)) {
|
|
85
|
+
segments[segments.length - 1] = { ...last, text: last.text + step.after.text };
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
segments.push({ op: "markChange", text: step.after.text, before: step.before.marks, after: step.after.marks });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (last?.op === "equal" && sameMarks(last.marks, step.after.marks)) {
|
|
92
|
+
segments[segments.length - 1] = { ...last, text: last.text + step.after.text };
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
segments.push({ op: "equal", text: step.after.text, marks: step.after.marks });
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const last = segments[segments.length - 1];
|
|
100
|
+
if (last?.op === step.op && sameMarks(last.marks, step.token.marks)) {
|
|
101
|
+
segments[segments.length - 1] = { ...last, text: last.text + step.token.text };
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
segments.push({ op: step.op, text: step.token.text, marks: step.token.marks });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return segments;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Diffs two sequences of `{text, marks}` runs (the flattened inline content
|
|
111
|
+
* of one node) at word granularity. A token never spans a run boundary, so
|
|
112
|
+
* it can never straddle two different mark sets by construction.
|
|
113
|
+
*/
|
|
114
|
+
export const diffTextRuns = (before, after) => coalesce(lcsSteps(tokensOf(before), tokensOf(after)));
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Attrs, SmartMark, SmartNode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* A word-granularity diff segment within one inline-content owner's flattened
|
|
4
|
+
* text. Word, not character: character-level diffing fragments on every
|
|
5
|
+
* keystroke-sized edit and is visually noisy for review UI; word-level is
|
|
6
|
+
* what every comparable tool (Word, Google Docs) renders track-changes at.
|
|
7
|
+
* A run whose text matches on both sides but whose marks don't is reported
|
|
8
|
+
* as `markChange`, not a delete+insert of identical text.
|
|
9
|
+
*/
|
|
10
|
+
export type TextDiffSegment = {
|
|
11
|
+
readonly op: "equal";
|
|
12
|
+
readonly text: string;
|
|
13
|
+
readonly marks: readonly SmartMark[];
|
|
14
|
+
} | {
|
|
15
|
+
readonly op: "insert";
|
|
16
|
+
readonly text: string;
|
|
17
|
+
readonly marks: readonly SmartMark[];
|
|
18
|
+
} | {
|
|
19
|
+
readonly op: "delete";
|
|
20
|
+
readonly text: string;
|
|
21
|
+
readonly marks: readonly SmartMark[];
|
|
22
|
+
} | {
|
|
23
|
+
readonly op: "markChange";
|
|
24
|
+
readonly text: string;
|
|
25
|
+
readonly before: readonly SmartMark[];
|
|
26
|
+
readonly after: readonly SmartMark[];
|
|
27
|
+
};
|
|
28
|
+
/** A node id present in `after` but not `before`. Only topmost added roots are reported - a node whose parent id is itself newly-added is part of that parent's own subtree, not a separate entry. */
|
|
29
|
+
export interface AddedNodeChange {
|
|
30
|
+
readonly kind: "added";
|
|
31
|
+
readonly nodeId: string;
|
|
32
|
+
readonly node: SmartNode;
|
|
33
|
+
readonly parentId: string | null;
|
|
34
|
+
readonly path: number[];
|
|
35
|
+
}
|
|
36
|
+
/** A node id present in `before` but not `after`. Only topmost removed roots are reported, mirroring `AddedNodeChange`. */
|
|
37
|
+
export interface RemovedNodeChange {
|
|
38
|
+
readonly kind: "removed";
|
|
39
|
+
readonly nodeId: string;
|
|
40
|
+
readonly node: SmartNode;
|
|
41
|
+
readonly parentId: string | null;
|
|
42
|
+
readonly path: number[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A node id present in both trees with at least one difference. Carries
|
|
46
|
+
* whichever of `move`/`typeChange`/`attrsChange`/`contentChange` actually
|
|
47
|
+
* differ on one entry per id, rather than separate flat entries per change
|
|
48
|
+
* kind - a renderer needs one lookup per node id, not a correlation step.
|
|
49
|
+
*/
|
|
50
|
+
export interface ChangedNodeChange {
|
|
51
|
+
readonly kind: "changed";
|
|
52
|
+
readonly nodeId: string;
|
|
53
|
+
readonly move?: {
|
|
54
|
+
readonly fromParentId: string | null;
|
|
55
|
+
readonly toParentId: string | null;
|
|
56
|
+
readonly fromPath: number[];
|
|
57
|
+
readonly toPath: number[];
|
|
58
|
+
};
|
|
59
|
+
readonly typeChange?: {
|
|
60
|
+
readonly before: string;
|
|
61
|
+
readonly after: string;
|
|
62
|
+
};
|
|
63
|
+
readonly attrsChange?: {
|
|
64
|
+
readonly before: Attrs;
|
|
65
|
+
readonly after: Attrs;
|
|
66
|
+
readonly changedKeys: readonly string[];
|
|
67
|
+
};
|
|
68
|
+
readonly contentChange?: readonly TextDiffSegment[];
|
|
69
|
+
}
|
|
70
|
+
export interface DocumentDiff {
|
|
71
|
+
readonly added: readonly AddedNodeChange[];
|
|
72
|
+
readonly removed: readonly RemovedNodeChange[];
|
|
73
|
+
readonly changed: readonly ChangedNodeChange[];
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { type NormalizationRun } from "./normalization.js";
|
|
2
|
+
import type { Attrs, NormalizerRegistration, PersistedEditorDocument, ResolvedPos, SmartHistory, SmartMark, SmartNode, SmartOperation, SmartRange, SmartSchema, SmartSelection, SmartTransaction } from "./types.js";
|
|
3
|
+
import type { PositionLookup, ScopeRequest, ScopeResult } from "./scope/types.js";
|
|
4
|
+
import type { ContextMenuContribution, KeyboardShortcutContribution, PluginCommand } from "./plugin/types.js";
|
|
5
|
+
export interface FoundationEditorState extends PersistedEditorDocument {
|
|
6
|
+
selection: SmartSelection;
|
|
7
|
+
storedMarks?: SmartMark[];
|
|
8
|
+
}
|
|
9
|
+
export interface TransactOptions {
|
|
10
|
+
source?: SmartTransaction["metadata"]["source"];
|
|
11
|
+
timestamp?: number;
|
|
12
|
+
historyGroup?: string;
|
|
13
|
+
addToHistory?: boolean;
|
|
14
|
+
compositionId?: string;
|
|
15
|
+
authorId?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class TransactionBuilder {
|
|
18
|
+
readonly selectionBefore: SmartSelection;
|
|
19
|
+
readonly operations: SmartOperation[];
|
|
20
|
+
selectionAfter: SmartSelection;
|
|
21
|
+
storedMarksAfter?: SmartMark[];
|
|
22
|
+
/** True when the caller intentionally set the post-transaction marks. */
|
|
23
|
+
/** @internal Transaction assembly uses this to distinguish an explicit clear from the default. */
|
|
24
|
+
storedMarksExplicit: boolean;
|
|
25
|
+
constructor(selectionBefore: SmartSelection, storedMarks?: SmartMark[]);
|
|
26
|
+
insertNode(position: ResolvedPos, node: SmartNode): void;
|
|
27
|
+
removeNode(position: ResolvedPos, node: SmartNode): void;
|
|
28
|
+
replaceNode(position: ResolvedPos, before: SmartNode, after: SmartNode): void;
|
|
29
|
+
moveNode(from: ResolvedPos, to: ResolvedPos, nodeId: string): void;
|
|
30
|
+
splitNode(position: ResolvedPos, depth: number, newId?: string): void;
|
|
31
|
+
mergeNode(position: ResolvedPos, depth: number, retiredId: string, splitOffset: number): void;
|
|
32
|
+
setNodeAttributes(position: ResolvedPos, before: Attrs, after: Attrs): void;
|
|
33
|
+
setNodeType(position: ResolvedPos, before: string, after: string, beforeAttrs: Attrs, afterAttrs: Attrs): void;
|
|
34
|
+
insertText(position: ResolvedPos, text: string, marks?: SmartMark[]): void;
|
|
35
|
+
deleteText(position: ResolvedPos, text: string, marks?: SmartMark[]): void;
|
|
36
|
+
addMark(range: SmartRange, mark: SmartMark): void;
|
|
37
|
+
removeMark(range: SmartRange, mark: SmartMark): void;
|
|
38
|
+
setSelection(selection: SmartSelection): void;
|
|
39
|
+
setStoredMarks(marks: SmartMark[] | undefined): void;
|
|
40
|
+
}
|
|
41
|
+
export interface FoundationEditorOptions {
|
|
42
|
+
document: SmartNode;
|
|
43
|
+
selection: SmartSelection;
|
|
44
|
+
revision?: number;
|
|
45
|
+
schema?: SmartSchema;
|
|
46
|
+
/** Defaults to the built-in registry's commands - a custom plugin list's registry.commands should be passed here to keep it in sync with a custom `schema`. */
|
|
47
|
+
commands?: ReadonlyMap<string, PluginCommand>;
|
|
48
|
+
/** Defaults to the built-in registry's keyboardShortcuts, for the same reason as `commands`. */
|
|
49
|
+
keyboardShortcuts?: readonly KeyboardShortcutContribution[];
|
|
50
|
+
/** Defaults to the built-in registry's contextMenu, for the same reason as `commands`. */
|
|
51
|
+
contextMenu?: readonly ContextMenuContribution[];
|
|
52
|
+
normalizers?: readonly NormalizerRegistration[];
|
|
53
|
+
historyLimit?: number;
|
|
54
|
+
historyByteLimit?: number;
|
|
55
|
+
coalescenceWindowMs?: number;
|
|
56
|
+
storedMarks?: readonly SmartMark[];
|
|
57
|
+
/**
|
|
58
|
+
* How many committed transactions to retain for rebasing an incoming
|
|
59
|
+
* transaction whose baseRevision is behind current (Phase 12b-client -
|
|
60
|
+
* without a real transport, single-writer usage never falls behind, so
|
|
61
|
+
* this never matters). Unbounded retention isn't viable for a long-lived
|
|
62
|
+
* session; a transaction behind this window fails with
|
|
63
|
+
* ResyncRequiredError rather than attempting a partial rebase.
|
|
64
|
+
*/
|
|
65
|
+
revisionLogLimit?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface ReplaceFoundationStateOptions {
|
|
68
|
+
selection: SmartSelection;
|
|
69
|
+
storedMarks?: readonly SmartMark[];
|
|
70
|
+
/** External replacement starts a new history epoch by default. */
|
|
71
|
+
resetHistory?: boolean;
|
|
72
|
+
}
|
|
73
|
+
export declare class FoundationEditor {
|
|
74
|
+
readonly schema: SmartSchema;
|
|
75
|
+
readonly commands: ReadonlyMap<string, PluginCommand>;
|
|
76
|
+
readonly keyboardShortcuts: readonly KeyboardShortcutContribution[];
|
|
77
|
+
readonly contextMenu: readonly ContextMenuContribution[];
|
|
78
|
+
private current;
|
|
79
|
+
private currentHistory;
|
|
80
|
+
private readonly normalizers;
|
|
81
|
+
private activeBuilder;
|
|
82
|
+
private listeners;
|
|
83
|
+
private readonly semanticIndex;
|
|
84
|
+
private readonly historyOptions;
|
|
85
|
+
lastNormalization: NormalizationRun | null;
|
|
86
|
+
/**
|
|
87
|
+
* Every committed transaction since this instance was created or last
|
|
88
|
+
* replaceState'd, oldest first, bounded to `revisionLogLimit` - the
|
|
89
|
+
* "missed operations" source for rebasing an incoming stale transaction
|
|
90
|
+
* (see dispatch()). Index i holds the transaction that advanced the
|
|
91
|
+
* document from revision (current.revision - revisionLog.length + i) to
|
|
92
|
+
* the next.
|
|
93
|
+
*/
|
|
94
|
+
private revisionLog;
|
|
95
|
+
private readonly revisionLogLimit;
|
|
96
|
+
constructor(options: FoundationEditorOptions);
|
|
97
|
+
get state(): FoundationEditorState;
|
|
98
|
+
get history(): SmartHistory;
|
|
99
|
+
/** Readonly canonical references for memoized renderers and indexes. */
|
|
100
|
+
get document(): FoundationEditorState["document"];
|
|
101
|
+
get selection(): SmartSelection;
|
|
102
|
+
get storedMarks(): readonly SmartMark[] | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Commit listeners receive the canonical readonly document reference. This
|
|
105
|
+
* preserves the structural-sharing memoization contract and avoids cloning
|
|
106
|
+
* the complete document once per listener on every keystroke.
|
|
107
|
+
*/
|
|
108
|
+
private notify;
|
|
109
|
+
/**
|
|
110
|
+
* Replaces the canonical envelope without recreating the editor instance.
|
|
111
|
+
* This is an explicit host revision boundary, never a response to a prop diff.
|
|
112
|
+
*/
|
|
113
|
+
replaceState(envelope: PersistedEditorDocument, options: ReplaceFoundationStateOptions): SmartTransaction;
|
|
114
|
+
resolveScope(request: ScopeRequest, selection?: SmartSelection): ScopeResult;
|
|
115
|
+
get positions(): PositionLookup;
|
|
116
|
+
resolve(position: {
|
|
117
|
+
pos: ResolvedPos["pos"];
|
|
118
|
+
affinity?: ResolvedPos["affinity"];
|
|
119
|
+
}): ResolvedPos;
|
|
120
|
+
transact(callback: (transaction: TransactionBuilder) => unknown, options?: TransactOptions): SmartTransaction | null;
|
|
121
|
+
/**
|
|
122
|
+
* Transactions committed since revision `sinceRevision`, oldest first -
|
|
123
|
+
* the same source `dispatch()` itself uses to rebase an incoming stale
|
|
124
|
+
* transaction, exposed so a host-implemented CollabTransport can answer
|
|
125
|
+
* `getRevisionHistory` without this editor needing to know anything about
|
|
126
|
+
* transports. Returns null when `sinceRevision` is older than what this
|
|
127
|
+
* instance retained (see `revisionLogLimit`) - the caller must resync.
|
|
128
|
+
*/
|
|
129
|
+
getTransactionsSince(sinceRevision: number): readonly SmartTransaction[] | null;
|
|
130
|
+
dispatch(input: SmartTransaction): void;
|
|
131
|
+
typeText(text: string, options?: Omit<TransactOptions, "source">): SmartTransaction | null;
|
|
132
|
+
setSelection(selection: SmartSelection, options?: Omit<TransactOptions, "addToHistory">): SmartTransaction | null;
|
|
133
|
+
setStoredMarks(marks: readonly SmartMark[] | undefined, options?: Omit<TransactOptions, "addToHistory">): SmartTransaction | null;
|
|
134
|
+
undo(): boolean;
|
|
135
|
+
redo(): boolean;
|
|
136
|
+
subscribe(listener: (transaction: SmartTransaction, state: FoundationEditorState) => void): () => void;
|
|
137
|
+
}
|
|
138
|
+
export declare const createFoundationEditor: (options: FoundationEditorOptions) => FoundationEditor;
|