@stll/folio-core 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +602 -50
- package/dist/ai-edits/block-identity.d.ts +4 -0
- package/dist/ai-edits/block-identity.js +9 -0
- package/dist/ai-edits/blockRange.d.ts +28 -1
- package/dist/ai-edits/blockRange.js +67 -1
- package/dist/ai-edits/headless.d.ts +4 -4
- package/dist/ai-edits/headless.js +9 -9
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.d.ts +7 -7
- package/dist/ai-edits/read.js +110 -3
- package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
- package/dist/ai-edits/table-cell-mutations.js +237 -0
- package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
- package/dist/ai-edits/table-mutation-plan.js +90 -0
- package/dist/ai-edits/table-row-column-mutations.d.ts +100 -0
- package/dist/ai-edits/table-row-column-mutations.js +300 -0
- package/dist/ai-edits/table-targets.d.ts +32 -0
- package/dist/ai-edits/table-targets.js +70 -0
- package/dist/ai-edits/types.d.ts +34 -0
- package/dist/compat/eigenpal.js +1 -1
- package/dist/content-controls/mutateContentControls.js +1 -1
- package/dist/controller/activeEditorStory.d.ts +36 -0
- package/dist/controller/activeEditorStory.js +30 -0
- package/dist/controller/collaborationModules.d.ts +7 -0
- package/dist/controller/collaborationModules.js +15 -0
- package/dist/controller/contentControlWidgetController.d.ts +55 -0
- package/dist/controller/contentControlWidgetController.js +141 -0
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/fontReadiness.js +2 -0
- package/dist/controller/headerFooterEditorManager.d.ts +41 -0
- package/dist/controller/headerFooterEditorManager.js +182 -0
- package/dist/controller/hiddenEditorApi.js +2 -2
- package/dist/controller/hiddenEditorManager.d.ts +13 -2
- package/dist/controller/hiddenEditorManager.js +32 -11
- package/dist/controller/layoutPipeline.d.ts +2 -0
- package/dist/controller/layoutPipeline.js +16 -1
- package/dist/controller/noteEditorManager.d.ts +36 -0
- package/dist/controller/noteEditorManager.js +210 -0
- package/dist/document-operations.d.ts +35 -3
- package/dist/document-operations.js +161 -3
- package/dist/docx/blockContentParser.js +2 -2
- package/dist/docx/commentParser.js +6 -1
- package/dist/docx/conformance.js +8 -1
- package/dist/docx/documentGrid.d.ts +8 -0
- package/dist/docx/documentGrid.js +8 -0
- package/dist/docx/drawingUtils.js +1 -1
- package/dist/docx/ensureParaIds.js +1 -1
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/notePropertiesParser.js +1 -1
- package/dist/docx/numberingParser.js +1 -1
- package/dist/docx/paragraphParser.js +63 -58
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/parser.js +3 -3
- package/dist/docx/rezip.js +1 -1
- package/dist/docx/runParser.js +4 -2
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sectionParser.js +1 -1
- package/dist/docx/selectiveSave.js +1 -1
- package/dist/docx/serializer/commentSerializer.js +1 -2
- package/dist/docx/serializer/documentSerializer.js +2 -2
- package/dist/docx/serializer/headerFooterSerializer.js +2 -2
- package/dist/docx/serializer/noteSerializer.js +2 -2
- package/dist/docx/serializer/paragraphSerializer.js +7 -1
- package/dist/docx/serializer/runSerializer.js +4 -2
- package/dist/docx/serializer/stylesSerializer.js +1 -1
- package/dist/docx/serializer/tableSerializer.d.ts +5 -4
- package/dist/docx/serializer/tableSerializer.js +17 -13
- package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
- package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
- package/dist/docx/server/boundedArchive.d.ts +14 -3
- package/dist/docx/server/boundedArchive.js +56 -11
- package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
- package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
- package/dist/docx/server/inspectDocxPackage.js +217 -0
- package/dist/docx/server/validateDocxConformance.d.ts +41 -0
- package/dist/docx/server/validateDocxConformance.js +336 -0
- package/dist/docx/settingsParser.js +11 -1
- package/dist/docx/shapeParser.js +1 -1
- package/dist/docx/styleParser.js +4 -2
- package/dist/docx/tableParser.js +18 -7
- package/dist/docx/textBoxParser.d.ts +3 -3
- package/dist/docx/textBoxParser.js +16 -12
- package/dist/docx/xmlSafety.d.ts +5 -0
- package/dist/docx/xmlSafety.js +9 -0
- package/dist/fields/resolveFieldValues.js +1 -3
- package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
- package/dist/i18n/messages/catalogs.gen.js +17 -0
- package/dist/i18n/messages/messages.gen.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
- package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +136 -20
- package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
- package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
- package/dist/layout-bridge/engine/clickToPosition.js +2 -2
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +43 -28
- package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
- package/dist/layout-engine/justificationCompatibility.js +8 -0
- package/dist/layout-engine/keep-together.js +11 -1
- package/dist/layout-engine/measure/cache.js +21 -5
- package/dist/layout-engine/measure/lineBreakProvider.js +53 -34
- package/dist/layout-engine/measure/measureBlocks.js +6 -3
- package/dist/layout-engine/measure/measureContainer.js +1 -1
- package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
- package/dist/layout-engine/measure/measureHelpers.js +3 -3
- package/dist/layout-engine/measure/measureParagraph.js +69 -25
- package/dist/layout-engine/measure/measureProvider.js +4 -3
- package/dist/layout-engine/measure/tableCellFlow.js +5 -2
- package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
- package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
- package/dist/layout-engine/paginator.js +5 -1
- package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
- package/dist/layout-engine/paragraphSpacing.js +107 -13
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +26 -13
- package/dist/layout-painter/registry/modules/textBox.js +5 -1
- package/dist/layout-painter/renderPage.d.ts +5 -2
- package/dist/layout-painter/renderPage.js +56 -12
- package/dist/layout-painter/renderParagraph.js +22 -6
- package/dist/layout-painter/renderTable.d.ts +5 -1
- package/dist/layout-painter/renderTable.js +5 -2
- package/dist/layout-painter/renderTextBox.d.ts +2 -1
- package/dist/layout-painter/renderTextBox.js +25 -14
- package/dist/managers/DocumentLoaderManager.js +1 -1
- package/dist/managers/FindReplaceManager.d.ts +8 -0
- package/dist/managers/FindReplaceManager.js +18 -0
- package/dist/managers/TableSelectionManager.d.ts +6 -0
- package/dist/managers/TableSelectionManager.js +14 -0
- package/dist/model.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +154 -18
- package/dist/prosemirror/commands/comments.d.ts +3 -3
- package/dist/prosemirror/commands/comments.js +248 -12
- package/dist/prosemirror/commands/contentControls.js +1 -1
- package/dist/prosemirror/commands/index.js +1 -1
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
- package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +286 -61
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
- package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/toProseDoc.js +347 -98
- package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
- package/dist/prosemirror/extensions/StarterKit.js +6 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +4 -1
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +24 -1
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +9 -3
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
- package/dist/prosemirror/findReplaceSelection.d.ts +6 -1
- package/dist/prosemirror/findReplaceSelection.js +57 -13
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +34 -8
- package/dist/prosemirror/plugins/contentControlWidgets.js +125 -91
- package/dist/prosemirror/plugins/selectionTracker.js +1 -0
- package/dist/prosemirror/plugins/suggestionMode.js +1 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +5 -1
- package/dist/prosemirror/schema/nodes.d.ts +64 -7
- package/dist/prosemirror/selectionState.js +1 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
- package/dist/prosemirror/tableCellMergeRevision.js +22 -0
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
- package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
- package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
- package/dist/prosemirror/validation.js +9 -1
- package/dist/render-dom/BodySelectionOverlay.d.ts +31 -0
- package/dist/render-dom/BodySelectionOverlay.js +76 -0
- package/dist/render-dom/HeaderFooterSelectionOverlay.d.ts +28 -0
- package/dist/render-dom/HeaderFooterSelectionOverlay.js +121 -0
- package/dist/render-dom/RemoteSelectionOverlay.d.ts +30 -0
- package/dist/render-dom/RemoteSelectionOverlay.js +67 -0
- package/dist/render-dom/RenderedDomContext.d.ts +40 -0
- package/dist/render-dom/RenderedDomContext.js +126 -0
- package/dist/render-dom/resolveSidebarItemPositions.d.ts +33 -0
- package/dist/render-dom/resolveSidebarItemPositions.js +45 -0
- package/dist/server.d.ts +6 -2
- package/dist/server.js +5 -1
- package/dist/utils/findReplace.d.ts +32 -0
- package/dist/utils/findReplace.js +118 -0
- package/dist/utils/fontFamilyMerge.js +9 -11
- package/dist/utils/fontLoader.js +3 -2
- package/dist/utils/fontResolver.js +22 -4
- package/dist/utils/fontWeights.d.ts +1 -1
- package/dist/utils/fontWeights.js +1 -1
- package/dist/utils/headerFooter.js +24 -1
- package/dist/utils/paragraphFormattingMerge.js +1 -0
- package/package.json +1 -1
|
@@ -41,7 +41,7 @@ import { SuperscriptExtension } from "./marks/SuperscriptExtension.js";
|
|
|
41
41
|
import { TextColorExtension } from "./marks/TextColorExtension.js";
|
|
42
42
|
import { TextEffectExtension } from "./marks/TextEffectExtension.js";
|
|
43
43
|
import { EmbossExtension, EmphasisMarkExtension, ImprintExtension, TextOutlineExtension, TextShadowExtension } from "./marks/TextEffectsExtensions.js";
|
|
44
|
-
import { DeletionExtension, InsertionExtension } from "./marks/TrackedChangeExtensions.js";
|
|
44
|
+
import { DeletionExtension, InsertionExtension, RunPropertyChangeExtension } from "./marks/TrackedChangeExtensions.js";
|
|
45
45
|
import { UnderlineExtension } from "./marks/UnderlineExtension.js";
|
|
46
46
|
import { BlockSdtExtension } from "./nodes/BlockSdtExtension.js";
|
|
47
47
|
import { FieldExtension } from "./nodes/FieldExtension.js";
|
|
@@ -50,10 +50,12 @@ import { HorizontalRuleExtension } from "./nodes/HorizontalRuleExtension.js";
|
|
|
50
50
|
import { ImageExtension } from "./nodes/ImageExtension.js";
|
|
51
51
|
import { MathExtension } from "./nodes/MathExtension.js";
|
|
52
52
|
import { PageBreakExtension } from "./nodes/PageBreakExtension.js";
|
|
53
|
+
import { RenderedPageBreakExtension } from "./nodes/RenderedPageBreakExtension.js";
|
|
53
54
|
import { SdtExtension } from "./nodes/SdtExtension.js";
|
|
54
55
|
import { ShapeExtension } from "./nodes/ShapeExtension.js";
|
|
55
56
|
import { TabExtension } from "./nodes/TabExtension.js";
|
|
56
57
|
import { TextBoxExtension } from "./nodes/TextBoxExtension.js";
|
|
58
|
+
import { TextBoxAnchorExtension } from "./nodes/TextBoxAnchorExtension.js";
|
|
57
59
|
//#region src/prosemirror/extensions/StarterKit.ts
|
|
58
60
|
/**
|
|
59
61
|
* Create the full set of extensions for the DOCX editor
|
|
@@ -101,10 +103,12 @@ function createStarterKit(options = {}) {
|
|
|
101
103
|
add("comment", CommentExtension());
|
|
102
104
|
add("insertion", InsertionExtension());
|
|
103
105
|
add("deletion", DeletionExtension());
|
|
106
|
+
add("runPropertyChange", RunPropertyChangeExtension());
|
|
104
107
|
add("hardBreak", HardBreakExtension());
|
|
105
108
|
add("tab", TabExtension());
|
|
106
109
|
add("image", ImageExtension());
|
|
107
110
|
add("textBox", TextBoxExtension());
|
|
111
|
+
add("textBoxAnchor", TextBoxAnchorExtension());
|
|
108
112
|
add("shape", ShapeExtension());
|
|
109
113
|
add("imageDrag", ImageDragExtension());
|
|
110
114
|
add("imagePaste", ImagePasteExtension());
|
|
@@ -112,6 +116,7 @@ function createStarterKit(options = {}) {
|
|
|
112
116
|
add("gapCursor", GapCursorExtension());
|
|
113
117
|
add("horizontalRule", HorizontalRuleExtension());
|
|
114
118
|
add("pageBreak", PageBreakExtension());
|
|
119
|
+
add("renderedPageBreak", RenderedPageBreakExtension());
|
|
115
120
|
add("field", FieldExtension());
|
|
116
121
|
add("sdt", SdtExtension());
|
|
117
122
|
add("blockSdt", BlockSdtExtension());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { autospacingMatchesBase } from "../../autospacingBase.js";
|
|
2
1
|
import { directionIsRtl } from "../../paragraphDirection.js";
|
|
3
2
|
import { expectParagraphAttrs } from "../../attrs/index.js";
|
|
3
|
+
import { autospacingMatchesBase } from "../../autospacingBase.js";
|
|
4
4
|
import { createNodeExtension } from "../create.js";
|
|
5
5
|
import { paragraphToStyle } from "../../../utils/formatToStyle.js";
|
|
6
6
|
import { collectHeadings } from "../../../utils/headingCollector.js";
|
|
@@ -187,8 +187,10 @@ const paragraphNodeSpec = {
|
|
|
187
187
|
spaceAfter: { default: null },
|
|
188
188
|
lineSpacing: { default: null },
|
|
189
189
|
lineSpacingRule: { default: null },
|
|
190
|
+
snapToGrid: { default: null },
|
|
190
191
|
spacingExplicit: { default: null },
|
|
191
192
|
spacingFromDocDefaults: { default: null },
|
|
193
|
+
spacingFromImplicitDefaultStyle: { default: null },
|
|
192
194
|
indentLeft: { default: null },
|
|
193
195
|
indentRight: { default: null },
|
|
194
196
|
indentFirstLine: { default: null },
|
|
@@ -219,6 +221,7 @@ const paragraphNodeSpec = {
|
|
|
219
221
|
pageBreakBefore: { default: null },
|
|
220
222
|
renderedPageBreakBefore: { default: null },
|
|
221
223
|
_pageBreakCarrier: { default: null },
|
|
224
|
+
_trailingPageBreak: { default: null },
|
|
222
225
|
keepNext: { default: null },
|
|
223
226
|
keepLines: { default: null },
|
|
224
227
|
widowControl: { default: null },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PPR_CHANGE_SCOPED_ATTR_KEYS } from "../../commands/propertyChangeScope.js";
|
|
2
1
|
import { Priority } from "../types.js";
|
|
3
2
|
import { createExtension } from "../create.js";
|
|
4
3
|
import { SUGGESTION_META, makeRevisionInfo } from "../../plugins/suggestionMode.js";
|
|
4
|
+
import { PPR_CHANGE_SCOPED_ATTR_KEYS } from "../../commands/propertyChangeScope.js";
|
|
5
5
|
import { goToNextCell, goToPrevCell } from "../nodes/TableExtension.js";
|
|
6
6
|
//#region src/prosemirror/extensions/features/ListExtension.ts
|
|
7
7
|
function chainCommands(...commands) {
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { Extension } from "../types.js";
|
|
2
2
|
import { EditorState, PluginKey } from "prosemirror-state";
|
|
3
|
+
import { Node } from "prosemirror-model";
|
|
3
4
|
|
|
4
5
|
//#region src/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts
|
|
5
6
|
declare const paraIdAllocatorKey: PluginKey<any>;
|
|
7
|
+
/**
|
|
8
|
+
* Allocate initial paragraph IDs before constructing editor state.
|
|
9
|
+
*
|
|
10
|
+
* Rebuilding only changed branches avoids applying one ProseMirror transaction
|
|
11
|
+
* step per missing paragraph. Live edits still use the transaction-based plugin
|
|
12
|
+
* below so history, mappings, and duplicate ownership retain their semantics.
|
|
13
|
+
*/
|
|
14
|
+
declare const ensureParaIdsInDoc: (doc: Node) => Node;
|
|
6
15
|
declare const ensureParaIdsInState: (state: EditorState) => EditorState;
|
|
7
16
|
declare const ParaIdAllocatorExtension: (options?: Partial<{}> | undefined) => Extension;
|
|
8
17
|
//#endregion
|
|
9
|
-
export { ParaIdAllocatorExtension, ensureParaIdsInState, paraIdAllocatorKey };
|
|
18
|
+
export { ParaIdAllocatorExtension, ensureParaIdsInDoc, ensureParaIdsInState, paraIdAllocatorKey };
|
|
@@ -1,8 +1,46 @@
|
|
|
1
|
-
import { generateHexId } from "../../../utils/hexId.js";
|
|
2
1
|
import { createExtension } from "../create.js";
|
|
3
2
|
import { ignoreTrackedChanges } from "./ParagraphChangeTrackerExtension.js";
|
|
3
|
+
import { generateHexId } from "../../../utils/hexId.js";
|
|
4
|
+
import { Fragment } from "prosemirror-model";
|
|
4
5
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
5
6
|
//#region src/prosemirror/extensions/features/ParaIdAllocatorExtension.ts
|
|
7
|
+
/**
|
|
8
|
+
* ParaIdAllocator — assigns a stable `w14:paraId` to every paragraph.
|
|
9
|
+
*
|
|
10
|
+
* Lifted from
|
|
11
|
+
* https://github.com/eigenpal/docx-editor/blob/main/packages/core/src/prosemirror/extensions/features/ParaIdAllocatorExtension.ts
|
|
12
|
+
* (Apache-2.0). Adapted to folio's `createExtension` + import style;
|
|
13
|
+
* keep behaviour in sync upstream. folio divergences: duplicate
|
|
14
|
+
* resolution maps the original paragraph's position through the
|
|
15
|
+
* transaction (see below), and the appended allocation transaction is
|
|
16
|
+
* excluded from paragraph change tracking like `ensureParaIdsInState`.
|
|
17
|
+
*
|
|
18
|
+
* Why: AI tooling, chat citation chips, and the change tracker all
|
|
19
|
+
* anchor on `paraId`. A paragraph with `paraId: null` is invisible
|
|
20
|
+
* to those surfaces; a duplicated paraId (the second half of an
|
|
21
|
+
* Enter-split, or content pasted from another doc) silently desyncs
|
|
22
|
+
* their anchors. This plugin closes both gaps by allocating fresh
|
|
23
|
+
* ids in an `appendTransaction` hook after every doc-changed step.
|
|
24
|
+
*
|
|
25
|
+
* Id lifecycle rules (locked by the co-located tests):
|
|
26
|
+
* - Missing/empty/reserved-zero id: a fresh random id is minted.
|
|
27
|
+
* - Split: the half holding the paragraph's original start position
|
|
28
|
+
* keeps the id; the other half gets a fresh one. Anchors inside the
|
|
29
|
+
* content stay resolvable on the half that carries them.
|
|
30
|
+
* - Merge/join: the surviving paragraph keeps its id; the absorbed id
|
|
31
|
+
* dangles by design (consumers degrade to snapshot fallback).
|
|
32
|
+
* - Paste/duplicate carrying an id already in the doc: the paragraph
|
|
33
|
+
* whose mapped pre-transaction position matches keeps it — pasting a
|
|
34
|
+
* copy above its source no longer steals the source's id. When no
|
|
35
|
+
* occurrence maps back (e.g. both are new), the first in document
|
|
36
|
+
* order keeps it.
|
|
37
|
+
* - Paste of an id unknown to this doc (cross-doc paste, cut-then-
|
|
38
|
+
* paste move): the id is kept, so a moved paragraph stays anchored.
|
|
39
|
+
* - Undo/redo: allocation applies with `addToHistory: false`, and
|
|
40
|
+
* ProseMirror remaps it into the originating history event. Redoing a
|
|
41
|
+
* split therefore restores the same allocated id instead of minting
|
|
42
|
+
* another one.
|
|
43
|
+
*/
|
|
6
44
|
const paraIdAllocatorKey = new PluginKey("paraIdAllocator");
|
|
7
45
|
const isUsableParaId = (value) => typeof value === "string" && value.length > 0 && value !== "00000000";
|
|
8
46
|
/**
|
|
@@ -76,6 +114,59 @@ const collectParaIdUpdates = (doc, keeperPositions) => {
|
|
|
76
114
|
updates.sort((a, b) => a.pos - b.pos);
|
|
77
115
|
return updates;
|
|
78
116
|
};
|
|
117
|
+
const collectInitialParaIds = (doc) => {
|
|
118
|
+
let needsRewrite = false;
|
|
119
|
+
const taken = /* @__PURE__ */ new Set();
|
|
120
|
+
doc.descendants((node) => {
|
|
121
|
+
if (node.type.name !== "paragraph") return true;
|
|
122
|
+
const id = node.attrs["paraId"];
|
|
123
|
+
if (!isUsableParaId(id) || taken.has(id)) needsRewrite = true;
|
|
124
|
+
else taken.add(id);
|
|
125
|
+
return false;
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
needsRewrite,
|
|
129
|
+
taken
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
const rewriteInitialParaIds = (parent, taken, seen) => {
|
|
133
|
+
let changed = false;
|
|
134
|
+
const children = [];
|
|
135
|
+
parent.forEach((child) => {
|
|
136
|
+
let next = child;
|
|
137
|
+
if (child.type.name === "paragraph") {
|
|
138
|
+
const id = child.attrs["paraId"];
|
|
139
|
+
if (!isUsableParaId(id) || seen.has(id)) {
|
|
140
|
+
let newId = generateHexId();
|
|
141
|
+
while (taken.has(newId)) newId = generateHexId();
|
|
142
|
+
taken.add(newId);
|
|
143
|
+
seen.add(newId);
|
|
144
|
+
next = child.type.create({
|
|
145
|
+
...child.attrs,
|
|
146
|
+
paraId: newId
|
|
147
|
+
}, child.content, child.marks);
|
|
148
|
+
} else seen.add(id);
|
|
149
|
+
} else if (child.childCount > 0) {
|
|
150
|
+
const content = rewriteInitialParaIds(child, taken, seen);
|
|
151
|
+
if (content !== child.content) next = child.copy(content);
|
|
152
|
+
}
|
|
153
|
+
if (next !== child) changed = true;
|
|
154
|
+
children.push(next);
|
|
155
|
+
});
|
|
156
|
+
return changed ? Fragment.fromArray(children) : parent.content;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Allocate initial paragraph IDs before constructing editor state.
|
|
160
|
+
*
|
|
161
|
+
* Rebuilding only changed branches avoids applying one ProseMirror transaction
|
|
162
|
+
* step per missing paragraph. Live edits still use the transaction-based plugin
|
|
163
|
+
* below so history, mappings, and duplicate ownership retain their semantics.
|
|
164
|
+
*/
|
|
165
|
+
const ensureParaIdsInDoc = (doc) => {
|
|
166
|
+
const { needsRewrite, taken } = collectInitialParaIds(doc);
|
|
167
|
+
if (!needsRewrite) return doc;
|
|
168
|
+
return doc.copy(rewriteInitialParaIds(doc, taken, /* @__PURE__ */ new Set()));
|
|
169
|
+
};
|
|
79
170
|
const ensureParaIdsInState = (state) => {
|
|
80
171
|
const updates = collectParaIdUpdates(state.doc);
|
|
81
172
|
if (updates.length === 0) return state;
|
|
@@ -109,4 +200,4 @@ const ParaIdAllocatorExtension = createExtension({
|
|
|
109
200
|
}
|
|
110
201
|
});
|
|
111
202
|
//#endregion
|
|
112
|
-
export { ParaIdAllocatorExtension, ensureParaIdsInState, paraIdAllocatorKey };
|
|
203
|
+
export { ParaIdAllocatorExtension, ensureParaIdsInDoc, ensureParaIdsInState, paraIdAllocatorKey };
|
|
@@ -30,6 +30,7 @@ declare function hasUntrackedChanges(state: EditorState): boolean;
|
|
|
30
30
|
*/
|
|
31
31
|
declare function clearTrackedChanges(state: EditorState): Transaction;
|
|
32
32
|
declare function ignoreTrackedChanges(tr: Transaction): Transaction;
|
|
33
|
+
declare function markStructuralChange(tr: Transaction): Transaction;
|
|
33
34
|
declare const ParagraphChangeTrackerExtension: (options?: Partial<{}> | undefined) => Extension;
|
|
34
35
|
//#endregion
|
|
35
|
-
export { ParagraphChangeTrackerExtension, ParagraphChangeTrackerState, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, paragraphChangeTrackerKey };
|
|
36
|
+
export { ParagraphChangeTrackerExtension, ParagraphChangeTrackerState, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, markStructuralChange, paragraphChangeTrackerKey };
|
|
@@ -12,6 +12,7 @@ import { AddMarkStep, AddNodeMarkStep, RemoveMarkStep, RemoveNodeMarkStep } from
|
|
|
12
12
|
const paragraphChangeTrackerKey = new PluginKey("paragraphChangeTracker");
|
|
13
13
|
const CLEAR_META = "clear";
|
|
14
14
|
const IGNORE_META = "ignore";
|
|
15
|
+
const STRUCTURAL_META = "structural";
|
|
15
16
|
/**
|
|
16
17
|
* Count paragraph nodes in a ProseMirror document
|
|
17
18
|
*/
|
|
@@ -103,7 +104,7 @@ function createParagraphChangeTrackerPlugin() {
|
|
|
103
104
|
const newCount = countParagraphs(tr.doc);
|
|
104
105
|
const newState = {
|
|
105
106
|
changedParaIds: new Set(prevState.changedParaIds),
|
|
106
|
-
structuralChange: prevState.structuralChange,
|
|
107
|
+
structuralChange: prevState.structuralChange || meta === STRUCTURAL_META,
|
|
107
108
|
hasUntrackedChanges: prevState.hasUntrackedChanges,
|
|
108
109
|
paragraphCount: newCount
|
|
109
110
|
};
|
|
@@ -177,6 +178,9 @@ function clearTrackedChanges(state) {
|
|
|
177
178
|
function ignoreTrackedChanges(tr) {
|
|
178
179
|
return tr.setMeta(paragraphChangeTrackerKey, IGNORE_META);
|
|
179
180
|
}
|
|
181
|
+
function markStructuralChange(tr) {
|
|
182
|
+
return tr.setMeta(paragraphChangeTrackerKey, STRUCTURAL_META);
|
|
183
|
+
}
|
|
180
184
|
const ParagraphChangeTrackerExtension = createExtension({
|
|
181
185
|
name: "paragraphChangeTracker",
|
|
182
186
|
defaultOptions: {},
|
|
@@ -185,4 +189,4 @@ const ParagraphChangeTrackerExtension = createExtension({
|
|
|
185
189
|
}
|
|
186
190
|
});
|
|
187
191
|
//#endregion
|
|
188
|
-
export { ParagraphChangeTrackerExtension, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, paragraphChangeTrackerKey };
|
|
192
|
+
export { ParagraphChangeTrackerExtension, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, markStructuralChange, paragraphChangeTrackerKey };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { formatPx, twipsToPixels } from "../../../utils/units.js";
|
|
2
1
|
import { expectCharacterSpacingMarkAttrs } from "../../attrs/index.js";
|
|
2
|
+
import { formatPx, twipsToPixels } from "../../../utils/units.js";
|
|
3
3
|
import { createMarkExtension } from "../create.js";
|
|
4
4
|
//#region src/prosemirror/extensions/marks/CharacterSpacingExtension.ts
|
|
5
5
|
/**
|
|
@@ -18,5 +18,13 @@ declare const InsertionExtension: (options?: Partial<Record<string, unknown>> |
|
|
|
18
18
|
* Renders with per-author colored strikethrough.
|
|
19
19
|
*/
|
|
20
20
|
declare const DeletionExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
|
|
21
|
+
/**
|
|
22
|
+
* Run property change — formatting changed while review tracking was active.
|
|
23
|
+
*
|
|
24
|
+
* The current formatting remains represented by the normal formatting marks;
|
|
25
|
+
* this mark carries the previous run properties and revision metadata needed
|
|
26
|
+
* to serialize, list, accept, and reject the change.
|
|
27
|
+
*/
|
|
28
|
+
declare const RunPropertyChangeExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
|
|
21
29
|
//#endregion
|
|
22
|
-
export { DeletionExtension, InsertionExtension };
|
|
30
|
+
export { DeletionExtension, InsertionExtension, RunPropertyChangeExtension };
|
|
@@ -109,5 +109,28 @@ const DeletionExtension = createMarkExtension({
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
|
+
/**
|
|
113
|
+
* Run property change — formatting changed while review tracking was active.
|
|
114
|
+
*
|
|
115
|
+
* The current formatting remains represented by the normal formatting marks;
|
|
116
|
+
* this mark carries the previous run properties and revision metadata needed
|
|
117
|
+
* to serialize, list, accept, and reject the change.
|
|
118
|
+
*/
|
|
119
|
+
const RunPropertyChangeExtension = createMarkExtension({
|
|
120
|
+
name: "runPropertyChange",
|
|
121
|
+
schemaMarkName: "runPropertyChange",
|
|
122
|
+
markSpec: {
|
|
123
|
+
attrs: { changes: { default: [] } },
|
|
124
|
+
inclusive: false,
|
|
125
|
+
parseDOM: [{ tag: "span.docx-run-property-change" }],
|
|
126
|
+
toDOM() {
|
|
127
|
+
return [
|
|
128
|
+
"span",
|
|
129
|
+
{ class: "docx-run-property-change" },
|
|
130
|
+
0
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
112
135
|
//#endregion
|
|
113
|
-
export { DeletionExtension, InsertionExtension };
|
|
136
|
+
export { DeletionExtension, InsertionExtension, RunPropertyChangeExtension };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parseFieldInstruction } from "../../../docx/fieldParser.js";
|
|
2
1
|
import { expectFieldAttrs } from "../../attrs/index.js";
|
|
3
2
|
import { createNodeExtension } from "../create.js";
|
|
3
|
+
import { parseFieldInstruction } from "../../../docx/fieldParser.js";
|
|
4
4
|
//#region src/prosemirror/extensions/nodes/FieldExtension.ts
|
|
5
5
|
/**
|
|
6
6
|
* Field Extension — inline field node (PAGE, NUMPAGES, DATE, MERGEFIELD, etc.)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { NodeExtension } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts
|
|
4
|
+
/** Zero-width cached pagination boundary preserved from DOCX. */
|
|
5
|
+
declare const RenderedPageBreakExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { RenderedPageBreakExtension };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createNodeExtension } from "../create.js";
|
|
2
|
+
//#region src/prosemirror/extensions/nodes/RenderedPageBreakExtension.ts
|
|
3
|
+
/** Zero-width cached pagination boundary preserved from DOCX. */
|
|
4
|
+
const RenderedPageBreakExtension = createNodeExtension({
|
|
5
|
+
name: "renderedPageBreak",
|
|
6
|
+
schemaNodeName: "renderedPageBreak",
|
|
7
|
+
nodeSpec: {
|
|
8
|
+
inline: true,
|
|
9
|
+
group: "inline",
|
|
10
|
+
atom: true,
|
|
11
|
+
selectable: false,
|
|
12
|
+
parseDOM: [{ tag: "span[data-docx-rendered-page-break]" }],
|
|
13
|
+
toDOM() {
|
|
14
|
+
return ["span", {
|
|
15
|
+
"data-docx-rendered-page-break": "true",
|
|
16
|
+
style: "display: none;"
|
|
17
|
+
}];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
//#endregion
|
|
22
|
+
export { RenderedPageBreakExtension };
|
|
@@ -3,8 +3,8 @@ import { expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, mergeTable
|
|
|
3
3
|
import { createExtension, createNodeExtension } from "../create.js";
|
|
4
4
|
import { resolveColor } from "../../../utils/colorResolver.js";
|
|
5
5
|
import { panic } from "better-result";
|
|
6
|
-
import { Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
7
6
|
import { CellSelection, TableMap, columnResizing, mergeCells, removeRow, selectedRect, splitCell, tableEditing } from "prosemirror-tables";
|
|
7
|
+
import { Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
8
8
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
9
9
|
//#region src/prosemirror/extensions/nodes/TableExtension.ts
|
|
10
10
|
/**
|
|
@@ -190,7 +190,7 @@ const tableSpec = {
|
|
|
190
190
|
}
|
|
191
191
|
};
|
|
192
192
|
const tableRowSpec = {
|
|
193
|
-
content: "(tableCell | tableHeader)
|
|
193
|
+
content: "(tableCell | tableHeader)*",
|
|
194
194
|
tableRole: "row",
|
|
195
195
|
attrs: {
|
|
196
196
|
height: { default: null },
|
|
@@ -198,7 +198,9 @@ const tableRowSpec = {
|
|
|
198
198
|
isHeader: { default: false },
|
|
199
199
|
hidden: { default: false },
|
|
200
200
|
_originalFormatting: { default: null },
|
|
201
|
-
trPrChange: { default: null }
|
|
201
|
+
trPrChange: { default: null },
|
|
202
|
+
trIns: { default: null },
|
|
203
|
+
trDel: { default: null }
|
|
202
204
|
},
|
|
203
205
|
parseDOM: [{ tag: "tr" }],
|
|
204
206
|
toDOM(node) {
|
|
@@ -315,8 +317,10 @@ const tableCellSpec = {
|
|
|
315
317
|
margins: { default: null },
|
|
316
318
|
textDirection: { default: null },
|
|
317
319
|
noWrap: { default: false },
|
|
320
|
+
hideMark: { default: false },
|
|
318
321
|
_originalFormatting: { default: null },
|
|
319
322
|
tcPrChange: { default: null },
|
|
323
|
+
cellMarker: { default: null },
|
|
320
324
|
_preserveVMergeRestart: { default: null },
|
|
321
325
|
_docxVMergeContinuationCells: { default: null }
|
|
322
326
|
},
|
|
@@ -369,8 +373,10 @@ const tableHeaderSpec = {
|
|
|
369
373
|
margins: { default: null },
|
|
370
374
|
textDirection: { default: null },
|
|
371
375
|
noWrap: { default: false },
|
|
376
|
+
hideMark: { default: false },
|
|
372
377
|
_originalFormatting: { default: null },
|
|
373
378
|
tcPrChange: { default: null },
|
|
379
|
+
cellMarker: { default: null },
|
|
374
380
|
_preserveVMergeRestart: { default: null },
|
|
375
381
|
_docxVMergeContinuationCells: { default: null }
|
|
376
382
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NodeExtension } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Zero-width inline anchor for a text box extracted to a sibling PM block.
|
|
6
|
+
*
|
|
7
|
+
* Keeping the anchor in the paragraph lets ordinary ProseMirror transactions
|
|
8
|
+
* map its position as surrounding text is edited. The save conversion consumes
|
|
9
|
+
* it when the sibling text box is restored to the DOCX run stream.
|
|
10
|
+
*/
|
|
11
|
+
declare const TextBoxAnchorExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { TextBoxAnchorExtension };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expectTextBoxAnchorAttrs } from "../../textBoxAnchorAttrs.js";
|
|
2
|
+
import { createNodeExtension } from "../create.js";
|
|
3
|
+
//#region src/prosemirror/extensions/nodes/TextBoxAnchorExtension.ts
|
|
4
|
+
/**
|
|
5
|
+
* Zero-width inline anchor for a text box extracted to a sibling PM block.
|
|
6
|
+
*
|
|
7
|
+
* Keeping the anchor in the paragraph lets ordinary ProseMirror transactions
|
|
8
|
+
* map its position as surrounding text is edited. The save conversion consumes
|
|
9
|
+
* it when the sibling text box is restored to the DOCX run stream.
|
|
10
|
+
*/
|
|
11
|
+
const TextBoxAnchorExtension = createNodeExtension({
|
|
12
|
+
name: "textBoxAnchor",
|
|
13
|
+
schemaNodeName: "textBoxAnchor",
|
|
14
|
+
nodeSpec: {
|
|
15
|
+
inline: true,
|
|
16
|
+
group: "inline",
|
|
17
|
+
marks: "_",
|
|
18
|
+
atom: true,
|
|
19
|
+
selectable: false,
|
|
20
|
+
attrs: { anchorId: {} },
|
|
21
|
+
parseDOM: [{
|
|
22
|
+
tag: "span[data-docx-textbox-anchor]",
|
|
23
|
+
getAttrs(dom) {
|
|
24
|
+
if (!(dom instanceof HTMLElement)) return false;
|
|
25
|
+
const anchorId = dom.dataset["docxTextboxAnchor"];
|
|
26
|
+
return anchorId ? { anchorId } : false;
|
|
27
|
+
}
|
|
28
|
+
}],
|
|
29
|
+
toDOM(node) {
|
|
30
|
+
const { anchorId } = expectTextBoxAnchorAttrs(node);
|
|
31
|
+
return ["span", {
|
|
32
|
+
"data-docx-textbox-anchor": anchorId,
|
|
33
|
+
"aria-hidden": "true",
|
|
34
|
+
contenteditable: "false",
|
|
35
|
+
style: "display: inline-block; width: 0; height: 0; overflow: hidden; pointer-events: none;"
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { TextBoxAnchorExtension };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../../../types/document.js";
|
|
2
2
|
import { OutlineStyleAttr } from "../../../types/documentEnumValues.js";
|
|
3
3
|
import { NodeExtension } from "../types.js";
|
|
4
|
-
import { ImagePositionAttrs } from "../../schema/nodes.js";
|
|
4
|
+
import { ImagePositionAttrs, TextBoxAttrs as TextBoxAttrs$1 } from "../../schema/nodes.js";
|
|
5
5
|
|
|
6
6
|
//#region src/prosemirror/extensions/nodes/TextBoxExtension.d.ts
|
|
7
7
|
type TextBoxAttrs = {
|
|
@@ -28,7 +28,10 @@ type TextBoxAttrs = {
|
|
|
28
28
|
distRight?: number; /** Position for floating/anchored text boxes. */
|
|
29
29
|
position?: ImagePositionAttrs; /** Original DOCX placement hint for save-path reconstruction. */
|
|
30
30
|
_docxPlacement?: "standalone" | "inlineWithPrevious"; /** Original DOCX paragraph group for standalone text-box reconstruction. */
|
|
31
|
-
_docxGroupId?: string;
|
|
31
|
+
_docxGroupId?: string; /** Inline anchor linking this block node to its source run position. */
|
|
32
|
+
_docxAnchorId?: string; /** Original run-level revision wrapper for save-path reconstruction. */
|
|
33
|
+
_docxTrackedChange?: TextBoxAttrs$1["_docxTrackedChange"]; /** Original inline content-control ancestry for save-path reconstruction. */
|
|
34
|
+
_docxInlineSdts?: TextBoxAttrs$1["_docxInlineSdts"];
|
|
32
35
|
};
|
|
33
36
|
declare const TextBoxExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
|
|
34
37
|
//#endregion
|
|
@@ -50,7 +50,10 @@ const TextBoxExtension = createNodeExtension({
|
|
|
50
50
|
distRight: { default: null },
|
|
51
51
|
position: { default: null },
|
|
52
52
|
_docxPlacement: { default: null },
|
|
53
|
-
_docxGroupId: { default: null }
|
|
53
|
+
_docxGroupId: { default: null },
|
|
54
|
+
_docxAnchorId: { default: null },
|
|
55
|
+
_docxTrackedChange: { default: null },
|
|
56
|
+
_docxInlineSdts: { default: null }
|
|
54
57
|
},
|
|
55
58
|
parseDOM: [{
|
|
56
59
|
tag: "div.docx-textbox",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FindOptions } from "../utils/findReplace.js";
|
|
1
2
|
import { Node } from "prosemirror-model";
|
|
2
3
|
|
|
3
4
|
//#region src/prosemirror/findReplaceSelection.d.ts
|
|
@@ -18,6 +19,10 @@ type FindMatchRange = {
|
|
|
18
19
|
from: number;
|
|
19
20
|
to: number;
|
|
20
21
|
};
|
|
22
|
+
type ProseMirrorFindMatch = FindMatchPosition & FindMatchRange & {
|
|
23
|
+
text: string;
|
|
24
|
+
};
|
|
21
25
|
declare function resolveFindMatchRange(doc: Node, match: FindMatchPosition): FindMatchRange | null;
|
|
26
|
+
declare function findInProseMirrorDocument(doc: Node, searchText: string, options: FindOptions): ProseMirrorFindMatch[];
|
|
22
27
|
//#endregion
|
|
23
|
-
export { FindMatchPosition, FindMatchRange, resolveFindMatchRange };
|
|
28
|
+
export { FindMatchPosition, FindMatchRange, ProseMirrorFindMatch, findInProseMirrorDocument, resolveFindMatchRange };
|
|
@@ -1,29 +1,55 @@
|
|
|
1
|
+
import { findAllMatches } from "../utils/findReplace.js";
|
|
1
2
|
//#region src/prosemirror/findReplaceSelection.ts
|
|
2
3
|
function resolveFindMatchRange(doc, match) {
|
|
3
|
-
let paragraphIndex = 0;
|
|
4
4
|
let resolved = null;
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
if (paragraphIndex !== match.paragraphIndex) {
|
|
8
|
-
paragraphIndex++;
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
5
|
+
forEachSearchParagraph(doc, (paragraph, paragraphPos, paragraphIndex) => {
|
|
6
|
+
if (paragraphIndex !== match.paragraphIndex) return true;
|
|
11
7
|
resolved = resolveTextRangeInParagraph({
|
|
12
|
-
paragraph
|
|
13
|
-
paragraphPos
|
|
8
|
+
paragraph,
|
|
9
|
+
paragraphPos,
|
|
14
10
|
startOffset: match.startOffset,
|
|
15
11
|
endOffset: match.endOffset
|
|
16
12
|
});
|
|
17
13
|
return false;
|
|
18
|
-
};
|
|
14
|
+
});
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
function findInProseMirrorDocument(doc, searchText, options) {
|
|
18
|
+
if (!searchText) return [];
|
|
19
|
+
const matches = [];
|
|
20
|
+
forEachSearchParagraph(doc, (paragraph, paragraphPos, paragraphIndex) => {
|
|
21
|
+
const text = getSearchableParagraphText(paragraph);
|
|
22
|
+
for (const { start, end } of findAllMatches(text, searchText, options)) {
|
|
23
|
+
const range = resolveTextRangeInParagraph({
|
|
24
|
+
paragraph,
|
|
25
|
+
paragraphPos,
|
|
26
|
+
startOffset: start,
|
|
27
|
+
endOffset: end
|
|
28
|
+
});
|
|
29
|
+
if (range) matches.push({
|
|
30
|
+
paragraphIndex,
|
|
31
|
+
startOffset: start,
|
|
32
|
+
endOffset: end,
|
|
33
|
+
text: text.slice(start, end),
|
|
34
|
+
...range
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
});
|
|
39
|
+
return matches;
|
|
40
|
+
}
|
|
41
|
+
function forEachSearchParagraph(doc, visit) {
|
|
42
|
+
let paragraphIndex = 0;
|
|
19
43
|
const walkBlocks = (container, contentStart) => {
|
|
20
44
|
let offset = 0;
|
|
21
45
|
for (let childIndex = 0; childIndex < container.childCount; childIndex++) {
|
|
22
46
|
const child = container.child(childIndex);
|
|
23
47
|
const childPos = contentStart + offset;
|
|
24
48
|
if (child.type.name === "paragraph") {
|
|
25
|
-
if (!
|
|
49
|
+
if (!visit(child, childPos, paragraphIndex)) return false;
|
|
50
|
+
paragraphIndex++;
|
|
26
51
|
} else if (child.type.name === "table" && !walkTable(child, childPos)) return false;
|
|
52
|
+
else if (child.type.name === "blockSdt" && !walkBlocks(child, childPos + 1)) return false;
|
|
27
53
|
offset += child.nodeSize;
|
|
28
54
|
}
|
|
29
55
|
return true;
|
|
@@ -53,7 +79,6 @@ function resolveFindMatchRange(doc, match) {
|
|
|
53
79
|
return true;
|
|
54
80
|
};
|
|
55
81
|
walkBlocks(doc, 0);
|
|
56
|
-
return resolved;
|
|
57
82
|
}
|
|
58
83
|
function resolveTextRangeInParagraph({ paragraph, paragraphPos, startOffset, endOffset }) {
|
|
59
84
|
let textOffset = 0;
|
|
@@ -83,5 +108,24 @@ function getSearchTextTokenLength(node) {
|
|
|
83
108
|
if (node.type.name === "tab" || node.type.name === "hardBreak") return 1;
|
|
84
109
|
return 0;
|
|
85
110
|
}
|
|
111
|
+
function getSearchableParagraphText(paragraph) {
|
|
112
|
+
let text = "";
|
|
113
|
+
paragraph.descendants((node) => {
|
|
114
|
+
if (node.isText) {
|
|
115
|
+
text += node.text ?? "";
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (node.type.name === "tab") {
|
|
119
|
+
text += " ";
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (node.type.name === "hardBreak") {
|
|
123
|
+
text += "\n";
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
});
|
|
128
|
+
return text;
|
|
129
|
+
}
|
|
86
130
|
//#endregion
|
|
87
|
-
export { resolveFindMatchRange };
|
|
131
|
+
export { findInProseMirrorDocument, resolveFindMatchRange };
|