@stll/folio-core 0.54.2 → 0.55.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 +22 -1
- package/dist/ai-edits/headless.js +1 -0
- package/dist/compare/content-types.d.ts +3 -15
- package/dist/controller/canonicalComposition.d.ts +36 -0
- package/dist/controller/canonicalComposition.js +168 -0
- package/dist/controller/canonicalInput.d.ts +45 -0
- package/dist/controller/canonicalInput.js +338 -0
- package/dist/controller/canonicalOperations.d.ts +22 -0
- package/dist/controller/canonicalOperations.js +85 -0
- package/dist/controller/canonicalReview.d.ts +12 -0
- package/dist/controller/canonicalReview.js +19 -0
- package/dist/controller/canonicalSession.d.ts +149 -0
- package/dist/controller/canonicalSession.js +1038 -0
- package/dist/controller/canonicalStoryEditor.d.ts +34 -0
- package/dist/controller/canonicalStoryEditor.js +82 -0
- package/dist/controller/canonicalStructure.d.ts +16 -0
- package/dist/controller/canonicalStructure.js +269 -0
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/folioEditor.js +9 -0
- package/dist/controller/headerFooterEditorManager.d.ts +4 -0
- package/dist/controller/headerFooterEditorManager.js +71 -3
- package/dist/controller/hiddenEditorApi.d.ts +35 -0
- package/dist/controller/hiddenEditorApi.js +25 -8
- package/dist/controller/hiddenEditorManager.d.ts +11 -2
- package/dist/controller/hiddenEditorManager.js +456 -30
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +2 -0
- package/dist/controller/noteEditorManager.d.ts +4 -0
- package/dist/controller/noteEditorManager.js +113 -15
- package/dist/docx/attributeRemainder.js +1 -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 +41 -0
- package/dist/docx/contentTypeRegistry.d.ts +8 -0
- package/dist/docx/contentTypeRegistry.js +64 -0
- package/dist/docx/ensureParaIds.d.ts +7 -1
- package/dist/docx/ensureParaIds.js +163 -211
- package/dist/docx/foldedListNumberFields.d.ts +85 -0
- package/dist/docx/foldedListNumberFields.js +267 -0
- package/dist/docx/headerFooterVerbatim.d.ts +14 -1
- package/dist/docx/headerFooterVerbatim.js +95 -2
- 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 +65 -16
- 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 +76 -22
- package/dist/docx/parser.js +2 -1
- 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 +7 -3
- package/dist/docx/rezip.js +107 -45
- 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 +11 -0
- package/dist/docx/saveDiagnostics.js +0 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +4 -1
- package/dist/docx/selectiveXmlPatch.d.ts +16 -8
- package/dist/docx/selectiveXmlPatch.js +74 -2
- 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/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 +11 -0
- package/dist/docx/storyBlockReplay.js +367 -0
- package/dist/docx/streamingXmlParser.d.ts +22 -1
- package/dist/docx/streamingXmlParser.js +49 -3
- package/dist/docx/structuralXmlPatch.js +8 -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/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 +8 -1
- package/dist/markdown/renderBlock.js +15 -1
- package/dist/markdown/renderParagraph.js +9 -13
- package/dist/markdown/renderRuns.js +3 -2
- 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 +97 -0
- package/dist/prosemirror/canonicalCommands.js +28 -0
- package/dist/prosemirror/commands/pageBreak.js +15 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
- package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -3
- package/dist/prosemirror/conversion/toProseDoc.js +51 -11
- 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 +50 -19
- 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/TextColorExtension.js +3 -2
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +70 -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/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/plugins/suggestionMode.js +50 -2
- 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/content.d.ts +2 -2
- package/dist/utils/createDocument.js +2 -2
- package/package.json +14 -2
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,11 @@
|
|
|
1
|
+
//#region src/docx/saveDiagnostics.d.ts
|
|
2
|
+
/** Save diagnostics describe fidelity fallbacks without including document content. */
|
|
3
|
+
type SaveDiagnostic = {
|
|
4
|
+
type: "sourceReplayMismatch";
|
|
5
|
+
part: string;
|
|
6
|
+
};
|
|
7
|
+
type SaveDiagnosticOptions = {
|
|
8
|
+
onDiagnostic?: ((diagnostic: SaveDiagnostic) => void) | undefined;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SaveDiagnostic, SaveDiagnosticOptions };
|
|
File without changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { SaveDiagnosticOptions } from "./saveDiagnostics.js";
|
|
2
3
|
//#region src/docx/selectiveSave.d.ts
|
|
3
|
-
type SelectiveSaveOptions = {
|
|
4
|
+
type SelectiveSaveOptions = SaveDiagnosticOptions & {
|
|
4
5
|
/** Changed paragraph IDs to selectively patch */
|
|
5
6
|
changedParaIds: Set<string>;
|
|
6
7
|
/** Whether paragraph membership, order, or block structure changed. */
|
|
@@ -268,7 +268,10 @@ async function attemptSelectiveSave(doc, originalBuffer, options) {
|
|
|
268
268
|
}
|
|
269
269
|
if (!await patchCommentsExtended(zip, commentPlan, updates)) return null;
|
|
270
270
|
if (!await patchNumberingPart(zip, doc, updates)) return null;
|
|
271
|
-
for (const [path, xml] of await collectHeaderFooterUpdates(doc,
|
|
271
|
+
for (const [path, xml] of await collectHeaderFooterUpdates(doc, {
|
|
272
|
+
sourceZip: zip,
|
|
273
|
+
onDiagnostic: options.onDiagnostic
|
|
274
|
+
})) updates.set(path, xml);
|
|
272
275
|
await queueSettingsUpdates(zip, updates);
|
|
273
276
|
const corePropsFile = zip.file("docProps/core.xml");
|
|
274
277
|
if (corePropsFile) {
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
+
import { XmlElement } from "./xmlParser.js";
|
|
1
2
|
//#region src/docx/selectiveXmlPatch.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Selective XML Patch Module
|
|
4
|
-
*
|
|
5
|
-
* Patches only changed paragraphs in document.xml, preserving
|
|
6
|
-
* unchanged content byte-for-byte. Uses string offset tracking
|
|
7
|
-
* with proper tag depth counting (not regex) to handle nested elements.
|
|
8
|
-
*/
|
|
9
3
|
/**
|
|
10
4
|
* Whether `char` ends an element's tag name in XML — a whitespace separator
|
|
11
5
|
* (space, tab, CR, or LF, all valid before attributes per XML 1.0 §3.1), the
|
|
@@ -170,6 +164,20 @@ type XmlSplice = {
|
|
|
170
164
|
* end, so its original offsets cannot be applied to the resulting string.
|
|
171
165
|
*/
|
|
172
166
|
declare const spliceXml: (xml: string, splices: readonly XmlSplice[]) => string | null;
|
|
167
|
+
/**
|
|
168
|
+
* A paragraph splice cannot change the owning part's root declarations. Refuse
|
|
169
|
+
* fragments that inherit a prefix from the serialized root when the source
|
|
170
|
+
* root does not bind that prefix to the same URI; the caller can then use the
|
|
171
|
+
* full serializer, which owns the root namespace set.
|
|
172
|
+
*/
|
|
173
|
+
type SpliceNamespaceOptions = {
|
|
174
|
+
originalXml: string;
|
|
175
|
+
serializedXml: string;
|
|
176
|
+
fragments: readonly string[];
|
|
177
|
+
originalRoot?: XmlElement;
|
|
178
|
+
serializedRoot?: XmlElement;
|
|
179
|
+
};
|
|
180
|
+
declare const spliceSupportsRootNamespaces: ({ originalXml, serializedXml, fragments, originalRoot, serializedRoot }: SpliceNamespaceOptions) => boolean;
|
|
173
181
|
type NoteElementName = "footnote" | "endnote";
|
|
174
182
|
declare const collectChangedNoteParaIds: (baselineXml: string, currentXml: string) => Set<string>;
|
|
175
183
|
type BuildPatchedNotePartXmlOptions = {
|
|
@@ -265,4 +273,4 @@ declare const patchNumberingDefinitions: ({ originalXml, baselineXml, currentXml
|
|
|
265
273
|
*/
|
|
266
274
|
declare function appendNumberingDefs(xml: string, currentXml: string, added: ChangedNumberingDefs): string | null;
|
|
267
275
|
//#endregion
|
|
268
|
-
export { ChangedNumberingDefs, NotePartPatch, NotePartPatchRefusal, ParagraphContainer, ParagraphOffsets, PatchValidationResult, ScannedParagraph, XmlSplice, appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceXml, validatePatchSafety };
|
|
276
|
+
export { ChangedNumberingDefs, NotePartPatch, NotePartPatchRefusal, ParagraphContainer, ParagraphOffsets, PatchValidationResult, ScannedParagraph, XmlSplice, appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceSupportsRootNamespaces, spliceXml, validatePatchSafety };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { patchBreaksCommentRangeBalance } from "./commentRangeIntegrity.js";
|
|
2
2
|
import { resolveParagraphIdentities } from "./paraIdAttribute.js";
|
|
3
|
+
import { readRootNamespaceBindings } from "./serializer/partNamespaces.js";
|
|
3
4
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
4
5
|
import { PARAGRAPH_SCAN_NAMES, hasCanonicalWordprocessingPrefixes, matchCloseTag, matchOpenTag, resolveSelectiveScanPrefixes, splicesAsCanonical } from "./wordprocessingPrefixes.js";
|
|
5
|
-
import {
|
|
6
|
+
import { resolveNamespaceUri } from "./xmlNamespaceContext.js";
|
|
7
|
+
import { NAMESPACES, WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findAttributeByNamespaceUri, getAttributeByNamespaceUri, getChildElements, getLocalName, getNamespacePrefix, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
|
|
6
8
|
//#region src/docx/selectiveXmlPatch.ts
|
|
7
9
|
/**
|
|
8
10
|
* Selective XML Patch Module
|
|
@@ -425,6 +427,14 @@ const routeChangedParagraphs = (originalXml, serializedXml, changedIds) => {
|
|
|
425
427
|
newXml: authored ? newXml : withoutMintedIds(newXml, sourceXml)
|
|
426
428
|
});
|
|
427
429
|
}
|
|
430
|
+
if (!spliceSupportsRootNamespaces({
|
|
431
|
+
originalXml,
|
|
432
|
+
serializedXml,
|
|
433
|
+
fragments: splices.map(({ newXml }) => newXml)
|
|
434
|
+
})) return {
|
|
435
|
+
type: "refused",
|
|
436
|
+
reason: "root-namespace-requirements-changed"
|
|
437
|
+
};
|
|
428
438
|
const candidate = spliceXml(originalXml, splices);
|
|
429
439
|
if (candidate === null) return {
|
|
430
440
|
type: "refused",
|
|
@@ -514,6 +524,68 @@ const spliceXml = (xml, splices) => {
|
|
|
514
524
|
}
|
|
515
525
|
return patchBreaksCommentRangeBalance(xml, result) ? null : result;
|
|
516
526
|
};
|
|
527
|
+
const spliceSupportsRootNamespaces = ({ originalXml, serializedXml, fragments, originalRoot, serializedRoot }) => {
|
|
528
|
+
const original = originalRoot ?? parseXmlDocument(originalXml);
|
|
529
|
+
const serialized = serializedRoot ?? parseXmlDocument(serializedXml);
|
|
530
|
+
if (!original || !serialized) return false;
|
|
531
|
+
const originalBindings = readRootNamespaceBindings(originalXml);
|
|
532
|
+
const serializedBindings = readRootNamespaceBindings(serializedXml);
|
|
533
|
+
const mcNamespace = /* @__PURE__ */ new Set([NAMESPACES.mc]);
|
|
534
|
+
const ignorableUris = (root) => {
|
|
535
|
+
const uris = /* @__PURE__ */ new Set();
|
|
536
|
+
for (const prefix of (getAttributeByNamespaceUri(root, mcNamespace, "Ignorable") ?? "").split(/\s+/u).filter(Boolean)) {
|
|
537
|
+
const uri = resolveNamespaceUri(root.namespaceScope, prefix);
|
|
538
|
+
if (uri) uris.add(uri);
|
|
539
|
+
}
|
|
540
|
+
return uris;
|
|
541
|
+
};
|
|
542
|
+
const originalNamespaceUses = /* @__PURE__ */ new Set();
|
|
543
|
+
const collectSourceNamespaces = (element) => {
|
|
544
|
+
const uri = getNamespaceUri(element);
|
|
545
|
+
if (uri) originalNamespaceUses.add(uri);
|
|
546
|
+
for (const attribute of Object.keys(element.attributes ?? {})) {
|
|
547
|
+
if (attribute === "xmlns" || attribute.startsWith("xmlns:")) continue;
|
|
548
|
+
const prefix = getNamespacePrefix(attribute);
|
|
549
|
+
const attributeUri = prefix ? resolveNamespaceUri(element.namespaceScope, prefix) : void 0;
|
|
550
|
+
if (attributeUri) originalNamespaceUses.add(attributeUri);
|
|
551
|
+
}
|
|
552
|
+
for (const child of element.elements ?? []) collectSourceNamespaces(child);
|
|
553
|
+
};
|
|
554
|
+
collectSourceNamespaces(original);
|
|
555
|
+
const originalIgnorable = ignorableUris(original);
|
|
556
|
+
const serializedIgnorable = ignorableUris(serialized);
|
|
557
|
+
const inheritedPrefixes = /* @__PURE__ */ new Set();
|
|
558
|
+
const visit = (element, ancestorIgnorableUris) => {
|
|
559
|
+
const localIgnorableUris = new Set(ancestorIgnorableUris);
|
|
560
|
+
for (const uri of ignorableUris(element)) localIgnorableUris.add(uri);
|
|
561
|
+
const requirePrefix = (prefix) => {
|
|
562
|
+
const localUri = resolveNamespaceUri(element.namespaceScope, prefix);
|
|
563
|
+
if (!localUri) inheritedPrefixes.add(prefix);
|
|
564
|
+
const uri = localUri ?? serializedBindings.get(prefix);
|
|
565
|
+
if (!uri) return false;
|
|
566
|
+
return !serializedIgnorable.has(uri) || originalNamespaceUses.has(uri) || originalIgnorable.has(uri) || localIgnorableUris.has(uri);
|
|
567
|
+
};
|
|
568
|
+
const namePrefix = element.name?.split(":").at(0);
|
|
569
|
+
if (namePrefix && namePrefix !== element.name && !requirePrefix(namePrefix)) return false;
|
|
570
|
+
for (const attribute of Object.keys(element.attributes ?? {})) {
|
|
571
|
+
if (attribute === "xmlns" || attribute.startsWith("xmlns:")) continue;
|
|
572
|
+
const prefix = attribute.split(":").at(0);
|
|
573
|
+
if (prefix && prefix !== attribute && !requirePrefix(prefix)) return false;
|
|
574
|
+
}
|
|
575
|
+
for (const child of element.elements ?? []) if (!visit(child, localIgnorableUris)) return false;
|
|
576
|
+
return true;
|
|
577
|
+
};
|
|
578
|
+
for (const fragment of fragments) {
|
|
579
|
+
const parsed = parseXmlDocument(fragment);
|
|
580
|
+
if (!parsed) return false;
|
|
581
|
+
if (!visit(parsed, /* @__PURE__ */ new Set())) return false;
|
|
582
|
+
}
|
|
583
|
+
for (const prefix of inheritedPrefixes) {
|
|
584
|
+
const serializedUri = serializedBindings.get(prefix);
|
|
585
|
+
if (serializedUri === void 0 || originalBindings.get(prefix) !== serializedUri) return false;
|
|
586
|
+
}
|
|
587
|
+
return true;
|
|
588
|
+
};
|
|
517
589
|
/**
|
|
518
590
|
* Depth-count the end of the element that opens at `start` (an `<openLiteral…>`
|
|
519
591
|
* offset), returning its full range. Nested same-name opens increment depth;
|
|
@@ -1269,4 +1341,4 @@ function escapeRegExp(str) {
|
|
|
1269
1341
|
return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
1270
1342
|
}
|
|
1271
1343
|
//#endregion
|
|
1272
|
-
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceXml, validatePatchSafety };
|
|
1344
|
+
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceSupportsRootNamespaces, spliceXml, validatePatchSafety };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
import { SaveDiagnosticOptions } from "../saveDiagnostics.js";
|
|
2
3
|
import { SourcePart } from "./partNamespaces.js";
|
|
3
4
|
//#region src/docx/serializer/headerFooterSerializer.d.ts
|
|
4
5
|
/**
|
|
@@ -9,6 +10,9 @@ import { SourcePart } from "./partNamespaces.js";
|
|
|
9
10
|
* document bound keeps its URI
|
|
10
11
|
* @returns Complete XML string for header*.xml or footer*.xml
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
type HeaderFooterSerializeOptions = SourcePart & SaveDiagnosticOptions & {
|
|
14
|
+
originalBuffer?: ArrayBuffer | undefined;
|
|
15
|
+
};
|
|
16
|
+
declare function serializeHeaderFooter(hf: document_d_exports.HeaderFooter, source?: HeaderFooterSerializeOptions): string;
|
|
13
17
|
//#endregion
|
|
14
18
|
export { serializeHeaderFooter };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
1
|
+
import { canReplayHeaderFooterBlocks, canReplayHeaderFooterVerbatim, getHeaderFooterSourceBaseline, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
2
2
|
import { isEmptyParagraph } from "../paragraphParser.js";
|
|
3
|
+
import { buildStoryBlockReplay } from "../storyBlockReplay.js";
|
|
3
4
|
import { captureVerbatimXml } from "../verbatimCapture.js";
|
|
4
5
|
import { getLocalName, parseXmlDocument } from "../xmlParser.js";
|
|
5
6
|
import { serializeBlockCustomXml } from "./blockCustomXmlSerializer.js";
|
|
@@ -49,17 +50,14 @@ function serializeBlock(block) {
|
|
|
49
50
|
default: return block;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Serialize a HeaderFooter object to valid OOXML XML
|
|
54
|
-
*
|
|
55
|
-
* @param hf - HeaderFooter object to serialize
|
|
56
|
-
* @param source - The part being replaced, so a prefix only the source
|
|
57
|
-
* document bound keeps its URI
|
|
58
|
-
* @returns Complete XML string for header*.xml or footer*.xml
|
|
59
|
-
*/
|
|
60
53
|
function serializeHeaderFooter(hf, source) {
|
|
54
|
+
const baseline = getHeaderFooterSourceBaseline(hf, source?.originalBuffer);
|
|
55
|
+
if (baseline.type === "mismatch") source?.onDiagnostic?.({
|
|
56
|
+
type: "sourceReplayMismatch",
|
|
57
|
+
part: source.path
|
|
58
|
+
});
|
|
61
59
|
const verbatim = getHeaderFooterVerbatimXml(hf);
|
|
62
|
-
if (verbatim && canReplayHeaderFooterVerbatim(hf)) return verbatim;
|
|
60
|
+
if (baseline.type === "captured" && verbatim && canReplayHeaderFooterVerbatim(hf)) return verbatim;
|
|
63
61
|
const rootTag = hf.type === "header" ? "w:hdr" : "w:ftr";
|
|
64
62
|
const watermarkXml = serializeWatermarkParagraph(hf);
|
|
65
63
|
const watermarkInsertIndex = hf.watermarkBlockIndex !== void 0 ? Math.max(0, Math.min(hf.watermarkBlockIndex, hf.content.length)) : 0;
|
|
@@ -75,13 +73,23 @@ function serializeHeaderFooter(hf, source) {
|
|
|
75
73
|
});
|
|
76
74
|
contentXml = blocksXml.slice(0, watermarkInsertIndex).join("") + (mergesIntoRetainedHost ? "" : watermarkXml) + blocksXml.slice(watermarkInsertIndex).join("");
|
|
77
75
|
} else contentXml = blocksXml.join("");
|
|
78
|
-
|
|
76
|
+
const serializedXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
79
77
|
partPath: source?.path ?? `word/${hf.type}.xml`,
|
|
80
78
|
rootName: rootTag,
|
|
81
79
|
baselinePrefixes: HEADER_FOOTER_BASELINE_PREFIXES,
|
|
82
80
|
sourceBindings: source?.bindings,
|
|
83
81
|
body: contentXml
|
|
84
82
|
});
|
|
83
|
+
if (baseline.type === "captured" && verbatim && canReplayHeaderFooterBlocks(hf, baseline.content)) {
|
|
84
|
+
const replayed = buildStoryBlockReplay({
|
|
85
|
+
sourceXml: verbatim,
|
|
86
|
+
baselineContent: baseline.content,
|
|
87
|
+
currentContent: hf.content,
|
|
88
|
+
serializedXml
|
|
89
|
+
});
|
|
90
|
+
if (replayed !== null) return replayed;
|
|
91
|
+
}
|
|
92
|
+
return serializedXml;
|
|
85
93
|
}
|
|
86
94
|
function serializeRawWatermarkIntoHost({ hostXml, rawWatermarkXml }) {
|
|
87
95
|
const rawHost = parseXmlDocument(rawWatermarkXml);
|
|
@@ -16,9 +16,9 @@ declare function serializeFootnotes(footnotes: readonly document_d_exports.Footn
|
|
|
16
16
|
declare function serializeEndnotes(endnotes: readonly document_d_exports.Endnote[]): string;
|
|
17
17
|
/** Serialize a brand-new footnote part, including Word's required separators
|
|
18
18
|
* and the automatic reference mark at the start of every normal note. */
|
|
19
|
-
declare function serializeNewFootnotesPart(footnotes: readonly document_d_exports.Footnote[]): string;
|
|
19
|
+
declare function serializeNewFootnotesPart(footnotes: readonly document_d_exports.Footnote[], document?: document_d_exports.Document): string;
|
|
20
20
|
/** Serialize a brand-new endnote part, including Word's required separators
|
|
21
21
|
* and the automatic reference mark at the start of every normal note. */
|
|
22
|
-
declare function serializeNewEndnotesPart(endnotes: readonly document_d_exports.Endnote[]): string;
|
|
22
|
+
declare function serializeNewEndnotesPart(endnotes: readonly document_d_exports.Endnote[], document?: document_d_exports.Document): string;
|
|
23
23
|
//#endregion
|
|
24
24
|
export { serializeEndnotes, serializeFootnotes, serializeNewEndnotesPart, serializeNewFootnotesPart };
|