@stll/folio-core 0.7.0 → 0.9.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/README.md +39 -0
- package/dist/ai-edits/apply.js +18 -4
- package/dist/ai-edits/blockRange.d.ts +13 -2
- package/dist/ai-edits/blockRange.js +23 -2
- package/dist/ai-edits/headless.d.ts +31 -4
- package/dist/ai-edits/headless.js +148 -35
- package/dist/ai-edits/index.d.ts +6 -4
- package/dist/ai-edits/index.js +4 -1
- package/dist/ai-edits/scoped-reading.d.ts +9 -0
- package/dist/ai-edits/scoped-reading.js +60 -0
- package/dist/ai-edits/snapshot.js +53 -7
- package/dist/ai-edits/types.d.ts +46 -3
- package/dist/compat/eigenpal.d.ts +8 -3
- package/dist/compat/eigenpal.js +7 -2
- package/dist/controller/fontReadiness.d.ts +29 -0
- package/dist/controller/fontReadiness.js +139 -0
- package/dist/controller/latestRequestGate.d.ts +13 -0
- package/dist/controller/latestRequestGate.js +16 -0
- package/dist/controller/layoutPipeline.js +88 -10
- package/dist/document-operations.d.ts +10 -3
- package/dist/document-operations.js +29 -14
- package/dist/docx/blockContentParser.js +53 -10
- package/dist/docx/commentParser.js +1 -1
- package/dist/docx/compatibility.d.ts +30 -2
- package/dist/docx/compatibility.js +118 -39
- package/dist/docx/conformance.d.ts +6 -0
- package/dist/docx/conformance.js +18 -0
- package/dist/docx/encryption/agileDecryption.js +1 -1
- package/dist/docx/encryption/encryptionInfo.js +1 -1
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/ensureParaIds.d.ts +29 -0
- package/dist/docx/ensureParaIds.js +423 -0
- package/dist/docx/fontTableParser.d.ts +6 -0
- package/dist/docx/fontTableParser.js +72 -0
- package/dist/docx/groupDrawingParser.js +7 -2
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/normalizeBaseDirection.js +1 -1
- package/dist/docx/numberingParser.js +2 -0
- package/dist/docx/paragraphParser.js +21 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +141 -2
- package/dist/docx/parser.d.ts +1 -1
- package/dist/docx/parser.js +14 -9
- package/dist/docx/rezip.js +70 -5
- package/dist/docx/runConsolidator.js +4 -0
- package/dist/docx/runParser.js +19 -1
- package/dist/docx/selectiveSave.js +3 -3
- package/dist/docx/selectiveXmlPatch.d.ts +10 -1
- package/dist/docx/selectiveXmlPatch.js +1 -1
- package/dist/docx/serializer/fontTableSerializer.d.ts +6 -0
- package/dist/docx/serializer/fontTableSerializer.js +26 -0
- package/dist/docx/serializer/headerFooterSerializer.js +1 -1
- package/dist/docx/serializer/paragraphSerializer.js +8 -0
- package/dist/docx/serializer/runSerializer.js +14 -2
- package/dist/docx/serializer/settingsSerializer.d.ts +6 -0
- package/dist/docx/serializer/settingsSerializer.js +16 -0
- package/dist/docx/serializer/stylesSerializer.d.ts +6 -0
- package/dist/docx/serializer/stylesSerializer.js +56 -0
- package/dist/docx/serializer/tableSerializer.js +29 -26
- package/dist/docx/serializer/themeSerializer.d.ts +6 -0
- package/dist/docx/serializer/themeSerializer.js +36 -0
- package/dist/docx/settingsParser.js +46 -0
- package/dist/docx/styleParser.js +26 -1
- package/dist/docx/tableParser.js +19 -1
- package/dist/docx/textBoxParser.js +6 -1
- package/dist/docx/vmlImageParser.js +146 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
- package/dist/i18n/messages/catalogs.gen.js +5910 -5910
- package/dist/index.d.ts +8 -3
- package/dist/index.js +7 -2
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +22 -3
- package/dist/layout-bridge/convert/paragraphFrames.d.ts +7 -0
- package/dist/layout-bridge/convert/paragraphFrames.js +136 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +93 -17
- package/dist/layout-bridge/engine/hitTest.js +2 -1
- package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
- package/dist/layout-bridge/engine/measuring/index.js +2 -1
- package/dist/layout-bridge/engine/selectionRects.js +2 -1
- package/dist/layout-engine/headerFooterRefs.d.ts +7 -0
- package/dist/layout-engine/headerFooterRefs.js +40 -0
- package/dist/layout-engine/index.d.ts +3 -2
- package/dist/layout-engine/index.js +68 -106
- package/dist/layout-engine/measure/cache.js +11 -3
- package/dist/layout-engine/measure/font-metrics.worker.js +1 -0
- package/dist/layout-engine/measure/index.d.ts +2 -1
- package/dist/layout-engine/measure/index.js +2 -1
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +33 -0
- package/dist/layout-engine/measure/lineBreakProvider.js +252 -0
- package/dist/layout-engine/measure/lineBreaks.d.ts +7 -2
- package/dist/layout-engine/measure/lineBreaks.js +11 -18
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +4 -1
- package/dist/layout-engine/measure/listMarkerWidth.js +33 -8
- package/dist/layout-engine/measure/measureBlocks.d.ts +4 -2
- package/dist/layout-engine/measure/measureBlocks.js +138 -86
- package/dist/layout-engine/measure/measureContainer.js +32 -9
- package/dist/layout-engine/measure/measureHelpers.js +5 -2
- package/dist/layout-engine/measure/measureParagraph.js +346 -74
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -1
- package/dist/layout-engine/measure/measureWorker.d.ts +2 -2
- package/dist/layout-engine/measure/measureWorker.js +8 -19
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +3 -14
- package/dist/layout-engine/measure/tableCellFloating.d.ts +10 -3
- package/dist/layout-engine/measure/tableCellFloating.js +37 -29
- package/dist/layout-engine/measure/tableCellFlow.d.ts +27 -0
- package/dist/layout-engine/measure/tableCellFlow.js +73 -0
- package/dist/layout-engine/measure/tableCellGrid.d.ts +15 -0
- package/dist/layout-engine/measure/tableCellGrid.js +62 -0
- package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +18 -0
- package/dist/layout-engine/measure/textBoxParagraphLayout.js +32 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
- package/dist/layout-engine/paginator.d.ts +2 -1
- package/dist/layout-engine/paginator.js +7 -6
- package/dist/layout-engine/paragraphFrame.d.ts +22 -0
- package/dist/layout-engine/paragraphFrame.js +17 -0
- package/dist/layout-engine/paragraphSequence.d.ts +7 -0
- package/dist/layout-engine/paragraphSequence.js +25 -0
- package/dist/layout-engine/paragraphSpacing.d.ts +17 -0
- package/dist/layout-engine/paragraphSpacing.js +30 -0
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +63 -0
- package/dist/layout-engine/renderedBreakReconciliation.js +86 -0
- package/dist/layout-engine/tableRowBreak.d.ts +5 -2
- package/dist/layout-engine/tableRowBreak.js +62 -29
- package/dist/layout-engine/types.d.ts +54 -12
- package/dist/layout-engine/types.js +15 -2
- package/dist/layout-painter/anchoredImagePosition.d.ts +23 -0
- package/dist/layout-painter/anchoredImagePosition.js +95 -0
- package/dist/layout-painter/borderStroke.d.ts +23 -0
- package/dist/layout-painter/borderStroke.js +39 -0
- package/dist/layout-painter/renderImage.d.ts +5 -4
- package/dist/layout-painter/renderImage.js +18 -4
- package/dist/layout-painter/renderPage.d.ts +2 -27
- package/dist/layout-painter/renderPage.js +15 -101
- package/dist/layout-painter/renderParagraph.js +45 -26
- package/dist/layout-painter/renderTable.d.ts +2 -0
- package/dist/layout-painter/renderTable.js +257 -47
- package/dist/layout-painter/renderTextBox.js +17 -7
- package/dist/managers/DocumentLoaderManager.d.ts +1 -1
- package/dist/managers/DocumentLoaderManager.js +2 -2
- package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
- package/dist/paged-layout/sectionBlockWidths.js +9 -0
- package/dist/paged-layout/sectionGeometry.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +32 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +35 -18
- package/dist/prosemirror/conversion/toProseDoc.js +73 -37
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +8 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +2 -0
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +68 -16
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/LanguageExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/marks/LanguageExtension.js +30 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +1 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +12 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +4 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +6 -1
- package/dist/prosemirror/schema/nodes.d.ts +16 -12
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +3 -1
- package/dist/prosemirror/utils/tabCalculator.js +12 -10
- package/dist/prosemirror/validation.js +4 -1
- package/dist/redline.js +13 -3
- package/dist/server.d.ts +9 -4
- package/dist/server.js +7 -2
- package/dist/style-sets/extract.d.ts +35 -0
- package/dist/style-sets/extract.js +123 -0
- package/dist/style-sets/stellaStyle.d.ts +13 -0
- package/dist/style-sets/stellaStyle.js +516 -0
- package/dist/style-sets/types.d.ts +31 -0
- package/dist/style-sets/types.js +5 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/utils/createDocument.d.ts +12 -2
- package/dist/utils/createDocument.js +55 -36
- package/dist/utils/fontResolver.js +6 -6
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/hexId.d.ts +8 -1
- package/dist/utils/hexId.js +11 -3
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
- package/dist/utils/paragraphFormattingMerge.js +14 -4
- package/package.json +5 -1
|
@@ -1,7 +1,77 @@
|
|
|
1
|
-
import { findDeep, getChildElements, getLocalName } from "./xmlParser.js";
|
|
1
|
+
import { findDeep, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
|
|
2
|
+
import { pixelsToEmu } from "../utils/units.js";
|
|
2
3
|
import { getTextBoxContentElement, isTextBoxDrawing, parseTextBox, parseTextBoxContent } from "./textBoxParser.js";
|
|
3
4
|
import { parseParagraph } from "./paragraphParser.js";
|
|
4
5
|
//#region src/docx/paragraphTextBoxEnrichment.ts
|
|
6
|
+
const VML_HORIZONTAL_RELATIVES = /* @__PURE__ */ new Set([
|
|
7
|
+
"character",
|
|
8
|
+
"column",
|
|
9
|
+
"insideMargin",
|
|
10
|
+
"leftMargin",
|
|
11
|
+
"margin",
|
|
12
|
+
"outsideMargin",
|
|
13
|
+
"page",
|
|
14
|
+
"rightMargin"
|
|
15
|
+
]);
|
|
16
|
+
const VML_VERTICAL_RELATIVES = /* @__PURE__ */ new Set([
|
|
17
|
+
"insideMargin",
|
|
18
|
+
"line",
|
|
19
|
+
"margin",
|
|
20
|
+
"outsideMargin",
|
|
21
|
+
"page",
|
|
22
|
+
"paragraph",
|
|
23
|
+
"topMargin",
|
|
24
|
+
"bottomMargin"
|
|
25
|
+
]);
|
|
26
|
+
const parseVmlStyle = (value) => {
|
|
27
|
+
const declarations = {};
|
|
28
|
+
for (const declaration of value?.split(";") ?? []) {
|
|
29
|
+
const separator = declaration.indexOf(":");
|
|
30
|
+
if (separator < 0) continue;
|
|
31
|
+
const key = declaration.slice(0, separator).trim().toLowerCase();
|
|
32
|
+
if (key) declarations[key] = declaration.slice(separator + 1).trim();
|
|
33
|
+
}
|
|
34
|
+
return declarations;
|
|
35
|
+
};
|
|
36
|
+
const vmlLengthToPixels = (value) => {
|
|
37
|
+
const match = /^(?<amount>-?(?:\d+(?:\.\d+)?|\.\d+))\s*(?<unit>pt|in|px|cm|mm|pc)?$/iu.exec(value?.trim() ?? "");
|
|
38
|
+
const amount = Number.parseFloat(match?.groups?.["amount"] ?? "");
|
|
39
|
+
if (!Number.isFinite(amount)) return;
|
|
40
|
+
switch (match?.groups?.["unit"]?.toLowerCase()) {
|
|
41
|
+
case "pt": return amount / 72 * 96;
|
|
42
|
+
case "in": return amount * 96;
|
|
43
|
+
case "cm": return amount / 2.54 * 96;
|
|
44
|
+
case "mm": return amount / 25.4 * 96;
|
|
45
|
+
case "pc": return amount * 16;
|
|
46
|
+
case "px":
|
|
47
|
+
case void 0: return amount;
|
|
48
|
+
default: return;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const horizontalRelativeTo = (value) => {
|
|
52
|
+
for (const relative of VML_HORIZONTAL_RELATIVES) if (relative.toLowerCase() === value?.toLowerCase()) return relative;
|
|
53
|
+
return "character";
|
|
54
|
+
};
|
|
55
|
+
const verticalRelativeTo = (value) => {
|
|
56
|
+
for (const relative of VML_VERTICAL_RELATIVES) if (relative.toLowerCase() === value?.toLowerCase()) return relative;
|
|
57
|
+
return "paragraph";
|
|
58
|
+
};
|
|
59
|
+
const parseVmlInsets = (textBoxEl) => {
|
|
60
|
+
const [left, top, right, bottom, extra] = getAttribute(textBoxEl, null, "inset")?.split(",").map((value) => vmlLengthToPixels(value)) ?? [];
|
|
61
|
+
if (extra !== void 0 || left === void 0 || top === void 0 || right === void 0 || bottom === void 0) return;
|
|
62
|
+
return {
|
|
63
|
+
left: pixelsToEmu(left),
|
|
64
|
+
top: pixelsToEmu(top),
|
|
65
|
+
right: pixelsToEmu(right),
|
|
66
|
+
bottom: pixelsToEmu(bottom)
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const parseVmlFill = (shapeEl) => getAttribute(shapeEl, null, "filled")?.toLowerCase() === "f" ? { type: "none" } : void 0;
|
|
70
|
+
const vmlWrapType = (positioned, zIndex) => {
|
|
71
|
+
if (!positioned) return "inline";
|
|
72
|
+
if (Number.isFinite(zIndex) && zIndex < 0) return "behind";
|
|
73
|
+
return "inFront";
|
|
74
|
+
};
|
|
5
75
|
const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media) => {
|
|
6
76
|
const xmlChildren = getChildElements(paraXml);
|
|
7
77
|
let parsedIndex = 0;
|
|
@@ -11,7 +81,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
|
|
|
11
81
|
if (parsedIndex < paragraph.content.length && paragraph.content[parsedIndex]?.type !== "run") parsedIndex += 1;
|
|
12
82
|
continue;
|
|
13
83
|
}
|
|
14
|
-
const { textBoxDrawings, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
|
|
84
|
+
const { textBoxDrawings, vmlTextBoxes, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
|
|
15
85
|
const parsedContent = paragraph.content[parsedIndex];
|
|
16
86
|
const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
|
|
17
87
|
const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
|
|
@@ -33,6 +103,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
|
|
|
33
103
|
...textBox.outline !== void 0 ? { outline: textBox.outline } : {},
|
|
34
104
|
textBody: {
|
|
35
105
|
content: textBox.content,
|
|
106
|
+
...textBox.autoFit !== void 0 ? { autoFit: textBox.autoFit } : {},
|
|
36
107
|
...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
|
|
37
108
|
}
|
|
38
109
|
};
|
|
@@ -52,6 +123,24 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
|
|
|
52
123
|
parsedIndex += 1;
|
|
53
124
|
}
|
|
54
125
|
}
|
|
126
|
+
for (const pictEl of vmlTextBoxes) {
|
|
127
|
+
const shape = parseVmlTextBoxShape(pictEl, styles, theme, numbering, rels, media);
|
|
128
|
+
if (!shape) continue;
|
|
129
|
+
const shapeContent = {
|
|
130
|
+
type: "shape",
|
|
131
|
+
shape
|
|
132
|
+
};
|
|
133
|
+
if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
|
|
134
|
+
else {
|
|
135
|
+
const newRun = {
|
|
136
|
+
type: "run",
|
|
137
|
+
content: [shapeContent]
|
|
138
|
+
};
|
|
139
|
+
paragraph.content.splice(parsedIndex, 0, newRun);
|
|
140
|
+
lastConsumedRun = newRun;
|
|
141
|
+
parsedIndex += 1;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
55
144
|
if (hasNonTextBoxContent && parsedRun) {
|
|
56
145
|
lastConsumedRun = parsedRun;
|
|
57
146
|
parsedIndex += 1;
|
|
@@ -60,6 +149,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
|
|
|
60
149
|
};
|
|
61
150
|
const scanRunForTextBoxDrawings = (xmlRun) => {
|
|
62
151
|
const textBoxDrawings = [];
|
|
152
|
+
const vmlTextBoxes = [];
|
|
63
153
|
let hasNonTextBoxContent = false;
|
|
64
154
|
const visitDrawing = (drawingEl) => {
|
|
65
155
|
if (isTextBoxDrawing(drawingEl)) {
|
|
@@ -75,6 +165,11 @@ const scanRunForTextBoxDrawings = (xmlRun) => {
|
|
|
75
165
|
visitDrawing(el);
|
|
76
166
|
continue;
|
|
77
167
|
}
|
|
168
|
+
if (name === "pict") {
|
|
169
|
+
if (findDeep(el, "v", "textbox")) vmlTextBoxes.push(el);
|
|
170
|
+
else hasNonTextBoxContent = true;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
78
173
|
if (name === "AlternateContent") {
|
|
79
174
|
const branches = getChildElements(el);
|
|
80
175
|
const choice = branches.find((branch) => getLocalName(branch.name ?? "") === "Choice");
|
|
@@ -97,8 +192,52 @@ const scanRunForTextBoxDrawings = (xmlRun) => {
|
|
|
97
192
|
}
|
|
98
193
|
return {
|
|
99
194
|
textBoxDrawings,
|
|
195
|
+
vmlTextBoxes,
|
|
100
196
|
hasNonTextBoxContent
|
|
101
197
|
};
|
|
102
198
|
};
|
|
199
|
+
const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media) => {
|
|
200
|
+
const shapeEl = findDeep(pictEl, "v", "shape");
|
|
201
|
+
const textBoxEl = shapeEl ? findDeep(shapeEl, "v", "textbox") : null;
|
|
202
|
+
const contentEl = textBoxEl ? findDeep(textBoxEl, "w", "txbxContent") : null;
|
|
203
|
+
if (!shapeEl || !textBoxEl || !contentEl) return null;
|
|
204
|
+
const style = parseVmlStyle(getAttribute(shapeEl, null, "style"));
|
|
205
|
+
const width = vmlLengthToPixels(style["width"]);
|
|
206
|
+
const height = vmlLengthToPixels(style["height"]);
|
|
207
|
+
if (width === void 0 || height === void 0 || width <= 0 || height <= 0) return null;
|
|
208
|
+
const left = vmlLengthToPixels(style["margin-left"] ?? style["left"]);
|
|
209
|
+
const top = vmlLengthToPixels(style["margin-top"] ?? style["top"]);
|
|
210
|
+
const positioned = style["position"]?.toLowerCase() === "absolute";
|
|
211
|
+
const zIndex = Number.parseInt(style["z-index"] ?? "", 10);
|
|
212
|
+
const margins = parseVmlInsets(textBoxEl);
|
|
213
|
+
const fill = parseVmlFill(shapeEl);
|
|
214
|
+
const shape = {
|
|
215
|
+
type: "shape",
|
|
216
|
+
shapeType: "textBox",
|
|
217
|
+
size: {
|
|
218
|
+
width: pixelsToEmu(width),
|
|
219
|
+
height: pixelsToEmu(height)
|
|
220
|
+
},
|
|
221
|
+
...fill === void 0 ? {} : { fill },
|
|
222
|
+
wrap: { type: vmlWrapType(positioned, zIndex) },
|
|
223
|
+
textBody: {
|
|
224
|
+
content: parseTextBoxContent(contentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0),
|
|
225
|
+
...margins === void 0 ? {} : { margins }
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const id = getAttribute(shapeEl, null, "id");
|
|
229
|
+
if (id) shape.id = id;
|
|
230
|
+
if (positioned) shape.position = {
|
|
231
|
+
horizontal: {
|
|
232
|
+
relativeTo: horizontalRelativeTo(style["mso-position-horizontal-relative"]),
|
|
233
|
+
...left === void 0 ? {} : { posOffset: pixelsToEmu(left) }
|
|
234
|
+
},
|
|
235
|
+
vertical: {
|
|
236
|
+
relativeTo: verticalRelativeTo(style["mso-position-vertical-relative"]),
|
|
237
|
+
...top === void 0 ? {} : { posOffset: pixelsToEmu(top) }
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
return shape;
|
|
241
|
+
};
|
|
103
242
|
//#endregion
|
|
104
243
|
export { enrichParagraphTextBoxes };
|
package/dist/docx/parser.d.ts
CHANGED
package/dist/docx/parser.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
2
|
-
import { applyThemeFontLang, parseTheme } from "./themeParser.js";
|
|
3
|
-
import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
4
|
-
import { DocxModelValidationError, formatDocumentModelIssues, validateFolioDocumentModel } from "./modelValidation.js";
|
|
5
|
-
import { parseNumbering } from "./numberingParser.js";
|
|
6
|
-
import { DocxEncryptionError } from "./encryption/errors.js";
|
|
7
|
-
import { getMediaMimeType, mediaToDataUrl, unzipDocx } from "./unzip.js";
|
|
8
|
-
import { parseComments } from "./commentParser.js";
|
|
9
|
-
import { parseFooter, parseHeader } from "./headerFooterParser.js";
|
|
10
1
|
import { toArrayBuffer } from "../utils/docxInput.js";
|
|
11
2
|
import { loadFontsWithMapping } from "../utils/fontLoader.js";
|
|
12
3
|
import { convertTiffToPngDataUrl, isTiffMimeType } from "../utils/tiffConverter.js";
|
|
4
|
+
import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
5
|
+
import { applyThemeFontLang, parseTheme } from "./themeParser.js";
|
|
6
|
+
import { parseComments } from "./commentParser.js";
|
|
13
7
|
import { normalizeCommentReferences } from "./commentReferenceNormalization.js";
|
|
8
|
+
import { detectDocxConformanceClass } from "./conformance.js";
|
|
9
|
+
import { parseNumbering } from "./numberingParser.js";
|
|
14
10
|
import { extractAllTemplateVariables, parseDocumentBody } from "./documentParser.js";
|
|
11
|
+
import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
12
|
+
import { parseFooter, parseHeader } from "./headerFooterParser.js";
|
|
15
13
|
import { normalizeHeaderFooterReferences } from "./headerFooterReferenceNormalization.js";
|
|
14
|
+
import { DocxModelValidationError, formatDocumentModelIssues, validateFolioDocumentModel } from "./modelValidation.js";
|
|
16
15
|
import { extractMetafileRaster, isMetafileMimeType } from "./metafileRaster.js";
|
|
16
|
+
import { parseFontTable } from "./fontTableParser.js";
|
|
17
17
|
import { normalizeNumberingReferences } from "./numberingReferenceNormalization.js";
|
|
18
18
|
import { parseSettings } from "./settingsParser.js";
|
|
19
19
|
import { parseStylesPackage } from "./styleParser.js";
|
|
20
20
|
import { normalizeTrackedMoveRanges } from "./trackedMoveRangeNormalization.js";
|
|
21
|
+
import { DocxEncryptionError } from "./encryption/errors.js";
|
|
22
|
+
import { getMediaMimeType, mediaToDataUrl, unzipDocx } from "./unzip.js";
|
|
21
23
|
import { TaggedError } from "better-result";
|
|
22
24
|
//#region src/docx/parser.ts
|
|
23
25
|
/**
|
|
@@ -83,6 +85,7 @@ async function parseDocx(input, options = {}) {
|
|
|
83
85
|
onProgress("Parsed styles", 30);
|
|
84
86
|
onProgress("Parsing numbering...", 30);
|
|
85
87
|
const numbering = timeStage("numbering", () => parseNumbering(raw.numberingXml));
|
|
88
|
+
const fontTable = timeStage("fontTable", () => parseFontTable(raw.fontTableXml));
|
|
86
89
|
onProgress("Parsed numbering", 35);
|
|
87
90
|
onProgress("Processing media files...", 35);
|
|
88
91
|
const media = await timeStageAsync("media", () => buildMediaMap(raw, rels));
|
|
@@ -167,11 +170,13 @@ async function parseDocx(input, options = {}) {
|
|
|
167
170
|
onProgress("Assembling document...", 95);
|
|
168
171
|
const document = {
|
|
169
172
|
package: {
|
|
173
|
+
conformanceClass: detectDocxConformanceClass(raw.documentXml),
|
|
170
174
|
document: documentBody,
|
|
171
175
|
settings,
|
|
172
176
|
...styleDefinitions !== void 0 ? { styles: styleDefinitions } : {},
|
|
173
177
|
theme,
|
|
174
178
|
numbering: numbering.definitions,
|
|
179
|
+
...fontTable ? { fontTable } : {},
|
|
175
180
|
...headers !== void 0 ? { headers } : {},
|
|
176
181
|
...footers !== void 0 ? { footers } : {},
|
|
177
182
|
...footnotes !== void 0 ? { footnotes } : {},
|
package/dist/docx/rezip.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { applyReplyThreadMarkers } from "./commentReplyMarkers.js";
|
|
2
1
|
import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
2
|
+
import { parseNumbering } from "./numberingParser.js";
|
|
3
3
|
import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
4
4
|
import { assertValidFolioDocumentModel } from "./modelValidation.js";
|
|
5
|
-
import {
|
|
5
|
+
import { isPreservableDocxEntry } from "./unzip.js";
|
|
6
|
+
import { applyReplyThreadMarkers } from "./commentReplyMarkers.js";
|
|
6
7
|
import { buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, extractParagraphXml } from "./selectiveXmlPatch.js";
|
|
7
8
|
import { escapeXml } from "./serializer/xmlUtils.js";
|
|
8
9
|
import { ensureThreadedCommentParaIds, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
@@ -10,7 +11,10 @@ import { serializeDocument } from "./serializer/documentSerializer.js";
|
|
|
10
11
|
import { serializeHeaderFooter } from "./serializer/headerFooterSerializer.js";
|
|
11
12
|
import { serializeEndnotes, serializeFootnotes } from "./serializer/noteSerializer.js";
|
|
12
13
|
import { serializeNumberingXml } from "./serializer/numberingSerializer.js";
|
|
13
|
-
import {
|
|
14
|
+
import { serializeFontTableXml } from "./serializer/fontTableSerializer.js";
|
|
15
|
+
import { serializeSettingsXml } from "./serializer/settingsSerializer.js";
|
|
16
|
+
import { serializeStylesXml } from "./serializer/stylesSerializer.js";
|
|
17
|
+
import { serializeThemeXml } from "./serializer/themeSerializer.js";
|
|
14
18
|
import { panic } from "better-result";
|
|
15
19
|
import JSZip from "jszip";
|
|
16
20
|
//#region src/docx/rezip.ts
|
|
@@ -1169,7 +1173,7 @@ function createEmptyDocx() {
|
|
|
1169
1173
|
zip.file("docProps/app.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
1170
1174
|
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">
|
|
1171
1175
|
<Application>EigenPal DOCX Editor</Application>
|
|
1172
|
-
<AppVersion>1.
|
|
1176
|
+
<AppVersion>1.0000</AppVersion>
|
|
1173
1177
|
</Properties>`);
|
|
1174
1178
|
return zip.generateAsync({
|
|
1175
1179
|
type: "arraybuffer",
|
|
@@ -1184,11 +1188,72 @@ function createEmptyDocx() {
|
|
|
1184
1188
|
* @returns Promise resolving to DOCX as ArrayBuffer
|
|
1185
1189
|
*/
|
|
1186
1190
|
async function createDocx(doc) {
|
|
1187
|
-
const emptyBuffer = await
|
|
1191
|
+
const emptyBuffer = await createDocumentSeedDocx(doc);
|
|
1188
1192
|
return repackDocx({
|
|
1189
1193
|
...doc,
|
|
1190
1194
|
originalBuffer: emptyBuffer
|
|
1191
1195
|
});
|
|
1192
1196
|
}
|
|
1197
|
+
const createDocumentSeedDocx = async (doc) => {
|
|
1198
|
+
const buffer = await createEmptyDocx();
|
|
1199
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
1200
|
+
const relationships = ["<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>"];
|
|
1201
|
+
const overrides = [];
|
|
1202
|
+
let nextRelationshipId = 2;
|
|
1203
|
+
if (doc.package.styles) {
|
|
1204
|
+
assertStyleNumberingReferences(doc);
|
|
1205
|
+
zip.file("word/styles.xml", serializeStylesXml(doc.package.styles));
|
|
1206
|
+
}
|
|
1207
|
+
const numbering = doc.package.numbering;
|
|
1208
|
+
if (numbering && (numbering.abstractNums.length > 0 || numbering.nums.length > 0)) {
|
|
1209
|
+
zip.file("word/numbering.xml", serializeNumberingXml(numbering));
|
|
1210
|
+
relationships.push(relationshipXml(nextRelationshipId, "numbering", "numbering.xml"));
|
|
1211
|
+
overrides.push(overrideXml("/word/numbering.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"));
|
|
1212
|
+
nextRelationshipId += 1;
|
|
1213
|
+
}
|
|
1214
|
+
if (doc.package.theme) {
|
|
1215
|
+
zip.file("word/theme/theme1.xml", serializeThemeXml(doc.package.theme));
|
|
1216
|
+
relationships.push(relationshipXml(nextRelationshipId, "theme", "theme/theme1.xml"));
|
|
1217
|
+
overrides.push(overrideXml("/word/theme/theme1.xml", "application/vnd.openxmlformats-officedocument.theme+xml"));
|
|
1218
|
+
nextRelationshipId += 1;
|
|
1219
|
+
}
|
|
1220
|
+
if (doc.package.fontTable && doc.package.fontTable.fonts.length > 0) {
|
|
1221
|
+
zip.file("word/fontTable.xml", serializeFontTableXml(doc.package.fontTable));
|
|
1222
|
+
relationships.push(relationshipXml(nextRelationshipId, "fontTable", "fontTable.xml"));
|
|
1223
|
+
overrides.push(overrideXml("/word/fontTable.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"));
|
|
1224
|
+
nextRelationshipId += 1;
|
|
1225
|
+
}
|
|
1226
|
+
if (doc.package.settings) {
|
|
1227
|
+
zip.file("word/settings.xml", serializeSettingsXml(doc.package.settings));
|
|
1228
|
+
relationships.push(relationshipXml(nextRelationshipId, "settings", "settings.xml"));
|
|
1229
|
+
overrides.push(overrideXml("/word/settings.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"));
|
|
1230
|
+
}
|
|
1231
|
+
zip.file("word/_rels/document.xml.rels", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">${relationships.join("")}</Relationships>`);
|
|
1232
|
+
if (overrides.length > 0) {
|
|
1233
|
+
const contentTypesFile = zip.file("[Content_Types].xml");
|
|
1234
|
+
if (!contentTypesFile) panic("Fresh DOCX seed is missing [Content_Types].xml");
|
|
1235
|
+
const contentTypes = await contentTypesFile.async("string");
|
|
1236
|
+
zip.file("[Content_Types].xml", contentTypes.replace("</Types>", `${overrides.join("")}\n</Types>`));
|
|
1237
|
+
}
|
|
1238
|
+
return zip.generateAsync({
|
|
1239
|
+
type: "arraybuffer",
|
|
1240
|
+
compression: "DEFLATE",
|
|
1241
|
+
compressionOptions: { level: 6 }
|
|
1242
|
+
});
|
|
1243
|
+
};
|
|
1244
|
+
const relationshipXml = (id, type, target) => `<Relationship Id="rId${id}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/${type}" Target="${target}"/>`;
|
|
1245
|
+
const overrideXml = (partName, contentType) => `<Override PartName="${partName}" ContentType="${contentType}"/>`;
|
|
1246
|
+
const assertStyleNumberingReferences = (doc) => {
|
|
1247
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
1248
|
+
for (const style of doc.package.styles?.styles ?? []) {
|
|
1249
|
+
const numId = style.pPr?.numPr?.numId;
|
|
1250
|
+
if (numId !== void 0) referenced.add(numId);
|
|
1251
|
+
}
|
|
1252
|
+
if (referenced.size === 0) return;
|
|
1253
|
+
const available = new Set(doc.package.numbering?.nums.map((numbering) => numbering.numId) ?? []);
|
|
1254
|
+
for (const numId of referenced) if (!available.has(numId)) panic(`Style references missing numbering definition ${numId}`);
|
|
1255
|
+
const availableAbstract = new Set(doc.package.numbering?.abstractNums.map((numbering) => numbering.abstractNumId) ?? []);
|
|
1256
|
+
for (const numbering of doc.package.numbering?.nums ?? []) if (!availableAbstract.has(numbering.abstractNumId)) panic(`Numbering definition ${numbering.numId} references missing abstract numbering`);
|
|
1257
|
+
};
|
|
1193
1258
|
//#endregion
|
|
1194
1259
|
export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxPackageFidelityError, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, isDocxBuffer, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx };
|
|
@@ -38,8 +38,12 @@ function formattingEquals(a, b) {
|
|
|
38
38
|
if (!colorEquals(a.color, b.color)) return false;
|
|
39
39
|
if (!shadingEquals(a.shading, b.shading)) return false;
|
|
40
40
|
if (!fontFamilyEquals(a.fontFamily, b.fontFamily)) return false;
|
|
41
|
+
if (!languageEquals(a.language, b.language)) return false;
|
|
41
42
|
return true;
|
|
42
43
|
}
|
|
44
|
+
function languageEquals(a, b) {
|
|
45
|
+
return a?.val === b?.val && a?.eastAsia === b?.eastAsia && a?.bidi === b?.bidi;
|
|
46
|
+
}
|
|
43
47
|
/**
|
|
44
48
|
* Compare underline settings
|
|
45
49
|
*/
|
package/dist/docx/runParser.js
CHANGED
|
@@ -89,6 +89,9 @@ function collectFirstRunPropertyChildren(rPr) {
|
|
|
89
89
|
case "kern":
|
|
90
90
|
children.kern ??= child;
|
|
91
91
|
break;
|
|
92
|
+
case "lang":
|
|
93
|
+
children.lang ??= child;
|
|
94
|
+
break;
|
|
92
95
|
case "outline":
|
|
93
96
|
children.outline ??= child;
|
|
94
97
|
break;
|
|
@@ -262,6 +265,17 @@ function parseRunProperties(rPr, theme, _styles) {
|
|
|
262
265
|
}
|
|
263
266
|
formatting.fontFamily = fontFamily;
|
|
264
267
|
}
|
|
268
|
+
const lang = propertyChildren.lang;
|
|
269
|
+
if (lang) {
|
|
270
|
+
const val = getAttribute(lang, "w", "val") || void 0;
|
|
271
|
+
const eastAsia = getAttribute(lang, "w", "eastAsia") || void 0;
|
|
272
|
+
const bidi = getAttribute(lang, "w", "bidi") || void 0;
|
|
273
|
+
if (val || eastAsia || bidi) formatting.language = {
|
|
274
|
+
...val ? { val } : {},
|
|
275
|
+
...eastAsia ? { eastAsia } : {},
|
|
276
|
+
...bidi ? { bidi } : {}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
265
279
|
const spacing = propertyChildren.spacing;
|
|
266
280
|
if (spacing) {
|
|
267
281
|
const val = parseNumericAttribute(spacing, "w", "val");
|
|
@@ -531,7 +545,11 @@ function parseRunContents(runElement, rels, media, rootXmlns = {}) {
|
|
|
531
545
|
if (vmlDrawing) contents.push(vmlDrawing);
|
|
532
546
|
break;
|
|
533
547
|
}
|
|
534
|
-
case "object":
|
|
548
|
+
case "object": {
|
|
549
|
+
const objectPreview = parseVmlImageContent(child, rels, media, rootXmlns);
|
|
550
|
+
if (objectPreview) contents.push(objectPreview);
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
535
553
|
case "rPr": break;
|
|
536
554
|
case "lastRenderedPageBreak": break;
|
|
537
555
|
case "cr":
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { hasUnsynthesizedReplyRanges } from "./commentReplyMarkers.js";
|
|
2
1
|
import { RELATIONSHIP_TYPES } from "./relsParser.js";
|
|
3
|
-
import {
|
|
2
|
+
import { parseCommentsExtended } from "./commentParser.js";
|
|
4
3
|
import { parseNumbering } from "./numberingParser.js";
|
|
4
|
+
import { validateFolioDocumentModel } from "./modelValidation.js";
|
|
5
|
+
import { hasUnsynthesizedReplyRanges } from "./commentReplyMarkers.js";
|
|
5
6
|
import { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds } from "./selectiveXmlPatch.js";
|
|
6
7
|
import { ensureThreadedCommentParaIds, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
7
8
|
import { serializeDocument } from "./serializer/documentSerializer.js";
|
|
8
9
|
import { serializeEndnotes, serializeFootnotes } from "./serializer/noteSerializer.js";
|
|
9
10
|
import { serializeNumberingXml } from "./serializer/numberingSerializer.js";
|
|
10
11
|
import { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_PART_LOWER, addCommentsExtendedOverride, addCommentsExtendedRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, updateCoreProperties } from "./rezip.js";
|
|
11
|
-
import { parseCommentsExtended } from "./commentParser.js";
|
|
12
12
|
import "./selectiveSaveFlags.js";
|
|
13
13
|
//#region src/docx/selectiveSave.ts
|
|
14
14
|
const SYNTHETIC_IMAGE_RID_PREFIX = "rId_img_";
|
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
* unchanged content byte-for-byte. Uses string offset tracking
|
|
7
7
|
* with proper tag depth counting (not regex) to handle nested elements.
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether `char` ends an element's tag name in XML — a whitespace separator
|
|
11
|
+
* (space, tab, CR, or LF, all valid before attributes per XML 1.0 §3.1), the
|
|
12
|
+
* tag close `>`, or a self-close `/`. Manual tag scanners must accept every
|
|
13
|
+
* whitespace form, not just a literal space, so newline-formatted markup
|
|
14
|
+
* (`<w:p\n w14:paraId="…">`) is still recognized as the element rather than
|
|
15
|
+
* mistaken for a longer-named sibling.
|
|
16
|
+
*/
|
|
17
|
+
declare function isXmlNameBoundary(char: string | undefined): boolean;
|
|
9
18
|
/**
|
|
10
19
|
* Find the exact string start and end offsets of a <w:p> element
|
|
11
20
|
* identified by its w14:paraId attribute.
|
|
@@ -100,4 +109,4 @@ declare function collectChangedNumberingDefs(baselineXml: string, currentXml: st
|
|
|
100
109
|
*/
|
|
101
110
|
declare function buildPatchedNumberingXml(originalXml: string, currentXml: string, changed: ChangedNumberingDefs): string | null;
|
|
102
111
|
//#endregion
|
|
103
|
-
export { ChangedNumberingDefs, PatchSafetyOptions, PatchValidationResult, buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, validatePatchSafety };
|
|
112
|
+
export { ChangedNumberingDefs, PatchSafetyOptions, PatchValidationResult, buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, validatePatchSafety };
|
|
@@ -484,4 +484,4 @@ function escapeRegExp(str) {
|
|
|
484
484
|
return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
485
485
|
}
|
|
486
486
|
//#endregion
|
|
487
|
-
export { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, validatePatchSafety };
|
|
487
|
+
export { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, validatePatchSafety };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { escapeXml } from "./xmlUtils.js";
|
|
2
|
+
//#region src/docx/serializer/fontTableSerializer.ts
|
|
3
|
+
const W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
4
|
+
const serializeFontTableXml = (fontTable) => {
|
|
5
|
+
const fonts = fontTable.fonts.map(serializeFont).join("");
|
|
6
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w:fonts xmlns:w="${W_NS}">${fonts}</w:fonts>`;
|
|
7
|
+
};
|
|
8
|
+
const serializeFont = (font) => {
|
|
9
|
+
const parts = [];
|
|
10
|
+
if (font.altName) parts.push(`<w:altName w:val="${escapeXml(font.altName)}"/>`);
|
|
11
|
+
if (font.panose1) parts.push(`<w:panose1 w:val="${escapeXml(font.panose1)}"/>`);
|
|
12
|
+
if (font.charset) parts.push(`<w:charset w:val="${escapeXml(font.charset)}"/>`);
|
|
13
|
+
if (font.family) parts.push(`<w:family w:val="${font.family}"/>`);
|
|
14
|
+
if (font.pitch) parts.push(`<w:pitch w:val="${font.pitch}"/>`);
|
|
15
|
+
if (font.sig) {
|
|
16
|
+
const attrs = [];
|
|
17
|
+
for (const [key, value] of Object.entries(font.sig)) {
|
|
18
|
+
if (value === void 0) continue;
|
|
19
|
+
attrs.push(`w:${key}="${escapeXml(value)}"`);
|
|
20
|
+
}
|
|
21
|
+
if (attrs.length > 0) parts.push(`<w:sig ${attrs.join(" ")}/>`);
|
|
22
|
+
}
|
|
23
|
+
return `<w:font w:name="${escapeXml(font.name)}">${parts.join("")}</w:font>`;
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { serializeFontTableXml };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
1
2
|
import { escapeXml } from "./xmlUtils.js";
|
|
2
3
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
3
4
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
4
5
|
import { serializeTable } from "./tableSerializer.js";
|
|
5
|
-
import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
6
6
|
//#region src/docx/serializer/headerFooterSerializer.ts
|
|
7
7
|
const NAMESPACES = {
|
|
8
8
|
wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
|
|
@@ -112,8 +112,12 @@ function serializeNumbering(numPr) {
|
|
|
112
112
|
function serializeFrameProperties(frame) {
|
|
113
113
|
if (!frame) return "";
|
|
114
114
|
const attrs = [];
|
|
115
|
+
if (frame.dropCap) attrs.push(`w:dropCap="${frame.dropCap}"`);
|
|
116
|
+
if (frame.lines !== void 0) attrs.push(`w:lines="${intAttr(frame.lines)}"`);
|
|
115
117
|
if (frame.width !== void 0) attrs.push(`w:w="${intAttr(frame.width)}"`);
|
|
116
118
|
if (frame.height !== void 0) attrs.push(`w:h="${intAttr(frame.height)}"`);
|
|
119
|
+
if (frame.hSpace !== void 0) attrs.push(`w:hSpace="${intAttr(frame.hSpace)}"`);
|
|
120
|
+
if (frame.vSpace !== void 0) attrs.push(`w:vSpace="${intAttr(frame.vSpace)}"`);
|
|
117
121
|
if (frame.hAnchor) attrs.push(`w:hAnchor="${frame.hAnchor}"`);
|
|
118
122
|
if (frame.vAnchor) attrs.push(`w:vAnchor="${frame.vAnchor}"`);
|
|
119
123
|
if (frame.x !== void 0) attrs.push(`w:x="${frame.x}"`);
|
|
@@ -161,6 +165,8 @@ function serializeParagraphFormatting(formatting, propertyChanges, pPrMark) {
|
|
|
161
165
|
if (tabsXml) parts.push(tabsXml);
|
|
162
166
|
pushToggle("suppressLineNumbers", formatting.suppressLineNumbers);
|
|
163
167
|
pushToggle("suppressAutoHyphens", formatting.suppressAutoHyphens);
|
|
168
|
+
pushToggle("kinsoku", formatting.kinsoku);
|
|
169
|
+
pushToggle("overflowPunct", formatting.overflowPunctuation);
|
|
164
170
|
const spacingXml = serializeSpacing(formatting);
|
|
165
171
|
if (spacingXml) parts.push(spacingXml);
|
|
166
172
|
const indXml = serializeIndentation(formatting);
|
|
@@ -346,6 +352,8 @@ function serializeInlineSdt(sdt) {
|
|
|
346
352
|
case "simpleField": return serializeSimpleField(item);
|
|
347
353
|
case "complexField": return serializeComplexField(item);
|
|
348
354
|
case "inlineSdt": return serializeInlineSdt(item);
|
|
355
|
+
case "insertion": return serializeTrackedChange("ins", item);
|
|
356
|
+
case "deletion": return serializeTrackedChange("del", item);
|
|
349
357
|
case "mathEquation": return item.ommlXml || "";
|
|
350
358
|
default: return item;
|
|
351
359
|
}
|
|
@@ -85,6 +85,13 @@ function serializeTextFormatting(formatting) {
|
|
|
85
85
|
if (formatting.fontFamily.csTheme) fontAttrs.push(`w:cstheme="${formatting.fontFamily.csTheme}"`);
|
|
86
86
|
if (fontAttrs.length > 0) parts.push(`<w:rFonts ${fontAttrs.join(" ")}/>`);
|
|
87
87
|
}
|
|
88
|
+
if (formatting.language) {
|
|
89
|
+
const languageAttrs = [];
|
|
90
|
+
if (formatting.language.val) languageAttrs.push(`w:val="${escapeXml(formatting.language.val)}"`);
|
|
91
|
+
if (formatting.language.eastAsia) languageAttrs.push(`w:eastAsia="${escapeXml(formatting.language.eastAsia)}"`);
|
|
92
|
+
if (formatting.language.bidi) languageAttrs.push(`w:bidi="${escapeXml(formatting.language.bidi)}"`);
|
|
93
|
+
if (languageAttrs.length > 0) parts.push(`<w:lang ${languageAttrs.join(" ")}/>`);
|
|
94
|
+
}
|
|
88
95
|
if (formatting.bold === true) parts.push("<w:b/>");
|
|
89
96
|
else if (formatting.bold === false) parts.push("<w:b w:val=\"0\"/>");
|
|
90
97
|
if (formatting.boldCs === true) parts.push("<w:bCs/>");
|
|
@@ -456,13 +463,18 @@ function serializeShapeContent(content) {
|
|
|
456
463
|
if (tb.margins.right != null) bpAttrs.push(`rIns="${intAttr(tb.margins.right)}"`);
|
|
457
464
|
if (tb.margins.bottom != null) bpAttrs.push(`bIns="${intAttr(tb.margins.bottom)}"`);
|
|
458
465
|
}
|
|
466
|
+
let autoFitXml = "";
|
|
467
|
+
if (tb.autoFit === "shape") autoFitXml = "<a:spAutoFit/>";
|
|
468
|
+
else if (tb.autoFit === "normal") autoFitXml = "<a:normAutofit/>";
|
|
469
|
+
else if (tb.autoFit === "none") autoFitXml = "<a:noAutofit/>";
|
|
470
|
+
const bodyPrXml = autoFitXml ? `<wps:bodyPr ${bpAttrs.join(" ")}>${autoFitXml}</wps:bodyPr>` : `<wps:bodyPr ${bpAttrs.join(" ")}/>`;
|
|
459
471
|
if (isTextBox) textBody = [
|
|
460
472
|
"<wps:txbx><w:txbxContent>",
|
|
461
473
|
serializeShapeTextBody(tb.content),
|
|
462
474
|
"</w:txbxContent></wps:txbx>",
|
|
463
|
-
|
|
475
|
+
bodyPrXml
|
|
464
476
|
].join("");
|
|
465
|
-
else textBody =
|
|
477
|
+
else textBody = bodyPrXml;
|
|
466
478
|
}
|
|
467
479
|
const graphic = [
|
|
468
480
|
"<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { escapeXml, intAttr } from "./xmlUtils.js";
|
|
2
|
+
//#region src/docx/serializer/settingsSerializer.ts
|
|
3
|
+
const W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
4
|
+
const serializeSettingsXml = (settings) => {
|
|
5
|
+
const parts = [`<w:defaultTabStop w:val="${intAttr(settings.defaultTabStop)}"/>`];
|
|
6
|
+
if (settings.evenAndOddHeaders) parts.push("<w:evenAndOddHeaders/>");
|
|
7
|
+
if (settings.themeFontLang) {
|
|
8
|
+
const attrs = [];
|
|
9
|
+
if (settings.themeFontLang.eastAsia) attrs.push(`w:eastAsia="${escapeXml(settings.themeFontLang.eastAsia)}"`);
|
|
10
|
+
if (settings.themeFontLang.bidi) attrs.push(`w:bidi="${escapeXml(settings.themeFontLang.bidi)}"`);
|
|
11
|
+
if (attrs.length > 0) parts.push(`<w:themeFontLang ${attrs.join(" ")}/>`);
|
|
12
|
+
}
|
|
13
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w:settings xmlns:w="${W_NS}">${parts.join("")}</w:settings>`;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { serializeSettingsXml };
|