@beyondwork/docx-react-component 1.0.1 → 1.0.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 +44 -104
- package/package.json +50 -30
- package/src/README.md +85 -0
- package/src/api/README.md +22 -0
- package/src/api/public-types.ts +525 -0
- package/src/compare/diff-engine.ts +530 -0
- package/src/compare/export-redlines.ts +162 -0
- package/src/compare/snapshot.ts +37 -0
- package/src/component-inventory.md +99 -0
- package/src/core/README.md +10 -0
- package/src/core/commands/README.md +3 -0
- package/src/core/commands/formatting-commands.ts +161 -0
- package/src/core/commands/image-commands.ts +144 -0
- package/src/core/commands/index.ts +1013 -0
- package/src/core/commands/list-commands.ts +370 -0
- package/src/core/commands/review-commands.ts +108 -0
- package/src/core/commands/text-commands.ts +119 -0
- package/src/core/schema/README.md +3 -0
- package/src/core/schema/text-schema.ts +512 -0
- package/src/core/selection/README.md +3 -0
- package/src/core/selection/mapping.ts +238 -0
- package/src/core/selection/review-anchors.ts +94 -0
- package/src/core/state/README.md +3 -0
- package/src/core/state/editor-state.ts +580 -0
- package/src/core/state/text-transaction.ts +276 -0
- package/src/formats/xlsx/io/parse-shared-strings.ts +41 -0
- package/src/formats/xlsx/io/parse-sheet.ts +289 -0
- package/src/formats/xlsx/io/parse-styles.ts +57 -0
- package/src/formats/xlsx/io/parse-workbook.ts +75 -0
- package/src/formats/xlsx/io/xlsx-session.ts +306 -0
- package/src/formats/xlsx/model/cell.ts +189 -0
- package/src/formats/xlsx/model/sheet.ts +244 -0
- package/src/formats/xlsx/model/styles.ts +118 -0
- package/src/formats/xlsx/model/workbook.ts +449 -0
- package/src/index.ts +45 -0
- package/src/io/README.md +10 -0
- package/src/io/docx-session.ts +1763 -0
- package/src/io/export/README.md +3 -0
- package/src/io/export/export-session.ts +165 -0
- package/src/io/export/minimal-docx.ts +115 -0
- package/src/io/export/reattach-preserved-parts.ts +54 -0
- package/src/io/export/serialize-comments.ts +876 -0
- package/src/io/export/serialize-footnotes.ts +217 -0
- package/src/io/export/serialize-headers-footers.ts +200 -0
- package/src/io/export/serialize-main-document.ts +982 -0
- package/src/io/export/serialize-numbering.ts +97 -0
- package/src/io/export/serialize-revisions.ts +389 -0
- package/src/io/export/serialize-runtime-revisions.ts +265 -0
- package/src/io/export/serialize-tables.ts +147 -0
- package/src/io/export/split-review-boundaries.ts +194 -0
- package/src/io/normalize/README.md +3 -0
- package/src/io/normalize/normalize-text.ts +437 -0
- package/src/io/ooxml/README.md +3 -0
- package/src/io/ooxml/parse-comments.ts +779 -0
- package/src/io/ooxml/parse-complex-content.ts +287 -0
- package/src/io/ooxml/parse-fields.ts +438 -0
- package/src/io/ooxml/parse-footnotes.ts +403 -0
- package/src/io/ooxml/parse-headers-footers.ts +483 -0
- package/src/io/ooxml/parse-inline-media.ts +431 -0
- package/src/io/ooxml/parse-main-document.ts +1846 -0
- package/src/io/ooxml/parse-numbering.ts +425 -0
- package/src/io/ooxml/parse-revisions.ts +658 -0
- package/src/io/ooxml/parse-shapes.ts +271 -0
- package/src/io/ooxml/parse-tables.ts +568 -0
- package/src/io/ooxml/parse-theme.ts +314 -0
- package/src/io/ooxml/part-manifest.ts +136 -0
- package/src/io/ooxml/revision-boundaries.ts +351 -0
- package/src/io/opc/README.md +3 -0
- package/src/io/opc/corrupt-package.ts +166 -0
- package/src/io/opc/docx-package.ts +74 -0
- package/src/io/opc/package-reader.ts +325 -0
- package/src/io/opc/package-writer.ts +273 -0
- package/src/legal/bookmarks.ts +196 -0
- package/src/legal/cross-references.ts +356 -0
- package/src/legal/defined-terms.ts +203 -0
- package/src/model/README.md +3 -0
- package/src/model/canonical-document.ts +1911 -0
- package/src/model/cds-1.0.0.ts +196 -0
- package/src/model/snapshot.ts +393 -0
- package/src/preservation/README.md +3 -0
- package/src/preservation/markup-compatibility.ts +48 -0
- package/src/preservation/opaque-fragment-store.ts +89 -0
- package/src/preservation/opaque-region.ts +233 -0
- package/src/preservation/package-preservation.ts +120 -0
- package/src/preservation/preserved-part-manifest.ts +56 -0
- package/src/preservation/relationship-retention.ts +57 -0
- package/src/preservation/store.ts +185 -0
- package/src/review/README.md +16 -0
- package/src/review/store/README.md +3 -0
- package/src/review/store/comment-anchors.ts +70 -0
- package/src/review/store/comment-remapping.ts +154 -0
- package/src/review/store/comment-store.ts +331 -0
- package/src/review/store/comment-thread.ts +109 -0
- package/src/review/store/revision-actions.ts +394 -0
- package/src/review/store/revision-store.ts +303 -0
- package/src/review/store/revision-types.ts +168 -0
- package/src/review/store/runtime-comment-store.ts +43 -0
- package/src/runtime/README.md +3 -0
- package/src/runtime/ai-action-policy.ts +764 -0
- package/src/runtime/document-runtime.ts +967 -0
- package/src/runtime/read-only-diagnostics-runtime.ts +232 -0
- package/src/runtime/review-runtime.ts +44 -0
- package/src/runtime/revision-runtime.ts +107 -0
- package/src/runtime/session-capabilities.ts +138 -0
- package/src/runtime/surface-projection.ts +570 -0
- package/src/runtime/table-commands.ts +87 -0
- package/src/runtime/table-schema.ts +140 -0
- package/src/runtime/virtualized-rendering.ts +258 -0
- package/src/ui/README.md +30 -0
- package/src/ui/WordReviewEditor.tsx +1506 -0
- package/src/ui/comments/README.md +3 -0
- package/src/ui/compatibility/README.md +3 -0
- package/src/ui/editor-surface/README.md +3 -0
- package/src/ui/headless/comment-decoration-model.ts +124 -0
- package/src/ui/headless/revision-decoration-model.ts +128 -0
- package/src/ui/headless/selection-helpers.ts +34 -0
- package/src/ui/headless/use-editor-keyboard.ts +98 -0
- package/src/ui/review/README.md +3 -0
- package/src/ui/shared/revision-filters.ts +31 -0
- package/src/ui/status/README.md +3 -0
- package/src/ui/theme/README.md +3 -0
- package/src/ui/toolbar/README.md +3 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +48 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +44 -0
- package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +58 -0
- package/src/ui-tailwind/chrome/use-before-unload.ts +20 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +139 -0
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +98 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +123 -0
- package/src/ui-tailwind/editor-surface/pm-schema.ts +452 -0
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +327 -0
- package/src/ui-tailwind/editor-surface/search-plugin.ts +157 -0
- package/src/ui-tailwind/editor-surface/tw-caret.tsx +12 -0
- package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +150 -0
- package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +118 -0
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +52 -0
- package/src/ui-tailwind/editor-surface/tw-paragraph-block.tsx +151 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +215 -0
- package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +111 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +122 -0
- package/src/ui-tailwind/index.ts +61 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +276 -0
- package/src/ui-tailwind/review/tw-health-panel.tsx +120 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +120 -0
- package/src/ui-tailwind/review/tw-revision-sidebar.tsx +164 -0
- package/src/ui-tailwind/status/tw-status-bar.tsx +58 -0
- package/src/ui-tailwind/theme/editor-theme.css +190 -0
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +48 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +231 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +140 -0
- package/src/validation/README.md +3 -0
- package/src/validation/compatibility-engine.ts +317 -0
- package/src/validation/compatibility-report.ts +160 -0
- package/src/validation/diagnostics.ts +203 -0
- package/src/validation/import-diagnostics.ts +128 -0
- package/src/validation/low-priority-word-surfaces.ts +373 -0
- package/dist/chunk-32W6IVQE.js +0 -7725
- package/dist/chunk-32W6IVQE.js.map +0 -1
- package/dist/index.cjs +0 -23722
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -7
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -16011
- package/dist/index.js.map +0 -1
- package/dist/public-types-DqCURAz8.d.cts +0 -1152
- package/dist/public-types-DqCURAz8.d.ts +0 -1152
- package/dist/tailwind.cjs +0 -8295
- package/dist/tailwind.cjs.map +0 -1
- package/dist/tailwind.d.cts +0 -323
- package/dist/tailwind.d.ts +0 -323
- package/dist/tailwind.js +0 -553
- package/dist/tailwind.js.map +0 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
|
+
import { keymap } from "prosemirror-keymap";
|
|
3
|
+
import { columnResizing, goToNextCell, isInTable, tableEditing } from "prosemirror-tables";
|
|
4
|
+
|
|
5
|
+
import type { SelectionSnapshot } from "../../api/public-types";
|
|
6
|
+
import { createSelectionSnapshot } from "../../ui/headless/selection-helpers";
|
|
7
|
+
import type { PositionMap } from "./pm-position-map";
|
|
8
|
+
|
|
9
|
+
export interface CommandBridgeCallbacks {
|
|
10
|
+
onInsertText: (text: string) => void;
|
|
11
|
+
onDeleteBackward: () => void;
|
|
12
|
+
onDeleteForward: () => void;
|
|
13
|
+
onSplitParagraph: () => void;
|
|
14
|
+
onInsertHardBreak: () => void;
|
|
15
|
+
onInsertTab: () => void;
|
|
16
|
+
onUndo: () => void;
|
|
17
|
+
onRedo: () => void;
|
|
18
|
+
onSelectionChange: (selection: SelectionSnapshot) => void;
|
|
19
|
+
getPositionMap: () => PositionMap | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const bridgeKey = new PluginKey("command-bridge");
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates ProseMirror plugins that intercept user input and dispatch
|
|
26
|
+
* runtime commands instead of letting PM mutate its own state.
|
|
27
|
+
*
|
|
28
|
+
* All doc-changing transactions are blocked. Only the explicit input
|
|
29
|
+
* hooks below are allowed to trigger runtime commands.
|
|
30
|
+
*/
|
|
31
|
+
export function createCommandBridgePlugins(
|
|
32
|
+
callbacks: CommandBridgeCallbacks,
|
|
33
|
+
): Plugin[] {
|
|
34
|
+
// Transaction filter: block ALL doc-changing transactions.
|
|
35
|
+
// The runtime is the sole authority for document mutations.
|
|
36
|
+
const filterPlugin = new Plugin({
|
|
37
|
+
key: bridgeKey,
|
|
38
|
+
filterTransaction(tr) {
|
|
39
|
+
// Allow selection-only and metadata-only transactions
|
|
40
|
+
if (!tr.docChanged) return true;
|
|
41
|
+
// Block doc changes — runtime handles mutations via callbacks
|
|
42
|
+
return false;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Selection sync: when PM selection changes, notify the runtime.
|
|
47
|
+
const selectionPlugin = new Plugin({
|
|
48
|
+
view() {
|
|
49
|
+
return {
|
|
50
|
+
update(view, prevState) {
|
|
51
|
+
if (!view.state.selection.eq(prevState.selection)) {
|
|
52
|
+
const posMap = callbacks.getPositionMap();
|
|
53
|
+
if (!posMap) return;
|
|
54
|
+
|
|
55
|
+
const { from, to } = view.state.selection;
|
|
56
|
+
const runtimeAnchor = posMap.pmToRuntime(from);
|
|
57
|
+
const runtimeHead = posMap.pmToRuntime(to);
|
|
58
|
+
callbacks.onSelectionChange(
|
|
59
|
+
createSelectionSnapshot(runtimeAnchor, runtimeHead),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Text input hook: intercept typed characters.
|
|
68
|
+
const inputPlugin = new Plugin({
|
|
69
|
+
props: {
|
|
70
|
+
handleTextInput(_view, _from, _to, text) {
|
|
71
|
+
callbacks.onInsertText(text);
|
|
72
|
+
return true; // Block PM from processing
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Block paste (rich paste is not safe, plain paste via text.insert is TODO)
|
|
76
|
+
handlePaste() {
|
|
77
|
+
return true; // Block
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// Block drop
|
|
81
|
+
handleDrop() {
|
|
82
|
+
return true; // Block
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Keymap: intercept editing keys and dispatch runtime commands.
|
|
88
|
+
const keymapPlugin = keymap({
|
|
89
|
+
Backspace: () => {
|
|
90
|
+
callbacks.onDeleteBackward();
|
|
91
|
+
return true;
|
|
92
|
+
},
|
|
93
|
+
Delete: () => {
|
|
94
|
+
callbacks.onDeleteForward();
|
|
95
|
+
return true;
|
|
96
|
+
},
|
|
97
|
+
Enter: () => {
|
|
98
|
+
callbacks.onSplitParagraph();
|
|
99
|
+
return true;
|
|
100
|
+
},
|
|
101
|
+
"Shift-Enter": () => {
|
|
102
|
+
callbacks.onInsertHardBreak();
|
|
103
|
+
return true;
|
|
104
|
+
},
|
|
105
|
+
Tab: (state, dispatch, view) => {
|
|
106
|
+
if (isInTable(state)) {
|
|
107
|
+
return goToNextCell(1)(state, dispatch, view);
|
|
108
|
+
}
|
|
109
|
+
callbacks.onInsertTab();
|
|
110
|
+
return true;
|
|
111
|
+
},
|
|
112
|
+
"Shift-Tab": (state, dispatch, view) => {
|
|
113
|
+
if (isInTable(state)) {
|
|
114
|
+
return goToNextCell(-1)(state, dispatch, view);
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
},
|
|
118
|
+
"Mod-z": () => {
|
|
119
|
+
callbacks.onUndo();
|
|
120
|
+
return true;
|
|
121
|
+
},
|
|
122
|
+
"Mod-y": () => {
|
|
123
|
+
callbacks.onRedo();
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
"Shift-Mod-z": () => {
|
|
127
|
+
callbacks.onRedo();
|
|
128
|
+
return true;
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Table editing: provides Tab/Shift-Tab navigation between cells and
|
|
133
|
+
// selection handles. Doc-changing table transactions (new rows, etc.) are
|
|
134
|
+
// filtered by the runtime filter above; navigation-only steps pass through.
|
|
135
|
+
const tablePlugin = tableEditing();
|
|
136
|
+
const columnResizingPlugin = columnResizing();
|
|
137
|
+
|
|
138
|
+
return [filterPlugin, selectionPlugin, inputPlugin, keymapPlugin, tablePlugin, columnResizingPlugin];
|
|
139
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
2
|
+
|
|
3
|
+
import type { CommentDecorationModel } from "../../ui/headless/comment-decoration-model";
|
|
4
|
+
import { getCommentHighlightClass, type MarkupDisplay } from "../../ui/headless/comment-decoration-model";
|
|
5
|
+
import type { RevisionDecorationModel } from "../../ui/headless/revision-decoration-model";
|
|
6
|
+
import { getRevisionHighlightClass } from "../../ui/headless/revision-decoration-model";
|
|
7
|
+
import type { PositionMap } from "./pm-position-map";
|
|
8
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build ProseMirror DecorationSet from runtime comment and revision models.
|
|
12
|
+
*
|
|
13
|
+
* Uses the existing headless decoration models to compute Tailwind class
|
|
14
|
+
* strings, then converts them to PM inline decorations at the correct
|
|
15
|
+
* PM positions via the PositionMap.
|
|
16
|
+
*/
|
|
17
|
+
export function buildDecorations(
|
|
18
|
+
doc: PMNode,
|
|
19
|
+
positionMap: PositionMap,
|
|
20
|
+
commentModel: CommentDecorationModel | undefined,
|
|
21
|
+
revisionModel: RevisionDecorationModel | undefined,
|
|
22
|
+
markupDisplay: MarkupDisplay,
|
|
23
|
+
showTrackedChanges = true,
|
|
24
|
+
): DecorationSet {
|
|
25
|
+
const decorations: Decoration[] = [];
|
|
26
|
+
|
|
27
|
+
// Walk comment threads and create inline decorations
|
|
28
|
+
if (commentModel) {
|
|
29
|
+
for (const thread of commentModel.threads) {
|
|
30
|
+
const cls = getCommentHighlightClass(
|
|
31
|
+
commentModel,
|
|
32
|
+
thread.from,
|
|
33
|
+
thread.to,
|
|
34
|
+
markupDisplay,
|
|
35
|
+
);
|
|
36
|
+
if (!cls) continue;
|
|
37
|
+
|
|
38
|
+
const pmFrom = positionMap.runtimeToPm(thread.from);
|
|
39
|
+
const pmTo = positionMap.runtimeToPm(thread.to);
|
|
40
|
+
if (pmFrom < pmTo) {
|
|
41
|
+
decorations.push(
|
|
42
|
+
Decoration.inline(pmFrom, pmTo, {
|
|
43
|
+
class: cls,
|
|
44
|
+
"data-comment-id": thread.commentId,
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Walk revision entries and create inline decorations.
|
|
52
|
+
// Deletion hiding in clean mode ALWAYS applies, even when showTrackedChanges is off.
|
|
53
|
+
// Visual styling (underlines, colors) only applies when showTrackedChanges is on.
|
|
54
|
+
if (revisionModel) {
|
|
55
|
+
for (const rev of revisionModel.revisions) {
|
|
56
|
+
// Always hide deletions in clean mode (final-text semantics).
|
|
57
|
+
// This is the critical behavior: "hide tracked changes" must show
|
|
58
|
+
// the document as if accepted, not show deleted text as kept text.
|
|
59
|
+
if (markupDisplay === "clean" && rev.kind === "deletion") {
|
|
60
|
+
const pmFrom = positionMap.runtimeToPm(rev.from);
|
|
61
|
+
const pmTo = positionMap.runtimeToPm(rev.to);
|
|
62
|
+
if (pmFrom < pmTo) {
|
|
63
|
+
decorations.push(
|
|
64
|
+
Decoration.inline(pmFrom, pmTo, {
|
|
65
|
+
class: "hidden",
|
|
66
|
+
"data-revision-id": rev.revisionId,
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Skip visual styling when tracked changes display is off
|
|
74
|
+
if (!showTrackedChanges) continue;
|
|
75
|
+
|
|
76
|
+
const cls = getRevisionHighlightClass(
|
|
77
|
+
revisionModel,
|
|
78
|
+
rev.from,
|
|
79
|
+
rev.to,
|
|
80
|
+
markupDisplay,
|
|
81
|
+
);
|
|
82
|
+
if (!cls) continue;
|
|
83
|
+
|
|
84
|
+
const pmFrom = positionMap.runtimeToPm(rev.from);
|
|
85
|
+
const pmTo = positionMap.runtimeToPm(rev.to);
|
|
86
|
+
if (pmFrom < pmTo) {
|
|
87
|
+
decorations.push(
|
|
88
|
+
Decoration.inline(pmFrom, pmTo, {
|
|
89
|
+
class: cls,
|
|
90
|
+
"data-revision-id": rev.revisionId,
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return DecorationSet.create(doc, decorations);
|
|
98
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { EditorSurfaceSnapshot, SurfaceBlockSnapshot } from "../../api/public-types";
|
|
2
|
+
|
|
3
|
+
export interface PositionMap {
|
|
4
|
+
runtimeToPm(runtimePos: number): number;
|
|
5
|
+
pmToRuntime(pmPos: number): number;
|
|
6
|
+
pmDocSize: number;
|
|
7
|
+
runtimeStorySize: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface MapEntry {
|
|
11
|
+
runtimeStart: number;
|
|
12
|
+
pmStart: number;
|
|
13
|
+
runtimeEnd: number;
|
|
14
|
+
pmEnd: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function buildPositionMap(surface: EditorSurfaceSnapshot): PositionMap {
|
|
18
|
+
const entries: MapEntry[] = [];
|
|
19
|
+
const pmDocSize = walkBlocks(surface.blocks, 1, entries);
|
|
20
|
+
const runtimeStorySize = surface.storySize;
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
runtimeToPm(runtimePos: number): number {
|
|
24
|
+
if (runtimePos <= 0) {
|
|
25
|
+
return entries[0]?.pmStart ?? 1;
|
|
26
|
+
}
|
|
27
|
+
if (runtimePos >= runtimeStorySize) {
|
|
28
|
+
return pmDocSize - 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (runtimePos >= entry.runtimeStart && runtimePos <= entry.runtimeEnd) {
|
|
33
|
+
return entry.pmStart + (runtimePos - entry.runtimeStart);
|
|
34
|
+
}
|
|
35
|
+
if (runtimePos < entry.runtimeStart) {
|
|
36
|
+
return entry.pmStart;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return entries[entries.length - 1]?.pmEnd ?? 1;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
pmToRuntime(pmPos: number): number {
|
|
44
|
+
if (pmPos <= 1) {
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
if (pmPos >= pmDocSize - 1) {
|
|
48
|
+
return runtimeStorySize;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
if (pmPos >= entry.pmStart && pmPos <= entry.pmEnd) {
|
|
53
|
+
return entry.runtimeStart + (pmPos - entry.pmStart);
|
|
54
|
+
}
|
|
55
|
+
if (pmPos < entry.pmStart) {
|
|
56
|
+
return entry.runtimeStart;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return runtimeStorySize;
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
pmDocSize,
|
|
64
|
+
runtimeStorySize,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function walkBlocks(
|
|
69
|
+
blocks: SurfaceBlockSnapshot[],
|
|
70
|
+
pmCursor: number,
|
|
71
|
+
entries: MapEntry[],
|
|
72
|
+
): number {
|
|
73
|
+
let nextPmCursor = pmCursor;
|
|
74
|
+
|
|
75
|
+
for (const block of blocks) {
|
|
76
|
+
switch (block.kind) {
|
|
77
|
+
case "paragraph": {
|
|
78
|
+
const pmContentStart = nextPmCursor + 1;
|
|
79
|
+
const runtimeLength = block.to - block.from;
|
|
80
|
+
entries.push({
|
|
81
|
+
runtimeStart: block.from,
|
|
82
|
+
pmStart: pmContentStart,
|
|
83
|
+
runtimeEnd: block.to,
|
|
84
|
+
pmEnd: pmContentStart + runtimeLength,
|
|
85
|
+
});
|
|
86
|
+
nextPmCursor += runtimeLength + 2;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case "opaque_block": {
|
|
90
|
+
entries.push({
|
|
91
|
+
runtimeStart: block.from,
|
|
92
|
+
pmStart: nextPmCursor,
|
|
93
|
+
runtimeEnd: block.to,
|
|
94
|
+
pmEnd: nextPmCursor + 1,
|
|
95
|
+
});
|
|
96
|
+
nextPmCursor += 1;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case "sdt_block": {
|
|
100
|
+
nextPmCursor += 1;
|
|
101
|
+
nextPmCursor = walkBlocks(block.children, nextPmCursor, entries);
|
|
102
|
+
nextPmCursor += 1;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case "table": {
|
|
106
|
+
nextPmCursor += 1;
|
|
107
|
+
for (const row of block.rows) {
|
|
108
|
+
nextPmCursor += 1;
|
|
109
|
+
for (const cell of row.cells) {
|
|
110
|
+
nextPmCursor += 1;
|
|
111
|
+
nextPmCursor = walkBlocks(cell.content, nextPmCursor, entries);
|
|
112
|
+
nextPmCursor += 1;
|
|
113
|
+
}
|
|
114
|
+
nextPmCursor += 1;
|
|
115
|
+
}
|
|
116
|
+
nextPmCursor += 1;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return nextPmCursor;
|
|
123
|
+
}
|