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.
Files changed (127) hide show
  1. package/dist/esm/core/bidi/segments.js +1 -2
  2. package/dist/esm/core/converter/facade.d.ts +5 -0
  3. package/dist/esm/core/converter/project.js +5 -1
  4. package/dist/esm/core/converter/ream.d.ts +6 -0
  5. package/dist/esm/core/converter/ream.js +34 -8
  6. package/dist/esm/core/document-model/index.d.ts +1 -1
  7. package/dist/esm/core/document-model/types.d.ts +659 -7
  8. package/dist/esm/core/drawingml/chart-geometry.d.ts +34 -10
  9. package/dist/esm/core/drawingml/chart-geometry.js +424 -92
  10. package/dist/esm/core/drawingml/chart-parser.js +301 -11
  11. package/dist/esm/core/drawingml/colors.d.ts +7 -7
  12. package/dist/esm/core/drawingml/colors.js +84 -18
  13. package/dist/esm/core/drawingml/preset-geometry.js +240 -6
  14. package/dist/esm/core/drawingml/shape-render.d.ts +12 -0
  15. package/dist/esm/core/drawingml/shape-render.js +116 -3
  16. package/dist/esm/core/drawingml/sparkline-geometry.js +6 -4
  17. package/dist/esm/core/drawingml/theme-parser.d.ts +51 -0
  18. package/dist/esm/core/drawingml/theme-parser.js +92 -1
  19. package/dist/esm/core/font/measure.d.ts +5 -0
  20. package/dist/esm/core/font/measure.js +21 -1
  21. package/dist/esm/core/font/ttf-subset.js +26 -1
  22. package/dist/esm/core/images.d.ts +2 -2
  23. package/dist/esm/core/images.js +353 -43
  24. package/dist/esm/core/indexed-colors.d.ts +11 -0
  25. package/dist/esm/core/indexed-colors.js +81 -0
  26. package/dist/esm/core/ir/flow.d.ts +23 -1
  27. package/dist/esm/core/ir/sheet.d.ts +61 -0
  28. package/dist/esm/{excel → core}/number-format.d.ts +37 -0
  29. package/dist/esm/core/number-format.js +800 -0
  30. package/dist/esm/core/numbering/apply.d.ts +5 -3
  31. package/dist/esm/core/numbering/apply.js +42 -11
  32. package/dist/esm/core/numbering/index.js +2 -0
  33. package/dist/esm/core/numbering/state.d.ts +13 -1
  34. package/dist/esm/core/numbering/state.js +256 -15
  35. package/dist/esm/core/opc/alternate-content.d.ts +13 -0
  36. package/dist/esm/core/opc/alternate-content.js +72 -0
  37. package/dist/esm/core/opc/core-properties.js +1 -0
  38. package/dist/esm/core/opc/package.d.ts +14 -1
  39. package/dist/esm/core/opc/package.js +43 -4
  40. package/dist/esm/core/opc/relationships.js +1 -0
  41. package/dist/esm/core/opc/xml-entities.d.ts +12 -0
  42. package/dist/esm/core/opc/xml-entities.js +91 -0
  43. package/dist/esm/core/po-helpers.js +16 -1
  44. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  45. package/dist/esm/core/spreadsheet-model/types.d.ts +137 -0
  46. package/dist/esm/core/style-cascade/resolver.js +66 -11
  47. package/dist/esm/core/style-cascade/table.js +35 -11
  48. package/dist/esm/core/style-cascade/types.d.ts +42 -1
  49. package/dist/esm/core/style-cascade/types.js +4 -0
  50. package/dist/esm/core/vector.d.ts +30 -0
  51. package/dist/esm/excel/activex-parser.js +1 -0
  52. package/dist/esm/excel/column-bands.d.ts +26 -1
  53. package/dist/esm/excel/column-bands.js +156 -20
  54. package/dist/esm/excel/comments-parser.js +5 -3
  55. package/dist/esm/excel/conditional-format.d.ts +25 -2
  56. package/dist/esm/excel/conditional-format.js +63 -19
  57. package/dist/esm/excel/escaped-text.d.ts +9 -0
  58. package/dist/esm/excel/escaped-text.js +20 -0
  59. package/dist/esm/excel/form-control-parser.js +1 -0
  60. package/dist/esm/excel/formula/dates.js +1 -1
  61. package/dist/esm/excel/header-footer.d.ts +9 -1
  62. package/dist/esm/excel/header-footer.js +162 -14
  63. package/dist/esm/excel/index.d.ts +1 -1
  64. package/dist/esm/excel/index.js +2 -2
  65. package/dist/esm/excel/pivot-table-parser.js +1 -0
  66. package/dist/esm/excel/print-model.d.ts +75 -0
  67. package/dist/esm/excel/print-model.js +899 -77
  68. package/dist/esm/excel/printer-settings.d.ts +16 -0
  69. package/dist/esm/excel/printer-settings.js +36 -0
  70. package/dist/esm/excel/rich-value.d.ts +13 -0
  71. package/dist/esm/excel/rich-value.js +120 -0
  72. package/dist/esm/excel/shared-strings-parser.js +11 -7
  73. package/dist/esm/excel/sheet-drawing.d.ts +11 -0
  74. package/dist/esm/excel/sheet-drawing.js +26 -3
  75. package/dist/esm/excel/sheet-shape-parser.d.ts +53 -1
  76. package/dist/esm/excel/sheet-shape-parser.js +461 -32
  77. package/dist/esm/excel/sheet-to-flow.d.ts +23 -2
  78. package/dist/esm/excel/sheet-to-flow.js +553 -36
  79. package/dist/esm/excel/slicer-parser.js +1 -0
  80. package/dist/esm/excel/styles-parser.d.ts +30 -2
  81. package/dist/esm/excel/styles-parser.js +177 -40
  82. package/dist/esm/excel/table-parser.js +1 -0
  83. package/dist/esm/excel/vml-drawing.d.ts +68 -0
  84. package/dist/esm/excel/vml-drawing.js +158 -0
  85. package/dist/esm/excel/workbook-parser.d.ts +5 -0
  86. package/dist/esm/excel/workbook-parser.js +5 -1
  87. package/dist/esm/excel/worksheet-parser.d.ts +2 -1
  88. package/dist/esm/excel/worksheet-parser.js +150 -61
  89. package/dist/esm/excel/xlsx-reader.js +242 -11
  90. package/dist/esm/excel/xlsx-to-pdf.js +12 -1
  91. package/dist/esm/html/html-writer.js +29 -6
  92. package/dist/esm/layout/page-doc.d.ts +87 -1
  93. package/dist/esm/layout/styled-layout.d.ts +46 -2
  94. package/dist/esm/layout/styled-layout.js +2345 -274
  95. package/dist/esm/pdf/cid-font.js +20 -9
  96. package/dist/esm/pdf/objects.d.ts +13 -0
  97. package/dist/esm/pdf/objects.js +18 -1
  98. package/dist/esm/pdf/shading.js +76 -6
  99. package/dist/esm/pdf/styled-page-emitter.js +355 -49
  100. package/dist/esm/pdf/text-page-renderer.js +1 -0
  101. package/dist/esm/pdf/vector-graphics.d.ts +31 -2
  102. package/dist/esm/pdf/vector-graphics.js +103 -3
  103. package/dist/esm/pptx/pptx-reader.js +2 -0
  104. package/dist/esm/pptx/slide-parser.d.ts +21 -4
  105. package/dist/esm/pptx/slide-parser.js +98 -24
  106. package/dist/esm/svg/svg-writer.js +23 -4
  107. package/dist/esm/word/document-parser.d.ts +96 -7
  108. package/dist/esm/word/document-parser.js +538 -116
  109. package/dist/esm/word/docx-reader.js +135 -43
  110. package/dist/esm/word/docx-writer.js +6 -1
  111. package/dist/esm/word/drawing-parser.d.ts +86 -5
  112. package/dist/esm/word/drawing-parser.js +1590 -54
  113. package/dist/esm/word/index.d.ts +4 -4
  114. package/dist/esm/word/numbering-parser.d.ts +2 -1
  115. package/dist/esm/word/numbering-parser.js +108 -21
  116. package/dist/esm/word/paragraph-properties.d.ts +11 -1
  117. package/dist/esm/word/paragraph-properties.js +219 -10
  118. package/dist/esm/word/run-properties.js +45 -1
  119. package/dist/esm/word/settings-parser.d.ts +24 -0
  120. package/dist/esm/word/settings-parser.js +32 -5
  121. package/dist/esm/word/shading.d.ts +11 -0
  122. package/dist/esm/word/shading.js +64 -0
  123. package/dist/esm/word/styles-parser.js +9 -2
  124. package/dist/esm/word/table-parser.d.ts +9 -1
  125. package/dist/esm/word/table-parser.js +182 -30
  126. package/package.json +7 -3
  127. 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, parseDiagramDrawing } from "../pptx/slide-parser.js";
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 body = poFindByPath(parser.parse(xml), ["w:document", "w:body"]);
45
- if (!body) return [];
46
- return parseBodyElements(poChildren(body), ctx);
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
- /** The empty {@link SectionProperties} fallback (no headers/footers). */
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 body = poFindByPath(parser.parse(xml), ["w:document", "w:body"]);
71
- if (!body) return [];
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
- for (const child of children) {
76
- if (poIs(child, "w:sectPr")) {
77
- sections.push({
78
- properties: parseSectPrNode(child),
79
- endIndex: bodyIdx
80
- });
81
- continue;
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
- if (poIs(child, "w:p")) {
84
- const pPrNode = poChildren(child).find((c) => poIs(c, "w:pPr"));
85
- const sectPrInPPr = pPrNode ? poChildren(pPrNode).find((c) => poIs(c, "w:sectPr")) : void 0;
86
- bodyIdx++;
87
- if (sectPrInPPr) sections.push({
88
- properties: parseSectPrNode(sectPrInPPr),
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
- ...pageSize ? { pageSize } : {},
267
+ pageSize,
138
268
  ...margins ? { margins } : {},
139
269
  headers,
140
270
  footers,
141
271
  ...titlePg ? { titlePg: true } : {},
142
- ...columns ? { columns } : {}
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
- for (const child of children) if (poIs(child, "w:bookmarkStart")) {
202
- const bookmarkName = poAttr(child, "name");
203
- if (bookmarkName !== void 0 && bookmarkName !== "" && bookmarkName !== "_GoBack") (pendingBookmarks ??= []).push(bookmarkName);
204
- } else if (poIs(child, "w:p")) {
205
- const drawings = tryExtractDrawingFromParagraph(child, ctx);
206
- if (drawings) out.push(...drawings);
207
- else {
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: "paragraph",
210
- paragraph: parseParagraph(child, ctx, pendingBookmarks)
378
+ kind: "table",
379
+ table: parseTable(child, ctx)
211
380
  });
212
- pendingBookmarks = void 0;
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
- if (!acc.drawing) acc.drawing = rc;
237
- } else if (poIs(rc, "w:pict") || poIs(rc, "w:object")) {
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 = { hasOther: false };
418
+ const scan = {
419
+ hasOther: false,
420
+ drawings: []
421
+ };
254
422
  scanForLoneDrawing(p, scan);
255
- const { drawing, vml } = scan;
256
- if (scan.hasOther || !drawing && !vml) return null;
257
- const fromVml = drawing === void 0;
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 spTree = ctx.resolveDiagram?.(content.dmRelId);
291
- if (!spTree) {
486
+ const diagram = ctx.resolveDiagram?.(content.dmRelId);
487
+ if (!diagram) {
292
488
  ctx.onLoss?.(noDiagramOverrideLoss());
293
489
  return null;
294
490
  }
295
- const shapes = parseDiagramDrawing(spTree, diagramTransform(spTree, {
491
+ const frame = {
296
492
  x: 0,
297
493
  y: 0,
298
494
  cx: content.widthEmu,
299
495
  cy: content.heightEmu
300
- }), (box) => ({
301
- wrap: "none",
302
- posH: {
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
- })) : null;
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
- if (!instr) return void 0;
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
- collectRuns(child, out, ctx, childHref, childAnchor);
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
- function parseRun(r, ctx) {
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:br")) if (poAttr(child, "type") === "page") pageBreak = true;
537
- else text += "\n";
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, defaultColorResolver);
542
- if (content && content.kind === "image") {
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.kind === "image") {
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 };