@stll/folio-core 0.54.2 → 0.56.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 +185 -33
- package/dist/ai-edits/headless.js +3 -2
- package/dist/ai-edits/types.d.ts +7 -1
- package/dist/compare/compare.js +1 -0
- package/dist/compare/content-types.d.ts +3 -15
- package/dist/compare/reproducible-package.d.ts +0 -17
- package/dist/compare/reproducible-package.js +12 -18
- package/dist/controller/canonicalClipboard.d.ts +23 -0
- package/dist/controller/canonicalClipboard.js +476 -0
- package/dist/controller/canonicalClipboardResources.d.ts +21 -0
- package/dist/controller/canonicalClipboardResources.js +382 -0
- package/dist/controller/canonicalComposition.d.ts +53 -0
- package/dist/controller/canonicalComposition.js +296 -0
- package/dist/controller/canonicalInlineProjection.d.ts +113 -0
- package/dist/controller/canonicalInlineProjection.js +393 -0
- package/dist/controller/canonicalInput.d.ts +54 -0
- package/dist/controller/canonicalInput.js +377 -0
- package/dist/controller/canonicalInputTimer.d.ts +7 -0
- package/dist/controller/canonicalInputTimer.js +11 -0
- package/dist/controller/canonicalOperations.d.ts +22 -0
- package/dist/controller/canonicalOperations.js +85 -0
- package/dist/controller/canonicalPublicOperations.d.ts +48 -0
- package/dist/controller/canonicalPublicOperations.js +556 -0
- package/dist/controller/canonicalReview.d.ts +12 -0
- package/dist/controller/canonicalReview.js +19 -0
- package/dist/controller/canonicalSession.d.ts +167 -0
- package/dist/controller/canonicalSession.js +1186 -0
- package/dist/controller/canonicalStoryEditor.d.ts +36 -0
- package/dist/controller/canonicalStoryEditor.js +87 -0
- package/dist/controller/canonicalStructure.d.ts +16 -0
- package/dist/controller/canonicalStructure.js +322 -0
- package/dist/controller/canonicalTocSelection.d.ts +11 -0
- package/dist/controller/canonicalTocSelection.js +43 -0
- package/dist/controller/folioEditor.d.ts +3 -10
- package/dist/controller/folioEditor.js +14 -4
- package/dist/controller/headerFooterEditorManager.d.ts +5 -0
- package/dist/controller/headerFooterEditorManager.js +72 -3
- package/dist/controller/hiddenEditorApi.d.ts +45 -0
- package/dist/controller/hiddenEditorApi.js +29 -8
- package/dist/controller/hiddenEditorManager.d.ts +13 -2
- package/dist/controller/hiddenEditorManager.js +639 -31
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +2 -0
- package/dist/controller/noteEditorManager.d.ts +5 -0
- package/dist/controller/noteEditorManager.js +114 -15
- package/dist/document-operations.d.ts +8 -1
- package/dist/document-operations.js +6 -4
- package/dist/docx/attributeRemainder.js +1 -0
- package/dist/docx/blockPlainText.d.ts +1 -1
- package/dist/docx/blockPlainText.js +11 -3
- package/dist/docx/canonicalResourceSave.d.ts +16 -0
- package/dist/docx/canonicalResourceSave.js +27 -0
- package/dist/docx/canonicalSave.d.ts +29 -0
- package/dist/docx/canonicalSave.js +101 -0
- package/dist/docx/canonicalSessionInput.d.ts +11 -0
- package/dist/docx/canonicalSessionInput.js +27 -0
- package/dist/docx/canonicalStoryRepack.d.ts +10 -0
- package/dist/docx/canonicalStoryRepack.js +74 -0
- package/dist/docx/contentTypeRegistry.d.ts +8 -0
- package/dist/docx/contentTypeRegistry.js +64 -0
- package/dist/docx/documentParser.d.ts +1 -13
- package/dist/docx/documentParser.js +1 -47
- package/dist/docx/ensureParaIds.d.ts +7 -1
- package/dist/docx/ensureParaIds.js +173 -215
- package/dist/docx/foldedListNumberFields.d.ts +85 -0
- package/dist/docx/foldedListNumberFields.js +267 -0
- package/dist/docx/footnoteParser.d.ts +1 -11
- package/dist/docx/footnoteParser.js +1 -16
- package/dist/docx/headerFooterParser.d.ts +1 -9
- package/dist/docx/headerFooterParser.js +1 -12
- package/dist/docx/headerFooterVerbatim.d.ts +39 -1
- package/dist/docx/headerFooterVerbatim.js +173 -2
- package/dist/docx/imageParser.d.ts +13 -1
- package/dist/docx/imageParser.js +20 -11
- package/dist/docx/metadataPrivacy.js +6 -1
- package/dist/docx/noteIds.d.ts +5 -0
- package/dist/docx/noteIds.js +6 -2
- package/dist/docx/noteReferenceMark.d.ts +3 -1
- package/dist/docx/noteReferenceMark.js +15 -14
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +17 -3
- package/dist/docx/packageParts.d.ts +3 -1
- package/dist/docx/packageParts.js +74 -19
- package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
- package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
- package/dist/docx/paragraphParser.js +101 -53
- package/dist/docx/paragraphPropertySource.d.ts +15 -1
- package/dist/docx/paragraphPropertySource.js +77 -22
- package/dist/docx/parser.js +3 -1
- package/dist/docx/removeHeaderFooterParts.js +17 -6
- package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
- package/dist/docx/reviewHistoryNamespace.js +4 -0
- package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
- package/dist/docx/reviewResolutionProvenance.js +153 -0
- package/dist/docx/rezip.d.ts +54 -6
- package/dist/docx/rezip.js +835 -257
- package/dist/docx/runConsolidator.d.ts +2 -58
- package/dist/docx/runConsolidator.js +3 -175
- package/dist/docx/runParser.d.ts +2 -1
- package/dist/docx/runParser.js +156 -116
- package/dist/docx/saveDiagnostics.d.ts +22 -0
- package/dist/docx/saveDiagnostics.js +0 -0
- package/dist/docx/selectiveSave.d.ts +3 -1
- package/dist/docx/selectiveSave.js +36 -4
- package/dist/docx/selectiveXmlPatch.d.ts +16 -8
- package/dist/docx/selectiveXmlPatch.js +81 -7
- package/dist/docx/serializer/documentSerializer.d.ts +9 -2
- package/dist/docx/serializer/documentSerializer.js +29 -10
- package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
- package/dist/docx/serializer/headerFooterSerializer.js +19 -11
- package/dist/docx/serializer/noteSerializer.d.ts +2 -2
- package/dist/docx/serializer/noteSerializer.js +24 -8
- package/dist/docx/serializer/paragraphSerializer.js +41 -4
- package/dist/docx/serializer/partNamespaces.js +2 -1
- package/dist/docx/serializer/runSerializer.js +3 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
- package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
- package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
- package/dist/docx/settingsParser.d.ts +1 -2
- package/dist/docx/settingsParser.js +5 -6
- package/dist/docx/storyBlockReplay.d.ts +31 -0
- package/dist/docx/storyBlockReplay.js +471 -0
- package/dist/docx/storyPlainText.d.ts +20 -0
- package/dist/docx/storyPlainText.js +23 -0
- package/dist/docx/streamingXmlParser.d.ts +22 -1
- package/dist/docx/streamingXmlParser.js +49 -3
- package/dist/docx/structuralXmlPatch.js +18 -23
- package/dist/docx/styleParser.d.ts +5 -1
- package/dist/docx/styleParser.js +1 -1
- package/dist/docx/tableParser.d.ts +1 -8
- package/dist/docx/tableParser.js +1 -28
- package/dist/docx/textBoxParser.d.ts +1 -5
- package/dist/docx/textBoxParser.js +1 -20
- package/dist/docx/unzip.js +6 -1
- package/dist/docx/verbatimCapture.d.ts +3 -1
- package/dist/docx/verbatimCapture.js +49 -6
- package/dist/i18n/messages/ar.gen.d.ts +5 -0
- package/dist/i18n/messages/ar.gen.js +656 -0
- package/dist/i18n/messages/cs.gen.d.ts +5 -0
- package/dist/i18n/messages/cs.gen.js +656 -0
- package/dist/i18n/messages/de.gen.d.ts +5 -0
- package/dist/i18n/messages/de.gen.js +656 -0
- package/dist/i18n/messages/en.gen.d.ts +5 -0
- package/dist/i18n/messages/en.gen.js +656 -0
- package/dist/i18n/messages/es.gen.d.ts +5 -0
- package/dist/i18n/messages/es.gen.js +656 -0
- package/dist/i18n/messages/et.gen.d.ts +5 -0
- package/dist/i18n/messages/et.gen.js +656 -0
- package/dist/i18n/messages/fr.gen.d.ts +5 -0
- package/dist/i18n/messages/fr.gen.js +656 -0
- package/dist/i18n/messages/he.gen.d.ts +5 -0
- package/dist/i18n/messages/he.gen.js +656 -0
- package/dist/i18n/messages/hi.gen.d.ts +5 -0
- package/dist/i18n/messages/hi.gen.js +656 -0
- package/dist/i18n/messages/hu.gen.d.ts +5 -0
- package/dist/i18n/messages/hu.gen.js +656 -0
- package/dist/i18n/messages/locales.d.ts +5 -0
- package/dist/i18n/messages/locales.js +22 -0
- package/dist/i18n/messages/lt.gen.d.ts +5 -0
- package/dist/i18n/messages/lt.gen.js +656 -0
- package/dist/i18n/messages/lv.gen.d.ts +5 -0
- package/dist/i18n/messages/lv.gen.js +656 -0
- package/dist/i18n/messages/pl.gen.d.ts +5 -0
- package/dist/i18n/messages/pl.gen.js +656 -0
- package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
- package/dist/i18n/messages/pt-BR.gen.js +656 -0
- package/dist/i18n/messages/sk.gen.d.ts +5 -0
- package/dist/i18n/messages/sk.gen.js +656 -0
- package/dist/i18n/messages/tr.gen.d.ts +5 -0
- package/dist/i18n/messages/tr.gen.js +656 -0
- package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
- package/dist/i18n/messages/zh-CN.gen.js +656 -0
- package/dist/i18n/messages.d.ts +2 -3
- package/dist/i18n/messages.js +1 -19
- package/dist/internal/acceptedBlockProjection.d.ts +12 -0
- package/dist/internal/acceptedBlockProjection.js +45 -0
- package/dist/internal/noteMarkerAttrs.d.ts +8 -0
- package/dist/internal/noteMarkerAttrs.js +16 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
- package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
- package/dist/internal/prosemirrorAttrBoundary.js +50 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
- package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
- package/dist/layout-bridge/convert/noteReferences.js +1 -6
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
- package/dist/managers/DocumentLoaderManager.d.ts +1 -0
- package/dist/managers/DocumentLoaderManager.js +9 -1
- package/dist/markdown/escape.d.ts +3 -1
- package/dist/markdown/escape.js +9 -2
- package/dist/markdown/renderBlock.js +20 -121
- package/dist/markdown/renderParagraph.js +13 -15
- package/dist/markdown/renderRuns.d.ts +7 -1
- package/dist/markdown/renderRuns.js +35 -15
- package/dist/markdown/renderTable.js +2 -0
- package/dist/markdown/types.d.ts +3 -9
- package/dist/prosemirror/attrs/index.d.ts +2 -12
- package/dist/prosemirror/attrs/index.js +22 -48
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/canonicalCommands.d.ts +121 -0
- package/dist/prosemirror/canonicalCommands.js +35 -0
- package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
- package/dist/prosemirror/canonicalSelectionRange.js +15 -0
- package/dist/prosemirror/clipboardIntent.d.ts +7 -0
- package/dist/prosemirror/clipboardIntent.js +9 -0
- package/dist/prosemirror/commands/pageBreak.js +15 -1
- package/dist/prosemirror/commands/pastePlainText.js +2 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
- package/dist/prosemirror/conversion/toProseDoc.js +55 -14
- package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
- package/dist/prosemirror/executeEditorCommand.js +26 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
- package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
- package/dist/prosemirror/insertOperations.js +2 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +16 -7
- package/dist/prosemirror/listNumbering.js +26 -5
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/markupViewNotes.js +3 -2
- package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/noteReferenceReview.js +5 -3
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
- package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
- package/dist/prosemirror/plugins/suggestionMode.js +57 -7
- package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
- package/dist/prosemirror/runFormattingFromMarks.js +15 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
- package/dist/prosemirror/schema/marks.d.ts +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +10 -2
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/textInput.js +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +2 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
- package/dist/prosemirror/validation.js +4 -0
- package/dist/types/canonicalCapabilities.d.ts +215 -0
- package/dist/types/canonicalCapabilities.js +212 -0
- package/dist/types/canonicalSave.d.ts +11 -0
- package/dist/types/canonicalSave.js +0 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/types/docxSerialization.d.ts +14 -0
- package/dist/types/docxSerialization.js +7 -0
- package/dist/utils/createDocument.js +2 -2
- package/package.json +16 -4
|
@@ -1,62 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { formattingEquals, isTextOnlyRun, runsMergeable } from "@stll/docx-core/ops";
|
|
2
3
|
//#region src/docx/runConsolidator.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Every `TextFormatting` field, named so the comparison below is total.
|
|
5
|
-
*
|
|
6
|
-
* A field this comparison forgets is a field one of two merged runs loses,
|
|
7
|
-
* silently and at parse time. Naming them turns a field added to the model
|
|
8
|
-
* without a comparison into a compile error rather than a fidelity defect.
|
|
9
|
-
*/
|
|
10
|
-
type ComparedTextFormattingField = "bold" | "boldCs" | "italic" | "italicCs" | "underline" | "strike" | "doubleStrike" | "vertAlign" | "smallCaps" | "allCaps" | "hidden" | "noProof" | "color" | "highlight" | "shading" | "fontSize" | "fontSizeCs" | "fontFamily" | "language" | "spacing" | "position" | "scale" | "kerning" | "effect" | "emphasisMark" | "emboss" | "imprint" | "outline" | "shadow" | "rtl" | "cs" | "styleId" | "preserved";
|
|
11
|
-
type ComparedTextFormatting = document_d_exports.ExhaustiveFields<document_d_exports.TextFormatting, ComparedTextFormattingField>;
|
|
12
|
-
/**
|
|
13
|
-
* Check if two TextFormatting objects are equivalent
|
|
14
|
-
*
|
|
15
|
-
* Uses deep comparison of all properties to determine if runs
|
|
16
|
-
* can be merged without losing formatting information.
|
|
17
|
-
*/
|
|
18
|
-
declare function formattingEquals(a: ComparedTextFormatting | undefined, b: ComparedTextFormatting | undefined): boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Check if a run contains only text content
|
|
21
|
-
* (runs with special content like images, fields, etc. should not be merged)
|
|
22
|
-
*/
|
|
23
|
-
declare function isTextOnlyRun(run: document_d_exports.Run): boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Check if a run can be merged with another run
|
|
26
|
-
* Runs with breaks, tabs, images, fields, etc. act as merge boundaries
|
|
27
|
-
*/
|
|
28
|
-
declare function canMergeRun(run: document_d_exports.Run): boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Every `Run` field, named by what a merge does with it.
|
|
31
|
-
*
|
|
32
|
-
* The merged run is the survivor spread whole, so a field added to the model
|
|
33
|
-
* is carried over from one side by default. Naming each one here forces the
|
|
34
|
-
* next field to state whether that default is right before it can compile.
|
|
35
|
-
*/
|
|
36
|
-
type MergeDecidedRunField =
|
|
37
|
-
/** Identical for every run. */
|
|
38
|
-
"type" |
|
|
39
|
-
/** Concatenated; see {@link mergeRunContent}. */
|
|
40
|
-
"content" |
|
|
41
|
-
/** Must be equal, and the survivor keeps it. */
|
|
42
|
-
"formatting" |
|
|
43
|
-
/** Must be equal, and the survivor keeps it. */
|
|
44
|
-
"preservedAttributes" |
|
|
45
|
-
/** Refuses the merge outright; see {@link canMergeRun}. */
|
|
46
|
-
"propertyChanges";
|
|
47
|
-
type MergeDecidedRun = document_d_exports.ExhaustiveFields<document_d_exports.Run, MergeDecidedRunField>;
|
|
48
|
-
/**
|
|
49
|
-
* May two adjacent runs become one?
|
|
50
|
-
*
|
|
51
|
-
* Every consolidation site asks this one question, because a merge that any
|
|
52
|
-
* one site decides differently is a merge the next parse undoes. A run holds
|
|
53
|
-
* three records a merged run can hold only one of: its typed formatting, the
|
|
54
|
-
* attributes `w:r` carried that the model has no field for, and the `w:rPr`
|
|
55
|
-
* children no reader took a value from. Merging two runs that disagree on any
|
|
56
|
-
* of them discards the loser's copy, which is how both runs' `w:rsid*` used to
|
|
57
|
-
* vanish at parse time — before the editor, before any gate could see it.
|
|
58
|
-
*/
|
|
59
|
-
declare function runsMergeable(a: MergeDecidedRun, b: MergeDecidedRun): boolean;
|
|
60
4
|
/**
|
|
61
5
|
* Consolidate an array of runs by merging consecutive runs with identical formatting
|
|
62
6
|
*
|
|
@@ -93,4 +37,4 @@ declare function getConsolidationStats(originalParagraphs: document_d_exports.Pa
|
|
|
93
37
|
reductionPercentage: number;
|
|
94
38
|
};
|
|
95
39
|
//#endregion
|
|
96
|
-
export {
|
|
40
|
+
export { consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun, runsMergeable };
|
|
@@ -1,180 +1,8 @@
|
|
|
1
1
|
import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
|
|
2
2
|
import { runHoldsPayload } from "./runPayload.js";
|
|
3
|
+
import { formattingEquals, isTextOnlyRun, mergeRunContent, runsMergeable, runsMergeable as runsMergeable$1 } from "@stll/docx-core/ops";
|
|
3
4
|
//#region src/docx/runConsolidator.ts
|
|
4
5
|
/**
|
|
5
|
-
* Check if two TextFormatting objects are equivalent
|
|
6
|
-
*
|
|
7
|
-
* Uses deep comparison of all properties to determine if runs
|
|
8
|
-
* can be merged without losing formatting information.
|
|
9
|
-
*/
|
|
10
|
-
function formattingEquals(a, b) {
|
|
11
|
-
if (!a && !b) return true;
|
|
12
|
-
if (!a || !b) return false;
|
|
13
|
-
if (a.bold !== b.bold) return false;
|
|
14
|
-
if (a.boldCs !== b.boldCs) return false;
|
|
15
|
-
if (a.italic !== b.italic) return false;
|
|
16
|
-
if (a.italicCs !== b.italicCs) return false;
|
|
17
|
-
if (a.strike !== b.strike) return false;
|
|
18
|
-
if (a.doubleStrike !== b.doubleStrike) return false;
|
|
19
|
-
if (a.smallCaps !== b.smallCaps) return false;
|
|
20
|
-
if (a.allCaps !== b.allCaps) return false;
|
|
21
|
-
if (a.hidden !== b.hidden) return false;
|
|
22
|
-
if (a.noProof !== b.noProof) return false;
|
|
23
|
-
if (a.emboss !== b.emboss) return false;
|
|
24
|
-
if (a.imprint !== b.imprint) return false;
|
|
25
|
-
if (a.outline !== b.outline) return false;
|
|
26
|
-
if (a.shadow !== b.shadow) return false;
|
|
27
|
-
if (a.rtl !== b.rtl) return false;
|
|
28
|
-
if (a.cs !== b.cs) return false;
|
|
29
|
-
if (a.fontSize !== b.fontSize) return false;
|
|
30
|
-
if (a.fontSizeCs !== b.fontSizeCs) return false;
|
|
31
|
-
if (a.spacing !== b.spacing) return false;
|
|
32
|
-
if (a.position !== b.position) return false;
|
|
33
|
-
if (a.scale !== b.scale) return false;
|
|
34
|
-
if (a.kerning !== b.kerning) return false;
|
|
35
|
-
if (a.vertAlign !== b.vertAlign) return false;
|
|
36
|
-
if (a.highlight !== b.highlight) return false;
|
|
37
|
-
if (a.effect !== b.effect) return false;
|
|
38
|
-
if (a.emphasisMark !== b.emphasisMark) return false;
|
|
39
|
-
if (a.styleId !== b.styleId) return false;
|
|
40
|
-
if (!underlineEquals(a.underline, b.underline)) return false;
|
|
41
|
-
if (!colorEquals(a.color, b.color)) return false;
|
|
42
|
-
if (!shadingEquals(a.shading, b.shading)) return false;
|
|
43
|
-
if (!fontFamilyEquals(a.fontFamily, b.fontFamily)) return false;
|
|
44
|
-
if (!languageEquals(a.language, b.language)) return false;
|
|
45
|
-
if (!preservedMarkupEquals(a.preserved, b.preserved)) return false;
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Compare two verbatim sinks position by position.
|
|
50
|
-
*
|
|
51
|
-
* The sink is ordered — by `index`, then by source order within an index — and
|
|
52
|
-
* the order is what puts the markup back between the same modelled siblings,
|
|
53
|
-
* so equality is by sequence, not by set.
|
|
54
|
-
*/
|
|
55
|
-
function preservedMarkupEquals(a, b) {
|
|
56
|
-
const left = a?.children ?? [];
|
|
57
|
-
const right = b?.children ?? [];
|
|
58
|
-
if (left.length !== right.length) return false;
|
|
59
|
-
return left.every(({ index, xml }, position) => {
|
|
60
|
-
const other = right[position];
|
|
61
|
-
return other !== void 0 && other.index === index && other.xml === xml;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Compare two attribute remainders as sets.
|
|
66
|
-
*
|
|
67
|
-
* An element cannot carry one expanded name twice, so (namespace, name) orders
|
|
68
|
-
* a remainder totally and the sorted keys compare exactly. Order is a set
|
|
69
|
-
* comparison rather than a sequence one because attribute order in XML says
|
|
70
|
-
* nothing: two runs that spelled the same attributes in a different order
|
|
71
|
-
* carry the same remainder and may still become one run.
|
|
72
|
-
*/
|
|
73
|
-
function preservedAttributesEqual(a, b) {
|
|
74
|
-
const left = canonicalRemainderKeys(a);
|
|
75
|
-
const right = canonicalRemainderKeys(b);
|
|
76
|
-
return left.length === right.length && left.every((key, index) => key === right[index]);
|
|
77
|
-
}
|
|
78
|
-
/** `\u0000` cannot appear in an XML name, namespace URI or attribute value. */
|
|
79
|
-
const REMAINDER_KEY_SEPARATOR = "\0";
|
|
80
|
-
const canonicalRemainderKeys = (attributes) => (attributes ?? []).map(({ namespace, name, value }) => [
|
|
81
|
-
namespace ?? "",
|
|
82
|
-
name,
|
|
83
|
-
value
|
|
84
|
-
].join(REMAINDER_KEY_SEPARATOR)).sort();
|
|
85
|
-
function languageEquals(a, b) {
|
|
86
|
-
return a?.val === b?.val && a?.eastAsia === b?.eastAsia && a?.bidi === b?.bidi;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Compare underline settings
|
|
90
|
-
*/
|
|
91
|
-
function underlineEquals(a, b) {
|
|
92
|
-
if (!a && !b) return true;
|
|
93
|
-
if (!a || !b) return false;
|
|
94
|
-
if (a.style !== b.style) return false;
|
|
95
|
-
return colorEquals(a.color, b.color);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Compare color values
|
|
99
|
-
*/
|
|
100
|
-
function colorEquals(a, b) {
|
|
101
|
-
if (!a && !b) return true;
|
|
102
|
-
if (!a || !b) return false;
|
|
103
|
-
return a.rgb === b.rgb && a.auto === b.auto && a.themeColor === b.themeColor && a.themeTint === b.themeTint && a.themeShade === b.themeShade;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Compare shading properties
|
|
107
|
-
*/
|
|
108
|
-
function shadingEquals(a, b) {
|
|
109
|
-
if (!a && !b) return true;
|
|
110
|
-
if (!a || !b) return false;
|
|
111
|
-
if (a.pattern !== b.pattern) return false;
|
|
112
|
-
if (!colorEquals(a.color, b.color)) return false;
|
|
113
|
-
if (!colorEquals(a.fill, b.fill)) return false;
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Compare font family settings
|
|
118
|
-
*/
|
|
119
|
-
function fontFamilyEquals(a, b) {
|
|
120
|
-
if (!a && !b) return true;
|
|
121
|
-
if (!a || !b) return false;
|
|
122
|
-
return a.ascii === b.ascii && a.hAnsi === b.hAnsi && a.eastAsia === b.eastAsia && a.cs === b.cs && a.asciiTheme === b.asciiTheme && a.hAnsiTheme === b.hAnsiTheme && a.eastAsiaTheme === b.eastAsiaTheme && a.csTheme === b.csTheme;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Check if a run contains only text content
|
|
126
|
-
* (runs with special content like images, fields, etc. should not be merged)
|
|
127
|
-
*/
|
|
128
|
-
function isTextOnlyRun(run) {
|
|
129
|
-
return run.content.every((c) => c.type === "text" || c.type === "softHyphen" || c.type === "noBreakHyphen");
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Check if run content can be merged (simple text types)
|
|
133
|
-
*/
|
|
134
|
-
function isMergeableContent(content) {
|
|
135
|
-
return content.type === "text" || content.type === "softHyphen" || content.type === "noBreakHyphen";
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Check if a run can be merged with another run
|
|
139
|
-
* Runs with breaks, tabs, images, fields, etc. act as merge boundaries
|
|
140
|
-
*/
|
|
141
|
-
function canMergeRun(run) {
|
|
142
|
-
if (run.propertyChanges && run.propertyChanges.length > 0) return false;
|
|
143
|
-
if (!runHoldsPayload(run)) return false;
|
|
144
|
-
return run.content.every(isMergeableContent);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* May two adjacent runs become one?
|
|
148
|
-
*
|
|
149
|
-
* Every consolidation site asks this one question, because a merge that any
|
|
150
|
-
* one site decides differently is a merge the next parse undoes. A run holds
|
|
151
|
-
* three records a merged run can hold only one of: its typed formatting, the
|
|
152
|
-
* attributes `w:r` carried that the model has no field for, and the `w:rPr`
|
|
153
|
-
* children no reader took a value from. Merging two runs that disagree on any
|
|
154
|
-
* of them discards the loser's copy, which is how both runs' `w:rsid*` used to
|
|
155
|
-
* vanish at parse time — before the editor, before any gate could see it.
|
|
156
|
-
*/
|
|
157
|
-
function runsMergeable(a, b) {
|
|
158
|
-
return canMergeRun(a) && canMergeRun(b) && formattingEquals(a.formatting, b.formatting) && preservedAttributesEqual(a.preservedAttributes, b.preservedAttributes);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Merge the content of two runs into a single content array
|
|
162
|
-
*/
|
|
163
|
-
function mergeRunContent(content1, content2) {
|
|
164
|
-
const result = [];
|
|
165
|
-
for (const c of content1) result.push(c);
|
|
166
|
-
const lastText = result.at(-1);
|
|
167
|
-
const firstText = content2[0];
|
|
168
|
-
if (lastText?.type === "text" && firstText?.type === "text") {
|
|
169
|
-
result[result.length - 1] = {
|
|
170
|
-
type: "text",
|
|
171
|
-
text: lastText.text + firstText.text
|
|
172
|
-
};
|
|
173
|
-
for (let i = 1; i < content2.length; i++) result.push(content2[i]);
|
|
174
|
-
} else for (const c of content2) result.push(c);
|
|
175
|
-
return result;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
6
|
* Consolidate an array of runs by merging consecutive runs with identical formatting
|
|
179
7
|
*
|
|
180
8
|
* @param runs - Array of runs to consolidate
|
|
@@ -200,7 +28,7 @@ function consolidateRuns(runs) {
|
|
|
200
28
|
};
|
|
201
29
|
continue;
|
|
202
30
|
}
|
|
203
|
-
if (runsMergeable(current, run)) current = {
|
|
31
|
+
if (runsMergeable$1(current, run)) current = {
|
|
204
32
|
...current,
|
|
205
33
|
content: mergeRunContent(current.content, run.content)
|
|
206
34
|
};
|
|
@@ -276,4 +104,4 @@ function getConsolidationStats(originalParagraphs, consolidatedParagraphs) {
|
|
|
276
104
|
};
|
|
277
105
|
}
|
|
278
106
|
//#endregion
|
|
279
|
-
export {
|
|
107
|
+
export { consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun, runsMergeable };
|
package/dist/docx/runParser.d.ts
CHANGED
|
@@ -60,7 +60,8 @@ declare const isBaselineVertAlign: (vertAlign: document_d_exports.TextFormatting
|
|
|
60
60
|
* it beat are not kept.
|
|
61
61
|
*
|
|
62
62
|
* An element that states nothing at all still yields a record: `undefined` here
|
|
63
|
-
* means the owner carried no `w:rPr`,
|
|
63
|
+
* means the owner carried no `w:rPr`, or a paragraph-mark carrier contained
|
|
64
|
+
* only metadata owned by the paragraph. An authored empty set remains {}.
|
|
64
65
|
*/
|
|
65
66
|
declare function parseRunProperties(rPr: XmlElement | null, theme: document_d_exports.Theme | null, owner: RunPropertyOwner): document_d_exports.TextFormatting | undefined;
|
|
66
67
|
/**
|
package/dist/docx/runParser.js
CHANGED
|
@@ -9,6 +9,7 @@ import { imageRawXmlFingerprint } from "./imageRawXml.js";
|
|
|
9
9
|
import { EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, PositionalTabAlignmentSchema, PositionalTabLeaderSchema, PositionalTabRelativeToSchema, TextEffectSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
10
10
|
import { preserveRunChild } from "./preservedRunContent.js";
|
|
11
11
|
import { standalonePreviewLedger } from "./previewBudget.js";
|
|
12
|
+
import { parseBoundaryJoins } from "./reviewResolutionProvenance.js";
|
|
12
13
|
import { parseShading } from "./shadingParser.js";
|
|
13
14
|
import { captureShapeAlternateContent } from "./shapeAlternateContent.js";
|
|
14
15
|
import { parseShapeFromDrawing, shouldPreserveRawShapeDrawing } from "./shapeParser.js";
|
|
@@ -22,6 +23,25 @@ import { WORDPROCESSINGML_NAMESPACE_URIS, cloneWithXmlnsDeclarations, findAllDee
|
|
|
22
23
|
import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
|
|
23
24
|
//#region src/docx/runParser.ts
|
|
24
25
|
/**
|
|
26
|
+
* Run Parser - Parse text runs (w:r) with complete formatting
|
|
27
|
+
*
|
|
28
|
+
* A run is a contiguous region of text with the same character formatting.
|
|
29
|
+
* Runs can contain:
|
|
30
|
+
* - Text (w:t)
|
|
31
|
+
* - Tabs (w:tab)
|
|
32
|
+
* - Line breaks (w:br)
|
|
33
|
+
* - Symbols (w:sym)
|
|
34
|
+
* - Footnote/endnote references
|
|
35
|
+
* - Field characters
|
|
36
|
+
* - Drawings/images (w:drawing)
|
|
37
|
+
* - And more...
|
|
38
|
+
*
|
|
39
|
+
* OOXML Reference:
|
|
40
|
+
* - Run: w:r
|
|
41
|
+
* - Run properties: w:rPr
|
|
42
|
+
* - Text content: w:t
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
25
45
|
* Sanity cap on `w:lang` `@w:val`/`@w:eastAsia`/`@w:bidi` tag length. BCP-47
|
|
26
46
|
* tags top out well under this; a hostile/corrupt tag here would drive the
|
|
27
47
|
* hyphenation dictionary lookup and segmenter cache keying with an
|
|
@@ -81,6 +101,11 @@ const OWNED_BY_A_SIBLING_RECORD = {
|
|
|
81
101
|
reader: "runParser#parseRun"
|
|
82
102
|
}) },
|
|
83
103
|
paragraphMark: {
|
|
104
|
+
specVanish: ownedElsewhere({
|
|
105
|
+
container: "run-properties",
|
|
106
|
+
child: "specVanish",
|
|
107
|
+
reader: "paragraphProperties#parseParagraphProperties"
|
|
108
|
+
}),
|
|
84
109
|
ins: ownedElsewhere({
|
|
85
110
|
container: "run-properties",
|
|
86
111
|
child: "ins",
|
|
@@ -354,7 +379,6 @@ const RUN_PROPERTY_HANDLERS = {
|
|
|
354
379
|
},
|
|
355
380
|
paragraphMark: {
|
|
356
381
|
...RUN_PROPERTY_BASE_HANDLERS,
|
|
357
|
-
specVanish: readLastOccurrenceOnly(() => void 0),
|
|
358
382
|
...OWNED_BY_A_SIBLING_RECORD.paragraphMark
|
|
359
383
|
},
|
|
360
384
|
standalone: {
|
|
@@ -386,7 +410,8 @@ const RUN_PROPERTY_HANDLERS = {
|
|
|
386
410
|
* it beat are not kept.
|
|
387
411
|
*
|
|
388
412
|
* An element that states nothing at all still yields a record: `undefined` here
|
|
389
|
-
* means the owner carried no `w:rPr`,
|
|
413
|
+
* means the owner carried no `w:rPr`, or a paragraph-mark carrier contained
|
|
414
|
+
* only metadata owned by the paragraph. An authored empty set remains {}.
|
|
390
415
|
*/
|
|
391
416
|
function parseRunProperties(rPr, theme, owner) {
|
|
392
417
|
if (!rPr) return;
|
|
@@ -403,6 +428,8 @@ function parseRunProperties(rPr, theme, owner) {
|
|
|
403
428
|
}
|
|
404
429
|
});
|
|
405
430
|
if (preserved) formatting.preserved = preserved;
|
|
431
|
+
const children = getChildElements(rPr);
|
|
432
|
+
if (owner === RUN_PROPERTY_OWNERS.paragraphMark && Object.keys(formatting).length === 0 && children.length > 0 && children.every((child) => WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(child) ?? "") && Object.hasOwn(OWNED_BY_A_SIBLING_RECORD.paragraphMark, getLocalName(child.name)))) return;
|
|
406
433
|
return formatting;
|
|
407
434
|
}
|
|
408
435
|
function parseRunPropertyChanges(rPr, theme, currentFormatting) {
|
|
@@ -413,6 +440,8 @@ function parseRunPropertyChanges(rPr, theme, currentFormatting) {
|
|
|
413
440
|
type: "runPropertyChange",
|
|
414
441
|
info: parsePropertyChangeInfo(changeElement)
|
|
415
442
|
};
|
|
443
|
+
const boundaryJoins = parseBoundaryJoins(changeElement);
|
|
444
|
+
if (boundaryJoins !== void 0) change.boundaryJoins = boundaryJoins;
|
|
416
445
|
const previousFormatting = parseRunProperties(previousRPr, theme, RUN_PROPERTY_OWNERS.standalone);
|
|
417
446
|
if (previousFormatting) change.previousFormatting = previousFormatting;
|
|
418
447
|
if (currentFormatting) change.currentFormatting = currentFormatting;
|
|
@@ -602,130 +631,141 @@ function parseDrawingContent(element, rels, media, previews) {
|
|
|
602
631
|
function parseRunContents(runElement, rels, media, previews, rootXmlns = {}) {
|
|
603
632
|
const contents = [];
|
|
604
633
|
const children = getChildElements(runElement);
|
|
605
|
-
for (const child of children)
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
contents.push(
|
|
634
|
+
for (const child of children) {
|
|
635
|
+
const localName = getLocalName(child.name);
|
|
636
|
+
switch (localName) {
|
|
637
|
+
case "t":
|
|
638
|
+
contents.push(parseTextContent(child));
|
|
639
|
+
break;
|
|
640
|
+
case "tab":
|
|
641
|
+
contents.push(parseTabContent());
|
|
642
|
+
break;
|
|
643
|
+
case "ptab":
|
|
644
|
+
contents.push(parsePositionalTabContent(child));
|
|
645
|
+
break;
|
|
646
|
+
case "br":
|
|
647
|
+
contents.push(parseBreakContent(child));
|
|
648
|
+
break;
|
|
649
|
+
case "sym":
|
|
650
|
+
contents.push(parseSymbolContent(child));
|
|
651
|
+
break;
|
|
652
|
+
case "footnoteReference":
|
|
653
|
+
contents.push(parseFootnoteReference(child));
|
|
654
|
+
break;
|
|
655
|
+
case "endnoteReference":
|
|
656
|
+
contents.push(parseEndnoteReference(child));
|
|
657
|
+
break;
|
|
658
|
+
case "footnoteRef":
|
|
659
|
+
case "endnoteRef":
|
|
660
|
+
if (WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(child) ?? "")) contents.push({
|
|
661
|
+
type: "noteMarker",
|
|
662
|
+
kind: localName === "footnoteRef" ? "footnote" : "endnote"
|
|
663
|
+
});
|
|
664
|
+
else contents.push(preserveRunChild(child));
|
|
665
|
+
break;
|
|
666
|
+
case "fldChar":
|
|
667
|
+
contents.push(parseFieldChar(child));
|
|
668
|
+
break;
|
|
669
|
+
case "instrText":
|
|
670
|
+
contents.push(parseInstrText(child));
|
|
671
|
+
break;
|
|
672
|
+
case "softHyphen":
|
|
673
|
+
contents.push({ type: "softHyphen" });
|
|
674
|
+
break;
|
|
675
|
+
case "noBreakHyphen":
|
|
676
|
+
contents.push({ type: "noBreakHyphen" });
|
|
677
|
+
break;
|
|
678
|
+
case "drawing": {
|
|
679
|
+
const drawing = parseDrawingContent(child, rels, media, previews);
|
|
680
|
+
if (drawing) contents.push(drawing);
|
|
648
681
|
break;
|
|
649
682
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
const objectPreview = parseVmlImageContent(child, rels, media, previews, rootXmlns);
|
|
655
|
-
contents.push(objectPreview ?? preserveRunChild(child));
|
|
656
|
-
break;
|
|
657
|
-
}
|
|
658
|
-
case "rPr": break;
|
|
659
|
-
case "commentReference": break;
|
|
660
|
-
case "lastRenderedPageBreak":
|
|
661
|
-
contents.push({ type: "renderedPageBreak" });
|
|
662
|
-
break;
|
|
663
|
-
case "cr":
|
|
664
|
-
contents.push({
|
|
665
|
-
type: "break",
|
|
666
|
-
sourceElement: "cr"
|
|
667
|
-
});
|
|
668
|
-
break;
|
|
669
|
-
case "AlternateContent": {
|
|
670
|
-
const alternateChildren = getChildElements(child);
|
|
671
|
-
const choiceEl = alternateChildren.find((el) => getLocalName(el.name) === "Choice");
|
|
672
|
-
const fallbackEl = alternateChildren.find((el) => getLocalName(el.name) === "Fallback");
|
|
673
|
-
const contentsBeforeAlternate = contents.length;
|
|
674
|
-
const choiceTextBoxDrawing = choiceEl ? getChildElements(choiceEl).find((element) => getLocalName(element.name) === "drawing" && isTextBoxDrawing(element)) : void 0;
|
|
675
|
-
const groupedChoiceDrawing = choiceEl ? getChildElements(choiceEl).find((element) => getLocalName(element.name) === "drawing" && findAllDeep(element, "wpg", "wgp").length > 0) : void 0;
|
|
676
|
-
if (groupedChoiceDrawing) {
|
|
677
|
-
const groupedDrawing = parseDrawingContent(groupedChoiceDrawing, rels, media, previews);
|
|
678
|
-
if (groupedDrawing?.type === "drawing" && groupedDrawing.rawXmlMode === DRAWING_RAW_XML_MODES.PREVIEW_ONLY && groupedDrawing.image.src) {
|
|
679
|
-
contents.push({
|
|
680
|
-
...groupedDrawing,
|
|
681
|
-
rawXml: captureVerbatimXml(child)
|
|
682
|
-
});
|
|
683
|
+
case "pict": {
|
|
684
|
+
const vmlDrawing = parseVmlImageContent(child, rels, media, previews, rootXmlns);
|
|
685
|
+
if (vmlDrawing) {
|
|
686
|
+
contents.push(vmlDrawing);
|
|
683
687
|
break;
|
|
684
688
|
}
|
|
689
|
+
if (shouldPreserveRawVmlPict(child)) contents.push(preserveOnlyDrawing(captureVerbatimXml(cloneWithXmlnsDeclarations(child, rootXmlns))));
|
|
690
|
+
break;
|
|
685
691
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
fallbackVml.rawXml = captureVerbatimXml(cloneWithXmlnsDeclarations(child, rootXmlns));
|
|
690
|
-
contents.push(fallbackVml);
|
|
692
|
+
case "object": {
|
|
693
|
+
const objectPreview = parseVmlImageContent(child, rels, media, previews, rootXmlns);
|
|
694
|
+
contents.push(objectPreview ?? preserveRunChild(child));
|
|
691
695
|
break;
|
|
692
696
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
const
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
|
|
697
|
+
case "rPr": break;
|
|
698
|
+
case "commentReference": break;
|
|
699
|
+
case "lastRenderedPageBreak":
|
|
700
|
+
contents.push({ type: "renderedPageBreak" });
|
|
701
|
+
break;
|
|
702
|
+
case "cr":
|
|
703
|
+
contents.push({
|
|
704
|
+
type: "break",
|
|
705
|
+
sourceElement: "cr"
|
|
706
|
+
});
|
|
707
|
+
break;
|
|
708
|
+
case "AlternateContent": {
|
|
709
|
+
const alternateChildren = getChildElements(child);
|
|
710
|
+
const choiceEl = alternateChildren.find((el) => getLocalName(el.name) === "Choice");
|
|
711
|
+
const fallbackEl = alternateChildren.find((el) => getLocalName(el.name) === "Fallback");
|
|
712
|
+
const contentsBeforeAlternate = contents.length;
|
|
713
|
+
const choiceTextBoxDrawing = choiceEl ? getChildElements(choiceEl).find((element) => getLocalName(element.name) === "drawing" && isTextBoxDrawing(element)) : void 0;
|
|
714
|
+
const groupedChoiceDrawing = choiceEl ? getChildElements(choiceEl).find((element) => getLocalName(element.name) === "drawing" && findAllDeep(element, "wpg", "wgp").length > 0) : void 0;
|
|
715
|
+
if (groupedChoiceDrawing) {
|
|
716
|
+
const groupedDrawing = parseDrawingContent(groupedChoiceDrawing, rels, media, previews);
|
|
717
|
+
if (groupedDrawing?.type === "drawing" && groupedDrawing.rawXmlMode === DRAWING_RAW_XML_MODES.PREVIEW_ONLY && groupedDrawing.image.src) {
|
|
718
|
+
contents.push({
|
|
719
|
+
...groupedDrawing,
|
|
720
|
+
rawXml: captureVerbatimXml(child)
|
|
721
|
+
});
|
|
722
|
+
break;
|
|
716
723
|
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
724
|
+
}
|
|
725
|
+
const fallbackPict = fallbackEl ? getChildElements(fallbackEl).find((el) => getLocalName(el.name) === "pict") : void 0;
|
|
726
|
+
const fallbackVml = fallbackPict && !choiceTextBoxDrawing ? parseVmlImageContent(fallbackPict, rels, media, previews, rootXmlns) : null;
|
|
727
|
+
if (fallbackVml?.image.src) {
|
|
728
|
+
fallbackVml.rawXml = captureVerbatimXml(cloneWithXmlnsDeclarations(child, rootXmlns));
|
|
729
|
+
contents.push(fallbackVml);
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
const targetEl = selectAlternateContentBranch(child);
|
|
733
|
+
if (targetEl) for (const innerChild of getChildElements(targetEl)) {
|
|
734
|
+
const innerName = getLocalName(innerChild.name);
|
|
735
|
+
if (innerName === "drawing") {
|
|
736
|
+
const innerDrawing = parseDrawingContent(innerChild, rels, media, previews);
|
|
737
|
+
if (innerDrawing) {
|
|
738
|
+
if (innerDrawing.type === "drawing" && (innerDrawing.rawXml !== void 0 || !innerDrawing.image.src)) innerDrawing.rawXml = captureVerbatimXml(child);
|
|
739
|
+
if (innerDrawing.type === "shape") {
|
|
740
|
+
const alternateContent = captureShapeAlternateContent({
|
|
741
|
+
shape: innerDrawing.shape,
|
|
742
|
+
alternateContent: child,
|
|
743
|
+
branch: targetEl,
|
|
744
|
+
drawing: innerChild
|
|
745
|
+
});
|
|
746
|
+
if (alternateContent) innerDrawing.alternateContent = alternateContent;
|
|
747
|
+
}
|
|
748
|
+
contents.push(innerDrawing);
|
|
749
|
+
}
|
|
750
|
+
} else if (innerName === "pict") {
|
|
751
|
+
const innerVml = parseVmlImageContent(innerChild, rels, media, previews, rootXmlns);
|
|
752
|
+
if (innerVml) {
|
|
753
|
+
innerVml.rawXml = captureVerbatimXml(cloneWithXmlnsDeclarations(child, rootXmlns));
|
|
754
|
+
contents.push(innerVml);
|
|
755
|
+
}
|
|
756
|
+
} else contents.push(...parseRunContents({
|
|
757
|
+
...targetEl,
|
|
758
|
+
elements: [innerChild]
|
|
759
|
+
}, rels, media, previews, rootXmlns));
|
|
760
|
+
}
|
|
761
|
+
const hasTextBoxBranch = [choiceEl, fallbackEl].some((branch) => getChildElements(branch).some((element) => getLocalName(element.name) === "drawing" && isTextBoxDrawing(element)));
|
|
762
|
+
if (contents.length === contentsBeforeAlternate && !hasTextBoxBranch) contents.push(preserveOnlyDrawing(captureVerbatimXml(cloneWithXmlnsDeclarations(child, rootXmlns))));
|
|
763
|
+
break;
|
|
721
764
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
765
|
+
default:
|
|
766
|
+
contents.push(preserveRunChild(child));
|
|
767
|
+
break;
|
|
725
768
|
}
|
|
726
|
-
default:
|
|
727
|
-
contents.push(preserveRunChild(child));
|
|
728
|
-
break;
|
|
729
769
|
}
|
|
730
770
|
return contents;
|
|
731
771
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
2
|
+
//#region src/docx/saveDiagnostics.d.ts
|
|
3
|
+
/** Save diagnostics describe fidelity fallbacks without including document content. */
|
|
4
|
+
type SaveDiagnostic = {
|
|
5
|
+
type: "sourceReplayMismatch";
|
|
6
|
+
part: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: "selectiveSaveRefused";
|
|
9
|
+
part: string;
|
|
10
|
+
} | {
|
|
11
|
+
type: "sourceReplayUnavailable";
|
|
12
|
+
part: string;
|
|
13
|
+
} | {
|
|
14
|
+
type: "canonicalResourceReplacement";
|
|
15
|
+
gap: typeof CANONICAL_GAP.resourceReplacement;
|
|
16
|
+
part: string;
|
|
17
|
+
};
|
|
18
|
+
type SaveDiagnosticOptions = {
|
|
19
|
+
onDiagnostic?: ((diagnostic: SaveDiagnostic) => void) | undefined;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { SaveDiagnostic, SaveDiagnosticOptions };
|
|
File without changes
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { SaveDiagnosticOptions } from "./saveDiagnostics.js";
|
|
3
|
+
import { DocumentBodyAuthorityOptions } from "./serializer/documentSerializer.js";
|
|
2
4
|
//#region src/docx/selectiveSave.d.ts
|
|
3
|
-
type SelectiveSaveOptions = {
|
|
5
|
+
type SelectiveSaveOptions = SaveDiagnosticOptions & DocumentBodyAuthorityOptions & {
|
|
4
6
|
/** Changed paragraph IDs to selectively patch */
|
|
5
7
|
changedParaIds: Set<string>;
|
|
6
8
|
/** Whether paragraph membership, order, or block structure changed. */
|