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