@stll/folio-core 0.4.0 → 0.6.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.d.ts +3 -9
- package/dist/ai-edits/apply.js +94 -14
- package/dist/ai-edits/blockRange.d.ts +33 -0
- package/dist/ai-edits/blockRange.js +58 -0
- package/dist/ai-edits/headless.d.ts +37 -4
- package/dist/ai-edits/headless.js +134 -16
- package/dist/ai-edits/index.d.ts +5 -3
- package/dist/ai-edits/index.js +3 -2
- package/dist/ai-edits/snapshot.d.ts +14 -2
- package/dist/ai-edits/snapshot.js +12 -1
- package/dist/ai-edits/types.d.ts +42 -3
- package/dist/compat/eigenpal.d.ts +3 -2
- package/dist/compat/eigenpal.js +6 -5
- package/dist/controller/layoutPipeline.d.ts +1 -0
- package/dist/controller/layoutPipeline.js +35 -137
- package/dist/controller/layoutScheduler.d.ts +2 -1
- package/dist/controller/layoutScheduler.js +6 -0
- package/dist/document-operations.d.ts +139 -0
- package/dist/document-operations.js +578 -0
- package/dist/docx/blockContentParser.js +17 -7
- package/dist/docx/encryption/agileDecryption.js +2 -1
- package/dist/docx/encryption/compoundFile.js +4 -2
- package/dist/docx/footnoteParser.d.ts +1 -17
- package/dist/docx/footnoteParser.js +1 -27
- package/dist/docx/groupDrawingParser.d.ts +8 -0
- package/dist/docx/groupDrawingParser.js +131 -0
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +8 -2
- package/dist/docx/paragraphParser.js +9 -3
- package/dist/docx/runParser.js +8 -1
- package/dist/docx/selectiveXmlPatch.js +4 -10
- package/dist/docx/serializer/numberingSerializer.js +3 -1
- package/dist/docx/settingsParser.d.ts +6 -3
- package/dist/docx/settingsParser.js +2 -0
- package/dist/docx/xmlParser.js +11 -4
- package/dist/i18n/messages/catalogs.gen.d.ts +1054 -34
- package/dist/i18n/messages/catalogs.gen.js +1122 -68
- package/dist/i18n/messages/messages.gen.d.ts +62 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +6 -5
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -7
- package/dist/layout-bridge/convert/toFlowBlocks.js +56 -19
- package/dist/layout-engine/index.d.ts +6 -5
- package/dist/layout-engine/index.js +143 -30
- package/dist/layout-engine/keep-together.d.ts +13 -8
- package/dist/layout-engine/keep-together.js +40 -25
- package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
- package/dist/layout-engine/layoutInstrumentation.js +10 -1
- package/dist/layout-engine/measure/measureBlocks.js +50 -18
- package/dist/layout-engine/measure/measureParagraph.js +61 -15
- package/dist/layout-engine/paginator.d.ts +2 -1
- package/dist/layout-engine/paginator.js +9 -3
- package/dist/layout-engine/textBoxGroup.d.ts +7 -0
- package/dist/layout-engine/textBoxGroup.js +8 -0
- package/dist/layout-engine/types.d.ts +30 -9
- package/dist/layout-engine/types.js +20 -2
- package/dist/layout-painter/renderPage.d.ts +15 -1
- package/dist/layout-painter/renderPage.js +27 -11
- package/dist/layout-painter/renderParagraph.js +18 -8
- package/dist/layout-painter/renderTable.js +10 -7
- package/dist/managers/DocumentLoaderManager.js +12 -5
- package/dist/model.js +1 -1
- package/dist/paged-layout/pageText.d.ts +14 -0
- package/dist/paged-layout/pageText.js +21 -0
- package/dist/prosemirror/attrs/index.js +2 -0
- package/dist/prosemirror/commands/comments.js +75 -5
- package/dist/prosemirror/commands/hyperlink.js +4 -2
- package/dist/prosemirror/commands/image.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
- package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +14 -3
- package/dist/prosemirror/conversion/toProseDoc.js +29 -8
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +10 -11
- package/dist/prosemirror/findReplaceSelection.js +2 -1
- package/dist/prosemirror/schema/nodes.d.ts +10 -5
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/utils/tabCalculator.js +4 -2
- package/dist/redline.d.ts +20 -0
- package/dist/redline.js +127 -0
- package/dist/server.d.ts +7 -3
- package/dist/server.js +6 -2
- package/dist/symbols.d.ts +35 -0
- package/dist/symbols.js +512 -0
- package/dist/utils/clipboard.js +3 -3
- package/dist/utils/fontLoader.js +3 -0
- package/dist/utils/fontResolver.js +48 -1
- package/dist/utils/zoom.d.ts +21 -0
- package/dist/utils/zoom.js +21 -0
- package/dist/version-comparison.d.ts +92 -0
- package/dist/version-comparison.js +436 -0
- package/package.json +3 -3
- package/dist/paged-layout/headerFooterMargins.d.ts +0 -75
- package/dist/paged-layout/headerFooterMargins.js +0 -122
|
@@ -205,32 +205,6 @@ function isSeparatorEndnote(endnote) {
|
|
|
205
205
|
return endnote.noteType === "separator" || endnote.noteType === "continuationSeparator" || endnote.noteType === "continuationNotice";
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
|
-
* Get footnote number for display (excluding separators)
|
|
209
|
-
* @param footnote - The footnote to get the number for
|
|
210
|
-
* @param footnoteMap - The footnote map
|
|
211
|
-
* @param startNumber - Starting number (default 1)
|
|
212
|
-
* @returns The display number, or null for separator footnotes
|
|
213
|
-
*/
|
|
214
|
-
function getFootnoteDisplayNumber(footnote, footnoteMap, startNumber = 1) {
|
|
215
|
-
if (isSeparatorFootnote(footnote)) return null;
|
|
216
|
-
const index = footnoteMap.getNormalFootnotes().findIndex((fn) => fn.id === footnote.id);
|
|
217
|
-
if (index === -1) return null;
|
|
218
|
-
return startNumber + index;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Get endnote number for display (excluding separators)
|
|
222
|
-
* @param endnote - The endnote to get the number for
|
|
223
|
-
* @param endnoteMap - The endnote map
|
|
224
|
-
* @param startNumber - Starting number (default 1)
|
|
225
|
-
* @returns The display number, or null for separator endnotes
|
|
226
|
-
*/
|
|
227
|
-
function getEndnoteDisplayNumber(endnote, endnoteMap, startNumber = 1) {
|
|
228
|
-
if (isSeparatorEndnote(endnote)) return null;
|
|
229
|
-
const index = endnoteMap.getNormalEndnotes().findIndex((en) => en.id === endnote.id);
|
|
230
|
-
if (index === -1) return null;
|
|
231
|
-
return startNumber + index;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
208
|
* Create an empty footnote map
|
|
235
209
|
*/
|
|
236
210
|
function createEmptyFootnoteMap() {
|
|
@@ -267,4 +241,4 @@ function mergeEndnoteMaps(...maps) {
|
|
|
267
241
|
return createEndnoteMap(byId, endnotes);
|
|
268
242
|
}
|
|
269
243
|
//#endregion
|
|
270
|
-
export { createEmptyEndnoteMap, createEmptyFootnoteMap,
|
|
244
|
+
export { createEmptyEndnoteMap, createEmptyFootnoteMap, getEndnoteText, getFootnoteText, isSeparatorEndnote, isSeparatorFootnote, mergeEndnoteMaps, mergeFootnoteMaps, parseEndnoteProperties, parseEndnotes, parseFootnoteProperties, parseFootnotes };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
|
|
4
|
+
//#region src/docx/groupDrawingParser.d.ts
|
|
5
|
+
/** Parse a WordprocessingGroup drawing into a safe SVG-backed image preview. */
|
|
6
|
+
declare const parseGroupDrawing: (drawing: XmlElement) => document_d_exports.Image | null;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { parseGroupDrawing };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { findAllDeep, findChildByLocalName, findChildrenByLocalName, getAttribute, getLocalName, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
2
|
+
import { emuToPixels } from "../utils/units.js";
|
|
3
|
+
import { parseImage } from "./imageParser.js";
|
|
4
|
+
//#region src/docx/groupDrawingParser.ts
|
|
5
|
+
const HEX_COLOR = /^[0-9A-Fa-f]{6}$/u;
|
|
6
|
+
const DEFAULT_TEXT_COLOR = "000000";
|
|
7
|
+
const DEFAULT_FONT_HALF_POINTS = 22;
|
|
8
|
+
const DEFAULT_LINE_WIDTH_EMU = 9525;
|
|
9
|
+
const HALF_POINT_TO_EMU = 6350;
|
|
10
|
+
const MAX_GROUP_SHAPES = 256;
|
|
11
|
+
const MAX_PATH_COMMANDS = 1e4;
|
|
12
|
+
const MAX_TEXT_CHARACTERS = 2e4;
|
|
13
|
+
const MAX_SVG_CHARACTERS = 1e6;
|
|
14
|
+
const escapeXml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
15
|
+
const numericAttr = (element, name) => {
|
|
16
|
+
const direct = parseNumericAttribute(element, null, name);
|
|
17
|
+
if (direct !== void 0) return direct;
|
|
18
|
+
const wordValue = getAttribute(element, "w", name);
|
|
19
|
+
if (!wordValue) return 0;
|
|
20
|
+
const parsed = Number.parseInt(wordValue, 10);
|
|
21
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
22
|
+
};
|
|
23
|
+
const childTransform = (wsp) => {
|
|
24
|
+
const xfrm = findChildByLocalName(findChildByLocalName(wsp, "spPr"), "xfrm");
|
|
25
|
+
const off = findChildByLocalName(xfrm, "off");
|
|
26
|
+
const ext = findChildByLocalName(xfrm, "ext");
|
|
27
|
+
return {
|
|
28
|
+
x: numericAttr(off, "x"),
|
|
29
|
+
y: numericAttr(off, "y"),
|
|
30
|
+
width: numericAttr(ext, "cx"),
|
|
31
|
+
height: numericAttr(ext, "cy")
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const colorFrom = (parent, fallback) => {
|
|
35
|
+
if (parent && getLocalName(parent.name ?? "") === "color") {
|
|
36
|
+
const value = getAttribute(parent, "w", "val");
|
|
37
|
+
if (value && HEX_COLOR.test(value)) return value.toUpperCase();
|
|
38
|
+
}
|
|
39
|
+
const value = getAttribute(findChildByLocalName(findChildByLocalName(parent, "solidFill"), "srgbClr"), null, "val");
|
|
40
|
+
if (value && HEX_COLOR.test(value)) return value.toUpperCase();
|
|
41
|
+
return fallback;
|
|
42
|
+
};
|
|
43
|
+
const wrapLine = (line, maxCharacters) => {
|
|
44
|
+
const words = line.trim().split(/\s+/u);
|
|
45
|
+
const lines = [];
|
|
46
|
+
let current = "";
|
|
47
|
+
for (const word of words) {
|
|
48
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
49
|
+
if (current && candidate.length > maxCharacters) {
|
|
50
|
+
lines.push(current);
|
|
51
|
+
current = word;
|
|
52
|
+
} else current = candidate;
|
|
53
|
+
}
|
|
54
|
+
if (current) lines.push(current);
|
|
55
|
+
return lines;
|
|
56
|
+
};
|
|
57
|
+
const pathData = (path) => {
|
|
58
|
+
const commands = [];
|
|
59
|
+
for (const command of path.elements ?? []) {
|
|
60
|
+
if (commands.length >= MAX_PATH_COMMANDS) break;
|
|
61
|
+
if (command.type !== "element") continue;
|
|
62
|
+
const point = findChildByLocalName(command, "pt");
|
|
63
|
+
const x = numericAttr(point, "x");
|
|
64
|
+
const y = numericAttr(point, "y");
|
|
65
|
+
const name = command.name?.split(":").at(-1);
|
|
66
|
+
if (name === "moveTo") commands.push(`M ${x} ${y}`);
|
|
67
|
+
else if (name === "lnTo") commands.push(`L ${x} ${y}`);
|
|
68
|
+
else if (name === "quadBezTo") {
|
|
69
|
+
const points = findChildrenByLocalName(command, "pt");
|
|
70
|
+
if (points.length >= 2) commands.push(`Q ${numericAttr(points[0] ?? null, "x")} ${numericAttr(points[0] ?? null, "y")} ${numericAttr(points[1] ?? null, "x")} ${numericAttr(points[1] ?? null, "y")}`);
|
|
71
|
+
} else if (name === "cubicBezTo") {
|
|
72
|
+
const points = findChildrenByLocalName(command, "pt");
|
|
73
|
+
if (points.length >= 3) commands.push(`C ${numericAttr(points[0] ?? null, "x")} ${numericAttr(points[0] ?? null, "y")} ${numericAttr(points[1] ?? null, "x")} ${numericAttr(points[1] ?? null, "y")} ${numericAttr(points[2] ?? null, "x")} ${numericAttr(points[2] ?? null, "y")}`);
|
|
74
|
+
} else if (name === "close") commands.push("Z");
|
|
75
|
+
}
|
|
76
|
+
return commands.join(" ");
|
|
77
|
+
};
|
|
78
|
+
const renderGeometry = (wsp) => {
|
|
79
|
+
const { x, y, width, height } = childTransform(wsp);
|
|
80
|
+
if (width <= 0 || height <= 0) return "";
|
|
81
|
+
const spPr = findChildByLocalName(wsp, "spPr");
|
|
82
|
+
const fill = colorFrom(spPr, "none");
|
|
83
|
+
const line = findChildByLocalName(spPr, "ln");
|
|
84
|
+
const stroke = colorFrom(line, "none");
|
|
85
|
+
const strokeWidth = line ? parseNumericAttribute(line, null, "w") ?? DEFAULT_LINE_WIDTH_EMU : 0;
|
|
86
|
+
const paths = findAllDeep(findChildByLocalName(spPr, "custGeom"), "a", "path");
|
|
87
|
+
if (paths.length === 0) return `<rect x="${x}" y="${y}" width="${width}" height="${height}" fill="${fill === "none" ? "none" : `#${fill}`}" stroke="${stroke === "none" ? "none" : `#${stroke}`}" stroke-width="${strokeWidth}"/>`;
|
|
88
|
+
return paths.map((path) => {
|
|
89
|
+
const viewWidth = numericAttr(path, "w") || width;
|
|
90
|
+
const viewHeight = numericAttr(path, "h") || height;
|
|
91
|
+
const d = pathData(path);
|
|
92
|
+
if (!d) return "";
|
|
93
|
+
return `<path d="${d}" transform="translate(${x} ${y}) scale(${width / viewWidth} ${height / viewHeight})" fill="${fill === "none" ? "none" : `#${fill}`}" stroke="${stroke === "none" ? "none" : `#${stroke}`}" stroke-width="${strokeWidth}"/>`;
|
|
94
|
+
}).join("");
|
|
95
|
+
};
|
|
96
|
+
const renderTextBox = (wsp) => {
|
|
97
|
+
const { x, y, width, height } = childTransform(wsp);
|
|
98
|
+
if (width <= 0 || height <= 0) return "";
|
|
99
|
+
const paragraphs = findAllDeep(wsp, "w", "p");
|
|
100
|
+
const firstSize = findAllDeep(wsp, "w", "sz").at(0);
|
|
101
|
+
const halfPoints = numericAttr(firstSize ?? null, "val") || DEFAULT_FONT_HALF_POINTS;
|
|
102
|
+
const color = colorFrom(findAllDeep(wsp, "w", "color").at(0) ?? null, DEFAULT_TEXT_COLOR);
|
|
103
|
+
const fontSize = halfPoints * HALF_POINT_TO_EMU;
|
|
104
|
+
const maxCharacters = Math.max(1, Math.floor(width / (fontSize * .38)));
|
|
105
|
+
const lines = paragraphs.flatMap((paragraph) => wrapLine(getTextContent(paragraph).slice(0, MAX_TEXT_CHARACTERS), maxCharacters)).map(escapeXml);
|
|
106
|
+
if (lines.length === 0) return "";
|
|
107
|
+
const lineHeight = fontSize * 1.15;
|
|
108
|
+
const svgFontSize = 1e3;
|
|
109
|
+
const scale = fontSize / svgFontSize;
|
|
110
|
+
const lineStep = lineHeight / fontSize * svgFontSize;
|
|
111
|
+
return `<text x="0" y="${svgFontSize}" transform="translate(${x} ${y}) scale(${scale})" font-family="Arial, sans-serif" font-size="${svgFontSize}" fill="#${color}">${lines.map((line, index) => `<tspan x="0" dy="${index === 0 ? 0 : lineStep}">${line}</tspan>`).join("")}</text>`;
|
|
112
|
+
};
|
|
113
|
+
const createSvg = (group, width, height) => {
|
|
114
|
+
const content = findChildrenByLocalName(group, "wsp").slice(0, MAX_GROUP_SHAPES).map((wsp) => findChildByLocalName(wsp, "txbx") ? renderTextBox(wsp) : renderGeometry(wsp)).join("");
|
|
115
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${emuToPixels(width)}" height="${emuToPixels(height)}">${content}</svg>`;
|
|
116
|
+
};
|
|
117
|
+
/** Parse a WordprocessingGroup drawing into a safe SVG-backed image preview. */
|
|
118
|
+
const parseGroupDrawing = (drawing) => {
|
|
119
|
+
const group = findChildByLocalName(findAllDeep(drawing, "a", "graphicData").at(0) ?? null, "wgp");
|
|
120
|
+
if (!group) return null;
|
|
121
|
+
const image = parseImage(drawing, void 0, void 0);
|
|
122
|
+
if (!image || image.size.width <= 0 || image.size.height <= 0) return null;
|
|
123
|
+
const svg = createSvg(group, image.size.width, image.size.height);
|
|
124
|
+
if (svg.length > MAX_SVG_CHARACTERS) return null;
|
|
125
|
+
image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
126
|
+
image.mimeType = "image/svg+xml";
|
|
127
|
+
image.filename = "wordprocessing-group.svg";
|
|
128
|
+
return image;
|
|
129
|
+
};
|
|
130
|
+
//#endregion
|
|
131
|
+
export { parseGroupDrawing };
|
|
@@ -39,7 +39,9 @@ declare function createNumberingMap(definitions: document_d_exports.NumberingDef
|
|
|
39
39
|
declare function computeListRendering(numPr: {
|
|
40
40
|
numId?: number;
|
|
41
41
|
ilvl?: number;
|
|
42
|
-
}, numbering: NumberingMap): document_d_exports.ListRendering
|
|
42
|
+
}, numbering: NumberingMap): (document_d_exports.ListRendering & {
|
|
43
|
+
levelStarts: number[];
|
|
44
|
+
}) | null;
|
|
43
45
|
/**
|
|
44
46
|
* Format a number according to the specified format
|
|
45
47
|
*
|
|
@@ -581,7 +581,12 @@ function computeListRendering(numPr, numbering) {
|
|
|
581
581
|
const level = numbering.getLevel(numId, ilvl);
|
|
582
582
|
if (!level) return null;
|
|
583
583
|
const levelNumFmts = [];
|
|
584
|
-
|
|
584
|
+
const levelStarts = [];
|
|
585
|
+
for (let i = 0; i <= ilvl; i += 1) {
|
|
586
|
+
const listLevel = numbering.getLevel(numId, i);
|
|
587
|
+
levelNumFmts.push(level.isLgl ? "decimal" : listLevel?.numFmt ?? "decimal");
|
|
588
|
+
levelStarts.push(listLevel?.start ?? 1);
|
|
589
|
+
}
|
|
585
590
|
const instance = numbering.getInstance(numId);
|
|
586
591
|
const overrideForLevel = instance?.levelOverrides?.find((override) => override.ilvl === ilvl);
|
|
587
592
|
const rendering = {
|
|
@@ -590,7 +595,8 @@ function computeListRendering(numPr, numbering) {
|
|
|
590
595
|
marker: level.lvlText,
|
|
591
596
|
isBullet: level.numFmt === "bullet",
|
|
592
597
|
numFmt: level.isLgl ? "decimal" : level.numFmt,
|
|
593
|
-
levelNumFmts
|
|
598
|
+
levelNumFmts,
|
|
599
|
+
levelStarts
|
|
594
600
|
};
|
|
595
601
|
if (level.isLgl) rendering.isLegal = true;
|
|
596
602
|
if (level.rPr?.hidden) rendering.markerHidden = true;
|
|
@@ -436,7 +436,7 @@ function paragraphStartsWithRenderedPageBreak(node) {
|
|
|
436
436
|
return "continue";
|
|
437
437
|
};
|
|
438
438
|
const outcome = visit(node);
|
|
439
|
-
if (outcome === "forced") return
|
|
439
|
+
if (outcome === "forced") return sawRenderedPageBreak;
|
|
440
440
|
return outcome === "visible" && sawRenderedPageBreak;
|
|
441
441
|
}
|
|
442
442
|
function replaceLocalName(name, localName) {
|
|
@@ -949,13 +949,19 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
|
|
|
949
949
|
const level = numbering.getLevel(numId, ilvl);
|
|
950
950
|
if (level) {
|
|
951
951
|
const levelNumFmts = [];
|
|
952
|
-
|
|
952
|
+
const levelStarts = [];
|
|
953
|
+
for (let levelIndex = 0; levelIndex <= ilvl; levelIndex += 1) {
|
|
954
|
+
const listLevel = numbering.getLevel(numId, levelIndex);
|
|
955
|
+
levelNumFmts.push(level.isLgl ? "decimal" : listLevel?.numFmt ?? "decimal");
|
|
956
|
+
levelStarts.push(listLevel?.start ?? 1);
|
|
957
|
+
}
|
|
953
958
|
const listRendering = {
|
|
954
959
|
level: ilvl,
|
|
955
960
|
numId,
|
|
956
961
|
marker: level.lvlText,
|
|
957
962
|
isBullet: level.numFmt === "bullet",
|
|
958
|
-
levelNumFmts
|
|
963
|
+
levelNumFmts,
|
|
964
|
+
levelStarts
|
|
959
965
|
};
|
|
960
966
|
const instance = numbering.getInstance(numId);
|
|
961
967
|
const overrideForLevel = instance?.levelOverrides?.find((override) => override.ilvl === ilvl);
|
package/dist/docx/runParser.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cloneWithXmlnsDeclarations, elementToXml, findChild, findChildren, getAttribute, getChildElements, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
|
|
2
2
|
import { EmphasisMarkSchema, FontThemeSchema, HighlightColorSchema, ShadingPatternSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
3
3
|
import { parseImage } from "./imageParser.js";
|
|
4
|
+
import { parseGroupDrawing } from "./groupDrawingParser.js";
|
|
4
5
|
import { parseShapeFromDrawing, shouldPreserveRawShapeDrawing } from "./shapeParser.js";
|
|
5
6
|
import { parseVmlImageContent } from "./vmlImageParser.js";
|
|
6
7
|
import { resolveThemeFontRef } from "./themeParser.js";
|
|
@@ -442,6 +443,12 @@ function parseInstrText(element) {
|
|
|
442
443
|
* `shapeParser.parseShapeFromDrawing` into a `ShapeContent`.
|
|
443
444
|
*/
|
|
444
445
|
function parseDrawingContent(element, rels, media) {
|
|
446
|
+
const groupImage = parseGroupDrawing(element);
|
|
447
|
+
if (groupImage) return {
|
|
448
|
+
type: "drawing",
|
|
449
|
+
image: groupImage,
|
|
450
|
+
rawXml: elementToXml(element)
|
|
451
|
+
};
|
|
445
452
|
if (shouldPreserveRawShapeDrawing(element)) return {
|
|
446
453
|
type: "drawing",
|
|
447
454
|
image: {
|
|
@@ -550,7 +557,7 @@ function parseRunContents(runElement, rels, media, rootXmlns = {}) {
|
|
|
550
557
|
if (innerName === "drawing") {
|
|
551
558
|
const innerDrawing = parseDrawingContent(innerChild, rels, media);
|
|
552
559
|
if (innerDrawing) {
|
|
553
|
-
if (innerDrawing.type === "drawing" && !innerDrawing.image.src) innerDrawing.rawXml = elementToXml(child);
|
|
560
|
+
if (innerDrawing.type === "drawing" && (innerDrawing.rawXml !== void 0 || !innerDrawing.image.src)) innerDrawing.rawXml = elementToXml(child);
|
|
554
561
|
contents.push(innerDrawing);
|
|
555
562
|
}
|
|
556
563
|
} else if (innerName === "pict") {
|
|
@@ -50,11 +50,8 @@ function findParagraphOffsets(xml, paraId) {
|
|
|
50
50
|
start,
|
|
51
51
|
end: tagEnd + 1
|
|
52
52
|
};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
depth++;
|
|
56
|
-
pos = tagEnd + 1;
|
|
57
|
-
}
|
|
53
|
+
} else depth++;
|
|
54
|
+
pos = tagEnd + 1;
|
|
58
55
|
} else pos = tagStart + 1;
|
|
59
56
|
} else if (xml.startsWith("</w:p>", tagStart)) {
|
|
60
57
|
depth--;
|
|
@@ -226,11 +223,8 @@ function scanElementRange(xml, start, openLiteral, closeTag) {
|
|
|
226
223
|
start,
|
|
227
224
|
end: tagEnd + 1
|
|
228
225
|
};
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
depth++;
|
|
232
|
-
pos = tagEnd + 1;
|
|
233
|
-
}
|
|
226
|
+
} else depth++;
|
|
227
|
+
pos = tagEnd + 1;
|
|
234
228
|
} else if (xml.startsWith(closeTag, tagStart)) {
|
|
235
229
|
depth--;
|
|
236
230
|
if (depth === 0) return {
|
|
@@ -87,7 +87,9 @@ function serializeNum(instance) {
|
|
|
87
87
|
* change detection and per-definition splicing, never to overwrite the part.
|
|
88
88
|
*/
|
|
89
89
|
function serializeNumberingXml(numbering) {
|
|
90
|
-
|
|
90
|
+
const abstractNums = numbering.abstractNums.map(serializeAbstractNum).join("");
|
|
91
|
+
const nums = numbering.nums.map(serializeNum).join("");
|
|
92
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w:numbering xmlns:w="${W_NS}">${abstractNums}${nums}</w:numbering>`;
|
|
91
93
|
}
|
|
92
94
|
//#endregion
|
|
93
95
|
export { serializeNumberingXml };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
|
|
3
3
|
//#region src/docx/settingsParser.d.ts
|
|
4
|
+
type FolioDocumentSettings = document_d_exports.DocumentSettings & {
|
|
5
|
+
/** Swap left/right section margins on even physical pages. */mirrorMargins?: boolean;
|
|
6
|
+
};
|
|
4
7
|
/** OOXML default per §17.6.13 when `w:defaultTabStop` is absent. */
|
|
5
8
|
declare const DEFAULT_TAB_STOP_TWIPS = 720;
|
|
6
|
-
declare function parseSettings(xml: string | null):
|
|
7
|
-
|
|
8
|
-
export { DEFAULT_TAB_STOP_TWIPS,
|
|
9
|
+
declare function parseSettings(xml: string | null): FolioDocumentSettings;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { DEFAULT_TAB_STOP_TWIPS, FolioDocumentSettings, parseSettings };
|
|
@@ -13,6 +13,8 @@ function parseSettings(xml) {
|
|
|
13
13
|
const settings = { defaultTabStop: parseDefaultTabStop(root) };
|
|
14
14
|
const evenAndOddHeaders = root ? findChild(root, "w", "evenAndOddHeaders") : null;
|
|
15
15
|
if (evenAndOddHeaders && parseBooleanElement(evenAndOddHeaders)) settings.evenAndOddHeaders = true;
|
|
16
|
+
const mirrorMargins = root ? findChild(root, "w", "mirrorMargins") : null;
|
|
17
|
+
if (mirrorMargins && parseBooleanElement(mirrorMargins)) settings.mirrorMargins = true;
|
|
16
18
|
const themeFontLangEl = root ? findChild(root, "w", "themeFontLang") : null;
|
|
17
19
|
const eastAsiaLang = themeFontLangEl ? getAttribute(themeFontLangEl, "w", "eastAsia") || void 0 : void 0;
|
|
18
20
|
const bidiLang = themeFontLangEl ? getAttribute(themeFontLangEl, "w", "bidi") || void 0 : void 0;
|
package/dist/docx/xmlParser.js
CHANGED
|
@@ -31,6 +31,7 @@ const fxpParserOptions = {
|
|
|
31
31
|
parseAttributeValue: false,
|
|
32
32
|
ignoreDeclaration: true,
|
|
33
33
|
ignorePiTags: true,
|
|
34
|
+
jPath: false,
|
|
34
35
|
processEntities: true,
|
|
35
36
|
htmlEntities: true
|
|
36
37
|
};
|
|
@@ -65,15 +66,19 @@ function fxpNodeToElement(node) {
|
|
|
65
66
|
text: node[TEXT_KEY]
|
|
66
67
|
};
|
|
67
68
|
const attrs = node[ATTR_KEY];
|
|
68
|
-
for (const key
|
|
69
|
+
for (const key in node) {
|
|
69
70
|
if (key === ATTR_KEY) continue;
|
|
70
71
|
const children = node[key];
|
|
71
72
|
const element = {
|
|
72
73
|
type: "element",
|
|
73
74
|
name: key
|
|
74
75
|
};
|
|
75
|
-
if (attrs
|
|
76
|
-
if (children.length > 0)
|
|
76
|
+
if (attrs) element.attributes = attrs;
|
|
77
|
+
if (children.length > 0) {
|
|
78
|
+
const elements = [];
|
|
79
|
+
for (const child of children) elements.push(fxpNodeToElement(child));
|
|
80
|
+
element.elements = elements;
|
|
81
|
+
}
|
|
77
82
|
return element;
|
|
78
83
|
}
|
|
79
84
|
return { type: "element" };
|
|
@@ -84,7 +89,9 @@ function fxpNodeToElement(node) {
|
|
|
84
89
|
* `{ elements: [...] }`.
|
|
85
90
|
*/
|
|
86
91
|
function fxpToRootElement(nodes) {
|
|
87
|
-
|
|
92
|
+
const elements = [];
|
|
93
|
+
for (const node of nodes) elements.push(fxpNodeToElement(node));
|
|
94
|
+
return { elements };
|
|
88
95
|
}
|
|
89
96
|
/**
|
|
90
97
|
* Convert an XmlElement back into the fast-xml-parser preserveOrder format
|