reamkit 1.16.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/bidi/segments.js +1 -2
- package/dist/esm/core/converter/project.js +5 -1
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +473 -7
- package/dist/esm/core/drawingml/chart-geometry.d.ts +8 -12
- package/dist/esm/core/drawingml/chart-geometry.js +58 -9
- package/dist/esm/core/drawingml/chart-parser.js +44 -5
- package/dist/esm/core/drawingml/colors.d.ts +1 -1
- package/dist/esm/core/drawingml/colors.js +27 -1
- package/dist/esm/core/drawingml/preset-geometry.js +233 -0
- package/dist/esm/core/drawingml/shape-render.d.ts +12 -0
- package/dist/esm/core/drawingml/shape-render.js +116 -3
- package/dist/esm/core/drawingml/theme-parser.d.ts +10 -0
- package/dist/esm/core/drawingml/theme-parser.js +19 -1
- package/dist/esm/core/font/measure.d.ts +5 -0
- package/dist/esm/core/font/measure.js +21 -1
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +181 -0
- package/dist/esm/core/ir/flow.d.ts +23 -1
- package/dist/esm/core/numbering/apply.d.ts +5 -3
- package/dist/esm/core/numbering/apply.js +42 -11
- package/dist/esm/core/numbering/index.js +2 -0
- package/dist/esm/core/numbering/state.d.ts +13 -1
- package/dist/esm/core/numbering/state.js +256 -15
- package/dist/esm/core/po-helpers.js +16 -1
- package/dist/esm/core/style-cascade/resolver.js +66 -11
- package/dist/esm/core/style-cascade/table.js +35 -11
- package/dist/esm/core/style-cascade/types.d.ts +42 -1
- package/dist/esm/core/style-cascade/types.js +4 -0
- package/dist/esm/core/vector.d.ts +17 -0
- package/dist/esm/excel/print-model.js +1 -1
- package/dist/esm/excel/sheet-to-flow.js +10 -8
- package/dist/esm/excel/worksheet-parser.js +1 -1
- package/dist/esm/html/html-writer.js +18 -4
- package/dist/esm/layout/page-doc.d.ts +62 -2
- package/dist/esm/layout/styled-layout.d.ts +44 -2
- package/dist/esm/layout/styled-layout.js +1870 -228
- package/dist/esm/pdf/shading.js +76 -6
- package/dist/esm/pdf/styled-page-emitter.js +217 -43
- package/dist/esm/pdf/vector-graphics.d.ts +28 -1
- package/dist/esm/pdf/vector-graphics.js +94 -11
- package/dist/esm/pptx/pptx-reader.js +1 -0
- package/dist/esm/pptx/slide-parser.d.ts +21 -4
- package/dist/esm/pptx/slide-parser.js +86 -23
- package/dist/esm/svg/svg-writer.js +1 -1
- package/dist/esm/word/document-parser.d.ts +96 -7
- package/dist/esm/word/document-parser.js +537 -116
- package/dist/esm/word/docx-reader.js +135 -43
- package/dist/esm/word/docx-writer.js +6 -1
- package/dist/esm/word/drawing-parser.d.ts +53 -5
- package/dist/esm/word/drawing-parser.js +1540 -54
- package/dist/esm/word/index.d.ts +4 -4
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +107 -21
- package/dist/esm/word/paragraph-properties.d.ts +11 -1
- package/dist/esm/word/paragraph-properties.js +219 -10
- package/dist/esm/word/run-properties.js +45 -1
- package/dist/esm/word/settings-parser.d.ts +24 -0
- package/dist/esm/word/settings-parser.js +31 -5
- package/dist/esm/word/shading.d.ts +11 -0
- package/dist/esm/word/shading.js +64 -0
- package/dist/esm/word/styles-parser.js +8 -2
- package/dist/esm/word/table-parser.d.ts +9 -1
- package/dist/esm/word/table-parser.js +182 -30
- package/package.json +1 -1
|
@@ -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,
|
|
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
|
|
65
|
-
const
|
|
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
|
|
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
|
|
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
|
|
170
|
-
const draw =
|
|
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
|
|
173
|
-
if (
|
|
174
|
-
|
|
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,
|
|
180
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
259
|
+
if (chart) out.set(resolved.path, withChartColorStyle(chart, pkg, resolved.path, resolveColor));
|
|
227
260
|
}
|
|
228
261
|
return out;
|
|
229
262
|
}
|
|
230
|
-
function
|
|
231
|
-
const
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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.
|
|
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, ShapeShadow, 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,19 @@ 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;
|
|
107
155
|
/**
|
|
108
156
|
* §20.1.7.6 `a:xfrm` — how a shape sits in its box: rotated about its centre by
|
|
109
157
|
* `@rot` (sixtieth-thousandths of a degree) and mirrored by `@flipH`/`@flipV`.
|
|
@@ -136,7 +184,7 @@ export declare function parseCustGeom(cust: PoNode): ShapeGeometry;
|
|
|
136
184
|
* @param spPr The `wps:spPr` node.
|
|
137
185
|
* @param resolveColor Resolver for theme/scheme colours.
|
|
138
186
|
*/
|
|
139
|
-
export declare function parseFill(spPr: PoNode, resolveColor: ColorResolver): ShapeFill;
|
|
187
|
+
export declare function parseFill(spPr: PoNode, resolveColor: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined): ShapeFill;
|
|
140
188
|
/**
|
|
141
189
|
* Parse a shape's drop shadow from its `a:spPr` (§20.1.8.40 `a:effectLst` →
|
|
142
190
|
* `a:outerShdw`).
|