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,20 +1,21 @@
1
1
  import { ResourceStore } from "../core/ir/resources.js";
2
2
  import { FEATURES } from "../core/ir/features.js";
3
- import { applyNumbering, applyNumberingToHeadersFooters } from "../core/numbering/apply.js";
4
3
  import { EMPTY_STYLE_SHEET, resolveBodyStyles, resolveHeadersFootersStyles } from "../core/style-cascade/resolver.js";
5
4
  import { resolveTableStyles } from "../core/style-cascade/table.js";
6
5
  import "../core/style-cascade/index.js";
6
+ import { applyNumbering, applyNumberingToHeadersFooters } from "../core/numbering/apply.js";
7
+ import "../core/numbering/index.js";
7
8
  import { poFindDescendant } from "../core/po-helpers.js";
8
9
  import { bytesIncludePartName } from "../core/bytes.js";
9
10
  import { DEFAULT_THEME_PALETTE, makeColorResolver } from "../core/drawingml/colors.js";
10
11
  import { parseChart, withChartColorStyle } from "../core/drawingml/chart-parser.js";
11
- import { parseTheme } from "../core/drawingml/theme-parser.js";
12
+ import { parseTheme, parseThemeBgFillStyles, parseThemeEffectStyles, parseThemeFillStyles, parseThemeLineWidths } from "../core/drawingml/theme-parser.js";
12
13
  import { isOoxmlRel } from "../core/opc/relationship-types.js";
13
14
  import { OpcPackage } from "../core/opc/package.js";
14
15
  import { parseCoreProperties } from "../core/opc/core-properties.js";
15
16
  import "../core/opc/index.js";
16
17
  import { parseXml } from "../pptx/pptx-reader.js";
17
- import { EMPTY_SECTION, applyAuthorIds, parseCommentThreads, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections } from "./document-parser.js";
18
+ import { EMPTY_SECTION, applyAuthorIds, bodyIndexForBlock, newBlockCounter, parseBackgroundColor, parseBackgroundFill, parseCommentThreads, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections } from "./document-parser.js";
18
19
  import { parseStyles } from "./styles-parser.js";
19
20
  import { loadEmbeddedFonts } from "./font-table.js";
20
21
  import { EMPTY_NUMBERING, parseNumbering } from "./numbering-parser.js";
@@ -48,25 +49,44 @@ var THEME_PART = "word/theme/theme1.xml";
48
49
  function readDocx(docx) {
49
50
  const pkg = OpcPackage.open(docx);
50
51
  const main = pkg.getMainDocument();
51
- const resolveColor = buildColorResolver(pkg);
52
+ const resolveColor = buildColorResolver(pkg, main.path);
53
+ const themeData = loadTheme(pkg, main.path);
54
+ const themeLineWidths = themeData ? parseThemeLineWidths(themeData) : void 0;
55
+ const themeStyles = themeData ? {
56
+ fills: parseThemeFillStyles(themeData),
57
+ bgFills: parseThemeBgFillStyles(themeData),
58
+ effects: parseThemeEffectStyles(themeData)
59
+ } : void 0;
52
60
  const resources = new ResourceStore();
53
- const resolveImage = makeImageResolver(pkg, resources);
54
- const resolveHyperlink = makeHyperlinkResolver(pkg);
61
+ const resolveImage = makeImageResolver(pkg, resources, main.path);
62
+ const resolveHyperlink = makeHyperlinkResolver(pkg, main.path);
55
63
  const losses = [];
64
+ const settingsData = pkg.getPart(SETTINGS_PART);
65
+ const settings = settingsData ? parseSettings(settingsData) : EMPTY_SETTINGS;
56
66
  const ctx = {
57
67
  resolveColor,
68
+ ...settings.compatibilityMode === void 0 ? { autoSpacingPt: 14 } : {},
69
+ ...themeLineWidths && themeLineWidths.length > 0 ? { themeLineWidths } : {},
70
+ ...themeStyles ? { themeStyles } : {},
58
71
  resolveImage,
59
72
  resolveHyperlink,
60
- resolveDiagram: makeDiagramResolver(pkg, MAIN_DOCUMENT_PART),
73
+ resolveDiagram: makeDiagramResolver(pkg, main.path, resources),
74
+ resolveChartPart: makeChartResolver(pkg, main.path),
61
75
  onLoss: (loss) => losses.push(loss),
62
76
  openCommentRanges: /* @__PURE__ */ new Set()
63
77
  };
64
- const body = parseDocument(main.data, ctx);
65
- const rawSections = parseSections(main.data);
78
+ const blocks = newBlockCounter();
79
+ const body = parseDocument(main.data, ctx, blocks);
80
+ const backgroundColorHex = parseBackgroundColor(main.data);
81
+ const backgroundFill = parseBackgroundFill(main.data, ctx.resolveImage);
82
+ const rawSections = parseSections(main.data).map((s) => ({
83
+ ...s,
84
+ endIndex: bodyIndexForBlock(blocks, s.endIndex)
85
+ }));
66
86
  const stylesData = pkg.getPart(STYLES_PART);
67
87
  const styles = stylesData ? parseStyles(stylesData) : EMPTY_STYLE_SHEET;
68
88
  const numberingData = pkg.getPart(NUMBERING_PART);
69
- const numbering = numberingData ? parseNumbering(numberingData) : EMPTY_NUMBERING;
89
+ const numbering = numberingData ? parseNumbering(numberingData, makeImageResolver(pkg, resources, NUMBERING_PART)) : EMPTY_NUMBERING;
70
90
  const noteCtx = (part) => ({
71
91
  resolveColor,
72
92
  resolveImage: makeImageResolver(pkg, resources, part),
@@ -81,9 +101,7 @@ function readDocx(docx) {
81
101
  const peopleData = pkg.getPart(PEOPLE_PART);
82
102
  let rawComments = commentsData ? parseCommentThreads(commentsData, commentsExtendedData, noteCtx(COMMENTS_PART)) : void 0;
83
103
  if (rawComments && peopleData) rawComments = applyAuthorIds(rawComments, parsePeople(peopleData));
84
- const settingsData = pkg.getPart(SETTINGS_PART);
85
- const settings = settingsData ? parseSettings(settingsData) : EMPTY_SETTINGS;
86
- const sections = rawSections.length > 0 ? rawSections.map((s) => ({
104
+ const sections = withInheritedBands(rawSections.length > 0 ? rawSections.map((s) => ({
87
105
  ...s,
88
106
  properties: settings.evenAndOddHeaders ? {
89
107
  ...s.properties,
@@ -95,9 +113,9 @@ function readDocx(docx) {
95
113
  evenAndOddHeaders: true
96
114
  } : EMPTY_SECTION,
97
115
  endIndex: body.length
98
- }];
99
- const headersFooters = loadHeadersFootersForSections(pkg, sections, ctx, resources);
100
- const charts = loadCharts(pkg, resolveColor);
116
+ }]);
117
+ const headersFooters = loadHeadersFootersForSections(pkg, sections, ctx, resources, main.path);
118
+ const charts = loadCharts(pkg, resolveColor, chartOwningParts(pkg, sections, main.path));
101
119
  const embeddedFonts = loadEmbeddedFonts(pkg);
102
120
  const coreData = pkg.getPart(CORE_PROPS_PART);
103
121
  const info = infoFromCore(coreData ? parseCoreProperties(coreData) : void 0);
@@ -105,19 +123,23 @@ function readDocx(docx) {
105
123
  return {
106
124
  doc: {
107
125
  kind: "flow",
108
- body: resolveBodyStyles(applyNumbering(resolveTableStyles(body, styles), numbering), styles),
126
+ body: resolveBodyStyles(applyNumbering(resolveTableStyles(body, styles), numbering, styles), styles),
109
127
  sections,
110
128
  styles,
111
129
  numbering,
112
130
  ...rawFootnotes && rawFootnotes.size > 0 ? { footnotes: transformNotes(rawFootnotes, styles, numbering) } : {},
113
131
  ...rawEndnotes && rawEndnotes.size > 0 ? { endnotes: transformNotes(rawEndnotes, styles, numbering) } : {},
114
132
  ...rawComments && rawComments.size > 0 ? { comments: transformComments(rawComments, styles, numbering) } : {},
115
- headersFooters: resolveHeadersFootersStyles(applyNumberingToHeadersFooters(headersFooters, numbering), styles),
133
+ headersFooters: resolveHeadersFootersStyles(applyNumberingToHeadersFooters(headersFooters, numbering, styles), styles),
116
134
  charts,
117
135
  resources,
118
136
  ...embeddedFonts.size > 0 ? { embeddedFonts } : {},
119
137
  ...info ? { info } : {},
120
- ...language ? { language } : {}
138
+ ...language ? { language } : {},
139
+ ...settings.doNotExpandShiftReturn ? { doNotExpandShiftReturn: true } : {},
140
+ ...settings.displayBackgroundShape && backgroundFill ? { pageBackgroundFill: backgroundFill } : {},
141
+ ...settings.displayBackgroundShape && backgroundColorHex ? { pageBackgroundColorHex: backgroundColorHex } : {},
142
+ ...settings.gutterAtTop ? { gutterAtTop: true } : {}
121
143
  },
122
144
  losses
123
145
  };
@@ -144,7 +166,7 @@ var docxReader = {
144
166
  FEATURES.trackedChanges,
145
167
  FEATURES.fontsEmbedding
146
168
  ]),
147
- sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && bytesIncludePartName(bytes, "word/document.xml"),
169
+ sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && (bytesIncludePartName(bytes, "word/document.xml") || bytesIncludePartName(bytes, "word/styles.xml") || bytesIncludePartName(bytes, "word/_rels/")),
148
170
  read: (bytes) => readDocx(bytes)
149
171
  };
150
172
  function infoFromCore(core) {
@@ -158,28 +180,39 @@ function infoFromCore(core) {
158
180
  ...core.modified ? { modificationDate: core.modified } : {}
159
181
  };
160
182
  }
161
- function makeDiagramResolver(pkg, partName) {
183
+ function makeDiagramResolver(pkg, partName, store) {
162
184
  const cache = /* @__PURE__ */ new Map();
163
185
  return (relId) => {
164
186
  if (cache.has(relId)) return cache.get(relId);
165
- let spTree;
187
+ let resolved;
166
188
  const dataRel = pkg.getPartRelationships(partName).find((r) => r.id === relId);
167
189
  const data = dataRel ? pkg.resolveRelatedPart(partName, dataRel) : void 0;
168
190
  if (data) {
169
- const drawRel = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
170
- const draw = drawRel ? pkg.resolveRelatedPart(data.path, drawRel) : void 0;
191
+ const own = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
192
+ const draw = own ? pkg.resolveRelatedPart(data.path, own) : drawingFromOwner(pkg, partName, data.path);
171
193
  if (draw) for (const root of parseXml(draw.data)) {
172
- const found = poFindDescendant(root, "dsp:spTree");
173
- if (found) {
174
- spTree = found;
194
+ const spTree = poFindDescendant(root, "dsp:spTree");
195
+ if (spTree) {
196
+ resolved = {
197
+ spTree,
198
+ resolveImage: makeImageResolver(pkg, store, draw.path)
199
+ };
175
200
  break;
176
201
  }
177
202
  }
178
203
  }
179
- cache.set(relId, spTree);
180
- return spTree;
204
+ cache.set(relId, resolved);
205
+ return resolved;
181
206
  };
182
207
  }
208
+ function drawingFromOwner(pkg, ownerPart, dataPart) {
209
+ const drawings = pkg.getPartRelationships(ownerPart).filter((r) => r.type.endsWith("/diagramDrawing"));
210
+ if (drawings.length === 0) return void 0;
211
+ const index = (path) => /(\d*)\.[^.]+$/u.exec(path)?.[1] ?? "";
212
+ const want = index(dataPart);
213
+ const rel = drawings.find((r) => index(r.target) === want) ?? (drawings.length === 1 ? drawings[0] : void 0);
214
+ return rel ? pkg.resolveRelatedPart(ownerPart, rel) : void 0;
215
+ }
183
216
  function makeImageResolver(pkg, store, partName = MAIN_DOCUMENT_PART) {
184
217
  const byRelId = /* @__PURE__ */ new Map();
185
218
  for (const rel of pkg.getPartRelationships(partName)) {
@@ -216,56 +249,115 @@ function makeHyperlinkResolver(pkg, partName = MAIN_DOCUMENT_PART) {
216
249
  for (const rel of pkg.getPartRelationships(partName)) if (rel.type === REL_HYPERLINK && rel.targetMode === "External") byRelId.set(rel.id, rel.target);
217
250
  return (relId) => byRelId.get(relId);
218
251
  }
219
- function loadCharts(pkg, resolveColor) {
252
+ function loadCharts(pkg, resolveColor, parts) {
220
253
  const out = /* @__PURE__ */ new Map();
221
- for (const rel of pkg.getPartRelationships(MAIN_DOCUMENT_PART)) {
254
+ for (const part of parts) for (const rel of pkg.getPartRelationships(part)) {
222
255
  if (!isOoxmlRel(rel.type, "chart")) continue;
223
- const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
224
- if (!resolved) continue;
256
+ const resolved = pkg.resolveRelatedPart(part, rel);
257
+ if (!resolved || out.has(resolved.path)) continue;
225
258
  const chart = parseChart(resolved.data, resolveColor);
226
- if (chart) out.set(rel.id, withChartColorStyle(chart, pkg, resolved.path, resolveColor));
259
+ if (chart) out.set(resolved.path, withChartColorStyle(chart, pkg, resolved.path, resolveColor));
227
260
  }
228
261
  return out;
229
262
  }
230
- function buildColorResolver(pkg) {
231
- const themeData = loadTheme(pkg);
263
+ function makeChartResolver(pkg, partName) {
264
+ const byRelId = /* @__PURE__ */ new Map();
265
+ for (const rel of pkg.getPartRelationships(partName)) {
266
+ if (!isOoxmlRel(rel.type, "chart")) continue;
267
+ const resolved = pkg.resolveRelatedPart(partName, rel);
268
+ if (resolved) byRelId.set(rel.id, resolved.path);
269
+ }
270
+ return (relId) => byRelId.get(relId);
271
+ }
272
+ function buildColorResolver(pkg, mainPart) {
273
+ const themeData = loadTheme(pkg, mainPart);
232
274
  if (!themeData) return makeColorResolver(DEFAULT_THEME_PALETTE);
233
275
  const palette = new Map(DEFAULT_THEME_PALETTE);
234
276
  for (const [slot, hex] of parseTheme(themeData)) palette.set(slot, hex);
235
277
  return makeColorResolver(palette);
236
278
  }
237
- function loadTheme(pkg) {
238
- for (const rel of pkg.getPartRelationships(MAIN_DOCUMENT_PART)) {
279
+ function loadTheme(pkg, mainPart) {
280
+ for (const rel of pkg.getPartRelationships(mainPart)) {
239
281
  if (!isOoxmlRel(rel.type, "theme")) continue;
240
- const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
282
+ const resolved = pkg.resolveRelatedPart(mainPart, rel);
241
283
  if (resolved) return resolved.data;
242
284
  }
243
285
  return pkg.getPart(THEME_PART);
244
286
  }
245
- function loadHeadersFootersForSections(pkg, sections, ctx, store) {
287
+ /**
288
+ * §17.10.1 — a section that declares no header (or footer) of a given type
289
+ * takes the one before it. endingSectionProps.docx puts its references on the
290
+ * FIRST section and ends with a continuous one that states none, and reading
291
+ * each section alone left the page with no header and no footer at all.
292
+ *
293
+ * @param sections The sections in document order.
294
+ * @returns The same sections, each carrying the bands it inherits.
295
+ */
296
+ function withInheritedBands(sections) {
297
+ const out = [];
298
+ let headers = [];
299
+ let footers = [];
300
+ let titlePg = false;
301
+ for (const section of sections) {
302
+ const own = section.properties;
303
+ const inherits = own.headers.length === 0 && own.footers.length === 0;
304
+ headers = own.headers.length > 0 ? own.headers : headers;
305
+ footers = own.footers.length > 0 ? own.footers : footers;
306
+ titlePg = inherits ? titlePg : own.titlePg ?? false;
307
+ out.push(headers === own.headers && footers === own.footers && titlePg === (own.titlePg ?? false) ? section : {
308
+ ...section,
309
+ properties: {
310
+ ...own,
311
+ headers,
312
+ footers,
313
+ ...titlePg ? { titlePg: true } : {}
314
+ }
315
+ });
316
+ }
317
+ return out;
318
+ }
319
+ function loadHeadersFootersForSections(pkg, sections, ctx, store, mainPart) {
246
320
  const wanted = /* @__PURE__ */ new Set();
247
321
  for (const s of sections) {
248
322
  for (const h of s.properties.headers) wanted.add(h.relationshipId);
249
323
  for (const f of s.properties.footers) wanted.add(f.relationshipId);
250
324
  }
251
325
  if (wanted.size === 0) return /* @__PURE__ */ new Map();
252
- const rels = pkg.getPartRelationships(MAIN_DOCUMENT_PART);
326
+ const rels = pkg.getPartRelationships(mainPart);
253
327
  if (rels.length === 0) return /* @__PURE__ */ new Map();
254
328
  const out = /* @__PURE__ */ new Map();
255
329
  for (const rel of rels) {
256
330
  if (!wanted.has(rel.id)) continue;
257
331
  if (!isOoxmlRel(rel.type, "header") && !isOoxmlRel(rel.type, "footer")) continue;
258
- const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
332
+ const resolved = pkg.resolveRelatedPart(mainPart, rel);
259
333
  if (!resolved) continue;
260
334
  const hfCtx = {
261
335
  resolveColor: ctx.resolveColor,
262
336
  resolveImage: makeImageResolver(pkg, store, resolved.path),
263
- resolveHyperlink: makeHyperlinkResolver(pkg, resolved.path)
337
+ resolveHyperlink: makeHyperlinkResolver(pkg, resolved.path),
338
+ resolveChartPart: makeChartResolver(pkg, resolved.path),
339
+ ...ctx.themeLineWidths ? { themeLineWidths: ctx.themeLineWidths } : {},
340
+ ...ctx.themeStyles ? { themeStyles: ctx.themeStyles } : {}
264
341
  };
265
342
  out.set(rel.id, parseHeaderFooter(resolved.data, hfCtx));
266
343
  }
267
344
  return out;
268
345
  }
346
+ function chartOwningParts(pkg, sections, mainPart) {
347
+ const wanted = /* @__PURE__ */ new Set();
348
+ for (const s of sections) {
349
+ for (const h of s.properties.headers) wanted.add(h.relationshipId);
350
+ for (const f of s.properties.footers) wanted.add(f.relationshipId);
351
+ }
352
+ const parts = [mainPart];
353
+ for (const rel of pkg.getPartRelationships(mainPart)) {
354
+ if (!wanted.has(rel.id)) continue;
355
+ if (!isOoxmlRel(rel.type, "header") && !isOoxmlRel(rel.type, "footer")) continue;
356
+ const resolved = pkg.resolveRelatedPart(mainPart, rel);
357
+ if (resolved) parts.push(resolved.path);
358
+ }
359
+ return parts;
360
+ }
269
361
  function detectDocxLanguage(stylesData, documentData) {
270
362
  const re = /<w:lang\b[^>]*\bw:val="([^"]+)"/;
271
363
  const decoder = new TextDecoder();
@@ -46,6 +46,10 @@ var RASTER_MEDIA = {
46
46
  jpeg2000: {
47
47
  ext: "jp2",
48
48
  contentType: "image/jp2"
49
+ },
50
+ gif: {
51
+ ext: "gif",
52
+ contentType: "image/gif"
49
53
  }
50
54
  };
51
55
  function mediaInfo(bytes) {
@@ -550,7 +554,8 @@ function cellXml(cell, losses, state, scope) {
550
554
  }
551
555
  function tcPrXml(p) {
552
556
  const out = [];
553
- if (p.width !== void 0) out.push(`<w:tcW w:w="${twips(p.width)}" w:type="dxa"/>`);
557
+ if (p.widthFraction !== void 0) out.push(`<w:tcW w:w="${Math.round(p.widthFraction * 5e3)}" w:type="pct"/>`);
558
+ else if (p.width !== void 0) out.push(`<w:tcW w:w="${twips(p.width)}" w:type="dxa"/>`);
554
559
  if (p.colSpan !== void 0 && p.colSpan > 1) out.push(`<w:gridSpan w:val="${p.colSpan}"/>`);
555
560
  if (p.merge !== void 0) out.push(p.merge === "start" ? "<w:vMerge w:val=\"restart\"/>" : "<w:vMerge w:val=\"continue\"/>");
556
561
  const borders = bordersXml("w:tcBorders", p.borders);
@@ -1,7 +1,7 @@
1
- import { BodyElement, FloatAnchor, ShapeFill, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform } from '../core/document-model/index.js';
1
+ import { BodyElement, FloatAnchor, ImageCrop, InlineImage, PictureOutline, RelativeSize, ShapeFill, ShapeGeometry, ShapeGroupChild, ShapeLine, ShapeShadow, ShapeTextBody, ShapeTransform } from '../core/document-model/index.js';
2
2
  import { ColorResolver } from '../core/drawingml/colors.js';
3
3
  import { PoNode } from '../core/po-helpers.js';
4
- import { Pt } from '../core/ir/index.js';
4
+ import { Pt, ResourceId } from '../core/ir/index.js';
5
5
  /**
6
6
  * A parsed DrawingML shape without the owning paragraph's properties (attached by
7
7
  * the caller, mirroring how the image branch returns size + id and the caller
@@ -10,10 +10,14 @@ import { Pt } from '../core/ir/index.js';
10
10
  export interface ShapeData {
11
11
  readonly width: Pt;
12
12
  readonly height: Pt;
13
+ /** §20.5.2.17 — the shapes a `wpg:wgp` group holds, placed in its own box. */
14
+ readonly children?: ReadonlyArray<ShapeGroupChild>;
13
15
  readonly geometry: ShapeGeometry;
14
16
  readonly fill: ShapeFill;
15
17
  readonly line?: ShapeLine;
16
18
  readonly transform?: ShapeTransform;
19
+ /** `wp14:sizeRelH/V` — a size stated as a share of the page or margins. */
20
+ readonly relativeSize?: RelativeSize;
17
21
  /** The shape's text body (a `wps:txbx`), when it carries one. */
18
22
  readonly text?: ShapeTextBody;
19
23
  }
@@ -22,6 +26,23 @@ export interface ShapeData {
22
26
  * a module cycle with `document-parser` (which imports this module).
23
27
  */
24
28
  export type ParseBody = (children: ReadonlyArray<PoNode>) => Array<BodyElement>;
29
+ /**
30
+ * §21.1.2 `a:txBody` — the DrawingML text body a shape may carry instead of a
31
+ * `wps:txbx`. Supplied by the caller (the reader owns the PresentationML text
32
+ * reader that knows how to walk it), so this module stays free of it.
33
+ */
34
+ export type ParseDrawingText = (txBody: PoNode, resolveColor: ColorResolver) => ShapeTextBody | undefined;
35
+ /**
36
+ * §20.1.4.1.14/§20.1.4.1.15 — the theme's format scheme, as the raw nodes a
37
+ * `<wps:style>` reference indexes: the fill styles (`a:fillStyleLst`), the
38
+ * BACKGROUND fill styles (`a:bgFillStyleLst`, which an `a:fillRef` reaches with
39
+ * an index past 1000) and the effect styles (`a:effectStyleLst`).
40
+ */
41
+ export interface ThemeStyles {
42
+ readonly fills?: ReadonlyArray<PoNode>;
43
+ readonly bgFills?: ReadonlyArray<PoNode>;
44
+ readonly effects?: ReadonlyArray<PoNode>;
45
+ }
25
46
  /**
26
47
  * The result of parsing a `<w:drawing>` (or legacy VML picture): an embedded
27
48
  * picture, a DrawingML shape, a chart reference, or a SmartArt diagram. Each
@@ -32,6 +53,21 @@ export type DrawingContent = {
32
53
  readonly imageId: string;
33
54
  readonly width: Pt;
34
55
  readonly height: Pt;
56
+ /** §20.1.2.2.24 `a:ln` on `pic:spPr` / VML `@stroked` — the picture's frame. */
57
+ readonly outline?: PictureOutline;
58
+ /** §20.1.8.40 `a:outerShdw` on the same `pic:spPr` — the picture's shadow. */
59
+ readonly shadow?: ShapeShadow;
60
+ /** §20.1.8.55 `a:srcRect` — the part of the source the frame shows. */
61
+ readonly crop?: ImageCrop;
62
+ /** §20.1.7.6 `a:xfrm @rot` — the picture's rotation (1/60000°, clockwise). */
63
+ readonly rotation60k?: number;
64
+ /** §20.1.7.6 `a:xfrm @flipH/@flipV` — the picture drawn mirrored. */
65
+ readonly flipH?: boolean;
66
+ readonly flipV?: boolean;
67
+ /** `wp14:sizeRelH/V` — a size stated as a share of the page or margins. */
68
+ readonly relativeSize?: RelativeSize;
69
+ /** §20.4.2.6 `wp:effectExtent` on an INLINE drawing: space reserved around it. */
70
+ readonly effectExtent?: InlineImage['effectExtent'];
35
71
  /** `wp:docPr` `@descr`/`@title` — alternate text for the tagged-PDF Figure. */
36
72
  readonly altText?: string;
37
73
  readonly float?: FloatAnchor;
@@ -90,7 +126,7 @@ export declare function expandMcChildren(children: ReadonlyArray<PoNode>): Array
90
126
  * @param parseBody Optional body parser for a shape's text box (omitted ⇒ no text).
91
127
  * @returns The parsed content, or `null` when no anchor / recognizable graphic is found.
92
128
  */
93
- export declare function parseDrawing(drawing: PoNode, resolveColor: ColorResolver, parseBody?: ParseBody): DrawingContent | null;
129
+ export declare function parseDrawing(drawing: PoNode, resolveColor: ColorResolver, parseBody?: ParseBody, resolveImage?: (relId: string) => ResourceId | undefined, resolveChartPart?: (relId: string) => string | undefined, themeLineWidths?: ReadonlyArray<number>, themeStyles?: ThemeStyles, parseDrawingText?: ParseDrawingText): DrawingContent | null;
94
130
  /**
95
131
  * Parse a legacy `<w:pict>`/`<w:object>` VML picture (ISO/IEC 29500-1 §14, VML
96
132
  * transitional) into an `image` {@link DrawingContent}. Modern files use
@@ -103,7 +139,30 @@ export declare function parseDrawing(drawing: PoNode, resolveColor: ColorResolve
103
139
  * @param node The `w:pict` / `w:object` node.
104
140
  * @returns The picture, or `null` when there is no embedded `v:imagedata` or no usable size.
105
141
  */
106
- export declare function parseVmlPicture(node: PoNode): DrawingContent | null;
142
+ export declare function parseVmlPicture(node: PoNode, parseBody?: ParseBody): DrawingContent | null;
143
+ /**
144
+ * §14.1.2.5 — `@filled="f"` or a `<v:fill type="none">` says the shape is not
145
+ * filled; otherwise `@fillcolor`, defaulting to VML's own white. Exported
146
+ * because §17.2.1's page background is a `v:background` with exactly this fill
147
+ * on it — the same gradients and the same pictures.
148
+ *
149
+ * @param shape The VML element carrying the fill.
150
+ * @param shapeType Its `v:shapetype`, for the attributes it does not state.
151
+ * @param resolveImage Resolver for a `v:fill` that paints a PICTURE (`@r:id`).
152
+ * @returns The fill.
153
+ */
154
+ export declare function vmlFill(shape: PoNode, shapeType?: PoNode, resolveImage?: (id: string) => ResourceId | undefined): ShapeFill;
155
+ /**
156
+ * §20.1.7.6 `a:xfrm` — how a shape sits in its box: rotated about its centre by
157
+ * `@rot` (sixtieth-thousandths of a degree) and mirrored by `@flipH`/`@flipV`.
158
+ * The box itself comes from elsewhere — the anchor on a sheet, the extent in a
159
+ * document — and holds the shape UNROTATED, which is what makes this a separate
160
+ * transform rather than a different rectangle.
161
+ *
162
+ * @param xfrm The `a:xfrm` element.
163
+ * @returns The transform; empty when it states neither rotation nor a flip.
164
+ */
165
+ export declare function parseXfrm(xfrm: PoNode): ShapeTransform;
107
166
  /**
108
167
  * Parse an `a:prstGeom` (§20.1.9.18) into a preset {@link ShapeGeometry}: the
109
168
  * `@prst` preset name plus the `a:avLst` adjust values (each `a:gd`'s `val …`
@@ -125,7 +184,29 @@ export declare function parseCustGeom(cust: PoNode): ShapeGeometry;
125
184
  * @param spPr The `wps:spPr` node.
126
185
  * @param resolveColor Resolver for theme/scheme colours.
127
186
  */
128
- export declare function parseFill(spPr: PoNode, resolveColor: ColorResolver): ShapeFill;
187
+ export declare function parseFill(spPr: PoNode, resolveColor: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined): ShapeFill;
188
+ /**
189
+ * Parse a shape's drop shadow from its `a:spPr` (§20.1.8.40 `a:effectLst` →
190
+ * `a:outerShdw`).
191
+ *
192
+ * The spec states the displacement in polar form: `dist` in EMU and `dir` in
193
+ * 60 000ths of a degree, measured clockwise from due east in a frame whose y
194
+ * grows DOWNWARD — so the standard 2 700 000 (45°) puts the shadow down and to
195
+ * the right, which is where every reader draws it.
196
+ *
197
+ * @param spPr The shape's `spPr` node.
198
+ * @param resolveColor Resolver for theme/scheme colours.
199
+ * @returns The shadow, or undefined when the shape declares none.
200
+ */
201
+ export declare function parseShadow(spPr: PoNode, resolveColor: ColorResolver): ShapeShadow | undefined;
202
+ /**
203
+ * Build a {@link ShapeShadow} from an `a:outerShdw` node.
204
+ *
205
+ * @param shdw The `a:outerShdw` node.
206
+ * @param resolveColor Resolver for theme/scheme colours.
207
+ * @returns The shadow, or undefined when its colour will not resolve.
208
+ */
209
+ export declare function shadowFromOuterShdw(shdw: PoNode, resolveColor: ColorResolver): ShapeShadow | undefined;
129
210
  /**
130
211
  * Parse a shape's outline (`a:ln`) from its `a:spPr` into a {@link ShapeLine}:
131
212
  * width, cap, solid colour, dash pattern, and an explicit `a:noFill` (an unstroked