smartrte-core 0.2.0 → 1.0.0-beta.1
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 +21 -0
- package/dist/foundation/atom/formats.js +77 -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 +20 -0
- package/dist/foundation/list/formats.js +795 -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 +26 -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 +45 -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,398 @@
|
|
|
1
|
+
import { createNodeId, isTextNode } from "./identity.js";
|
|
2
|
+
import { popRedo, popUndo, recordHistory, createHistory, rebaseHistoryNodeAttributes } from "./history.js";
|
|
3
|
+
import { runNormalization } from "./normalization.js";
|
|
4
|
+
import { applyOperations } from "./operations.js";
|
|
5
|
+
import { createTransactionMap } from "./mapping.js";
|
|
6
|
+
import { resolvePos } from "./positions.js";
|
|
7
|
+
import { foundationRegistry, foundationSchema, repair, restoreUnknownMarks, restoreUnknownNodes, validate } from "./schema.js";
|
|
8
|
+
import { applyTransactionAtomic, RebaseConflictError, ResyncRequiredError } from "./transactions.js";
|
|
9
|
+
import { rebaseTransaction } from "./collab/rebase.js";
|
|
10
|
+
import { FoundationScopeIndex } from "./scope/resolveScope.js";
|
|
11
|
+
import { migrateNewlineTextToHardBreaks } from "./marks/hardBreak.js";
|
|
12
|
+
import { canonicalMarkOrder, createMarkNormalizer, marksAtInsertion } from "./marks/index.js";
|
|
13
|
+
import { createEditableBoundaryNormalizer, editableBoundaryOperations } from "./boundaries.js";
|
|
14
|
+
export class TransactionBuilder {
|
|
15
|
+
constructor(selectionBefore, storedMarks) {
|
|
16
|
+
this.selectionBefore = selectionBefore;
|
|
17
|
+
this.operations = [];
|
|
18
|
+
/** True when the caller intentionally set the post-transaction marks. */
|
|
19
|
+
/** @internal Transaction assembly uses this to distinguish an explicit clear from the default. */
|
|
20
|
+
this.storedMarksExplicit = false;
|
|
21
|
+
this.selectionAfter = structuredClone(selectionBefore);
|
|
22
|
+
this.storedMarksAfter = structuredClone(storedMarks);
|
|
23
|
+
}
|
|
24
|
+
insertNode(position, node) {
|
|
25
|
+
this.operations.push({ type: "insertNode", pos: position.pos, node: structuredClone(node) });
|
|
26
|
+
}
|
|
27
|
+
removeNode(position, node) {
|
|
28
|
+
this.operations.push({ type: "removeNode", pos: position.pos, node: structuredClone(node) });
|
|
29
|
+
}
|
|
30
|
+
replaceNode(position, before, after) {
|
|
31
|
+
this.operations.push({ type: "replaceNode", pos: position.pos, before: structuredClone(before), after: structuredClone(after) });
|
|
32
|
+
}
|
|
33
|
+
moveNode(from, to, nodeId) {
|
|
34
|
+
this.operations.push({ type: "moveNode", from: from.pos, to: to.pos, nodeId });
|
|
35
|
+
}
|
|
36
|
+
splitNode(position, depth, newId = createNodeId()) {
|
|
37
|
+
this.operations.push({ type: "splitNode", pos: position.pos, depth, newId });
|
|
38
|
+
}
|
|
39
|
+
mergeNode(position, depth, retiredId, splitOffset) {
|
|
40
|
+
this.operations.push({ type: "mergeNode", pos: position.pos, depth, retiredId, splitOffset });
|
|
41
|
+
}
|
|
42
|
+
setNodeAttributes(position, before, after) {
|
|
43
|
+
this.operations.push({ type: "setNodeAttributes", pos: position.pos, before: structuredClone(before), after: structuredClone(after) });
|
|
44
|
+
}
|
|
45
|
+
setNodeType(position, before, after, beforeAttrs, afterAttrs) {
|
|
46
|
+
this.operations.push({
|
|
47
|
+
type: "setNodeType",
|
|
48
|
+
pos: position.pos,
|
|
49
|
+
before,
|
|
50
|
+
after,
|
|
51
|
+
beforeAttrs: structuredClone(beforeAttrs),
|
|
52
|
+
afterAttrs: structuredClone(afterAttrs),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
insertText(position, text, marks) {
|
|
56
|
+
this.operations.push({ type: "insertText", pos: position.pos, text, ...(marks?.length ? { marks: structuredClone(marks) } : {}) });
|
|
57
|
+
}
|
|
58
|
+
deleteText(position, text, marks) {
|
|
59
|
+
this.operations.push({ type: "deleteText", pos: position.pos, text, ...(marks?.length ? { marks: structuredClone(marks) } : {}) });
|
|
60
|
+
}
|
|
61
|
+
addMark(range, mark) {
|
|
62
|
+
this.operations.push({ type: "addMark", range: structuredClone(range), mark: structuredClone(mark) });
|
|
63
|
+
}
|
|
64
|
+
removeMark(range, mark) {
|
|
65
|
+
this.operations.push({ type: "removeMark", range: structuredClone(range), mark: structuredClone(mark) });
|
|
66
|
+
}
|
|
67
|
+
setSelection(selection) {
|
|
68
|
+
this.selectionAfter = structuredClone(selection);
|
|
69
|
+
}
|
|
70
|
+
setStoredMarks(marks) {
|
|
71
|
+
this.storedMarksExplicit = true;
|
|
72
|
+
this.storedMarksAfter = structuredClone(marks);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const mapSelectionThroughBoundaryOperations = (selection, operations) => {
|
|
76
|
+
if (!operations.length)
|
|
77
|
+
return selection;
|
|
78
|
+
const map = createTransactionMap(operations);
|
|
79
|
+
// A node selection's head is the boundary immediately after the selected
|
|
80
|
+
// node. When a caret paragraph is inserted at that boundary, biasing the
|
|
81
|
+
// head forward would skip the new line and make ArrowRight manufacture a
|
|
82
|
+
// second paragraph. Keep both node-selection endpoints on the original
|
|
83
|
+
// side of the inserted boundary.
|
|
84
|
+
if (selection.type === "node")
|
|
85
|
+
return {
|
|
86
|
+
...selection,
|
|
87
|
+
anchor: map.map(selection.anchor, -1),
|
|
88
|
+
head: map.map(selection.head, -1),
|
|
89
|
+
};
|
|
90
|
+
return map.mapSelection(selection);
|
|
91
|
+
};
|
|
92
|
+
export class FoundationEditor {
|
|
93
|
+
constructor(options) {
|
|
94
|
+
this.activeBuilder = null;
|
|
95
|
+
this.listeners = new Set();
|
|
96
|
+
this.semanticIndex = new FoundationScopeIndex();
|
|
97
|
+
this.lastNormalization = null;
|
|
98
|
+
/**
|
|
99
|
+
* Every committed transaction since this instance was created or last
|
|
100
|
+
* replaceState'd, oldest first, bounded to `revisionLogLimit` - the
|
|
101
|
+
* "missed operations" source for rebasing an incoming stale transaction
|
|
102
|
+
* (see dispatch()). Index i holds the transaction that advanced the
|
|
103
|
+
* document from revision (current.revision - revisionLog.length + i) to
|
|
104
|
+
* the next.
|
|
105
|
+
*/
|
|
106
|
+
this.revisionLog = [];
|
|
107
|
+
this.schema = options.schema || foundationSchema;
|
|
108
|
+
this.commands = options.commands || foundationRegistry.commands;
|
|
109
|
+
this.keyboardShortcuts = options.keyboardShortcuts || foundationRegistry.keyboardShortcuts;
|
|
110
|
+
this.contextMenu = options.contextMenu || foundationRegistry.contextMenu;
|
|
111
|
+
const candidate = options.document.type === "doc"
|
|
112
|
+
? options.document
|
|
113
|
+
: { type: "doc", id: createNodeId(), children: [options.document] };
|
|
114
|
+
const migrated = migrateNewlineTextToHardBreaks(candidate);
|
|
115
|
+
const repaired = repair(migrated.document, this.schema);
|
|
116
|
+
// Symmetric with repair() above: an `unknown`/`unknown-mark` node whose
|
|
117
|
+
// recorded originalType this schema *does* recognize (e.g. a
|
|
118
|
+
// previously plugin-disabled table, now loading into a schema with the
|
|
119
|
+
// table plugin re-enabled) restores losslessly - a no-op for every
|
|
120
|
+
// other document, since restoreUnknownNodes/Marks only ever act on a
|
|
121
|
+
// matching originalType. See docs/bugs/disable-safety-restore-never-wired.md.
|
|
122
|
+
const restored = restoreUnknownMarks(restoreUnknownNodes(repaired.doc, this.schema), this.schema);
|
|
123
|
+
const boundaryOperations = editableBoundaryOperations(restored, this.schema);
|
|
124
|
+
const boundedDocument = boundaryOperations.length ? applyOperations(restored, boundaryOperations) : restored;
|
|
125
|
+
const boundedSelection = mapSelectionThroughBoundaryOperations(options.selection, boundaryOperations);
|
|
126
|
+
const errors = validate(boundedDocument, this.schema);
|
|
127
|
+
if (errors.length)
|
|
128
|
+
throw new Error(`Initial document is invalid: ${errors[0].message}`);
|
|
129
|
+
resolvePos(boundedDocument, boundedSelection.anchor);
|
|
130
|
+
resolvePos(boundedDocument, boundedSelection.head);
|
|
131
|
+
this.current = {
|
|
132
|
+
schemaVersion: this.schema.version,
|
|
133
|
+
revision: options.revision ?? 0,
|
|
134
|
+
document: boundedDocument,
|
|
135
|
+
selection: structuredClone(boundedSelection),
|
|
136
|
+
...(options.storedMarks?.length ? { storedMarks: canonicalMarkOrder(options.storedMarks) } : {}),
|
|
137
|
+
};
|
|
138
|
+
this.normalizers = [createEditableBoundaryNormalizer(), createMarkNormalizer(), ...(options.normalizers || [])];
|
|
139
|
+
this.historyOptions = {
|
|
140
|
+
historyLimit: options.historyLimit,
|
|
141
|
+
historyByteLimit: options.historyByteLimit,
|
|
142
|
+
coalescenceWindowMs: options.coalescenceWindowMs,
|
|
143
|
+
};
|
|
144
|
+
this.currentHistory = createHistory({
|
|
145
|
+
limit: options.historyLimit,
|
|
146
|
+
byteLimit: options.historyByteLimit,
|
|
147
|
+
coalescenceWindowMs: options.coalescenceWindowMs,
|
|
148
|
+
});
|
|
149
|
+
this.revisionLogLimit = Math.max(1, Math.floor(options.revisionLogLimit ?? 500));
|
|
150
|
+
}
|
|
151
|
+
get state() { return structuredClone(this.current); }
|
|
152
|
+
get history() { return structuredClone(this.currentHistory); }
|
|
153
|
+
/** Readonly canonical references for memoized renderers and indexes. */
|
|
154
|
+
get document() { return this.current.document; }
|
|
155
|
+
get selection() { return structuredClone(this.current.selection); }
|
|
156
|
+
get storedMarks() { return this.current.storedMarks; }
|
|
157
|
+
/**
|
|
158
|
+
* Commit listeners receive the canonical readonly document reference. This
|
|
159
|
+
* preserves the structural-sharing memoization contract and avoids cloning
|
|
160
|
+
* the complete document once per listener on every keystroke.
|
|
161
|
+
*/
|
|
162
|
+
notify(transaction) {
|
|
163
|
+
if (!this.listeners.size)
|
|
164
|
+
return;
|
|
165
|
+
const state = {
|
|
166
|
+
schemaVersion: this.current.schemaVersion,
|
|
167
|
+
revision: this.current.revision,
|
|
168
|
+
document: this.current.document,
|
|
169
|
+
selection: structuredClone(this.current.selection),
|
|
170
|
+
...(this.current.storedMarks ? { storedMarks: structuredClone(this.current.storedMarks) } : {}),
|
|
171
|
+
};
|
|
172
|
+
this.listeners.forEach((listener) => listener(structuredClone(transaction), state));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Replaces the canonical envelope without recreating the editor instance.
|
|
176
|
+
* This is an explicit host revision boundary, never a response to a prop diff.
|
|
177
|
+
*/
|
|
178
|
+
replaceState(envelope, options) {
|
|
179
|
+
const migrated = migrateNewlineTextToHardBreaks(envelope.document);
|
|
180
|
+
const repaired = repair(migrated.document, this.schema);
|
|
181
|
+
// See the matching comment in the constructor above.
|
|
182
|
+
const restored = restoreUnknownMarks(restoreUnknownNodes(repaired.doc, this.schema), this.schema);
|
|
183
|
+
const boundaryOperations = editableBoundaryOperations(restored, this.schema);
|
|
184
|
+
const boundedDocument = boundaryOperations.length ? applyOperations(restored, boundaryOperations) : restored;
|
|
185
|
+
const boundedSelection = mapSelectionThroughBoundaryOperations(options.selection, boundaryOperations);
|
|
186
|
+
const errors = validate(boundedDocument, this.schema);
|
|
187
|
+
if (errors.length)
|
|
188
|
+
throw new Error(`Replacement document is invalid: ${errors[0].message}`);
|
|
189
|
+
resolvePos(boundedDocument, boundedSelection.anchor);
|
|
190
|
+
resolvePos(boundedDocument, boundedSelection.head);
|
|
191
|
+
const before = this.current;
|
|
192
|
+
this.current = {
|
|
193
|
+
schemaVersion: this.schema.version,
|
|
194
|
+
revision: envelope.revision,
|
|
195
|
+
document: boundedDocument,
|
|
196
|
+
selection: structuredClone(boundedSelection),
|
|
197
|
+
...(options.storedMarks?.length ? { storedMarks: canonicalMarkOrder(options.storedMarks) } : {}),
|
|
198
|
+
};
|
|
199
|
+
if (options.resetHistory !== false) {
|
|
200
|
+
this.currentHistory = createHistory({
|
|
201
|
+
limit: this.historyOptions.historyLimit,
|
|
202
|
+
byteLimit: this.historyOptions.historyByteLimit,
|
|
203
|
+
coalescenceWindowMs: this.historyOptions.coalescenceWindowMs,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// The revision counter is jumping to a new, unrelated baseline
|
|
207
|
+
// (envelope.revision, not before.revision + 1) - nothing in the old log
|
|
208
|
+
// could ever be correctly composed with transactions issued against
|
|
209
|
+
// this new baseline, so it's discarded rather than carried forward.
|
|
210
|
+
this.revisionLog = [];
|
|
211
|
+
const replacement = {
|
|
212
|
+
id: createNodeId(),
|
|
213
|
+
baseRevision: before.revision,
|
|
214
|
+
operations: [],
|
|
215
|
+
selectionBefore: structuredClone(before.selection),
|
|
216
|
+
selectionAfter: structuredClone(boundedSelection),
|
|
217
|
+
...(before.storedMarks ? { storedMarksBefore: structuredClone(before.storedMarks) } : {}),
|
|
218
|
+
...(options.storedMarks?.length ? { storedMarksAfter: canonicalMarkOrder(options.storedMarks) } : {}),
|
|
219
|
+
metadata: { source: "api", timestamp: Date.now(), addToHistory: false },
|
|
220
|
+
};
|
|
221
|
+
this.notify(replacement);
|
|
222
|
+
return replacement;
|
|
223
|
+
}
|
|
224
|
+
resolveScope(request, selection = this.current.selection) {
|
|
225
|
+
return this.semanticIndex.resolve(this.current.document, selection, request, this.schema);
|
|
226
|
+
}
|
|
227
|
+
get positions() { return this.semanticIndex.positions(this.current.document, this.schema); }
|
|
228
|
+
resolve(position) {
|
|
229
|
+
return resolvePos(this.current.document, position.pos, position.affinity);
|
|
230
|
+
}
|
|
231
|
+
transact(callback, options = {}) {
|
|
232
|
+
if (this.activeBuilder) {
|
|
233
|
+
const result = callback(this.activeBuilder);
|
|
234
|
+
if (result && typeof result.then === "function")
|
|
235
|
+
throw new Error("A transaction cannot remain open across await.");
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
const builder = new TransactionBuilder(this.current.selection, this.current.storedMarks);
|
|
239
|
+
this.activeBuilder = builder;
|
|
240
|
+
try {
|
|
241
|
+
const result = callback(builder);
|
|
242
|
+
if (result && typeof result.then === "function")
|
|
243
|
+
throw new Error("A transaction cannot remain open across await.");
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
this.activeBuilder = null;
|
|
247
|
+
}
|
|
248
|
+
if (builder.operations.length && !builder.storedMarksExplicit && !builder.operations.every((operation) => operation.type === "insertText" && (!this.current.storedMarks?.length
|
|
249
|
+
|| JSON.stringify(canonicalMarkOrder(operation.marks)) === JSON.stringify(canonicalMarkOrder(this.current.storedMarks))))) {
|
|
250
|
+
builder.setStoredMarks(undefined);
|
|
251
|
+
}
|
|
252
|
+
const transaction = {
|
|
253
|
+
id: createNodeId(),
|
|
254
|
+
baseRevision: this.current.revision,
|
|
255
|
+
operations: builder.operations,
|
|
256
|
+
selectionBefore: structuredClone(builder.selectionBefore),
|
|
257
|
+
selectionAfter: structuredClone(builder.selectionAfter),
|
|
258
|
+
...(this.current.storedMarks ? { storedMarksBefore: structuredClone(this.current.storedMarks) } : {}),
|
|
259
|
+
...(builder.storedMarksAfter ? { storedMarksAfter: structuredClone(builder.storedMarksAfter) } : {}),
|
|
260
|
+
metadata: {
|
|
261
|
+
source: options.source || "api",
|
|
262
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
263
|
+
...(options.historyGroup ? { historyGroup: options.historyGroup } : {}),
|
|
264
|
+
addToHistory: options.addToHistory ?? builder.operations.length > 0,
|
|
265
|
+
...(options.compositionId ? { compositionId: options.compositionId } : {}),
|
|
266
|
+
...(options.authorId ? { authorId: options.authorId } : {}),
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
this.dispatch(transaction);
|
|
270
|
+
return transaction;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Transactions committed since revision `sinceRevision`, oldest first -
|
|
274
|
+
* the same source `dispatch()` itself uses to rebase an incoming stale
|
|
275
|
+
* transaction, exposed so a host-implemented CollabTransport can answer
|
|
276
|
+
* `getRevisionHistory` without this editor needing to know anything about
|
|
277
|
+
* transports. Returns null when `sinceRevision` is older than what this
|
|
278
|
+
* instance retained (see `revisionLogLimit`) - the caller must resync.
|
|
279
|
+
*/
|
|
280
|
+
getTransactionsSince(sinceRevision) {
|
|
281
|
+
const behindBy = this.current.revision - sinceRevision;
|
|
282
|
+
if (behindBy < 0)
|
|
283
|
+
return null;
|
|
284
|
+
if (behindBy > this.revisionLog.length)
|
|
285
|
+
return null;
|
|
286
|
+
return structuredClone(this.revisionLog.slice(this.revisionLog.length - behindBy));
|
|
287
|
+
}
|
|
288
|
+
dispatch(input) {
|
|
289
|
+
if (input.baseRevision !== this.current.revision) {
|
|
290
|
+
const missed = this.getTransactionsSince(input.baseRevision);
|
|
291
|
+
if (missed === null)
|
|
292
|
+
throw new ResyncRequiredError(this.current.revision);
|
|
293
|
+
const rebased = rebaseTransaction(input, missed, this.current.revision);
|
|
294
|
+
if (rebased.kind === "conflict")
|
|
295
|
+
throw new RebaseConflictError(rebased.reasons);
|
|
296
|
+
if (rebased.kind === "resync-required")
|
|
297
|
+
throw new ResyncRequiredError(rebased.atRevision);
|
|
298
|
+
if (rebased.kind === "dropped")
|
|
299
|
+
return;
|
|
300
|
+
input = rebased.transaction;
|
|
301
|
+
}
|
|
302
|
+
const historyAttributeUpdates = input.metadata.addToHistory ? [] : input.operations.flatMap((operation) => {
|
|
303
|
+
if (operation.type !== "setNodeAttributes")
|
|
304
|
+
return [];
|
|
305
|
+
const node = operation.pos.path.reduce((current, part) => current && !isTextNode(current) ? current.children?.[part] : undefined, this.current.document);
|
|
306
|
+
return node && !isTextNode(node) ? [{ nodeId: node.id, before: operation.before, after: operation.after }] : [];
|
|
307
|
+
});
|
|
308
|
+
const afterUserOperations = applyOperations(this.current.document, input.operations);
|
|
309
|
+
const normalization = runNormalization({
|
|
310
|
+
document: afterUserOperations,
|
|
311
|
+
originatingOperations: input.operations,
|
|
312
|
+
schema: this.schema,
|
|
313
|
+
normalizers: this.normalizers,
|
|
314
|
+
});
|
|
315
|
+
this.lastNormalization = normalization;
|
|
316
|
+
const normalizedSelection = normalization.operations.length
|
|
317
|
+
? createTransactionMap(normalization.operations).mapSelection(input.selectionAfter)
|
|
318
|
+
: input.selectionAfter;
|
|
319
|
+
const transaction = {
|
|
320
|
+
...structuredClone(input),
|
|
321
|
+
operations: [...structuredClone(input.operations), ...normalization.operations],
|
|
322
|
+
selectionAfter: normalizedSelection,
|
|
323
|
+
};
|
|
324
|
+
const envelope = applyTransactionAtomic(this.current, transaction, this.schema);
|
|
325
|
+
this.current = {
|
|
326
|
+
...envelope,
|
|
327
|
+
selection: structuredClone(transaction.selectionAfter),
|
|
328
|
+
storedMarks: structuredClone(transaction.storedMarksAfter),
|
|
329
|
+
};
|
|
330
|
+
this.currentHistory = recordHistory(this.currentHistory, transaction);
|
|
331
|
+
historyAttributeUpdates.forEach((update) => {
|
|
332
|
+
this.currentHistory = rebaseHistoryNodeAttributes(this.currentHistory, update.nodeId, update.before, update.after);
|
|
333
|
+
});
|
|
334
|
+
// Recorded regardless of addToHistory (unlike currentHistory/undo) -
|
|
335
|
+
// this log exists to rebase *other* incoming transactions, which needs
|
|
336
|
+
// every committed change, not just the user-undoable ones.
|
|
337
|
+
this.revisionLog.push(transaction);
|
|
338
|
+
if (this.revisionLog.length > this.revisionLogLimit)
|
|
339
|
+
this.revisionLog.splice(0, this.revisionLog.length - this.revisionLogLimit);
|
|
340
|
+
this.notify(transaction);
|
|
341
|
+
}
|
|
342
|
+
typeText(text, options = {}) {
|
|
343
|
+
const resolved = resolvePos(this.current.document, this.current.selection.head);
|
|
344
|
+
const marks = this.current.storedMarks || marksAtInsertion(this.current.document, resolved.pos, this.schema);
|
|
345
|
+
return this.transact((transaction) => {
|
|
346
|
+
transaction.insertText(resolved, text, marks);
|
|
347
|
+
const next = { path: [...resolved.pos.path], offset: resolved.pos.offset + text.length };
|
|
348
|
+
transaction.setSelection({ type: "text", anchor: next, head: next });
|
|
349
|
+
}, { ...options, source: "input", addToHistory: true });
|
|
350
|
+
}
|
|
351
|
+
setSelection(selection, options = {}) {
|
|
352
|
+
return this.transact((transaction) => {
|
|
353
|
+
transaction.setSelection(selection);
|
|
354
|
+
transaction.setStoredMarks(undefined);
|
|
355
|
+
}, { ...options, addToHistory: false });
|
|
356
|
+
}
|
|
357
|
+
setStoredMarks(marks, options = {}) {
|
|
358
|
+
// `marks?.length ? ... : undefined` used to collapse an explicitly-passed
|
|
359
|
+
// *empty* array down to `undefined` - indistinguishable, downstream, from
|
|
360
|
+
// "no override, infer from surrounding text" (marksAtInsertion). That
|
|
361
|
+
// silently defeated toggling the last active mark off at a collapsed
|
|
362
|
+
// cursor: marksAtInsertion's inclusive-boundary rule re-includes the mark
|
|
363
|
+
// from the text just typed, so the very next keystroke was re-marked
|
|
364
|
+
// regardless of the explicit toggle-off. An explicit `[]` must survive as
|
|
365
|
+
// a real (truthy) empty array so `editor.storedMarks || marksAtInsertion(...)`
|
|
366
|
+
// resolves to `[]`, not the fallback.
|
|
367
|
+
return this.transact((transaction) => transaction.setStoredMarks(marks !== undefined ? canonicalMarkOrder(marks) : undefined), {
|
|
368
|
+
...options, addToHistory: false,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
undo() {
|
|
372
|
+
const popped = popUndo(this.currentHistory);
|
|
373
|
+
if (!popped)
|
|
374
|
+
return false;
|
|
375
|
+
const inverse = { ...structuredClone(popped.entry.inverse), baseRevision: this.current.revision };
|
|
376
|
+
const envelope = applyTransactionAtomic(this.current, inverse, this.schema);
|
|
377
|
+
this.current = { ...envelope, selection: structuredClone(inverse.selectionAfter), storedMarks: structuredClone(inverse.storedMarksAfter) };
|
|
378
|
+
this.currentHistory = popped.history;
|
|
379
|
+
this.notify(inverse);
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
redo() {
|
|
383
|
+
const popped = popRedo(this.currentHistory);
|
|
384
|
+
if (!popped)
|
|
385
|
+
return false;
|
|
386
|
+
const forward = { ...structuredClone(popped.entry.forward), baseRevision: this.current.revision, metadata: { ...popped.entry.forward.metadata, addToHistory: false } };
|
|
387
|
+
const envelope = applyTransactionAtomic(this.current, forward, this.schema);
|
|
388
|
+
this.current = { ...envelope, selection: structuredClone(forward.selectionAfter), storedMarks: structuredClone(forward.storedMarksAfter) };
|
|
389
|
+
this.currentHistory = popped.history;
|
|
390
|
+
this.notify(forward);
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
subscribe(listener) {
|
|
394
|
+
this.listeners.add(listener);
|
|
395
|
+
return () => this.listeners.delete(listener);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
export const createFoundationEditor = (options) => new FoundationEditor(options);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SmartDocument, SmartNode } from "../types.js";
|
|
2
|
+
export type FormatId = "html" | "markdown" | "docx" | "pdf";
|
|
3
|
+
export type FormatFidelityLevel = "full" | "semantic" | "lossy" | "unsupported";
|
|
4
|
+
export interface ParseContext {
|
|
5
|
+
readonly format: FormatId;
|
|
6
|
+
}
|
|
7
|
+
export interface SerializeContext {
|
|
8
|
+
readonly format: FormatId;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The per-feature, per-format contract Phase 9 SS2.2 formalizes. Each of the
|
|
12
|
+
* five foundation features (list, marks, block, table, atom) declares one of
|
|
13
|
+
* these per format it participates in, rather than a single serializer
|
|
14
|
+
* containing scattered per-feature type checks.
|
|
15
|
+
*
|
|
16
|
+
* `parse`/`serialize` operate on a single feature's node(s) - they are the
|
|
17
|
+
* semantic mapping rule for "what does this feature mean in this format",
|
|
18
|
+
* not a whole-document driver. Whole-document assembly (correct ordering
|
|
19
|
+
* and nesting across all five features together) is a separate concern,
|
|
20
|
+
* owned by the format's top-level codec (see packages/core/src/foundation/
|
|
21
|
+
* formats/docx/export.ts, pdf/format.ts, and list/formats.ts's
|
|
22
|
+
* serializeCanonicalListHtml/serializeCanonicalListMarkdown for HTML/MD).
|
|
23
|
+
* This mirrors an existing split already present before this contract was
|
|
24
|
+
* formalized: packages/core/src/foundation/{list,marks,block,table,atom}/
|
|
25
|
+
* formats.ts already contain canonical*To{Docx,Pdf}* functions with exactly
|
|
26
|
+
* this per-feature, single-node shape, originally written for fixture-based
|
|
27
|
+
* fidelity verification (see SS2.3) rather than production document assembly.
|
|
28
|
+
*/
|
|
29
|
+
export interface FeatureFormatCodec<TFeature extends string = string> {
|
|
30
|
+
readonly feature: TFeature;
|
|
31
|
+
readonly format: FormatId;
|
|
32
|
+
readonly fidelity: FormatFidelityLevel;
|
|
33
|
+
/** Human-readable justification for the fidelity level - required, not decorative (see fidelity.ts's test enforcement). */
|
|
34
|
+
readonly note: string;
|
|
35
|
+
parse?: (input: unknown, ctx: ParseContext) => SmartNode | SmartNode[] | null;
|
|
36
|
+
serialize?: (node: SmartNode, ctx: SerializeContext) => unknown;
|
|
37
|
+
/** Applied when this feature's fidelity for this format is `lossy` or `unsupported` and no better representation exists. */
|
|
38
|
+
fallback?: (node: SmartNode) => SmartNode | null;
|
|
39
|
+
}
|
|
40
|
+
/** Whole-document entry points a format must provide, independent of any single feature. */
|
|
41
|
+
export interface DocumentFormatCodec {
|
|
42
|
+
readonly format: FormatId;
|
|
43
|
+
parseDocument?: (input: unknown, ctx: ParseContext) => SmartDocument;
|
|
44
|
+
serializeDocument?: (document: SmartDocument, ctx: SerializeContext) => unknown;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SmartDocument } from "../../types.js";
|
|
2
|
+
export declare const DOCX_MEDIA_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
3
|
+
export declare const smartDocumentToDocxXml: (document: SmartDocument) => string;
|
|
4
|
+
export declare const exportDocxDocument: (document: SmartDocument) => Promise<Blob>;
|