reamkit 1.15.4 → 1.17.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/esm/core/bidi/segments.js +1 -2
- package/dist/esm/core/converter/facade.d.ts +5 -0
- package/dist/esm/core/converter/project.js +5 -1
- package/dist/esm/core/converter/ream.d.ts +6 -0
- package/dist/esm/core/converter/ream.js +34 -8
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +659 -7
- package/dist/esm/core/drawingml/chart-geometry.d.ts +34 -10
- package/dist/esm/core/drawingml/chart-geometry.js +424 -92
- package/dist/esm/core/drawingml/chart-parser.js +301 -11
- package/dist/esm/core/drawingml/colors.d.ts +7 -7
- package/dist/esm/core/drawingml/colors.js +84 -18
- package/dist/esm/core/drawingml/preset-geometry.js +240 -6
- package/dist/esm/core/drawingml/shape-render.d.ts +12 -0
- package/dist/esm/core/drawingml/shape-render.js +116 -3
- package/dist/esm/core/drawingml/sparkline-geometry.js +6 -4
- package/dist/esm/core/drawingml/theme-parser.d.ts +51 -0
- package/dist/esm/core/drawingml/theme-parser.js +92 -1
- package/dist/esm/core/font/measure.d.ts +5 -0
- package/dist/esm/core/font/measure.js +21 -1
- package/dist/esm/core/font/ttf-subset.js +26 -1
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +353 -43
- package/dist/esm/core/indexed-colors.d.ts +11 -0
- package/dist/esm/core/indexed-colors.js +81 -0
- package/dist/esm/core/ir/flow.d.ts +23 -1
- package/dist/esm/core/ir/sheet.d.ts +61 -0
- package/dist/esm/{excel → core}/number-format.d.ts +37 -0
- package/dist/esm/core/number-format.js +800 -0
- package/dist/esm/core/numbering/apply.d.ts +5 -3
- package/dist/esm/core/numbering/apply.js +42 -11
- package/dist/esm/core/numbering/index.js +2 -0
- package/dist/esm/core/numbering/state.d.ts +13 -1
- package/dist/esm/core/numbering/state.js +256 -15
- package/dist/esm/core/opc/alternate-content.d.ts +13 -0
- package/dist/esm/core/opc/alternate-content.js +72 -0
- package/dist/esm/core/opc/core-properties.js +1 -0
- package/dist/esm/core/opc/package.d.ts +14 -1
- package/dist/esm/core/opc/package.js +43 -4
- package/dist/esm/core/opc/relationships.js +1 -0
- package/dist/esm/core/opc/xml-entities.d.ts +12 -0
- package/dist/esm/core/opc/xml-entities.js +91 -0
- package/dist/esm/core/po-helpers.js +16 -1
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +137 -0
- package/dist/esm/core/style-cascade/resolver.js +66 -11
- package/dist/esm/core/style-cascade/table.js +35 -11
- package/dist/esm/core/style-cascade/types.d.ts +42 -1
- package/dist/esm/core/style-cascade/types.js +4 -0
- package/dist/esm/core/vector.d.ts +30 -0
- package/dist/esm/excel/activex-parser.js +1 -0
- package/dist/esm/excel/column-bands.d.ts +26 -1
- package/dist/esm/excel/column-bands.js +156 -20
- package/dist/esm/excel/comments-parser.js +5 -3
- package/dist/esm/excel/conditional-format.d.ts +25 -2
- package/dist/esm/excel/conditional-format.js +63 -19
- package/dist/esm/excel/escaped-text.d.ts +9 -0
- package/dist/esm/excel/escaped-text.js +20 -0
- package/dist/esm/excel/form-control-parser.js +1 -0
- package/dist/esm/excel/formula/dates.js +1 -1
- package/dist/esm/excel/header-footer.d.ts +9 -1
- package/dist/esm/excel/header-footer.js +162 -14
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/index.js +2 -2
- package/dist/esm/excel/pivot-table-parser.js +1 -0
- package/dist/esm/excel/print-model.d.ts +75 -0
- package/dist/esm/excel/print-model.js +899 -77
- package/dist/esm/excel/printer-settings.d.ts +16 -0
- package/dist/esm/excel/printer-settings.js +36 -0
- package/dist/esm/excel/rich-value.d.ts +13 -0
- package/dist/esm/excel/rich-value.js +120 -0
- package/dist/esm/excel/shared-strings-parser.js +11 -7
- package/dist/esm/excel/sheet-drawing.d.ts +11 -0
- package/dist/esm/excel/sheet-drawing.js +26 -3
- package/dist/esm/excel/sheet-shape-parser.d.ts +53 -1
- package/dist/esm/excel/sheet-shape-parser.js +461 -32
- package/dist/esm/excel/sheet-to-flow.d.ts +23 -2
- package/dist/esm/excel/sheet-to-flow.js +553 -36
- package/dist/esm/excel/slicer-parser.js +1 -0
- package/dist/esm/excel/styles-parser.d.ts +30 -2
- package/dist/esm/excel/styles-parser.js +177 -40
- package/dist/esm/excel/table-parser.js +1 -0
- package/dist/esm/excel/vml-drawing.d.ts +68 -0
- package/dist/esm/excel/vml-drawing.js +158 -0
- package/dist/esm/excel/workbook-parser.d.ts +5 -0
- package/dist/esm/excel/workbook-parser.js +5 -1
- package/dist/esm/excel/worksheet-parser.d.ts +2 -1
- package/dist/esm/excel/worksheet-parser.js +150 -61
- package/dist/esm/excel/xlsx-reader.js +242 -11
- package/dist/esm/excel/xlsx-to-pdf.js +12 -1
- package/dist/esm/html/html-writer.js +29 -6
- package/dist/esm/layout/page-doc.d.ts +87 -1
- package/dist/esm/layout/styled-layout.d.ts +46 -2
- package/dist/esm/layout/styled-layout.js +2345 -274
- package/dist/esm/pdf/cid-font.js +20 -9
- package/dist/esm/pdf/objects.d.ts +13 -0
- package/dist/esm/pdf/objects.js +18 -1
- package/dist/esm/pdf/shading.js +76 -6
- package/dist/esm/pdf/styled-page-emitter.js +355 -49
- package/dist/esm/pdf/text-page-renderer.js +1 -0
- package/dist/esm/pdf/vector-graphics.d.ts +31 -2
- package/dist/esm/pdf/vector-graphics.js +103 -3
- package/dist/esm/pptx/pptx-reader.js +2 -0
- package/dist/esm/pptx/slide-parser.d.ts +21 -4
- package/dist/esm/pptx/slide-parser.js +98 -24
- package/dist/esm/svg/svg-writer.js +23 -4
- package/dist/esm/word/document-parser.d.ts +96 -7
- package/dist/esm/word/document-parser.js +538 -116
- package/dist/esm/word/docx-reader.js +135 -43
- package/dist/esm/word/docx-writer.js +6 -1
- package/dist/esm/word/drawing-parser.d.ts +86 -5
- package/dist/esm/word/drawing-parser.js +1590 -54
- package/dist/esm/word/index.d.ts +4 -4
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +108 -21
- package/dist/esm/word/paragraph-properties.d.ts +11 -1
- package/dist/esm/word/paragraph-properties.js +219 -10
- package/dist/esm/word/run-properties.js +45 -1
- package/dist/esm/word/settings-parser.d.ts +24 -0
- package/dist/esm/word/settings-parser.js +32 -5
- package/dist/esm/word/shading.d.ts +11 -0
- package/dist/esm/word/shading.js +64 -0
- package/dist/esm/word/styles-parser.js +9 -2
- package/dist/esm/word/table-parser.d.ts +9 -1
- package/dist/esm/word/table-parser.js +182 -30
- package/package.json +7 -3
- package/dist/esm/excel/number-format.js +0 -476
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
import { emuToPt, twipsToPt } from "../core/ir/units.js";
|
|
1
|
+
import { emuToPt, pt, twipsToPt } from "../core/ir/units.js";
|
|
2
2
|
import { poAttr, poAttrLocal, poChildren, poFindByPath, poFindDescendant, poIntAttr, poIs, poIsLocal, poText } from "../core/po-helpers.js";
|
|
3
3
|
import { defaultColorResolver } from "../core/drawingml/colors.js";
|
|
4
|
-
import { expandMcChildren, parseDrawing, parseVmlPicture } from "./drawing-parser.js";
|
|
5
|
-
import { diagramTransform, noDiagramOverrideLoss,
|
|
4
|
+
import { expandMcChildren, parseDrawing, parseVmlPicture, vmlFill } from "./drawing-parser.js";
|
|
5
|
+
import { diagramTransform, noDiagramOverrideLoss, parseDiagramNodes, parseTxBody } from "../pptx/slide-parser.js";
|
|
6
|
+
import { resolveInternalEntities } from "../core/opc/xml-entities.js";
|
|
6
7
|
import { parseOMath } from "./omml-parser.js";
|
|
7
8
|
import { parseRunProperties } from "./run-properties.js";
|
|
8
9
|
import { parseParagraphProperties } from "./paragraph-properties.js";
|
|
9
10
|
import { poElementToFlat } from "./po-to-flat.js";
|
|
10
|
-
import { parseTable } from "./table-parser.js";
|
|
11
|
+
import { parseBorders, parseTable } from "./table-parser.js";
|
|
11
12
|
import { XMLParser } from "fast-xml-parser";
|
|
12
13
|
//#region src/word/document-parser.ts
|
|
13
14
|
var decoder = new TextDecoder("utf-8");
|
|
15
|
+
var drawingTextParser = (txBody, resolveColor) => parseTxBody(txBody, void 0, void 0, resolveColor, void 0);
|
|
14
16
|
var parser = new XMLParser({
|
|
17
|
+
htmlEntities: true,
|
|
15
18
|
ignoreAttributes: false,
|
|
16
19
|
attributeNamePrefix: "@_",
|
|
17
20
|
preserveOrder: true,
|
|
18
21
|
parseAttributeValue: false,
|
|
19
22
|
parseTagValue: false,
|
|
20
|
-
trimValues: false
|
|
23
|
+
trimValues: false,
|
|
24
|
+
maxNestedTags: 1e3
|
|
21
25
|
});
|
|
22
26
|
var RUN_CONTAINER_TAGS = new Set([
|
|
23
27
|
"w:hyperlink",
|
|
@@ -39,19 +43,102 @@ var DEFAULT_PARSE_CONTEXT = { resolveColor: defaultColorResolver };
|
|
|
39
43
|
* @param ctx The document-wide parse context.
|
|
40
44
|
* @returns The body elements; empty when the `w:body` is absent.
|
|
41
45
|
*/
|
|
42
|
-
function parseDocument(documentXml, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
43
|
-
const xml = decoder.decode(documentXml);
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
return parseBodyElements(
|
|
46
|
+
function parseDocument(documentXml, ctx = DEFAULT_PARSE_CONTEXT, blocks) {
|
|
47
|
+
const xml = resolveInternalEntities(decoder.decode(documentXml));
|
|
48
|
+
const children = documentBodyChildren(parser.parse(xml));
|
|
49
|
+
if (children.length === 0) return [];
|
|
50
|
+
return parseBodyElements(children, ctx, blocks);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* §17.2.2 — the `w:document`'s body content. The schema allows one `w:body`
|
|
54
|
+
* and producers have written several: MultipleBodyBug.docx carries three, and
|
|
55
|
+
* reading only the first printed one paragraph of its three. They are read as
|
|
56
|
+
* the one body they stand for, in order.
|
|
57
|
+
*
|
|
58
|
+
* @param tree The parsed `document.xml`.
|
|
59
|
+
* @returns Every body's children, concatenated.
|
|
60
|
+
*/
|
|
61
|
+
function documentBodyChildren(tree) {
|
|
62
|
+
const doc = poFindByPath(tree, ["w:document"]);
|
|
63
|
+
if (!doc) return [];
|
|
64
|
+
const out = [];
|
|
65
|
+
for (const child of poChildren(doc)) if (poIs(child, "w:body")) out.push(...poChildren(child));
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* §17.2.1 `w:background` — the colour the whole page is painted, as a six-digit
|
|
70
|
+
* hex. Read from `@w:color` (Word's own attribute), falling back to the VML
|
|
71
|
+
* `v:background @fillcolor` beside it. `auto` and a gradient-only background
|
|
72
|
+
* (which carries no flat colour of its own) both come back undefined.
|
|
73
|
+
*
|
|
74
|
+
* @param documentXml The raw `document.xml` bytes.
|
|
75
|
+
* @returns The colour, or undefined when the document names none.
|
|
76
|
+
*/
|
|
77
|
+
function parseBackgroundColor(documentXml) {
|
|
78
|
+
const bg = backgroundNode(documentXml);
|
|
79
|
+
if (!bg) return void 0;
|
|
80
|
+
const vml = poChildren(bg).find((c) => poIs(c, "v:background"));
|
|
81
|
+
const hex = (poAttr(bg, "color") ?? (vml ? poAttr(vml, "fillcolor") : void 0))?.replace(/^#/u, "");
|
|
82
|
+
return hex !== void 0 && /^[0-9A-Fa-f]{6}$/u.test(hex) ? hex.toUpperCase() : void 0;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* §17.2.1 — the page background as the FILL it is. `@w:color` is only the flat
|
|
86
|
+
* fallback: the `v:background` beside it carries the gradient or the picture
|
|
87
|
+
* Word actually paints, and both references draw those. fill.docx runs a
|
|
88
|
+
* five-stop radial sweep where we painted its fallback navy, and
|
|
89
|
+
* tdf126533_pageBitmap.docx papers the page with an image.
|
|
90
|
+
*
|
|
91
|
+
* @param documentXml The raw `document.xml` bytes.
|
|
92
|
+
* @param resolveImage Resolver for a picture background's `r:id`.
|
|
93
|
+
* @returns The fill, or undefined when the document names no background.
|
|
94
|
+
*/
|
|
95
|
+
function parseBackgroundFill(documentXml, resolveImage) {
|
|
96
|
+
const bg = backgroundNode(documentXml);
|
|
97
|
+
if (!bg || poAttr(bg, "color") === void 0) return void 0;
|
|
98
|
+
const vml = poChildren(bg).find((c) => poIs(c, "v:background"));
|
|
99
|
+
if (!vml) return void 0;
|
|
100
|
+
const fill = vmlFill(vml, void 0, resolveImage);
|
|
101
|
+
return fill.kind === "gradient" || fill.kind === "picture" ? fill : void 0;
|
|
102
|
+
}
|
|
103
|
+
function backgroundNode(documentXml) {
|
|
104
|
+
const doc = poFindByPath(parser.parse(resolveInternalEntities(decoder.decode(documentXml))), ["w:document"]);
|
|
105
|
+
return doc ? poChildren(doc).find((c) => poIs(c, "w:background")) : void 0;
|
|
106
|
+
}
|
|
107
|
+
/** A fresh {@link BlockCounter}. */
|
|
108
|
+
function newBlockCounter() {
|
|
109
|
+
return {
|
|
110
|
+
index: [],
|
|
111
|
+
next: 0
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Translate a section boundary counted in source blocks into one counted in body
|
|
116
|
+
* elements: the number of elements that came from a block before `blockEnd`.
|
|
117
|
+
*
|
|
118
|
+
* @param blocks The counter filled while parsing the body.
|
|
119
|
+
* @param blockEnd The section's `endIndex`, in source blocks.
|
|
120
|
+
* @returns The matching body-element index.
|
|
121
|
+
*/
|
|
122
|
+
function bodyIndexForBlock(blocks, blockEnd) {
|
|
123
|
+
let n = 0;
|
|
124
|
+
while (n < blocks.index.length && blocks.index[n] < blockEnd) n++;
|
|
125
|
+
return n;
|
|
47
126
|
}
|
|
48
127
|
var HF_TYPES = new Set([
|
|
49
128
|
"default",
|
|
50
129
|
"first",
|
|
51
130
|
"even"
|
|
52
131
|
]);
|
|
53
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* The empty {@link SectionProperties} fallback (no headers/footers). §17.6.13 —
|
|
134
|
+
* on the page a document with no `w:sectPr` of its own is made on, which is the
|
|
135
|
+
* same US Letter a section with no `w:pgSz` gets.
|
|
136
|
+
*/
|
|
54
137
|
var EMPTY_SECTION = {
|
|
138
|
+
pageSize: {
|
|
139
|
+
width: twipsToPt(12240),
|
|
140
|
+
height: twipsToPt(15840)
|
|
141
|
+
},
|
|
55
142
|
headers: [],
|
|
56
143
|
footers: []
|
|
57
144
|
};
|
|
@@ -66,30 +153,38 @@ var EMPTY_SECTION = {
|
|
|
66
153
|
* @returns The sections in document order; empty when the `w:body` is absent.
|
|
67
154
|
*/
|
|
68
155
|
function parseSections(documentXml) {
|
|
69
|
-
const xml = decoder.decode(documentXml);
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
const children = poChildren(body);
|
|
156
|
+
const xml = resolveInternalEntities(decoder.decode(documentXml));
|
|
157
|
+
const children = documentBodyChildren(parser.parse(xml));
|
|
158
|
+
if (children.length === 0) return [];
|
|
73
159
|
const sections = [];
|
|
74
160
|
let bodyIdx = 0;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
161
|
+
let trailing;
|
|
162
|
+
const walk = (nodes) => {
|
|
163
|
+
for (const child of nodes) {
|
|
164
|
+
if (poIs(child, "w:sectPr")) {
|
|
165
|
+
trailing = parseSectPrNode(child);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (poIs(child, "w:p")) {
|
|
169
|
+
const pPrNode = poChildren(child).find((c) => poIs(c, "w:pPr"));
|
|
170
|
+
const sectPrInPPr = pPrNode ? poChildren(pPrNode).find((c) => poIs(c, "w:sectPr")) : void 0;
|
|
171
|
+
bodyIdx++;
|
|
172
|
+
if (sectPrInPPr) sections.push({
|
|
173
|
+
properties: parseSectPrNode(sectPrInPPr),
|
|
174
|
+
endIndex: bodyIdx
|
|
175
|
+
});
|
|
176
|
+
} else if (poIs(child, "w:tbl")) bodyIdx++;
|
|
177
|
+
else if (poIs(child, "w:sdt")) {
|
|
178
|
+
const content = poChildren(child).find((c) => poIs(c, "w:sdtContent"));
|
|
179
|
+
walk(content ? poChildren(content) : []);
|
|
180
|
+
}
|
|
82
181
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
endIndex: bodyIdx
|
|
90
|
-
});
|
|
91
|
-
} else if (poIs(child, "w:tbl")) bodyIdx++;
|
|
92
|
-
}
|
|
182
|
+
};
|
|
183
|
+
walk(children);
|
|
184
|
+
if (trailing) sections.push({
|
|
185
|
+
properties: trailing,
|
|
186
|
+
endIndex: bodyIdx
|
|
187
|
+
});
|
|
93
188
|
if (sections.length === 0 || sections[sections.length - 1].endIndex < bodyIdx) sections.push({
|
|
94
189
|
properties: EMPTY_SECTION,
|
|
95
190
|
endIndex: bodyIdx
|
|
@@ -97,10 +192,18 @@ function parseSections(documentXml) {
|
|
|
97
192
|
return sections;
|
|
98
193
|
}
|
|
99
194
|
function parseSectPrNode(sectPr) {
|
|
100
|
-
let pageSize
|
|
195
|
+
let pageSize = {
|
|
196
|
+
width: twipsToPt(12240),
|
|
197
|
+
height: twipsToPt(15840)
|
|
198
|
+
};
|
|
101
199
|
let margins;
|
|
102
200
|
let titlePg = false;
|
|
201
|
+
let pageNumberStart;
|
|
202
|
+
let lineNumbering;
|
|
103
203
|
let columns;
|
|
204
|
+
let sectionStart;
|
|
205
|
+
let pageBorders;
|
|
206
|
+
let gridLinePitchPt;
|
|
104
207
|
const headers = [];
|
|
105
208
|
const footers = [];
|
|
106
209
|
for (const child of poChildren(sectPr)) if (poIs(child, "w:pgSz")) {
|
|
@@ -119,30 +222,64 @@ function parseSectPrNode(sectPr) {
|
|
|
119
222
|
const left = poIntAttr(child, "left");
|
|
120
223
|
const header = poIntAttr(child, "header");
|
|
121
224
|
const footer = poIntAttr(child, "footer");
|
|
225
|
+
const gutter = poIntAttr(child, "gutter");
|
|
122
226
|
margins = {
|
|
123
227
|
top: twipsToPt(top ?? 1440),
|
|
124
228
|
right: twipsToPt(right ?? 1440),
|
|
125
229
|
bottom: twipsToPt(bottom ?? 1440),
|
|
126
230
|
left: twipsToPt(left ?? 1440),
|
|
127
231
|
...header !== void 0 ? { header: twipsToPt(header) } : {},
|
|
128
|
-
...footer !== void 0 ? { footer: twipsToPt(footer) } : {}
|
|
232
|
+
...footer !== void 0 ? { footer: twipsToPt(footer) } : {},
|
|
233
|
+
...gutter !== void 0 && gutter > 0 ? { gutter: twipsToPt(gutter) } : {}
|
|
129
234
|
};
|
|
130
235
|
} else if (poIs(child, "w:headerReference")) pushHeaderFooter(child, headers);
|
|
131
236
|
else if (poIs(child, "w:footerReference")) pushHeaderFooter(child, footers);
|
|
132
237
|
else if (poIs(child, "w:titlePg")) {
|
|
133
238
|
const val = poAttr(child, "val");
|
|
134
239
|
titlePg = val === void 0 || val === "" || val !== "0" && val !== "false";
|
|
240
|
+
} else if (poIs(child, "w:lnNumType")) {
|
|
241
|
+
const countBy = poIntAttr(child, "countBy") ?? 1;
|
|
242
|
+
const start = poIntAttr(child, "start") ?? 1;
|
|
243
|
+
const distance = poIntAttr(child, "distance");
|
|
244
|
+
const restartRaw = poAttr(child, "restart");
|
|
245
|
+
lineNumbering = {
|
|
246
|
+
countBy: countBy > 0 ? countBy : 1,
|
|
247
|
+
start,
|
|
248
|
+
...distance !== void 0 ? { distancePt: twipsToPt(distance) } : {},
|
|
249
|
+
restart: restartRaw === "newSection" || restartRaw === "continuous" ? restartRaw : "newPage"
|
|
250
|
+
};
|
|
251
|
+
} else if (poIs(child, "w:pgNumType")) {
|
|
252
|
+
const start = poIntAttr(child, "start");
|
|
253
|
+
if (start !== void 0) pageNumberStart = start;
|
|
135
254
|
} else if (poIs(child, "w:cols")) columns = parseColumns(child);
|
|
255
|
+
else if (poIs(child, "w:pgBorders")) {
|
|
256
|
+
const borders = parseBorders(child);
|
|
257
|
+
if (borders) pageBorders = {
|
|
258
|
+
borders,
|
|
259
|
+
offsetFrom: poAttr(child, "offsetFrom") === "page" ? "page" : "text"
|
|
260
|
+
};
|
|
261
|
+
} else if (poIs(child, "w:docGrid")) {
|
|
262
|
+
const type = poAttr(child, "type") ?? "default";
|
|
263
|
+
const pitch = poIntAttr(child, "linePitch");
|
|
264
|
+
if ((type === "lines" || type === "linesAndChars") && pitch !== void 0 && pitch > 0) gridLinePitchPt = twipsToPt(pitch);
|
|
265
|
+
} else if (poIs(child, "w:type")) sectionStart = poAttr(child, "val") === "continuous" ? "continuous" : "nextPage";
|
|
136
266
|
return {
|
|
137
|
-
|
|
267
|
+
pageSize,
|
|
138
268
|
...margins ? { margins } : {},
|
|
139
269
|
headers,
|
|
140
270
|
footers,
|
|
141
271
|
...titlePg ? { titlePg: true } : {},
|
|
142
|
-
...
|
|
272
|
+
...pageNumberStart !== void 0 ? { pageNumberStart } : {},
|
|
273
|
+
...lineNumbering ? { lineNumbering } : {},
|
|
274
|
+
...columns ? { columns } : {},
|
|
275
|
+
...sectionStart ? { sectionStart } : {},
|
|
276
|
+
...pageBorders ? { pageBorders } : {},
|
|
277
|
+
...gridLinePitchPt !== void 0 ? { gridLinePitchPt } : {}
|
|
143
278
|
};
|
|
144
279
|
}
|
|
145
280
|
function parseColumns(cols) {
|
|
281
|
+
const sepRaw = poAttr(cols, "sep");
|
|
282
|
+
const separator = sepRaw !== void 0 && sepRaw !== "0" && sepRaw !== "false";
|
|
146
283
|
const explicit = [];
|
|
147
284
|
for (const col of poChildren(cols)) {
|
|
148
285
|
if (!poIs(col, "w:col")) continue;
|
|
@@ -159,7 +296,8 @@ function parseColumns(cols) {
|
|
|
159
296
|
return {
|
|
160
297
|
count,
|
|
161
298
|
spacePt: twipsToPt(poIntAttr(cols, "space") ?? 720),
|
|
162
|
-
...explicit.length > 0 ? { explicit } : {}
|
|
299
|
+
...explicit.length > 0 ? { explicit } : {},
|
|
300
|
+
...separator ? { separator: true } : {}
|
|
163
301
|
};
|
|
164
302
|
}
|
|
165
303
|
function pushHeaderFooter(node, list) {
|
|
@@ -181,7 +319,7 @@ function pushHeaderFooter(node, list) {
|
|
|
181
319
|
* @returns The body elements; empty when neither root is found.
|
|
182
320
|
*/
|
|
183
321
|
function parseHeaderFooter(xml, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
184
|
-
const root = parser.parse(decoder.decode(xml)).find((n) => poIs(n, "w:hdr") || poIs(n, "w:ftr"));
|
|
322
|
+
const root = parser.parse(resolveInternalEntities(decoder.decode(xml))).find((n) => poIs(n, "w:hdr") || poIs(n, "w:ftr"));
|
|
185
323
|
if (!root) return [];
|
|
186
324
|
return parseBodyElements(poChildren(root), ctx);
|
|
187
325
|
}
|
|
@@ -195,29 +333,57 @@ function parseHeaderFooter(xml, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
|
195
333
|
* @param ctx The document-wide parse context.
|
|
196
334
|
* @returns The parsed body elements.
|
|
197
335
|
*/
|
|
198
|
-
function parseBodyElements(children, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
336
|
+
function parseBodyElements(children, ctx = DEFAULT_PARSE_CONTEXT, blocks, sdtRunProps) {
|
|
199
337
|
const out = [];
|
|
338
|
+
const mark = (n) => {
|
|
339
|
+
if (!blocks) return;
|
|
340
|
+
for (let i = 0; i < n; i++) blocks.index.push(blocks.next);
|
|
341
|
+
};
|
|
200
342
|
let pendingBookmarks;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
343
|
+
let pendingPageBreak = false;
|
|
344
|
+
for (const child of children) {
|
|
345
|
+
if (poIs(child, "w:br")) {
|
|
346
|
+
if (poAttr(child, "type") === "page") pendingPageBreak = true;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (poIs(child, "w:bookmarkStart")) {
|
|
350
|
+
const bookmarkName = poAttr(child, "name");
|
|
351
|
+
if (bookmarkName !== void 0 && bookmarkName !== "" && bookmarkName !== "_GoBack") (pendingBookmarks ??= []).push(bookmarkName);
|
|
352
|
+
} else if (poIs(child, "w:p")) {
|
|
353
|
+
const drawings = tryExtractDrawingFromParagraph(child, ctx);
|
|
354
|
+
if (drawings) {
|
|
355
|
+
out.push(...drawings);
|
|
356
|
+
mark(drawings.length);
|
|
357
|
+
} else {
|
|
358
|
+
const anchored = [];
|
|
359
|
+
const parsed = parseParagraph(child, ctx, pendingBookmarks, anchored, sdtRunProps);
|
|
360
|
+
const paragraph = pendingPageBreak ? {
|
|
361
|
+
...parsed,
|
|
362
|
+
properties: {
|
|
363
|
+
...parsed.properties,
|
|
364
|
+
pageBreakBefore: true
|
|
365
|
+
}
|
|
366
|
+
} : parsed;
|
|
367
|
+
pendingPageBreak = false;
|
|
368
|
+
out.push(...anchored, {
|
|
369
|
+
kind: "paragraph",
|
|
370
|
+
paragraph
|
|
371
|
+
});
|
|
372
|
+
mark(anchored.length + 1);
|
|
373
|
+
pendingBookmarks = void 0;
|
|
374
|
+
}
|
|
375
|
+
if (blocks) blocks.next++;
|
|
376
|
+
} else if (poIs(child, "w:tbl")) {
|
|
208
377
|
out.push({
|
|
209
|
-
kind: "
|
|
210
|
-
|
|
378
|
+
kind: "table",
|
|
379
|
+
table: parseTable(child, ctx)
|
|
211
380
|
});
|
|
212
|
-
|
|
381
|
+
mark(1);
|
|
382
|
+
if (blocks) blocks.next++;
|
|
383
|
+
} else if (poIs(child, "w:sdt")) {
|
|
384
|
+
const content = poChildren(child).find((c) => poIs(c, "w:sdtContent"));
|
|
385
|
+
if (content) out.push(...parseBodyElements(poChildren(content), ctx, blocks, sdtRunProps));
|
|
213
386
|
}
|
|
214
|
-
} else if (poIs(child, "w:tbl")) out.push({
|
|
215
|
-
kind: "table",
|
|
216
|
-
table: parseTable(child, ctx)
|
|
217
|
-
});
|
|
218
|
-
else if (poIs(child, "w:sdt")) {
|
|
219
|
-
const content = poChildren(child).find((c) => poIs(c, "w:sdtContent"));
|
|
220
|
-
if (content) out.push(...parseBodyElements(poChildren(content), ctx));
|
|
221
387
|
}
|
|
222
388
|
return out;
|
|
223
389
|
}
|
|
@@ -232,12 +398,11 @@ function scanForLoneDrawing(container, acc) {
|
|
|
232
398
|
for (const child of expandMcChildren(poChildren(container))) {
|
|
233
399
|
if (poIs(child, "w:pPr")) continue;
|
|
234
400
|
if (poIs(child, "w:r")) {
|
|
235
|
-
for (const rc of expandMcChildren(poChildren(child))) if (poIs(rc, "w:drawing"))
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!acc.vml && poFindDescendant(rc, "v:imagedata") !== void 0) acc.vml = rc;
|
|
401
|
+
for (const rc of expandMcChildren(poChildren(child))) if (poIs(rc, "w:drawing")) acc.drawings.push(rc);
|
|
402
|
+
else if (poIs(rc, "w:pict") || poIs(rc, "w:object")) {
|
|
403
|
+
if (!acc.vml && (poFindDescendant(rc, "v:imagedata") ?? poFindDescendant(rc, "v:textpath")) !== void 0) acc.vml = rc;
|
|
239
404
|
} else if (poIs(rc, "w:t") && poText(rc).length > 0) acc.hasOther = true;
|
|
240
|
-
else if (poIs(rc, "w:tab") || poIs(rc, "w:br") || poIs(rc, "w:noBreakHyphen")) acc.hasOther = true;
|
|
405
|
+
else if (poIs(rc, "w:tab") || poIs(rc, "w:ptab") || poIs(rc, "w:br") || poIs(rc, "w:noBreakHyphen")) acc.hasOther = true;
|
|
241
406
|
continue;
|
|
242
407
|
}
|
|
243
408
|
if (poIs(child, "m:oMath") || poIs(child, "m:oMathPara")) {
|
|
@@ -250,25 +415,56 @@ function scanForLoneDrawing(container, acc) {
|
|
|
250
415
|
}
|
|
251
416
|
}
|
|
252
417
|
function tryExtractDrawingFromParagraph(p, ctx) {
|
|
253
|
-
const scan = {
|
|
418
|
+
const scan = {
|
|
419
|
+
hasOther: false,
|
|
420
|
+
drawings: []
|
|
421
|
+
};
|
|
254
422
|
scanForLoneDrawing(p, scan);
|
|
255
|
-
const {
|
|
256
|
-
if (scan.hasOther ||
|
|
257
|
-
|
|
423
|
+
const { drawings, vml } = scan;
|
|
424
|
+
if (scan.hasOther || drawings.length === 0 && !vml) return null;
|
|
425
|
+
if (!vml && drawings.every((d) => poChildren(d).some((c) => poIs(c, "wp:anchor")))) return null;
|
|
258
426
|
const parseBody = (children) => parseBodyElements(children, ctx);
|
|
259
|
-
const content = fromVml ? parseVmlPicture(vml) : parseDrawing(drawing, ctx.resolveColor, parseBody);
|
|
260
|
-
if (!content) return null;
|
|
261
|
-
if (fromVml && content.kind === "image" && ctx.resolveImage?.(content.imageId) === void 0) return null;
|
|
262
427
|
const pPrNode = poChildren(p).find((c) => poIs(c, "w:pPr"));
|
|
263
|
-
const paragraphProperties = pPrNode ? parseParagraphProperties(poElementToFlat(pPrNode)) : {};
|
|
428
|
+
const paragraphProperties = pPrNode ? parseParagraphProperties(poElementToFlat(pPrNode), ctx.autoSpacingPt) : {};
|
|
429
|
+
if (drawings.length === 0) {
|
|
430
|
+
const content = parseVmlPicture(vml, parseBody);
|
|
431
|
+
if (!content) return null;
|
|
432
|
+
if (content.kind === "image" && ctx.resolveImage?.(content.imageId) === void 0) return null;
|
|
433
|
+
return blocksForDrawing(content, paragraphProperties, ctx);
|
|
434
|
+
}
|
|
435
|
+
const contents = drawings.map((d) => parseDrawing(d, ctx.resolveColor, parseBody, ctx.resolveImage, ctx.resolveChartPart, ctx.themeLineWidths, ctx.themeStyles, drawingTextParser)).filter((c) => c !== null);
|
|
436
|
+
if (contents.length > 1 && contents.some((c) => !c.float)) return null;
|
|
437
|
+
const out = [];
|
|
438
|
+
for (const content of contents) out.push(...blocksForDrawing(content, paragraphProperties, ctx) ?? []);
|
|
439
|
+
return out.length > 0 ? out : null;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* One parsed drawing as the body elements it becomes: a picture, a chart, a
|
|
443
|
+
* shape, or the several shapes a SmartArt diagram draws.
|
|
444
|
+
*
|
|
445
|
+
* @param content The parsed drawing.
|
|
446
|
+
* @param paragraphProperties The owning paragraph's properties, which a block
|
|
447
|
+
* carries for its spacing and alignment.
|
|
448
|
+
* @param ctx The document-wide parse context.
|
|
449
|
+
* @returns The blocks, or `null` when the drawing renders nothing.
|
|
450
|
+
*/
|
|
451
|
+
function blocksForDrawing(content, paragraphProperties, ctx) {
|
|
264
452
|
if (content.kind === "image") {
|
|
265
453
|
const resource = ctx.resolveImage?.(content.imageId);
|
|
266
454
|
return [{
|
|
267
455
|
kind: "image",
|
|
268
456
|
image: {
|
|
269
457
|
...resource ? { resource } : {},
|
|
458
|
+
...content.outline ? { outline: content.outline } : {},
|
|
459
|
+
...content.shadow ? { shadow: content.shadow } : {},
|
|
270
460
|
width: content.width,
|
|
271
461
|
height: content.height,
|
|
462
|
+
...content.crop ? { crop: content.crop } : {},
|
|
463
|
+
...content.rotation60k ? { rotation60k: content.rotation60k } : {},
|
|
464
|
+
...content.flipH ? { flipH: true } : {},
|
|
465
|
+
...content.flipV ? { flipV: true } : {},
|
|
466
|
+
...content.relativeSize ? { relativeSize: content.relativeSize } : {},
|
|
467
|
+
...content.effectExtent ? { effectExtent: content.effectExtent } : {},
|
|
272
468
|
paragraphProperties,
|
|
273
469
|
...content.altText ? { altText: content.altText } : {},
|
|
274
470
|
...content.float ? { float: content.float } : {}
|
|
@@ -287,31 +483,39 @@ function tryExtractDrawingFromParagraph(p, ctx) {
|
|
|
287
483
|
}
|
|
288
484
|
}];
|
|
289
485
|
if (content.kind === "diagram") {
|
|
290
|
-
const
|
|
291
|
-
if (!
|
|
486
|
+
const diagram = ctx.resolveDiagram?.(content.dmRelId);
|
|
487
|
+
if (!diagram) {
|
|
292
488
|
ctx.onLoss?.(noDiagramOverrideLoss());
|
|
293
489
|
return null;
|
|
294
490
|
}
|
|
295
|
-
const
|
|
491
|
+
const frame = {
|
|
296
492
|
x: 0,
|
|
297
493
|
y: 0,
|
|
298
494
|
cx: content.widthEmu,
|
|
299
495
|
cy: content.heightEmu
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
relativeFrom: "column",
|
|
304
|
-
offsetPt: emuToPt(box.x)
|
|
305
|
-
},
|
|
306
|
-
posV: {
|
|
307
|
-
relativeFrom: "paragraph",
|
|
308
|
-
offsetPt: emuToPt(box.y)
|
|
309
|
-
}
|
|
310
|
-
}), ctx.resolveColor, void 0);
|
|
311
|
-
return shapes.length > 0 ? shapes.map((shape) => ({
|
|
496
|
+
};
|
|
497
|
+
const nodes = parseDiagramNodes(diagram.spTree, diagramTransform(diagram.spTree, frame), ctx.resolveColor, void 0, diagram.resolveImage);
|
|
498
|
+
return [{
|
|
312
499
|
kind: "shape",
|
|
313
|
-
shape
|
|
314
|
-
|
|
500
|
+
shape: {
|
|
501
|
+
width: emuToPt(content.widthEmu),
|
|
502
|
+
height: emuToPt(content.heightEmu),
|
|
503
|
+
children: nodes.map(({ box, shape }) => ({
|
|
504
|
+
shape,
|
|
505
|
+
xPt: emuToPt(box.x),
|
|
506
|
+
yPt: emuToPt(box.y)
|
|
507
|
+
})),
|
|
508
|
+
geometry: {
|
|
509
|
+
kind: "preset",
|
|
510
|
+
preset: "rect",
|
|
511
|
+
adjust: /* @__PURE__ */ new Map()
|
|
512
|
+
},
|
|
513
|
+
fill: { kind: "none" },
|
|
514
|
+
paragraphProperties,
|
|
515
|
+
...content.altText ? { altText: content.altText } : {},
|
|
516
|
+
...content.float ? { float: content.float } : {}
|
|
517
|
+
}
|
|
518
|
+
}];
|
|
315
519
|
}
|
|
316
520
|
return [{
|
|
317
521
|
kind: "shape",
|
|
@@ -323,7 +527,7 @@ function tryExtractDrawingFromParagraph(p, ctx) {
|
|
|
323
527
|
}
|
|
324
528
|
}];
|
|
325
529
|
}
|
|
326
|
-
function parseParagraph(p, ctx, extraBookmarks) {
|
|
530
|
+
function parseParagraph(p, ctx, extraBookmarks, anchored, sdtRunProps) {
|
|
327
531
|
const bookmarks = [...extraBookmarks ?? []];
|
|
328
532
|
for (const child of poChildren(p)) {
|
|
329
533
|
if (!poIs(child, "w:bookmarkStart")) continue;
|
|
@@ -331,7 +535,11 @@ function parseParagraph(p, ctx, extraBookmarks) {
|
|
|
331
535
|
if (bookmarkName !== void 0 && bookmarkName !== "" && bookmarkName !== "_GoBack") bookmarks.push(bookmarkName);
|
|
332
536
|
}
|
|
333
537
|
const pPr = poChildren(p).find((c) => poIs(c, "w:pPr"));
|
|
334
|
-
let properties = parseParagraphProperties(pPr ? poElementToFlat(pPr) : void 0);
|
|
538
|
+
let properties = parseParagraphProperties(pPr ? poElementToFlat(pPr) : void 0, ctx.autoSpacingPt);
|
|
539
|
+
if (pPr && poChildren(pPr).some((c) => poIs(c, "w:sectPr"))) properties = {
|
|
540
|
+
...properties,
|
|
541
|
+
sectionBreak: true
|
|
542
|
+
};
|
|
335
543
|
const mathPara = poChildren(p).find((c) => poIs(c, "m:oMathPara"));
|
|
336
544
|
if (mathPara && properties.alignment === void 0) {
|
|
337
545
|
const paraPr = poChildren(mathPara).find((c) => poIs(c, "m:oMathParaPr"));
|
|
@@ -342,19 +550,79 @@ function parseParagraph(p, ctx, extraBookmarks) {
|
|
|
342
550
|
alignment
|
|
343
551
|
};
|
|
344
552
|
}
|
|
553
|
+
const pTabs = collectPositionTabs(p);
|
|
554
|
+
if (pTabs.length > 0) properties = {
|
|
555
|
+
...properties,
|
|
556
|
+
tabs: [...properties.tabs ?? [], ...pTabs]
|
|
557
|
+
};
|
|
345
558
|
const collected = [];
|
|
346
|
-
collectRuns(p, collected, ctx);
|
|
559
|
+
collectRuns(p, collected, ctx, void 0, void 0, anchored, sdtRunProps);
|
|
347
560
|
return {
|
|
348
561
|
properties,
|
|
349
562
|
runs: applyFieldFsm(collected),
|
|
350
563
|
...bookmarks.length > 0 ? { bookmarks } : {}
|
|
351
564
|
};
|
|
352
565
|
}
|
|
566
|
+
/**
|
|
567
|
+
* §17.3.3.15 `w:ptab` — the absolute-position tabs a paragraph holds, as stops.
|
|
568
|
+
*
|
|
569
|
+
* `@w:alignment` says which edge of the text column the tab reaches for; the
|
|
570
|
+
* `left` alignment reaches for no edge at all (it goes to where the text
|
|
571
|
+
* already is) and states no stop. `@w:relativeTo` distinguishes the margin from
|
|
572
|
+
* the paragraph's indent, which for a stop measured from the text margin is the
|
|
573
|
+
* same place.
|
|
574
|
+
*
|
|
575
|
+
* @param p The `w:p` element.
|
|
576
|
+
* @returns One stop per position tab, in document order.
|
|
577
|
+
*/
|
|
578
|
+
function collectPositionTabs(p) {
|
|
579
|
+
const out = [];
|
|
580
|
+
const visit = (node) => {
|
|
581
|
+
for (const child of poChildren(node)) {
|
|
582
|
+
if (poIs(child, "w:ptab")) {
|
|
583
|
+
const alignment = poAttr(child, "alignment");
|
|
584
|
+
if (alignment === "center" || alignment === "right") out.push({
|
|
585
|
+
positionPt: pt(0),
|
|
586
|
+
alignment,
|
|
587
|
+
relativeTo: alignment
|
|
588
|
+
});
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (poIs(child, "w:r") || poIs(child, "w:hyperlink") || poIs(child, "w:ins")) visit(child);
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
visit(p);
|
|
595
|
+
return out;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* §17.16.5.44 `MACROBUTTON macroName displayText` — the display text, which is
|
|
599
|
+
* everything after the macro's name and is all a reader ever sees of the field.
|
|
600
|
+
*
|
|
601
|
+
* @param instr The field instruction.
|
|
602
|
+
* @returns The display text, or `undefined` when this is not a MACROBUTTON.
|
|
603
|
+
*/
|
|
604
|
+
function macroButtonText(instr) {
|
|
605
|
+
const shown = /^\s*MACROBUTTON\s+\S+\s(.*)$/su.exec(instr)?.[1]?.replace(/\s+$/u, "");
|
|
606
|
+
return shown !== void 0 && shown !== "" ? shown : void 0;
|
|
607
|
+
}
|
|
353
608
|
function parseFieldInstr(instr) {
|
|
354
|
-
|
|
355
|
-
const kw = /^\s*([A-Za-z]+)/.exec(instr)?.[1]?.toUpperCase();
|
|
609
|
+
const kw = fieldKeyword(instr);
|
|
356
610
|
return kw === "PAGE" ? "PAGE" : kw === "NUMPAGES" ? "NUMPAGES" : void 0;
|
|
357
611
|
}
|
|
612
|
+
function fieldKeyword(instr) {
|
|
613
|
+
if (instr === void 0) return void 0;
|
|
614
|
+
return /^\s*([A-Za-z]+)/.exec(instr)?.[1]?.toUpperCase();
|
|
615
|
+
}
|
|
616
|
+
var CHECKBOX_CLEAR = "☐";
|
|
617
|
+
var CHECKBOX_CHECKED = "☒";
|
|
618
|
+
var SILENT_FIELDS = new Set([
|
|
619
|
+
"SET",
|
|
620
|
+
"ASK",
|
|
621
|
+
"XE",
|
|
622
|
+
"TC",
|
|
623
|
+
"RD",
|
|
624
|
+
"PRIVATE"
|
|
625
|
+
]);
|
|
358
626
|
function synthesizeFieldRun(result, field, href) {
|
|
359
627
|
const first = result[0];
|
|
360
628
|
const linked = href ?? result.find((r) => r.href !== void 0)?.href;
|
|
@@ -384,7 +652,9 @@ function applyFieldFsm(collected) {
|
|
|
384
652
|
phase: "instr",
|
|
385
653
|
instr: "",
|
|
386
654
|
result: [],
|
|
387
|
-
depth: 0
|
|
655
|
+
depth: 0,
|
|
656
|
+
...c.checkBox !== void 0 ? { checkBox: c.checkBox } : {},
|
|
657
|
+
properties: c.run.properties
|
|
388
658
|
};
|
|
389
659
|
continue;
|
|
390
660
|
}
|
|
@@ -402,8 +672,20 @@ function applyFieldFsm(collected) {
|
|
|
402
672
|
continue;
|
|
403
673
|
}
|
|
404
674
|
const field = parseFieldInstr(st.instr);
|
|
405
|
-
if (field) out.push(synthesizeFieldRun(st.result, field));
|
|
406
|
-
else out.push(...st.result);
|
|
675
|
+
if (SILENT_FIELDS.has(fieldKeyword(st.instr) ?? "")) {} else if (field) out.push(synthesizeFieldRun(st.result, field));
|
|
676
|
+
else if (st.result.length > 0) out.push(...st.result);
|
|
677
|
+
else {
|
|
678
|
+
const shown = macroButtonText(st.instr);
|
|
679
|
+
const box = fieldKeyword(st.instr) === "FORMCHECKBOX" && st.checkBox !== void 0 ? st.checkBox ? CHECKBOX_CHECKED : CHECKBOX_CLEAR : void 0;
|
|
680
|
+
if (shown !== void 0) out.push({
|
|
681
|
+
text: shown,
|
|
682
|
+
properties: {}
|
|
683
|
+
});
|
|
684
|
+
else if (box !== void 0) out.push({
|
|
685
|
+
text: box,
|
|
686
|
+
properties: st.properties ?? {}
|
|
687
|
+
});
|
|
688
|
+
}
|
|
407
689
|
st = null;
|
|
408
690
|
continue;
|
|
409
691
|
}
|
|
@@ -416,7 +698,7 @@ function applyFieldFsm(collected) {
|
|
|
416
698
|
if (st) out.push(...st.result);
|
|
417
699
|
return out;
|
|
418
700
|
}
|
|
419
|
-
function collectRuns(container, out, ctx, href, anchor) {
|
|
701
|
+
function collectRuns(container, out, ctx, href, anchor, anchored, sdtRunProps) {
|
|
420
702
|
for (const child of poChildren(container)) {
|
|
421
703
|
if (poIs(child, "w:pPr")) continue;
|
|
422
704
|
if (poIs(child, "w:commentRangeStart")) {
|
|
@@ -430,10 +712,14 @@ function collectRuns(container, out, ctx, href, anchor) {
|
|
|
430
712
|
continue;
|
|
431
713
|
}
|
|
432
714
|
if (poIs(child, "w:r")) {
|
|
433
|
-
const parsed = parseRun(child, ctx);
|
|
715
|
+
const parsed = parseRun(child, ctx, anchored);
|
|
434
716
|
const ranges = ctx.openCommentRanges && ctx.openCommentRanges.size > 0 ? [...ctx.openCommentRanges] : void 0;
|
|
435
|
-
const run = href !== void 0 || anchor !== void 0 || ranges !== void 0 ? {
|
|
717
|
+
const run = href !== void 0 || anchor !== void 0 || ranges !== void 0 || sdtRunProps ? {
|
|
436
718
|
...parsed.run,
|
|
719
|
+
...sdtRunProps ? { properties: {
|
|
720
|
+
...sdtRunProps,
|
|
721
|
+
...parsed.run.properties
|
|
722
|
+
} } : {},
|
|
437
723
|
...href !== void 0 ? { href } : {},
|
|
438
724
|
...anchor !== void 0 ? { anchor } : {},
|
|
439
725
|
...ranges !== void 0 ? { commentRangeRefs: ranges } : {}
|
|
@@ -441,7 +727,8 @@ function collectRuns(container, out, ctx, href, anchor) {
|
|
|
441
727
|
out.push({
|
|
442
728
|
run,
|
|
443
729
|
...parsed.fldChar ? { fldChar: parsed.fldChar } : {},
|
|
444
|
-
...parsed.instrText !== void 0 ? { instrText: parsed.instrText } : {}
|
|
730
|
+
...parsed.instrText !== void 0 ? { instrText: parsed.instrText } : {},
|
|
731
|
+
...parsed.checkBox !== void 0 ? { checkBox: parsed.checkBox } : {}
|
|
445
732
|
});
|
|
446
733
|
continue;
|
|
447
734
|
}
|
|
@@ -466,11 +753,11 @@ function collectRuns(container, out, ctx, href, anchor) {
|
|
|
466
753
|
const field = parseFieldInstr(poAttr(child, "instr"));
|
|
467
754
|
if (field) {
|
|
468
755
|
const inner = [];
|
|
469
|
-
collectRuns(child, inner, ctx, href, anchor);
|
|
756
|
+
collectRuns(child, inner, ctx, href, anchor, anchored, sdtRunProps);
|
|
470
757
|
out.push({ run: synthesizeFieldRun(applyFieldFsm(inner), field, href) });
|
|
471
758
|
continue;
|
|
472
759
|
}
|
|
473
|
-
collectRuns(child, out, ctx, href, anchor);
|
|
760
|
+
collectRuns(child, out, ctx, href, anchor, anchored, sdtRunProps);
|
|
474
761
|
continue;
|
|
475
762
|
}
|
|
476
763
|
if (tag && RUN_CONTAINER_TAGS.has(tag)) {
|
|
@@ -485,18 +772,111 @@ function collectRuns(container, out, ctx, href, anchor) {
|
|
|
485
772
|
if (bookmark !== void 0 && bookmark !== "") childAnchor = bookmark;
|
|
486
773
|
}
|
|
487
774
|
}
|
|
488
|
-
|
|
775
|
+
const childProps = tag === "w:sdt" ? sdtRunProperties(child) ?? sdtRunProps : sdtRunProps;
|
|
776
|
+
collectRuns(child, out, ctx, childHref, childAnchor, anchored, childProps);
|
|
489
777
|
}
|
|
490
778
|
}
|
|
491
779
|
}
|
|
492
|
-
|
|
780
|
+
/**
|
|
781
|
+
* §17.5.2.28 `w:sdt/w:sdtPr/w:rPr` — the run properties a content control
|
|
782
|
+
* lends what it holds, when it states any.
|
|
783
|
+
*
|
|
784
|
+
* @param sdt The `w:sdt` element.
|
|
785
|
+
* @returns The properties, or `undefined` when the control states none.
|
|
786
|
+
*/
|
|
787
|
+
function sdtRunProperties(sdt) {
|
|
788
|
+
const sdtPr = poChildren(sdt).find((c) => poIs(c, "w:sdtPr"));
|
|
789
|
+
const rPr = sdtPr ? poChildren(sdtPr).find((c) => poIs(c, "w:rPr")) : void 0;
|
|
790
|
+
if (!rPr) return void 0;
|
|
791
|
+
const props = parseRunProperties(poElementToFlat(rPr));
|
|
792
|
+
return Object.keys(props).length > 0 ? props : void 0;
|
|
793
|
+
}
|
|
794
|
+
var WINGDINGS_TO_UNICODE = new Map([
|
|
795
|
+
[108, "●"],
|
|
796
|
+
[109, "❍"],
|
|
797
|
+
[110, "■"],
|
|
798
|
+
[113, "❑"],
|
|
799
|
+
[115, "□"],
|
|
800
|
+
[116, "❒"],
|
|
801
|
+
[118, "❖"],
|
|
802
|
+
[167, "▪"],
|
|
803
|
+
[168, "▫"],
|
|
804
|
+
[252, "✔"],
|
|
805
|
+
[253, "✖"],
|
|
806
|
+
[254, "☒"],
|
|
807
|
+
[251, "☑"],
|
|
808
|
+
[224, "⇦"],
|
|
809
|
+
[225, "⇨"],
|
|
810
|
+
[226, "⇧"],
|
|
811
|
+
[227, "⇩"],
|
|
812
|
+
[231, "←"],
|
|
813
|
+
[232, "→"],
|
|
814
|
+
[233, "↑"],
|
|
815
|
+
[234, "↓"],
|
|
816
|
+
[235, "↖"],
|
|
817
|
+
[236, "↗"],
|
|
818
|
+
[237, "↙"],
|
|
819
|
+
[238, "↘"]
|
|
820
|
+
]);
|
|
821
|
+
var SYMBOL_TO_UNICODE = new Map([
|
|
822
|
+
[34, "∀"],
|
|
823
|
+
[36, "∃"],
|
|
824
|
+
[64, "≅"],
|
|
825
|
+
[92, "∴"],
|
|
826
|
+
[97, "α"],
|
|
827
|
+
[98, "β"],
|
|
828
|
+
[99, "χ"],
|
|
829
|
+
[100, "δ"],
|
|
830
|
+
[101, "ε"],
|
|
831
|
+
[102, "φ"],
|
|
832
|
+
[103, "γ"],
|
|
833
|
+
[104, "η"],
|
|
834
|
+
[105, "ι"],
|
|
835
|
+
[107, "κ"],
|
|
836
|
+
[108, "λ"],
|
|
837
|
+
[109, "μ"],
|
|
838
|
+
[110, "ν"],
|
|
839
|
+
[111, "ο"],
|
|
840
|
+
[112, "π"],
|
|
841
|
+
[113, "θ"],
|
|
842
|
+
[114, "ρ"],
|
|
843
|
+
[115, "σ"],
|
|
844
|
+
[116, "τ"],
|
|
845
|
+
[117, "υ"],
|
|
846
|
+
[119, "ω"],
|
|
847
|
+
[120, "ξ"],
|
|
848
|
+
[121, "ψ"],
|
|
849
|
+
[122, "ζ"],
|
|
850
|
+
[165, "∞"],
|
|
851
|
+
[177, "±"],
|
|
852
|
+
[179, "≥"],
|
|
853
|
+
[180, "×"],
|
|
854
|
+
[183, "•"],
|
|
855
|
+
[184, "÷"],
|
|
856
|
+
[185, "≠"],
|
|
857
|
+
[186, "≡"],
|
|
858
|
+
[187, "≈"],
|
|
859
|
+
[214, "√"],
|
|
860
|
+
[229, "∑"]
|
|
861
|
+
]);
|
|
862
|
+
function symbolChar(font, char) {
|
|
863
|
+
const cp = char !== void 0 ? Number.parseInt(char, 16) : NaN;
|
|
864
|
+
if (!Number.isFinite(cp) || cp <= 0) return "";
|
|
865
|
+
const low = cp & 255;
|
|
866
|
+
const mapped = (/wingdings|webdings|zapf/iu.test(font ?? "") ? WINGDINGS_TO_UNICODE : /symbol/iu.test(font ?? "") ? SYMBOL_TO_UNICODE : void 0)?.get(low);
|
|
867
|
+
if (mapped !== void 0) return mapped;
|
|
868
|
+
return String.fromCodePoint(cp);
|
|
869
|
+
}
|
|
870
|
+
function parseRun(r, ctx, anchored) {
|
|
493
871
|
const rPr = poChildren(r).find((c) => poIs(c, "w:rPr"));
|
|
494
872
|
const properties = parseRunProperties(rPr ? poElementToFlat(rPr) : void 0);
|
|
495
873
|
let text = "";
|
|
496
874
|
let pageBreak = false;
|
|
875
|
+
let columnBreak = false;
|
|
497
876
|
let inlineImage;
|
|
498
877
|
let fldChar;
|
|
499
878
|
let instrText;
|
|
879
|
+
let checkBox;
|
|
500
880
|
let footnoteRef;
|
|
501
881
|
let endnoteRef;
|
|
502
882
|
let commentRef;
|
|
@@ -506,6 +886,7 @@ function parseRun(r, ctx) {
|
|
|
506
886
|
if (poIs(child, "w:fldChar")) {
|
|
507
887
|
const t = poAttr(child, "fldCharType");
|
|
508
888
|
if (t === "begin" || t === "separate" || t === "end") fldChar = t;
|
|
889
|
+
if (t === "begin") checkBox = fieldCheckBoxState(child);
|
|
509
890
|
continue;
|
|
510
891
|
}
|
|
511
892
|
if (poIs(child, "w:instrText")) {
|
|
@@ -533,30 +914,49 @@ function parseRun(r, ctx) {
|
|
|
533
914
|
}
|
|
534
915
|
if (poIs(child, "w:t")) text += poText(child);
|
|
535
916
|
else if (poIs(child, "w:tab")) text += " ";
|
|
536
|
-
else if (poIs(child, "w:
|
|
537
|
-
else
|
|
917
|
+
else if (poIs(child, "w:ptab")) text += " ";
|
|
918
|
+
else if (poIs(child, "w:br")) {
|
|
919
|
+
const breakType = poAttr(child, "type");
|
|
920
|
+
if (breakType === "page") pageBreak = true;
|
|
921
|
+
else {
|
|
922
|
+
if (breakType === "column") columnBreak = true;
|
|
923
|
+
text += "\n";
|
|
924
|
+
}
|
|
925
|
+
} else if (poIs(child, "w:sym")) text += symbolChar(poAttr(child, "font"), poAttr(child, "char"));
|
|
538
926
|
else if (poIs(child, "w:noBreakHyphen")) text += "‑";
|
|
539
927
|
else if (poIs(child, "w:softHyphen")) text += "";
|
|
540
928
|
else if (poIs(child, "w:drawing")) {
|
|
541
|
-
const content = parseDrawing(child,
|
|
542
|
-
if (content && content
|
|
929
|
+
const content = parseDrawing(child, ctx.resolveColor, (children) => parseBodyElements(children, ctx), ctx.resolveImage, ctx.resolveChartPart, ctx.themeLineWidths, ctx.themeStyles, drawingTextParser);
|
|
930
|
+
if (content?.float && anchored) anchored.push(...blocksForDrawing(content, {}, ctx) ?? []);
|
|
931
|
+
else if ((content?.kind === "chart" || content?.kind === "shape" || content?.kind === "diagram") && anchored) anchored.push(...blocksForDrawing(content, {}, ctx) ?? []);
|
|
932
|
+
else if (content && content.kind === "image") {
|
|
543
933
|
const resource = ctx.resolveImage?.(content.imageId);
|
|
544
934
|
inlineImage = {
|
|
545
935
|
...resource ? { resource } : {},
|
|
936
|
+
...content.outline ? { outline: content.outline } : {},
|
|
937
|
+
...content.shadow ? { shadow: content.shadow } : {},
|
|
546
938
|
width: content.width,
|
|
547
|
-
height: content.height
|
|
939
|
+
height: content.height,
|
|
940
|
+
...content.crop ? { crop: content.crop } : {},
|
|
941
|
+
...content.rotation60k ? { rotation60k: content.rotation60k } : {},
|
|
942
|
+
...content.flipH ? { flipH: true } : {},
|
|
943
|
+
...content.flipV ? { flipV: true } : {},
|
|
944
|
+
...content.effectExtent ? { effectExtent: content.effectExtent } : {}
|
|
548
945
|
};
|
|
549
946
|
}
|
|
550
947
|
} else if (poIs(child, "w:pict") || poIs(child, "w:object")) {
|
|
551
|
-
const content = parseVmlPicture(child);
|
|
552
|
-
if (content && content
|
|
948
|
+
const content = parseVmlPicture(child, (children) => parseBodyElements(children, ctx));
|
|
949
|
+
if (content?.float && anchored) anchored.push(...blocksForDrawing(content, {}, ctx) ?? []);
|
|
950
|
+
else if (content && content.kind === "image") {
|
|
553
951
|
const resource = ctx.resolveImage?.(content.imageId);
|
|
554
952
|
if (resource) inlineImage = {
|
|
555
953
|
resource,
|
|
954
|
+
...content.outline ? { outline: content.outline } : {},
|
|
955
|
+
...content.shadow ? { shadow: content.shadow } : {},
|
|
556
956
|
width: content.width,
|
|
557
957
|
height: content.height
|
|
558
958
|
};
|
|
559
|
-
}
|
|
959
|
+
} else if (content && anchored) anchored.push(...blocksForDrawing(content, {}, ctx) ?? []);
|
|
560
960
|
}
|
|
561
961
|
}
|
|
562
962
|
return {
|
|
@@ -565,14 +965,36 @@ function parseRun(r, ctx) {
|
|
|
565
965
|
properties,
|
|
566
966
|
...inlineImage ? { inlineImage } : {},
|
|
567
967
|
...pageBreak ? { pageBreak: true } : {},
|
|
968
|
+
...columnBreak ? { columnBreak: true } : {},
|
|
568
969
|
...footnoteRef !== void 0 ? { footnoteRef } : {},
|
|
569
970
|
...endnoteRef !== void 0 ? { endnoteRef } : {},
|
|
570
971
|
...commentRef !== void 0 ? { commentRef } : {},
|
|
571
972
|
...noteNumber ? { noteNumber: true } : {}
|
|
572
973
|
},
|
|
573
974
|
...fldChar ? { fldChar } : {},
|
|
574
|
-
...instrText !== void 0 ? { instrText } : {}
|
|
975
|
+
...instrText !== void 0 ? { instrText } : {},
|
|
976
|
+
...checkBox !== void 0 ? { checkBox } : {}
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* §17.16.32 `w:fldChar/w:ffData/w:checkBox` — whether a form checkbox is
|
|
981
|
+
* ticked: its current `w:checked` if it states one, else the `w:default` it was
|
|
982
|
+
* created with, else clear.
|
|
983
|
+
*
|
|
984
|
+
* @param fldChar The field's `w:fldChar` (only a `begin` carries `w:ffData`).
|
|
985
|
+
* @returns The state, or undefined when this is not a checkbox field.
|
|
986
|
+
*/
|
|
987
|
+
function fieldCheckBoxState(fldChar) {
|
|
988
|
+
const ffData = poChildren(fldChar).find((c) => poIs(c, "w:ffData"));
|
|
989
|
+
const box = ffData ? poChildren(ffData).find((c) => poIs(c, "w:checkBox")) : void 0;
|
|
990
|
+
if (!box) return void 0;
|
|
991
|
+
const flag = (name) => {
|
|
992
|
+
const el = poChildren(box).find((c) => poIs(c, name));
|
|
993
|
+
if (!el) return void 0;
|
|
994
|
+
const val = poAttr(el, "val");
|
|
995
|
+
return val === void 0 || val === "" || val !== "0" && val !== "false";
|
|
575
996
|
};
|
|
997
|
+
return flag("w:checked") ?? flag("w:default") ?? false;
|
|
576
998
|
}
|
|
577
999
|
function elementTag(node) {
|
|
578
1000
|
for (const key of Object.keys(node)) if (key !== ":@" && key !== "#text") return key;
|
|
@@ -589,7 +1011,7 @@ function elementTag(node) {
|
|
|
589
1011
|
* @returns A map from note id to its body content.
|
|
590
1012
|
*/
|
|
591
1013
|
function parseNotes(notesXml, rootTag, noteTag, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
592
|
-
const xml = decoder.decode(notesXml);
|
|
1014
|
+
const xml = resolveInternalEntities(decoder.decode(notesXml));
|
|
593
1015
|
const root = poFindByPath(parser.parse(xml), [rootTag]);
|
|
594
1016
|
const out = /* @__PURE__ */ new Map();
|
|
595
1017
|
if (!root) return out;
|
|
@@ -604,7 +1026,7 @@ function parseNotes(notesXml, rootTag, noteTag, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
|
604
1026
|
return out;
|
|
605
1027
|
}
|
|
606
1028
|
function parseCommentsRaw(commentsXml, ctx) {
|
|
607
|
-
const xml = decoder.decode(commentsXml);
|
|
1029
|
+
const xml = resolveInternalEntities(decoder.decode(commentsXml));
|
|
608
1030
|
const root = poFindByPath(parser.parse(xml), ["w:comments"]);
|
|
609
1031
|
const comments = /* @__PURE__ */ new Map();
|
|
610
1032
|
const paraIds = /* @__PURE__ */ new Map();
|
|
@@ -648,7 +1070,7 @@ function parseCommentsRaw(commentsXml, ctx) {
|
|
|
648
1070
|
* @returns A map from `paraId` to its {@link CommentExtension}.
|
|
649
1071
|
*/
|
|
650
1072
|
function parseCommentsExtended(xml) {
|
|
651
|
-
const tree = parser.parse(decoder.decode(xml));
|
|
1073
|
+
const tree = parser.parse(resolveInternalEntities(decoder.decode(xml)));
|
|
652
1074
|
const out = /* @__PURE__ */ new Map();
|
|
653
1075
|
const root = tree.find((n) => poIsLocal(n, "commentsEx"));
|
|
654
1076
|
if (!root) return out;
|
|
@@ -710,7 +1132,7 @@ function parseCommentThreads(commentsXml, commentsExtendedXml, ctx = DEFAULT_PAR
|
|
|
710
1132
|
* @returns A map from author name to userId.
|
|
711
1133
|
*/
|
|
712
1134
|
function parsePeople(xml) {
|
|
713
|
-
const tree = parser.parse(decoder.decode(xml));
|
|
1135
|
+
const tree = parser.parse(resolveInternalEntities(decoder.decode(xml)));
|
|
714
1136
|
const out = /* @__PURE__ */ new Map();
|
|
715
1137
|
const root = tree.find((n) => poIsLocal(n, "people"));
|
|
716
1138
|
if (!root) return out;
|
|
@@ -750,4 +1172,4 @@ function applyAuthorIds(comments, people) {
|
|
|
750
1172
|
return out;
|
|
751
1173
|
}
|
|
752
1174
|
//#endregion
|
|
753
|
-
export { DEFAULT_PARSE_CONTEXT, EMPTY_SECTION, applyAuthorIds, parseBodyElements, parseCommentThreads, parseCommentsExtended, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections };
|
|
1175
|
+
export { DEFAULT_PARSE_CONTEXT, EMPTY_SECTION, applyAuthorIds, bodyIndexForBlock, newBlockCounter, parseBackgroundColor, parseBackgroundFill, parseBodyElements, parseCommentThreads, parseCommentsExtended, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections, sdtRunProperties };
|