@stll/folio-core 0.47.7 → 0.49.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 +565 -121
- package/dist/ai-edits/minimal-replacement.d.ts +64 -0
- package/dist/ai-edits/minimal-replacement.js +282 -0
- package/dist/controller/fontReadiness.js +3 -3
- package/dist/controller/hyphenationReadiness.d.ts +19 -0
- package/dist/controller/hyphenationReadiness.js +47 -0
- package/dist/controller/layoutPipeline.d.ts +3 -0
- package/dist/controller/layoutPipeline.js +70 -18
- package/dist/display-list/build/buildDisplayList.js +39 -12
- package/dist/display-list/build/pageFurniture.d.ts +7 -1
- package/dist/display-list/build/pageFurniture.js +21 -8
- package/dist/display-list/build/paragraphPrimitives.js +68 -11
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/display-list/build/textBoxPrimitives.js +1 -1
- package/dist/display-list/build/unsupported.d.ts +2 -2
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +0 -1
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +79 -64
- package/dist/docx/bulletMarkers.d.ts +18 -2
- package/dist/docx/bulletMarkers.js +27 -2
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +57 -45
- package/dist/docx/containerChildren.d.ts +21 -8
- package/dist/docx/containerChildren.js +39 -9
- package/dist/docx/documentParser.d.ts +5 -1
- package/dist/docx/documentParser.js +8 -5
- package/dist/docx/documentSectionFacts.d.ts +22 -0
- package/dist/docx/documentSectionFacts.js +43 -0
- package/dist/docx/drawingGroupChildren.d.ts +60 -0
- package/dist/docx/drawingGroupChildren.js +176 -0
- package/dist/docx/drawingUtils.js +3 -0
- package/dist/docx/fieldParser.d.ts +8 -1
- package/dist/docx/fieldParser.js +47 -3
- package/dist/docx/fontTableParser.js +34 -27
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +15 -12
- package/dist/docx/groupDrawingParser.d.ts +9 -2
- package/dist/docx/groupDrawingParser.js +125 -37
- package/dist/docx/headerFooterParser.d.ts +7 -2
- package/dist/docx/headerFooterParser.js +15 -5
- package/dist/docx/hyperlinkParser.d.ts +48 -36
- package/dist/docx/hyperlinkParser.js +97 -82
- package/dist/docx/numberingParser.js +108 -84
- package/dist/docx/packageParts.d.ts +45 -1
- package/dist/docx/packageParts.js +93 -2
- package/dist/docx/paraIdAttribute.d.ts +3 -2
- package/dist/docx/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +468 -365
- package/dist/docx/paragraphProperties.js +123 -109
- package/dist/docx/paragraphPropertySource.d.ts +6 -1
- package/dist/docx/paragraphPropertySource.js +9 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +143 -10
- package/dist/docx/parser.d.ts +7 -1
- package/dist/docx/parser.js +33 -16
- package/dist/docx/previewBudget.d.ts +55 -33
- package/dist/docx/previewBudget.js +59 -65
- package/dist/docx/rezip.js +41 -58
- package/dist/docx/runParser.d.ts +4 -1
- package/dist/docx/runParser.js +182 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/selectiveSaveFlags.d.ts +10 -3
- package/dist/docx/selectiveSaveFlags.js +1 -1
- package/dist/docx/selectiveXmlPatch.d.ts +56 -34
- package/dist/docx/selectiveXmlPatch.js +222 -115
- package/dist/docx/serializer/groupTextBoxWriteBack.d.ts +12 -0
- package/dist/docx/serializer/groupTextBoxWriteBack.js +101 -0
- package/dist/docx/serializer/paragraphSerializer.js +47 -42
- package/dist/docx/serializer/runSerializer.d.ts +5 -1
- package/dist/docx/serializer/runSerializer.js +4 -3
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -0
- package/dist/docx/shapeAlternateContent.d.ts +25 -0
- package/dist/docx/shapeAlternateContent.js +52 -0
- package/dist/docx/streamingXmlParser.d.ts +6 -2
- package/dist/docx/streamingXmlParser.js +12 -7
- package/dist/docx/styleParser.js +34 -8
- package/dist/docx/tableParser.d.ts +21 -12
- package/dist/docx/tableParser.js +518 -441
- package/dist/docx/textBoxParser.d.ts +18 -5
- package/dist/docx/textBoxParser.js +12 -6
- package/dist/docx/verbatimCapture.d.ts +10 -8
- package/dist/docx/verbatimCapture.js +45 -2
- package/dist/docx/vmlImageParser.d.ts +15 -13
- package/dist/docx/vmlImageParser.js +75 -60
- package/dist/docx/vmlPreview.d.ts +3 -3
- package/dist/docx/vmlPreview.js +3 -4
- package/dist/docx/xmlNamespaceContext.d.ts +9 -0
- package/dist/docx/xmlNamespaceContext.js +54 -0
- package/dist/docx/xmlParser.d.ts +6 -3
- package/dist/docx/xmlParser.js +11 -41
- package/dist/docx/xmlResourceLimits.d.ts +2 -1
- package/dist/docx/xmlResourceLimits.js +4 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/headless-layout.d.ts +11 -2
- package/dist/headless-layout.js +153 -107
- package/dist/internal/headlessRevisionResolution.js +50 -13
- package/dist/internal/paragraphFormattingSerialization.js +3 -3
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
- package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
- package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
- package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
- package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +284 -39
- package/dist/layout-bridge/engine/hitTest.js +5 -3
- package/dist/layout-bridge/engine/selectionRects.js +5 -3
- package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
- package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +102 -14
- package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
- package/dist/layout-engine/justificationCompatibility.js +9 -5
- package/dist/layout-engine/keep-together.d.ts +15 -6
- package/dist/layout-engine/keep-together.js +43 -16
- package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
- package/dist/layout-engine/layoutInstrumentation.js +8 -1
- package/dist/layout-engine/measure/advanceComposition.js +50 -7
- package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
- package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
- package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
- package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
- package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
- package/dist/layout-engine/measure/lineBreaks.js +10 -3
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
- package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
- package/dist/layout-engine/measure/measureBlocks.js +46 -10
- package/dist/layout-engine/measure/measureContainer.js +51 -8
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +34 -8
- package/dist/layout-engine/measure/measureParagraph.js +143 -101
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
- package/dist/layout-engine/measure/smallCapsCasing.d.ts +56 -0
- package/dist/layout-engine/measure/smallCapsCasing.js +88 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
- package/dist/layout-engine/measure/tabCalculator.js +2 -1
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +51 -19
- package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
- package/dist/layout-engine/measure/tableCellGrid.js +45 -5
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
- package/dist/layout-engine/noteAreaFlow.js +83 -0
- package/dist/layout-engine/paginator.d.ts +12 -1
- package/dist/layout-engine/paginator.js +18 -2
- package/dist/layout-engine/paragraphSpacing.d.ts +4 -2
- package/dist/layout-engine/paragraphSpacing.js +2 -1
- package/dist/layout-engine/tableRowBreak.d.ts +8 -1
- package/dist/layout-engine/tableRowBreak.js +25 -2
- package/dist/layout-engine/types.d.ts +108 -3
- package/dist/layout-engine/types.js +96 -1
- package/dist/layout-painter/index.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +32 -83
- package/dist/layout-painter/renderParagraph.d.ts +6 -1
- package/dist/layout-painter/renderParagraph.js +75 -26
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/layout-painter/renderTextBox.d.ts +12 -2
- package/dist/layout-painter/renderTextBox.js +26 -2
- package/dist/prosemirror/alternateContentAttrs.d.ts +9 -0
- package/dist/prosemirror/alternateContentAttrs.js +35 -0
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +133 -11
- package/dist/prosemirror/commands/comments.js +51 -41
- package/dist/prosemirror/contentControlRevisions.d.ts +43 -0
- package/dist/prosemirror/contentControlRevisions.js +84 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +54 -23
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +117 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +7 -7
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -7
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +6 -3
- package/dist/prosemirror/extensions/nodes/SdtExtension.js +9 -2
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +4 -2
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/paragraphDirection.d.ts +29 -2
- package/dist/prosemirror/paragraphDirection.js +21 -2
- package/dist/prosemirror/plugins/suggestionMode.js +37 -8
- package/dist/prosemirror/rejoinRunCarriers.d.ts +27 -0
- package/dist/prosemirror/rejoinRunCarriers.js +66 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +10 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.js +90 -0
- package/dist/prosemirror/schema/nodes.d.ts +50 -6
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +10 -1
- package/dist/utils/scriptSegments.d.ts +33 -4
- package/dist/utils/scriptSegments.js +39 -6
- package/dist/utils/textFormattingMerge.d.ts +17 -3
- package/dist/utils/textFormattingMerge.js +18 -12
- package/dist/utils/trailingText.d.ts +22 -0
- package/dist/utils/trailingText.js +32 -0
- package/package.json +2 -2
- package/dist/layout-engine/justifiedLineFit.d.ts +0 -7
- package/dist/layout-engine/justifiedLineFit.js +0 -6
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
2
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
3
|
+
import { findChildByLocalName, findDeep, getAttribute, getChildElements, getLocalName, parseNumericAttribute, parseXml } from "./xmlParser.js";
|
|
4
|
+
//#region src/docx/drawingGroupChildren.ts
|
|
5
|
+
/**
|
|
6
|
+
* The text boxes of a DrawingML group (`wpg:wgp`), read as frames folio can lay
|
|
7
|
+
* out, and written back into the group's authored XML.
|
|
8
|
+
*
|
|
9
|
+
* A group states a child coordinate space (`a:chOff` / `a:chExt`) that its
|
|
10
|
+
* own frame (`a:off` / `a:ext`) maps onto, and every child's `a:xfrm` is in
|
|
11
|
+
* that space; a nested `wpg:grpSp` repeats the mapping one level down
|
|
12
|
+
* (ECMA-376 §20.1.7.5). Composing the mappings gives each `wps:wsp` a frame
|
|
13
|
+
* in EMUs relative to the group's own top-left corner. Only the frame is
|
|
14
|
+
* mapped: the text inside keeps its authored size and the body insets stay in
|
|
15
|
+
* EMUs.
|
|
16
|
+
*/
|
|
17
|
+
/** `a:xfrm@rot` is in 60,000ths of a degree. */
|
|
18
|
+
const ROTATION_UNITS_PER_DEGREE = 6e4;
|
|
19
|
+
/** Deeper nesting than this is not a drawing anyone authored. */
|
|
20
|
+
const MAX_GROUP_DEPTH = 16;
|
|
21
|
+
const MAX_GROUP_TEXT_BOXES = 256;
|
|
22
|
+
const numberAttribute = (element, name) => parseNumericAttribute(element, null, name) ?? 0;
|
|
23
|
+
const onOffAttribute = (element, name) => {
|
|
24
|
+
const value = getAttribute(element, null, name);
|
|
25
|
+
return value === "1" || value === "true" || value === "on";
|
|
26
|
+
};
|
|
27
|
+
/** A `CT_GroupTransform2D` or `CT_Transform2D`; absent children read as zero. */
|
|
28
|
+
const readTransform = (xfrm) => {
|
|
29
|
+
const offset = findChildByLocalName(xfrm, "off");
|
|
30
|
+
const extent = findChildByLocalName(xfrm, "ext");
|
|
31
|
+
const childOffset = findChildByLocalName(xfrm, "chOff");
|
|
32
|
+
const childExtent = findChildByLocalName(xfrm, "chExt");
|
|
33
|
+
return {
|
|
34
|
+
x: numberAttribute(offset, "x"),
|
|
35
|
+
y: numberAttribute(offset, "y"),
|
|
36
|
+
width: numberAttribute(extent, "cx"),
|
|
37
|
+
height: numberAttribute(extent, "cy"),
|
|
38
|
+
childX: numberAttribute(childOffset, "x"),
|
|
39
|
+
childY: numberAttribute(childOffset, "y"),
|
|
40
|
+
childWidth: numberAttribute(childExtent, "cx"),
|
|
41
|
+
childHeight: numberAttribute(childExtent, "cy"),
|
|
42
|
+
rotation: numberAttribute(xfrm, "rot") / ROTATION_UNITS_PER_DEGREE,
|
|
43
|
+
flipH: onOffAttribute(xfrm, "flipH"),
|
|
44
|
+
flipV: onOffAttribute(xfrm, "flipV")
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
const groupTransform = (group) => readTransform(findChildByLocalName(findChildByLocalName(group, "grpSpPr"), "xfrm"));
|
|
48
|
+
const shapeTransform = (shape) => readTransform(findChildByLocalName(findChildByLocalName(shape, "spPr"), "xfrm"));
|
|
49
|
+
/**
|
|
50
|
+
* The top-level mapping: the group's child space stretched over the drawing's
|
|
51
|
+
* extent. A missing or empty child extent means the child space is the
|
|
52
|
+
* drawing's own.
|
|
53
|
+
*/
|
|
54
|
+
const rootMap = (group, width, height) => {
|
|
55
|
+
const transform = groupTransform(group);
|
|
56
|
+
const scaleX = transform.childWidth > 0 ? width / transform.childWidth : 1;
|
|
57
|
+
const scaleY = transform.childHeight > 0 ? height / transform.childHeight : 1;
|
|
58
|
+
return {
|
|
59
|
+
scaleX,
|
|
60
|
+
scaleY,
|
|
61
|
+
offsetX: -transform.childX * scaleX,
|
|
62
|
+
offsetY: -transform.childY * scaleY
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
/** A nested group's child space, mapped through its frame in the parent's space. */
|
|
66
|
+
const nestedMap = (parent, transform) => {
|
|
67
|
+
const scaleX = transform.childWidth > 0 ? transform.width / transform.childWidth : 1;
|
|
68
|
+
const scaleY = transform.childHeight > 0 ? transform.height / transform.childHeight : 1;
|
|
69
|
+
return {
|
|
70
|
+
scaleX: parent.scaleX * scaleX,
|
|
71
|
+
scaleY: parent.scaleY * scaleY,
|
|
72
|
+
offsetX: parent.scaleX * (transform.x - transform.childX * scaleX) + parent.offsetX,
|
|
73
|
+
offsetY: parent.scaleY * (transform.y - transform.childY * scaleY) + parent.offsetY
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const hasTextBox = (wsp) => findChildByLocalName(findChildByLocalName(wsp, "txbx"), "txbxContent") !== null;
|
|
77
|
+
/**
|
|
78
|
+
* Every `wps:wsp` with a text box in the group, nested groups included, with
|
|
79
|
+
* its frame in EMUs from the group's top-left corner.
|
|
80
|
+
*
|
|
81
|
+
* A nested group that is rotated or flipped turns its children's frames into
|
|
82
|
+
* something other than a rectangle in the drawing's axes, so its text boxes
|
|
83
|
+
* are left out and stay with the preview.
|
|
84
|
+
*/
|
|
85
|
+
const collectGroupTextBoxes = (group, width, height) => {
|
|
86
|
+
const frames = [];
|
|
87
|
+
const visit = (container, map, path, depth) => {
|
|
88
|
+
for (const [index, child] of getChildElements(container).entries()) {
|
|
89
|
+
if (frames.length >= MAX_GROUP_TEXT_BOXES) return;
|
|
90
|
+
const localName = getLocalName(child.name ?? "");
|
|
91
|
+
if (localName === "grpSp" && depth < MAX_GROUP_DEPTH) {
|
|
92
|
+
const transform = groupTransform(child);
|
|
93
|
+
if (transform.rotation === 0 && !transform.flipH && !transform.flipV) visit(child, nestedMap(map, transform), [...path, index], depth + 1);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (localName !== "wsp" || !hasTextBox(child)) continue;
|
|
97
|
+
const transform = shapeTransform(child);
|
|
98
|
+
const frameWidth = transform.width * map.scaleX;
|
|
99
|
+
const frameHeight = transform.height * map.scaleY;
|
|
100
|
+
if (!(frameWidth > 0 && frameHeight > 0)) continue;
|
|
101
|
+
frames.push({
|
|
102
|
+
path: [...path, index],
|
|
103
|
+
wsp: child,
|
|
104
|
+
x: transform.x * map.scaleX + map.offsetX,
|
|
105
|
+
y: transform.y * map.scaleY + map.offsetY,
|
|
106
|
+
width: frameWidth,
|
|
107
|
+
height: frameHeight,
|
|
108
|
+
rotation: transform.rotation,
|
|
109
|
+
flipH: transform.flipH,
|
|
110
|
+
flipV: transform.flipV
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
visit(group, rootMap(group, width, height), [], 0);
|
|
115
|
+
return frames;
|
|
116
|
+
};
|
|
117
|
+
/** Two FNV-1a passes with different offsets: a short, stable identity. */
|
|
118
|
+
const fingerprint = (text) => {
|
|
119
|
+
let first = 2166136261;
|
|
120
|
+
let second = 16777619;
|
|
121
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
122
|
+
const code = text.charCodeAt(index);
|
|
123
|
+
first = Math.imul(first ^ code, 16777619);
|
|
124
|
+
second = Math.imul(second ^ code, 96280213);
|
|
125
|
+
}
|
|
126
|
+
return `${(first >>> 0).toString(16).padStart(8, "0")}${(second >>> 0).toString(16).padStart(8, "0")}`;
|
|
127
|
+
};
|
|
128
|
+
/** Identity of a group drawing's authored XML. */
|
|
129
|
+
const groupXmlFingerprint = (rawXml) => fingerprint(rawXml);
|
|
130
|
+
/** Identity of a text box's content, compared on save to tell an edit. */
|
|
131
|
+
const groupTextContentFingerprint = (content) => fingerprint(canonicalJson(content));
|
|
132
|
+
/** The group a captured drawing carries; a Fallback branch holds none. */
|
|
133
|
+
const findGroup = (root) => findDeep(root, "wpg", "wgp") ?? void 0;
|
|
134
|
+
const childAtPath = (group, path) => {
|
|
135
|
+
let current = group;
|
|
136
|
+
for (const index of path) current = current ? getChildElements(current)[index] : void 0;
|
|
137
|
+
return current;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The text box content element a path names, or undefined when the path does
|
|
141
|
+
* not lead to a `wps:wsp` holding one.
|
|
142
|
+
*/
|
|
143
|
+
const textBoxContentAt = (group, path) => {
|
|
144
|
+
const wsp = childAtPath(group, path);
|
|
145
|
+
if (!wsp || getLocalName(wsp.name ?? "") !== "wsp") return;
|
|
146
|
+
return findChildByLocalName(findChildByLocalName(wsp, "txbx"), "txbxContent") ?? void 0;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* The captured group XML with each edited text box's content replaced, or
|
|
150
|
+
* undefined when an edit names no text box in it.
|
|
151
|
+
*
|
|
152
|
+
* The replacement is written as a placeholder element and substituted after
|
|
153
|
+
* the tree is serialized, so the new content is never reparsed and the rest
|
|
154
|
+
* of the capture is written exactly as it was read.
|
|
155
|
+
*/
|
|
156
|
+
const replaceGroupTextBoxContent = (rawXml, edits) => {
|
|
157
|
+
const root = parseXml(rawXml);
|
|
158
|
+
const group = findGroup(root);
|
|
159
|
+
if (!group) return;
|
|
160
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const [index, edit] of edits.entries()) {
|
|
162
|
+
const content = textBoxContentAt(group, edit.path);
|
|
163
|
+
if (!content) return;
|
|
164
|
+
const placeholder = `folio-group-text-${index}-${fingerprint(rawXml)}`;
|
|
165
|
+
content.elements = [{
|
|
166
|
+
type: "element",
|
|
167
|
+
name: placeholder
|
|
168
|
+
}];
|
|
169
|
+
replacements.set(`<${placeholder}/>`, edit.contentXml || "<w:p/>");
|
|
170
|
+
}
|
|
171
|
+
let xml = (root.elements ?? []).map((element) => captureVerbatimXml(element)).join("");
|
|
172
|
+
for (const [placeholder, contentXml] of replacements) xml = xml.replace(placeholder, () => contentXml);
|
|
173
|
+
return xml;
|
|
174
|
+
};
|
|
175
|
+
//#endregion
|
|
176
|
+
export { collectGroupTextBoxes, groupTextContentFingerprint, groupXmlFingerprint, readTransform, replaceGroupTextBoxContent };
|
|
@@ -107,6 +107,7 @@ function parseFill(spPr) {
|
|
|
107
107
|
function parseGradientFill(gradientFill) {
|
|
108
108
|
let type = "linear";
|
|
109
109
|
let angle;
|
|
110
|
+
let scaled;
|
|
110
111
|
const linear = findChildByLocalName(gradientFill, "lin");
|
|
111
112
|
if (linear) {
|
|
112
113
|
const authoredAngle = getAttribute(linear, null, "ang");
|
|
@@ -114,6 +115,7 @@ function parseGradientFill(gradientFill) {
|
|
|
114
115
|
const parsedAngle = Number.parseInt(authoredAngle, 10);
|
|
115
116
|
angle = Number.isNaN(parsedAngle) ? void 0 : parsedAngle / 6e4;
|
|
116
117
|
}
|
|
118
|
+
scaled = parseOnOffValue(getAttribute(linear, null, "scaled"), void 0, "a:lin@scaled");
|
|
117
119
|
}
|
|
118
120
|
const path = findChildByLocalName(gradientFill, "path");
|
|
119
121
|
if (path) {
|
|
@@ -139,6 +141,7 @@ function parseGradientFill(gradientFill) {
|
|
|
139
141
|
gradient: {
|
|
140
142
|
type,
|
|
141
143
|
...angle !== void 0 ? { angle } : {},
|
|
144
|
+
...scaled !== void 0 ? { scaled } : {},
|
|
142
145
|
stops
|
|
143
146
|
}
|
|
144
147
|
};
|
|
@@ -64,6 +64,13 @@ declare function parseFieldInstruction(instruction: string): ParsedFieldInstruct
|
|
|
64
64
|
* @returns Format string or undefined
|
|
65
65
|
*/
|
|
66
66
|
declare function getFormatSwitch(instruction: ParsedFieldInstruction): string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get the numeric picture switch value (\#), e.g. `0#` in `PAGE \# 0#`.
|
|
69
|
+
*
|
|
70
|
+
* @param instruction - Parsed instruction
|
|
71
|
+
* @returns Picture string or undefined
|
|
72
|
+
*/
|
|
73
|
+
declare function getNumericPictureSwitch(instruction: ParsedFieldInstruction): string | undefined;
|
|
67
74
|
/**
|
|
68
75
|
* Check if field has MERGEFORMAT switch (preserve formatting)
|
|
69
76
|
*
|
|
@@ -237,4 +244,4 @@ declare function getMergeFields(fields: document_d_exports.Field[]): document_d_
|
|
|
237
244
|
*/
|
|
238
245
|
declare function getMergeFieldNames(fields: document_d_exports.Field[]): string[];
|
|
239
246
|
//#endregion
|
|
240
|
-
export { ComplexFieldContext, ComplexFieldState, FieldSwitch, KNOWN_FIELD_TYPES, ParsedFieldInstruction, collectFields, computePageNumber, createComplexFieldContext, finalizeComplexField, formatDate, getFieldDisplayValue, getFieldsByType, getFormatSwitch, getMergeFieldNames, getMergeFields, getPageNumberFields, hasMergeFormat, isDateTimeField, isDocPropertyField, isHyperlinkField, isKnownFieldType, isMergeField, isPageNumberField, isReferenceField, isTocField, isTotalPagesField, parseFieldInstruction, parseFieldType, parseSimpleField, resetComplexFieldContext };
|
|
247
|
+
export { ComplexFieldContext, ComplexFieldState, FieldSwitch, KNOWN_FIELD_TYPES, ParsedFieldInstruction, collectFields, computePageNumber, createComplexFieldContext, finalizeComplexField, formatDate, getFieldDisplayValue, getFieldsByType, getFormatSwitch, getMergeFieldNames, getMergeFields, getNumericPictureSwitch, getPageNumberFields, hasMergeFormat, isDateTimeField, isDocPropertyField, isHyperlinkField, isKnownFieldType, isMergeField, isPageNumberField, isReferenceField, isTocField, isTotalPagesField, parseFieldInstruction, parseFieldType, parseSimpleField, resetComplexFieldContext };
|
package/dist/docx/fieldParser.js
CHANGED
|
@@ -141,6 +141,15 @@ function getFormatSwitch(instruction) {
|
|
|
141
141
|
return instruction.switches.find((s) => s.switch === "*" || s.switch === "@")?.value;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
+
* Get the numeric picture switch value (\#), e.g. `0#` in `PAGE \# 0#`.
|
|
145
|
+
*
|
|
146
|
+
* @param instruction - Parsed instruction
|
|
147
|
+
* @returns Picture string or undefined
|
|
148
|
+
*/
|
|
149
|
+
function getNumericPictureSwitch(instruction) {
|
|
150
|
+
return instruction.switches.find((s) => s.switch === "#")?.value;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
144
153
|
* Check if field has MERGEFORMAT switch (preserve formatting)
|
|
145
154
|
*
|
|
146
155
|
* @param instruction - Parsed instruction
|
|
@@ -345,16 +354,51 @@ function isTocField(field) {
|
|
|
345
354
|
* @returns Formatted page number string
|
|
346
355
|
*/
|
|
347
356
|
function computePageNumber(pageNumber, instruction, sectionFormat) {
|
|
357
|
+
const picture = instruction ? getNumericPictureSwitch(instruction) : void 0;
|
|
358
|
+
if (picture !== void 0) return applyNumericPicture(pageNumber, picture);
|
|
348
359
|
const format = instruction ? getFormatSwitch(instruction) : void 0;
|
|
349
360
|
if (!format || format.toUpperCase() === "MERGEFORMAT") return formatSectionPageNumber(pageNumber, sectionFormat);
|
|
361
|
+
const isLowercaseSwitch = format === format.toLowerCase();
|
|
350
362
|
switch (format.toUpperCase()) {
|
|
351
|
-
case "ROMAN":
|
|
352
|
-
|
|
363
|
+
case "ROMAN": {
|
|
364
|
+
const roman = toRoman(pageNumber);
|
|
365
|
+
return isLowercaseSwitch ? roman.toLowerCase() : roman;
|
|
366
|
+
}
|
|
367
|
+
case "ALPHABETIC": {
|
|
368
|
+
const letters = toLetter(pageNumber);
|
|
369
|
+
return isLowercaseSwitch ? letters.toLowerCase() : letters;
|
|
370
|
+
}
|
|
353
371
|
default: return String(pageNumber);
|
|
354
372
|
}
|
|
355
373
|
}
|
|
356
374
|
const formatSectionPageNumber = (pageNumber, format) => formatOoxmlCounter(pageNumber, format);
|
|
357
375
|
/**
|
|
376
|
+
* Apply a `\#` numeric picture (ECMA-376 §17.16.4.2) to an integer field
|
|
377
|
+
* value. `0` is a mandatory digit placeholder that zero-pads once the value
|
|
378
|
+
* runs out of digits; `#` is an optional placeholder that is left blank
|
|
379
|
+
* instead; every other picture character (including a thousands separator)
|
|
380
|
+
* is copied through literally. Placeholders line up with the value's digits
|
|
381
|
+
* from the right; digits that reach past the leftmost placeholder are kept,
|
|
382
|
+
* not truncated.
|
|
383
|
+
*/
|
|
384
|
+
function applyNumericPicture(value, picture) {
|
|
385
|
+
const negative = value < 0;
|
|
386
|
+
const digits = [...String(Math.trunc(Math.abs(value)))];
|
|
387
|
+
const pictureChars = [...picture];
|
|
388
|
+
const output = Array.from({ length: pictureChars.length });
|
|
389
|
+
let digitIndex = digits.length - 1;
|
|
390
|
+
for (let i = pictureChars.length - 1; i >= 0; i--) {
|
|
391
|
+
const char = pictureChars[i];
|
|
392
|
+
if (char === "0" || char === "#") if (digitIndex >= 0) {
|
|
393
|
+
output[i] = digits[digitIndex];
|
|
394
|
+
digitIndex--;
|
|
395
|
+
} else output[i] = char === "0" ? "0" : "";
|
|
396
|
+
else output[i] = char;
|
|
397
|
+
}
|
|
398
|
+
const overflow = digitIndex >= 0 ? digits.slice(0, digitIndex + 1).join("") : "";
|
|
399
|
+
return (negative ? "-" : "") + overflow + output.join("");
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
358
402
|
* Convert number to uppercase Roman numerals
|
|
359
403
|
*/
|
|
360
404
|
function toRoman(num) {
|
|
@@ -555,4 +599,4 @@ function getMergeFieldNames(fields) {
|
|
|
555
599
|
}).filter((name) => !!name);
|
|
556
600
|
}
|
|
557
601
|
//#endregion
|
|
558
|
-
export { KNOWN_FIELD_TYPES, collectFields, computePageNumber, createComplexFieldContext, finalizeComplexField, formatDate, getFieldDisplayValue, getFieldsByType, getFormatSwitch, getMergeFieldNames, getMergeFields, getPageNumberFields, hasMergeFormat, isDateTimeField, isDocPropertyField, isHyperlinkField, isKnownFieldType, isMergeField, isPageNumberField, isReferenceField, isTocField, isTotalPagesField, parseFieldInstruction, parseFieldType, parseSimpleField, resetComplexFieldContext };
|
|
602
|
+
export { KNOWN_FIELD_TYPES, collectFields, computePageNumber, createComplexFieldContext, finalizeComplexField, formatDate, getFieldDisplayValue, getFieldsByType, getFormatSwitch, getMergeFieldNames, getMergeFields, getNumericPictureSwitch, getPageNumberFields, hasMergeFormat, isDateTimeField, isDocPropertyField, isHyperlinkField, isKnownFieldType, isMergeField, isPageNumberField, isReferenceField, isTocField, isTotalPagesField, parseFieldInstruction, parseFieldType, parseSimpleField, resetComplexFieldContext };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DERIVED_PART_ROOT_ATTRIBUTES, attributeRemainder } from "./attributeRemainder.js";
|
|
2
|
-
import { CAPTURE,
|
|
2
|
+
import { CAPTURE, dispatchChildrenWithContext } from "./containerChildren.js";
|
|
3
3
|
import { getAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
4
4
|
//#region src/docx/fontTableParser.ts
|
|
5
5
|
const FONT_FAMILIES = [
|
|
@@ -22,14 +22,12 @@ const parseFontTable = (xml) => {
|
|
|
22
22
|
const root = parseXmlDocument(xml);
|
|
23
23
|
if (!root) return;
|
|
24
24
|
const fonts = [];
|
|
25
|
-
const preserved =
|
|
25
|
+
const preserved = dispatchChildrenWithContext({
|
|
26
26
|
element: root,
|
|
27
27
|
container: "w:fonts",
|
|
28
28
|
capturePosition: () => fonts.length,
|
|
29
|
-
handlers:
|
|
30
|
-
|
|
31
|
-
if (font) fonts.push(font);
|
|
32
|
-
} }
|
|
29
|
+
handlers: FONT_TABLE_HANDLERS,
|
|
30
|
+
context: fonts
|
|
33
31
|
});
|
|
34
32
|
const preservedAttributes = attributeRemainder({
|
|
35
33
|
element: root,
|
|
@@ -45,31 +43,18 @@ const parseFontTable = (xml) => {
|
|
|
45
43
|
const parseFont = (element) => {
|
|
46
44
|
const name = getAttribute(element, "w", "name");
|
|
47
45
|
if (!name) return;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (value === void 0) return;
|
|
52
|
-
font[key] = value;
|
|
53
|
-
modelled += 1;
|
|
46
|
+
const walk = {
|
|
47
|
+
font: { name },
|
|
48
|
+
modelled: 0
|
|
54
49
|
};
|
|
55
|
-
const preserved =
|
|
50
|
+
const preserved = dispatchChildrenWithContext({
|
|
56
51
|
element,
|
|
57
52
|
container: "w:font",
|
|
58
|
-
capturePosition: () => modelled,
|
|
59
|
-
handlers:
|
|
60
|
-
|
|
61
|
-
panose1: (child) => read("panose1", value(child)),
|
|
62
|
-
charset: (child) => read("charset", charsetOf(child)),
|
|
63
|
-
family: (child) => read("family", narrow(value(child), FONT_FAMILIES)),
|
|
64
|
-
notTrueType: CAPTURE,
|
|
65
|
-
pitch: (child) => read("pitch", narrow(value(child), FONT_PITCHES)),
|
|
66
|
-
sig: (child) => read("sig", signatureOf(child)),
|
|
67
|
-
embedRegular: (child) => read("embedRegular", embedOf(child)),
|
|
68
|
-
embedBold: (child) => read("embedBold", embedOf(child)),
|
|
69
|
-
embedItalic: (child) => read("embedItalic", embedOf(child)),
|
|
70
|
-
embedBoldItalic: (child) => read("embedBoldItalic", embedOf(child))
|
|
71
|
-
}
|
|
53
|
+
capturePosition: () => walk.modelled,
|
|
54
|
+
handlers: FONT_HANDLERS,
|
|
55
|
+
context: walk
|
|
72
56
|
});
|
|
57
|
+
const { font } = walk;
|
|
73
58
|
if (preserved !== void 0) font.preserved = preserved;
|
|
74
59
|
const preservedAttributes = attributeRemainder({
|
|
75
60
|
element,
|
|
@@ -129,5 +114,27 @@ const signatureOf = (element) => {
|
|
|
129
114
|
return Object.keys(signature).length === 0 ? void 0 : signature;
|
|
130
115
|
};
|
|
131
116
|
const narrow = (carried, members) => members.find((member) => member === carried);
|
|
117
|
+
const FONT_TABLE_HANDLERS = { font: (element, fonts) => {
|
|
118
|
+
const font = parseFont(element);
|
|
119
|
+
if (font) fonts.push(font);
|
|
120
|
+
} };
|
|
121
|
+
const read = (walk, key, carried) => {
|
|
122
|
+
if (carried === void 0) return;
|
|
123
|
+
walk.font[key] = carried;
|
|
124
|
+
walk.modelled += 1;
|
|
125
|
+
};
|
|
126
|
+
const FONT_HANDLERS = {
|
|
127
|
+
altName: (child, walk) => read(walk, "altName", value(child)),
|
|
128
|
+
panose1: (child, walk) => read(walk, "panose1", value(child)),
|
|
129
|
+
charset: (child, walk) => read(walk, "charset", charsetOf(child)),
|
|
130
|
+
family: (child, walk) => read(walk, "family", narrow(value(child), FONT_FAMILIES)),
|
|
131
|
+
notTrueType: CAPTURE,
|
|
132
|
+
pitch: (child, walk) => read(walk, "pitch", narrow(value(child), FONT_PITCHES)),
|
|
133
|
+
sig: (child, walk) => read(walk, "sig", signatureOf(child)),
|
|
134
|
+
embedRegular: (child, walk) => read(walk, "embedRegular", embedOf(child)),
|
|
135
|
+
embedBold: (child, walk) => read(walk, "embedBold", embedOf(child)),
|
|
136
|
+
embedItalic: (child, walk) => read(walk, "embedItalic", embedOf(child)),
|
|
137
|
+
embedBoldItalic: (child, walk) => read(walk, "embedBoldItalic", embedOf(child))
|
|
138
|
+
};
|
|
132
139
|
//#endregion
|
|
133
140
|
export { parseFontTable };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
3
|
import { ParseContext } from "./parseContext.js";
|
|
4
|
+
import { PreviewLedger } from "./previewBudget.js";
|
|
4
5
|
import { StyleMap } from "./styleParser.js";
|
|
5
6
|
import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
|
|
6
7
|
//#region src/docx/footnoteParser.d.ts
|
|
@@ -53,7 +54,7 @@ type EndnoteMap = {
|
|
|
53
54
|
* @param media - Media files for images
|
|
54
55
|
* @returns FootnoteMap with all footnotes
|
|
55
56
|
*/
|
|
56
|
-
declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext): FootnoteMap;
|
|
57
|
+
declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext, previews?: PreviewLedger): FootnoteMap;
|
|
57
58
|
/**
|
|
58
59
|
* Parse endnotes.xml
|
|
59
60
|
*
|
|
@@ -65,7 +66,7 @@ declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap |
|
|
|
65
66
|
* @param media - Media files for images
|
|
66
67
|
* @returns EndnoteMap with all endnotes
|
|
67
68
|
*/
|
|
68
|
-
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext): EndnoteMap;
|
|
69
|
+
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext, previews?: PreviewLedger): EndnoteMap;
|
|
69
70
|
/**
|
|
70
71
|
* Get plain text content of a footnote.
|
|
71
72
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { blockPlainText } from "./blockPlainText.js";
|
|
2
2
|
import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
|
|
3
3
|
import { parseParagraph } from "./paragraphParser.js";
|
|
4
|
+
import { standalonePreviewLedger } from "./previewBudget.js";
|
|
4
5
|
import { captureSdtSiblingMarkers, parseSdtProperties } from "./sdtProperties.js";
|
|
5
6
|
import { parseTable } from "./tableParser.js";
|
|
6
7
|
import { findChildren, findWordprocessingChild, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
|
|
@@ -27,13 +28,13 @@ function parseNoteId(element) {
|
|
|
27
28
|
const parsed = Number.parseInt(id, 10);
|
|
28
29
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
29
30
|
}
|
|
30
|
-
function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
|
|
31
|
+
function parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews) {
|
|
31
32
|
const blocks = [];
|
|
32
33
|
for (const child of getChildElements(element)) {
|
|
33
34
|
const localName = getLocalName(child.name ?? "");
|
|
34
|
-
if (localName === "p") blocks.push(parseParagraph(child, styles, theme, numbering, rels));
|
|
35
|
+
if (localName === "p") blocks.push(parseParagraph(child, styles, theme, numbering, rels, media, { previews }));
|
|
35
36
|
else if (localName === "tbl") {
|
|
36
|
-
const table = parseTable(child, styles, theme, numbering, rels, media);
|
|
37
|
+
const table = parseTable(child, styles, theme, numbering, rels, media, { previews });
|
|
37
38
|
if (table) blocks.push(table);
|
|
38
39
|
} else if (localName === "sdt") {
|
|
39
40
|
const sdtPr = findWordprocessingChild(child, "sdtPr");
|
|
@@ -46,7 +47,7 @@ function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
|
|
|
46
47
|
blocks.push({
|
|
47
48
|
type: "blockSdt",
|
|
48
49
|
properties,
|
|
49
|
-
content: sdtContent ? parseNoteBlockContent(sdtContent, styles, theme, numbering, rels, media) : []
|
|
50
|
+
content: sdtContent ? parseNoteBlockContent(sdtContent, styles, theme, numbering, rels, media, previews) : []
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
53
|
}
|
|
@@ -55,12 +56,12 @@ function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
|
|
|
55
56
|
/**
|
|
56
57
|
* Parse a single footnote element (w:footnote)
|
|
57
58
|
*/
|
|
58
|
-
function parseFootnote(element, styles, theme, numbering, rels, media) {
|
|
59
|
+
function parseFootnote(element, styles, theme, numbering, rels, media, previews) {
|
|
59
60
|
return {
|
|
60
61
|
type: "footnote",
|
|
61
62
|
id: parseNoteId(element),
|
|
62
63
|
noteType: parseNoteType(getNoteAttribute(element, "type")),
|
|
63
|
-
content: parseNoteBlockContent(element, styles, theme, numbering, rels, media)
|
|
64
|
+
content: parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews)
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
@@ -74,7 +75,7 @@ function parseFootnote(element, styles, theme, numbering, rels, media) {
|
|
|
74
75
|
* @param media - Media files for images
|
|
75
76
|
* @returns FootnoteMap with all footnotes
|
|
76
77
|
*/
|
|
77
|
-
function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
|
|
78
|
+
function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context, previews = standalonePreviewLedger()) {
|
|
78
79
|
const byId = /* @__PURE__ */ new Map();
|
|
79
80
|
const footnotes = [];
|
|
80
81
|
if (!footnotesXml) return createFootnoteMap(byId, footnotes);
|
|
@@ -82,13 +83,14 @@ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = n
|
|
|
82
83
|
if (!rootElement) return createFootnoteMap(byId, footnotes);
|
|
83
84
|
const footnoteElements = findChildren(rootElement, "w", "footnote");
|
|
84
85
|
for (const fnEl of footnoteElements) {
|
|
85
|
-
const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media);
|
|
86
|
+
const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media, previews);
|
|
86
87
|
if (byId.has(footnote.id)) {
|
|
87
88
|
context?.warn({
|
|
88
89
|
code: PARSE_WARNING_CODES.duplicateNoteId,
|
|
89
90
|
element: "w:footnote",
|
|
90
91
|
at: `w:id ${String(footnote.id)}`
|
|
91
92
|
});
|
|
93
|
+
previews.release(footnote);
|
|
92
94
|
continue;
|
|
93
95
|
}
|
|
94
96
|
byId.set(footnote.id, footnote);
|
|
@@ -123,12 +125,12 @@ function createFootnoteMap(byId, footnotes) {
|
|
|
123
125
|
/**
|
|
124
126
|
* Parse a single endnote element (w:endnote)
|
|
125
127
|
*/
|
|
126
|
-
function parseEndnote(element, styles, theme, numbering, rels, media) {
|
|
128
|
+
function parseEndnote(element, styles, theme, numbering, rels, media, previews) {
|
|
127
129
|
return {
|
|
128
130
|
type: "endnote",
|
|
129
131
|
id: parseNoteId(element),
|
|
130
132
|
noteType: parseNoteType(getNoteAttribute(element, "type")),
|
|
131
|
-
content: parseNoteBlockContent(element, styles, theme, numbering, rels, media)
|
|
133
|
+
content: parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews)
|
|
132
134
|
};
|
|
133
135
|
}
|
|
134
136
|
/**
|
|
@@ -142,7 +144,7 @@ function parseEndnote(element, styles, theme, numbering, rels, media) {
|
|
|
142
144
|
* @param media - Media files for images
|
|
143
145
|
* @returns EndnoteMap with all endnotes
|
|
144
146
|
*/
|
|
145
|
-
function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
|
|
147
|
+
function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context, previews = standalonePreviewLedger()) {
|
|
146
148
|
const byId = /* @__PURE__ */ new Map();
|
|
147
149
|
const endnotes = [];
|
|
148
150
|
if (!endnotesXml) return createEndnoteMap(byId, endnotes);
|
|
@@ -150,13 +152,14 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
|
|
|
150
152
|
if (!rootElement) return createEndnoteMap(byId, endnotes);
|
|
151
153
|
const endnoteElements = findChildren(rootElement, "w", "endnote");
|
|
152
154
|
for (const enEl of endnoteElements) {
|
|
153
|
-
const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media);
|
|
155
|
+
const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media, previews);
|
|
154
156
|
if (byId.has(endnote.id)) {
|
|
155
157
|
context?.warn({
|
|
156
158
|
code: PARSE_WARNING_CODES.duplicateNoteId,
|
|
157
159
|
element: "w:endnote",
|
|
158
160
|
at: `w:id ${String(endnote.id)}`
|
|
159
161
|
});
|
|
162
|
+
previews.release(endnote);
|
|
160
163
|
continue;
|
|
161
164
|
}
|
|
162
165
|
byId.set(endnote.id, endnote);
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
import { PreviewLedger } from "./previewBudget.js";
|
|
4
|
+
import { GroupTextBoxFrame } from "./drawingGroupChildren.js";
|
|
3
5
|
//#region src/docx/groupDrawingParser.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* The text boxes a group preview does not draw, which the paragraph parser
|
|
8
|
+
* lifts out as text boxes of their own. Undefined for any other image.
|
|
9
|
+
*/
|
|
10
|
+
declare const groupPreviewTextBoxes: (image: document_d_exports.Image) => readonly GroupTextBoxFrame[] | undefined;
|
|
4
11
|
/**
|
|
5
12
|
* Whether a `w:drawing` carries a WordprocessingGroup payload. A group this
|
|
6
13
|
* module declines to rasterize has no editable projection either — the shape
|
|
@@ -8,6 +15,6 @@ import { XmlElement } from "./xmlParser.js";
|
|
|
8
15
|
*/
|
|
9
16
|
declare const isGroupDrawing: (drawing: XmlElement) => boolean;
|
|
10
17
|
/** Parse a WordprocessingGroup drawing into a safe SVG-backed image preview. */
|
|
11
|
-
declare const parseGroupDrawing: (drawing: XmlElement, rels?: document_d_exports.RelationshipMap, media?: Map<string, document_d_exports.MediaFile>) => document_d_exports.Image | null;
|
|
18
|
+
declare const parseGroupDrawing: (drawing: XmlElement, previews: PreviewLedger, rels?: document_d_exports.RelationshipMap, media?: Map<string, document_d_exports.MediaFile>) => document_d_exports.Image | null;
|
|
12
19
|
//#endregion
|
|
13
|
-
export { isGroupDrawing, parseGroupDrawing };
|
|
20
|
+
export { groupPreviewTextBoxes, isGroupDrawing, parseGroupDrawing };
|