reamkit 1.2.0 → 1.3.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/README.md +3 -2
- package/dist/esm/core/converter/ream.js +4 -3
- package/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/drawingml/chart-geometry.d.ts +1 -1
- package/dist/esm/core/drawingml/chart-geometry.js +79 -117
- package/dist/esm/core/drawingml/chart-parser.d.ts +3 -0
- package/dist/esm/core/drawingml/chart-parser.js +28 -1
- package/dist/esm/core/numbering/apply.js +2 -1
- package/dist/esm/core/opc/index.d.ts +1 -0
- package/dist/esm/core/opc/package.js +3 -2
- package/dist/esm/core/opc/relationship-types.d.ts +1 -0
- package/dist/esm/core/opc/relationship-types.js +5 -2
- package/dist/esm/excel/print-model.d.ts +3 -0
- package/dist/esm/excel/print-model.js +4 -8
- package/dist/esm/excel/sheet-drawing.d.ts +9 -0
- package/dist/esm/excel/sheet-drawing.js +113 -0
- package/dist/esm/excel/worksheet-parser.d.ts +1 -0
- package/dist/esm/excel/worksheet-parser.js +4 -1
- package/dist/esm/excel/xlsx-reader.js +41 -0
- package/dist/esm/excel/xlsx-to-pdf.js +25 -18
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/layout/page-doc.d.ts +1 -0
- package/dist/esm/layout/styled-layout.d.ts +2 -0
- package/dist/esm/layout/styled-layout.js +321 -171
- package/dist/esm/pdf/encryption.d.ts +34 -0
- package/dist/esm/pdf/encryption.js +143 -0
- package/dist/esm/pdf/index.d.ts +2 -1
- package/dist/esm/pdf/styled-page-emitter.d.ts +2 -0
- package/dist/esm/pdf/styled-page-emitter.js +25 -7
- package/dist/esm/pdf/styled-page-renderer.d.ts +1 -0
- package/dist/esm/pdf/styled-page-renderer.js +17 -2
- package/dist/esm/pdf/writer.d.ts +2 -0
- package/dist/esm/pdf/writer.js +6 -1
- package/dist/esm/word/document-parser.js +4 -0
- package/dist/esm/word/docx-reader.js +7 -11
- package/dist/esm/word/docx-to-pdf.js +23 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -168,8 +168,9 @@ repeated titles, page breaks), DrawingML shapes and charts, OMML math,
|
|
|
168
168
|
Type0+CIDFontType2 embedding with subsetting, Knuth-Plass line breaking,
|
|
169
169
|
Liang hyphenation, OpenType ligatures/kerning + Arabic cursive joining,
|
|
170
170
|
BiDi (UAX #9), hyperlinks (PDF link annotations + HTML anchors,
|
|
171
|
-
scheme-allowlisted), tagged PDF, PDF/A-1/2/3 (a/b/u),
|
|
172
|
-
(PKCS#7/ECDSA/PAdES/RFC 3161), SVG page
|
|
171
|
+
scheme-allowlisted), tagged PDF, PDF/A-1/2/3 (a/b/u), PDF/UA-1, AES-256
|
|
172
|
+
encryption, digital signatures (PKCS#7/ECDSA/PAdES/RFC 3161), SVG page
|
|
173
|
+
preview, flowed HTML export. Reads OOXML Transitional and Strict.
|
|
173
174
|
|
|
174
175
|
See `handoff.md` for the full feature matrix and known limitations.
|
|
175
176
|
|
|
@@ -3,7 +3,7 @@ import { FontRegistry } from "../font/font-registry.js";
|
|
|
3
3
|
import { ConversionLossError } from "../ir/loss.js";
|
|
4
4
|
import { layoutStyledDocument } from "../../layout/styled-layout.js";
|
|
5
5
|
import { signPdf } from "../../pdf/signature.js";
|
|
6
|
-
import { renderStyledPdf } from "../../pdf/styled-page-renderer.js";
|
|
6
|
+
import { renderStyledPdf, renderStyledPdfEncrypted } from "../../pdf/styled-page-renderer.js";
|
|
7
7
|
import "../../pdf/index.js";
|
|
8
8
|
import { flowRenderOptions } from "./project.js";
|
|
9
9
|
import { writeHtml } from "../../html/html-writer.js";
|
|
@@ -73,7 +73,7 @@ var Ream = class Ream {
|
|
|
73
73
|
relationship: "Source",
|
|
74
74
|
description: "Source document"
|
|
75
75
|
});
|
|
76
|
-
|
|
76
|
+
const styled = {
|
|
77
77
|
registry,
|
|
78
78
|
...registriesByFamily ? { registriesByFamily } : {},
|
|
79
79
|
...flowRenderOptions(this.flow),
|
|
@@ -81,7 +81,8 @@ var Ream = class Ream {
|
|
|
81
81
|
...attachments.length > 0 ? { attachments } : {},
|
|
82
82
|
...signature ? { signaturePlaceholder: signature } : {},
|
|
83
83
|
...renderOptions
|
|
84
|
-
}
|
|
84
|
+
};
|
|
85
|
+
let pdf = styled.encrypt ? await renderStyledPdfEncrypted(this.flow.body, styled) : renderStyledPdf(this.flow.body, styled);
|
|
85
86
|
if (signature) pdf = await signPdf(pdf, signature);
|
|
86
87
|
this.enforceStrict(options, losses);
|
|
87
88
|
return {
|
|
@@ -132,6 +132,7 @@ export interface Run {
|
|
|
132
132
|
readonly footnoteRef?: string;
|
|
133
133
|
readonly endnoteRef?: string;
|
|
134
134
|
readonly noteNumber?: true;
|
|
135
|
+
readonly listMarker?: true;
|
|
135
136
|
readonly inlineImage?: InlineImage;
|
|
136
137
|
readonly math?: MathNode;
|
|
137
138
|
readonly pageBreak?: boolean;
|
|
@@ -382,6 +383,7 @@ export interface Chart {
|
|
|
382
383
|
readonly showValues?: boolean;
|
|
383
384
|
readonly catAxisTitle?: string;
|
|
384
385
|
readonly valAxisTitle?: string;
|
|
386
|
+
readonly seriesColorCycle?: ReadonlyArray<string>;
|
|
385
387
|
}
|
|
386
388
|
export interface ChartBlock {
|
|
387
389
|
readonly float?: FloatAnchor;
|
|
@@ -48,7 +48,7 @@ export type MeasureText = (text: string, sizePt: number) => number;
|
|
|
48
48
|
export declare const CHART_LABEL_PT = 9;
|
|
49
49
|
export declare const CHART_TITLE_PT = 13;
|
|
50
50
|
export declare const SERIES_COLORS: string[];
|
|
51
|
-
export declare const seriesColor: (s: ChartSeries, i: number) => string;
|
|
51
|
+
export declare const seriesColor: (s: ChartSeries, i: number, cycle?: ReadonlyArray<string>) => string;
|
|
52
52
|
export interface Scale {
|
|
53
53
|
readonly min: number;
|
|
54
54
|
readonly max: number;
|
|
@@ -10,7 +10,7 @@ var SERIES_COLORS = [
|
|
|
10
10
|
"5B9BD5",
|
|
11
11
|
"70AD47"
|
|
12
12
|
];
|
|
13
|
-
var seriesColor = (s, i) => s.colorHex ?? SERIES_COLORS[i % SERIES_COLORS.length];
|
|
13
|
+
var seriesColor = (s, i, cycle) => s.colorHex ?? (cycle && cycle.length > 0 ? cycle[i % cycle.length] : SERIES_COLORS[i % SERIES_COLORS.length]);
|
|
14
14
|
function niceNum(range, round) {
|
|
15
15
|
const exp = Math.floor(Math.log10(range));
|
|
16
16
|
const f = range / 10 ** exp;
|
|
@@ -40,6 +40,68 @@ var ticks = (s) => {
|
|
|
40
40
|
for (let v = s.min; v <= s.max + 1e-9; v += s.step) out.push(Math.abs(v) < 1e-9 ? 0 : v);
|
|
41
41
|
return out;
|
|
42
42
|
};
|
|
43
|
+
function pushChartTitle(labels, chart, wPt, hPt) {
|
|
44
|
+
if (!chart.title) return;
|
|
45
|
+
labels.push({
|
|
46
|
+
text: chart.title,
|
|
47
|
+
x: wPt / 2,
|
|
48
|
+
y: hPt - 4 - 13,
|
|
49
|
+
sizePt: 13,
|
|
50
|
+
colorHex: TITLE_COLOR,
|
|
51
|
+
align: "center"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function buildLegendBlock(chart, wPt, hPt, measure) {
|
|
55
|
+
return layoutLegend(chart.series.map((s, i) => ({
|
|
56
|
+
name: s.name ?? "",
|
|
57
|
+
colorHex: seriesColor(s, i, chart.seriesColorCycle)
|
|
58
|
+
})).filter((e) => e.name !== ""), chart.hasLegend, chart.legendPos ?? "b", wPt, hPt, measure);
|
|
59
|
+
}
|
|
60
|
+
function pushGridTicks(polylines, labels, tickVals, fmt, axis, at, x0, y0, plotW, plotH) {
|
|
61
|
+
for (const v of tickVals) if (axis === "x") {
|
|
62
|
+
const gx = at(v);
|
|
63
|
+
polylines.push({
|
|
64
|
+
points: [[gx, y0], [gx, y0 + plotH]],
|
|
65
|
+
strokeHex: GRID_COLOR,
|
|
66
|
+
widthPt: .75
|
|
67
|
+
});
|
|
68
|
+
labels.push({
|
|
69
|
+
text: fmt(v),
|
|
70
|
+
x: gx,
|
|
71
|
+
y: y0 - 9,
|
|
72
|
+
sizePt: 9,
|
|
73
|
+
colorHex: LABEL_COLOR,
|
|
74
|
+
align: "center"
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
const gy = at(v);
|
|
78
|
+
polylines.push({
|
|
79
|
+
points: [[x0, gy], [x0 + plotW, gy]],
|
|
80
|
+
strokeHex: GRID_COLOR,
|
|
81
|
+
widthPt: .75
|
|
82
|
+
});
|
|
83
|
+
labels.push({
|
|
84
|
+
text: fmt(v),
|
|
85
|
+
x: x0 - 3,
|
|
86
|
+
y: gy - 9 / 3,
|
|
87
|
+
sizePt: 9,
|
|
88
|
+
colorHex: LABEL_COLOR,
|
|
89
|
+
align: "right"
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function pushAxisLines(polylines, x0, y0, plotW, plotH) {
|
|
94
|
+
polylines.push({
|
|
95
|
+
points: [[x0, y0], [x0, y0 + plotH]],
|
|
96
|
+
strokeHex: AXIS_COLOR,
|
|
97
|
+
widthPt: 1
|
|
98
|
+
});
|
|
99
|
+
polylines.push({
|
|
100
|
+
points: [[x0, y0], [x0 + plotW, y0]],
|
|
101
|
+
strokeHex: AXIS_COLOR,
|
|
102
|
+
widthPt: 1
|
|
103
|
+
});
|
|
104
|
+
}
|
|
43
105
|
function buildFrame(chart, wPt, hPt, measure, horizontal, opts = {}) {
|
|
44
106
|
const rects = [];
|
|
45
107
|
const polylines = [];
|
|
@@ -53,10 +115,7 @@ function buildFrame(chart, wPt, hPt, measure, horizontal, opts = {}) {
|
|
|
53
115
|
let top = 4;
|
|
54
116
|
if (chart.title) top += 13 * 1.6;
|
|
55
117
|
if (chart.valAxisTitle) top += 9 * 1.4;
|
|
56
|
-
const legend =
|
|
57
|
-
name: s.name ?? "",
|
|
58
|
-
colorHex: seriesColor(s, i)
|
|
59
|
-
})).filter((e) => e.name !== ""), chart.hasLegend, chart.legendPos ?? "b", wPt, hPt, measure);
|
|
118
|
+
const legend = buildLegendBlock(chart, wPt, hPt, measure);
|
|
60
119
|
const plotRight = wPt - 4 - legend.rightWidth;
|
|
61
120
|
const tickLabelW = Math.max(0, ...tickVals.map((v) => measure(fmtVal(v), 9))) + 4;
|
|
62
121
|
const catLabelH = 9 * 1.6;
|
|
@@ -67,14 +126,7 @@ function buildFrame(chart, wPt, hPt, measure, horizontal, opts = {}) {
|
|
|
67
126
|
const plotH = Math.max(1, hPt - top - y0);
|
|
68
127
|
const valueOffset = (v) => (v - scale.min) / (scale.max - scale.min) * (horizontal ? plotW : plotH);
|
|
69
128
|
const zeroOffset = valueOffset(0);
|
|
70
|
-
|
|
71
|
-
text: chart.title,
|
|
72
|
-
x: wPt / 2,
|
|
73
|
-
y: hPt - 4 - 13,
|
|
74
|
-
sizePt: 13,
|
|
75
|
-
colorHex: TITLE_COLOR,
|
|
76
|
-
align: "center"
|
|
77
|
-
});
|
|
129
|
+
pushChartTitle(labels, chart, wPt, hPt);
|
|
78
130
|
if (chart.valAxisTitle) labels.push({
|
|
79
131
|
text: chart.valAxisTitle,
|
|
80
132
|
x: x0,
|
|
@@ -91,40 +143,8 @@ function buildFrame(chart, wPt, hPt, measure, horizontal, opts = {}) {
|
|
|
91
143
|
colorHex: LABEL_COLOR,
|
|
92
144
|
align: "center"
|
|
93
145
|
});
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (horizontal) {
|
|
97
|
-
const gx = x0 + off;
|
|
98
|
-
polylines.push({
|
|
99
|
-
points: [[gx, y0], [gx, y0 + plotH]],
|
|
100
|
-
strokeHex: GRID_COLOR,
|
|
101
|
-
widthPt: .75
|
|
102
|
-
});
|
|
103
|
-
labels.push({
|
|
104
|
-
text: fmtVal(v),
|
|
105
|
-
x: gx,
|
|
106
|
-
y: y0 - 9,
|
|
107
|
-
sizePt: 9,
|
|
108
|
-
colorHex: LABEL_COLOR,
|
|
109
|
-
align: "center"
|
|
110
|
-
});
|
|
111
|
-
} else {
|
|
112
|
-
const gy = y0 + off;
|
|
113
|
-
polylines.push({
|
|
114
|
-
points: [[x0, gy], [x0 + plotW, gy]],
|
|
115
|
-
strokeHex: GRID_COLOR,
|
|
116
|
-
widthPt: .75
|
|
117
|
-
});
|
|
118
|
-
labels.push({
|
|
119
|
-
text: fmtVal(v),
|
|
120
|
-
x: x0 - 3,
|
|
121
|
-
y: gy - 9 / 3,
|
|
122
|
-
sizePt: 9,
|
|
123
|
-
colorHex: LABEL_COLOR,
|
|
124
|
-
align: "right"
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
146
|
+
if (horizontal) pushGridTicks(polylines, labels, tickVals, fmtVal, "x", (v) => x0 + valueOffset(v), x0, y0, plotW, plotH);
|
|
147
|
+
else pushGridTicks(polylines, labels, tickVals, fmtVal, "y", (v) => y0 + valueOffset(v), x0, y0, plotW, plotH);
|
|
128
148
|
const slot = (horizontal ? plotH : plotW) / nCats;
|
|
129
149
|
for (let c = 0; c < nCats; c++) {
|
|
130
150
|
const cat = chart.categories[c] ?? "";
|
|
@@ -147,16 +167,7 @@ function buildFrame(chart, wPt, hPt, measure, horizontal, opts = {}) {
|
|
|
147
167
|
align: "center"
|
|
148
168
|
});
|
|
149
169
|
}
|
|
150
|
-
polylines
|
|
151
|
-
points: [[x0, y0], [x0, y0 + plotH]],
|
|
152
|
-
strokeHex: AXIS_COLOR,
|
|
153
|
-
widthPt: 1
|
|
154
|
-
});
|
|
155
|
-
polylines.push({
|
|
156
|
-
points: [[x0, y0], [x0 + plotW, y0]],
|
|
157
|
-
strokeHex: AXIS_COLOR,
|
|
158
|
-
widthPt: 1
|
|
159
|
-
});
|
|
170
|
+
pushAxisLines(polylines, x0, y0, plotW, plotH);
|
|
160
171
|
legend.emit(rects, labels);
|
|
161
172
|
return {
|
|
162
173
|
x0,
|
|
@@ -232,7 +243,7 @@ function buildBarScene(chart, wPt, hPt, measure) {
|
|
|
232
243
|
const o1 = f.valueOffset(top);
|
|
233
244
|
const lo = Math.min(o0, o1);
|
|
234
245
|
const span = Math.abs(o1 - o0);
|
|
235
|
-
const color = pointColor(series, c) ?? seriesColor(series, s);
|
|
246
|
+
const color = pointColor(series, c) ?? seriesColor(series, s, chart.seriesColorCycle);
|
|
236
247
|
if (horizontal) f.rects.push({
|
|
237
248
|
x: f.x0 + lo,
|
|
238
249
|
y: along,
|
|
@@ -271,7 +282,7 @@ function buildBarScene(chart, wPt, hPt, measure) {
|
|
|
271
282
|
for (let s = 0; s < chart.series.length; s++) {
|
|
272
283
|
const series = chart.series[s];
|
|
273
284
|
const len = f.valueOffset(series.values[c] ?? 0) - f.zeroOffset;
|
|
274
|
-
const color = pointColor(series, c) ?? seriesColor(series, s);
|
|
285
|
+
const color = pointColor(series, c) ?? seriesColor(series, s, chart.seriesColorCycle);
|
|
275
286
|
const along = slotStart + s * barW;
|
|
276
287
|
if (horizontal) {
|
|
277
288
|
const bx = f.x0 + f.zeroOffset + Math.min(0, len);
|
|
@@ -356,7 +367,7 @@ function buildAreaScene(chart, wPt, hPt, measure) {
|
|
|
356
367
|
const denom = percent ? chart.series.reduce((a, ss) => a + Math.abs(ss.values[c] ?? 0), 0) || 1 : 1;
|
|
357
368
|
return b + (series.values[c] ?? 0) / denom;
|
|
358
369
|
});
|
|
359
|
-
polygons.push(areaBand(top, base, f, xAt, seriesColor(series, s)));
|
|
370
|
+
polygons.push(areaBand(top, base, f, xAt, seriesColor(series, s, chart.seriesColorCycle)));
|
|
360
371
|
for (let c = 0; c < nCats; c++) cum[c] = top[c];
|
|
361
372
|
}
|
|
362
373
|
} else {
|
|
@@ -364,7 +375,7 @@ function buildAreaScene(chart, wPt, hPt, measure) {
|
|
|
364
375
|
for (let s = chart.series.length - 1; s >= 0; s--) {
|
|
365
376
|
const series = chart.series[s];
|
|
366
377
|
const top = Array.from({ length: nCats }, (_, c) => series.values[c] ?? 0);
|
|
367
|
-
polygons.push(areaBand(top, base, f, xAt, seriesColor(series, s)));
|
|
378
|
+
polygons.push(areaBand(top, base, f, xAt, seriesColor(series, s, chart.seriesColorCycle)));
|
|
368
379
|
}
|
|
369
380
|
}
|
|
370
381
|
return {
|
|
@@ -397,69 +408,20 @@ function buildScatterScene(chart, wPt, hPt, measure) {
|
|
|
397
408
|
const yTicks = ticks(yScale);
|
|
398
409
|
let top = 4;
|
|
399
410
|
if (chart.title) top += 13 * 1.6;
|
|
400
|
-
const legend =
|
|
401
|
-
name: s.name ?? "",
|
|
402
|
-
colorHex: seriesColor(s, i)
|
|
403
|
-
})).filter((e) => e.name !== ""), chart.hasLegend, chart.legendPos ?? "b", wPt, hPt, measure);
|
|
411
|
+
const legend = buildLegendBlock(chart, wPt, hPt, measure);
|
|
404
412
|
const x0 = 4 + (Math.max(0, ...yTicks.map((v) => measure(formatTick(v, yScale.step), 9))) + 4);
|
|
405
413
|
const y0 = 4 + legend.bottomHeight + 9 * 1.6;
|
|
406
414
|
const plotW = Math.max(1, wPt - 4 - legend.rightWidth - x0);
|
|
407
415
|
const plotH = Math.max(1, hPt - top - y0);
|
|
408
416
|
const xAt = (v) => x0 + (v - xScale.min) / (xScale.max - xScale.min) * plotW;
|
|
409
417
|
const yAt = (v) => y0 + (v - yScale.min) / (yScale.max - yScale.min) * plotH;
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
sizePt: 13,
|
|
415
|
-
colorHex: TITLE_COLOR,
|
|
416
|
-
align: "center"
|
|
417
|
-
});
|
|
418
|
-
for (const v of yTicks) {
|
|
419
|
-
const gy = yAt(v);
|
|
420
|
-
polylines.push({
|
|
421
|
-
points: [[x0, gy], [x0 + plotW, gy]],
|
|
422
|
-
strokeHex: GRID_COLOR,
|
|
423
|
-
widthPt: .75
|
|
424
|
-
});
|
|
425
|
-
labels.push({
|
|
426
|
-
text: formatTick(v, yScale.step),
|
|
427
|
-
x: x0 - 3,
|
|
428
|
-
y: gy - 9 / 3,
|
|
429
|
-
sizePt: 9,
|
|
430
|
-
colorHex: LABEL_COLOR,
|
|
431
|
-
align: "right"
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
for (const v of xTicks) {
|
|
435
|
-
const gx = xAt(v);
|
|
436
|
-
polylines.push({
|
|
437
|
-
points: [[gx, y0], [gx, y0 + plotH]],
|
|
438
|
-
strokeHex: GRID_COLOR,
|
|
439
|
-
widthPt: .75
|
|
440
|
-
});
|
|
441
|
-
labels.push({
|
|
442
|
-
text: formatTick(v, xScale.step),
|
|
443
|
-
x: gx,
|
|
444
|
-
y: y0 - 9,
|
|
445
|
-
sizePt: 9,
|
|
446
|
-
colorHex: LABEL_COLOR,
|
|
447
|
-
align: "center"
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
polylines.push({
|
|
451
|
-
points: [[x0, y0], [x0, y0 + plotH]],
|
|
452
|
-
strokeHex: AXIS_COLOR,
|
|
453
|
-
widthPt: 1
|
|
454
|
-
});
|
|
455
|
-
polylines.push({
|
|
456
|
-
points: [[x0, y0], [x0 + plotW, y0]],
|
|
457
|
-
strokeHex: AXIS_COLOR,
|
|
458
|
-
widthPt: 1
|
|
459
|
-
});
|
|
418
|
+
pushChartTitle(labels, chart, wPt, hPt);
|
|
419
|
+
pushGridTicks(polylines, labels, yTicks, (v) => formatTick(v, yScale.step), "y", yAt, x0, y0, plotW, plotH);
|
|
420
|
+
pushGridTicks(polylines, labels, xTicks, (v) => formatTick(v, xScale.step), "x", xAt, x0, y0, plotW, plotH);
|
|
421
|
+
pushAxisLines(polylines, x0, y0, plotW, plotH);
|
|
460
422
|
for (let s = 0; s < chart.series.length; s++) {
|
|
461
423
|
const series = chart.series[s];
|
|
462
|
-
const color = seriesColor(series, s);
|
|
424
|
+
const color = seriesColor(series, s, chart.seriesColorCycle);
|
|
463
425
|
for (let i = 0; i < series.values.length; i++) {
|
|
464
426
|
const px = xAt(series.xValues?.[i] ?? i);
|
|
465
427
|
const py = yAt(series.values[i] ?? 0);
|
|
@@ -485,7 +447,7 @@ function buildLineScene(chart, wPt, hPt, measure) {
|
|
|
485
447
|
const f = buildFrame(chart, wPt, hPt, measure, false, { dataRange: allVals.length > 0 ? [Math.min(...allVals), Math.max(...allVals)] : [0, 1] });
|
|
486
448
|
for (let s = 0; s < chart.series.length; s++) {
|
|
487
449
|
const series = chart.series[s];
|
|
488
|
-
const color = seriesColor(series, s);
|
|
450
|
+
const color = seriesColor(series, s, chart.seriesColorCycle);
|
|
489
451
|
const pts = [];
|
|
490
452
|
for (let c = 0; c < f.nCats; c++) {
|
|
491
453
|
const x = f.x0 + c * f.slot + f.slot / 2;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { Chart } from '../document-model/index.js';
|
|
2
|
+
import { OpcPackage } from '../opc/index.js';
|
|
2
3
|
import { ColorResolver } from './colors.js';
|
|
3
4
|
export declare function parseChart(chartXml: Uint8Array, resolveColor: ColorResolver): Chart | null;
|
|
5
|
+
export declare function parseChartColorStyle(colorsXml: Uint8Array, resolveColor: ColorResolver): Array<string>;
|
|
6
|
+
export declare function withChartColorStyle(chart: Chart, pkg: OpcPackage, chartPartPath: string, resolveColor: ColorResolver): Chart;
|
|
@@ -191,5 +191,32 @@ function isLegendPos(v) {
|
|
|
191
191
|
function isGrouping(v) {
|
|
192
192
|
return v === "clustered" || v === "stacked" || v === "percentStacked" || v === "standard";
|
|
193
193
|
}
|
|
194
|
+
function parseChartColorStyle(colorsXml, resolveColor) {
|
|
195
|
+
const root = parser.parse(new TextDecoder().decode(colorsXml)).find((n) => {
|
|
196
|
+
const tag = Object.keys(n).find((k) => k !== ":@" && k !== "#text");
|
|
197
|
+
return tag !== void 0 && tag.endsWith("colorStyle");
|
|
198
|
+
});
|
|
199
|
+
if (!root) return [];
|
|
200
|
+
const out = [];
|
|
201
|
+
for (const child of poChildren(root)) {
|
|
202
|
+
const hex = resolveColorNode(child, resolveColor);
|
|
203
|
+
if (hex !== void 0) out.push(hex);
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
function withChartColorStyle(chart, pkg, chartPartPath, resolveColor) {
|
|
208
|
+
for (const rel of pkg.getPartRelationships(chartPartPath)) {
|
|
209
|
+
if (rel.type !== REL_CHART_COLOR_STYLE) continue;
|
|
210
|
+
const resolved = pkg.resolveRelatedPart(chartPartPath, rel);
|
|
211
|
+
if (!resolved) continue;
|
|
212
|
+
const cycle = parseChartColorStyle(resolved.data, resolveColor);
|
|
213
|
+
if (cycle.length > 0) return {
|
|
214
|
+
...chart,
|
|
215
|
+
seriesColorCycle: cycle
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return chart;
|
|
219
|
+
}
|
|
220
|
+
var REL_CHART_COLOR_STYLE = "http://schemas.microsoft.com/office/2011/relationships/chartColorStyle";
|
|
194
221
|
//#endregion
|
|
195
|
-
export { parseChart };
|
|
222
|
+
export { parseChart, withChartColorStyle };
|
|
@@ -12,7 +12,8 @@ function applyNumbering(body, numbering) {
|
|
|
12
12
|
const level = (instance ? numbering.abstractNums.get(instance.abstractNumId) : void 0)?.levels.get(ref.ilvl);
|
|
13
13
|
const markerRun = {
|
|
14
14
|
text: `${marker}\t`,
|
|
15
|
-
properties: level?.runProperties ?? {}
|
|
15
|
+
properties: level?.runProperties ?? {},
|
|
16
|
+
listMarker: true
|
|
16
17
|
};
|
|
17
18
|
const newProps = mergeIndentFromLevel(p.properties, level?.paragraphProperties);
|
|
18
19
|
return {
|
|
@@ -3,3 +3,4 @@ export type { Relationship } from './relationships.js';
|
|
|
3
3
|
export { REL_OFFICE_DOCUMENT, REL_CORE_PROPERTIES, REL_EXTENDED_PROPERTIES, } from './relationship-types.js';
|
|
4
4
|
export { parseCoreProperties } from './core-properties.js';
|
|
5
5
|
export type { CoreProperties } from './core-properties.js';
|
|
6
|
+
export { isOoxmlRel } from './relationship-types.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseRelationships } from "./relationships.js";
|
|
2
|
-
import "./relationship-types.js";
|
|
2
|
+
import { isOoxmlRel } from "./relationship-types.js";
|
|
3
3
|
import { unzipSync } from "fflate";
|
|
4
4
|
//#region src/core/opc/package.ts
|
|
5
5
|
var ROOT_RELS_PATH = "_rels/.rels";
|
|
@@ -11,6 +11,7 @@ var OpcPackage = class OpcPackage {
|
|
|
11
11
|
}
|
|
12
12
|
relsCache = /* @__PURE__ */ new Map();
|
|
13
13
|
static open(buffer, options = {}) {
|
|
14
|
+
if (buffer.length >= 4 && buffer[0] === 208 && buffer[1] === 207 && buffer[2] === 17 && buffer[3] === 224) throw new Error("OLE compound file: a password-protected (encrypted) OOXML document or a legacy binary .doc/.xls — re-save as an unencrypted .docx/.xlsx");
|
|
14
15
|
const maxArchive = options.maxArchiveBytes ?? 128 * MIB;
|
|
15
16
|
const maxEntry = options.maxEntryBytes ?? 256 * MIB;
|
|
16
17
|
const maxTotal = options.maxTotalBytes ?? 512 * MIB;
|
|
@@ -77,7 +78,7 @@ var OpcPackage = class OpcPackage {
|
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
getMainDocumentPath() {
|
|
80
|
-
const candidates = this.rootRelationships.filter((r) => r.type
|
|
81
|
+
const candidates = this.rootRelationships.filter((r) => isOoxmlRel(r.type, "officeDocument") && r.targetMode === "Internal");
|
|
81
82
|
if (candidates.length === 0) throw new Error("OPC package has no officeDocument relationship");
|
|
82
83
|
if (candidates.length > 1) throw new Error(`OPC package has multiple officeDocument relationships (${candidates.length})`);
|
|
83
84
|
return resolveTarget("/", candidates[0].target);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const REL_OFFICE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
|
|
2
2
|
export declare const REL_CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
|
3
3
|
export declare const REL_EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
|
4
|
+
export declare function isOoxmlRel(type: string, name: string): boolean;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
//#region src/core/opc/relationship-types.ts
|
|
2
|
-
var
|
|
2
|
+
var OOXML_REL_BASES = ["http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "http://purl.oclc.org/ooxml/officeDocument/relationships/"];
|
|
3
|
+
function isOoxmlRel(type, name) {
|
|
4
|
+
return OOXML_REL_BASES.some((base) => type === base + name);
|
|
5
|
+
}
|
|
3
6
|
//#endregion
|
|
4
|
-
export {
|
|
7
|
+
export { isOoxmlRel };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { BodyElement, SectionProperties } from '../core/document-model/index.js';
|
|
2
2
|
import { CellRange, DefinedName, ParsedWorksheet, XlsxStyles } from './index.js';
|
|
3
|
+
export declare const TWIPS_PER_EXCEL_CHAR = 105;
|
|
4
|
+
export declare const DEFAULT_COL_TWIPS = 960;
|
|
5
|
+
export declare const DEFAULT_ROW_TWIPS = 300;
|
|
3
6
|
export declare function sectionFromWorksheet(worksheet: ParsedWorksheet): SectionProperties | undefined;
|
|
4
7
|
export declare function resolvePrintArea(definedNames: ReadonlyArray<DefinedName>, sheetIdx: number): CellRange | undefined;
|
|
5
8
|
export declare function resolvePrintTitleRows(definedNames: ReadonlyArray<DefinedName>, sheetIdx: number): {
|
|
@@ -2,10 +2,6 @@ import { eighthPtToPt, halfPtToPt, twipsToPt } from "../core/ir/units.js";
|
|
|
2
2
|
import { parseAreaRef, parseTitleRowRange } from "./defined-name-ref.js";
|
|
3
3
|
import { applyNumberFormat } from "./number-format.js";
|
|
4
4
|
import "./index.js";
|
|
5
|
-
//#region src/excel/print-model.ts
|
|
6
|
-
var TWIPS_PER_EXCEL_CHAR = 105;
|
|
7
|
-
var DEFAULT_COL_TWIPS = 960;
|
|
8
|
-
var DEFAULT_ROW_TWIPS = 300;
|
|
9
5
|
var TWIPS_PER_POINT = 20;
|
|
10
6
|
var TWIPS_PER_INCH = 1440;
|
|
11
7
|
var PAPER_SIZES_TWIPS = new Map([
|
|
@@ -154,9 +150,9 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
154
150
|
const cEnd = Math.min(m.endColumn, colWindowEnd);
|
|
155
151
|
for (let r = Math.max(m.startRow, rowStart); r <= rEnd; r++) for (let c = Math.max(m.startColumn, colStart); c <= cEnd; c++) if (!(r === m.startRow && c === m.startColumn)) insideMerge.add(key(r, c));
|
|
156
152
|
}
|
|
157
|
-
const columnWidths = new Array(colCount).fill(
|
|
153
|
+
const columnWidths = new Array(colCount).fill(960);
|
|
158
154
|
for (const col of worksheet.columns) {
|
|
159
|
-
const twips = Math.round(col.widthChars *
|
|
155
|
+
const twips = Math.round(col.widthChars * 105);
|
|
160
156
|
for (let abs = col.min - 1; abs <= col.max - 1; abs++) {
|
|
161
157
|
const i = abs - colStart;
|
|
162
158
|
if (i >= 0 && i < colCount) columnWidths[i] = twips;
|
|
@@ -164,7 +160,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
164
160
|
}
|
|
165
161
|
const totalGridTwips = columnWidths.reduce((sum, w) => sum + w, 0);
|
|
166
162
|
let totalGridHeightTwips = 0;
|
|
167
|
-
for (let r = 0; r < rowCount; r++) totalGridHeightTwips += rowHeightMap.get(r)?.heightTwips ??
|
|
163
|
+
for (let r = 0; r < rowCount; r++) totalGridHeightTwips += rowHeightMap.get(r)?.heightTwips ?? 300;
|
|
168
164
|
const printScale = computePrintScale(worksheet, totalGridTwips, sheetContentWidthTwips(worksheet), totalGridHeightTwips, sheetContentHeightTwips(worksheet));
|
|
169
165
|
const scaled = printScale < .999;
|
|
170
166
|
const breakRows = new Set(worksheet.rowBreaks ?? []);
|
|
@@ -217,7 +213,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
217
213
|
cc++;
|
|
218
214
|
}
|
|
219
215
|
if (cc < colCount) {
|
|
220
|
-
const charsFit = Math.max(1, Math.round(availTwips /
|
|
216
|
+
const charsFit = Math.max(1, Math.round(availTwips / 105));
|
|
221
217
|
if (text.length > charsFit) text = text.slice(0, charsFit);
|
|
222
218
|
}
|
|
223
219
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpcPackage } from '../core/opc/index.js';
|
|
2
|
+
import { ParsedWorksheet } from './worksheet-parser.js';
|
|
3
|
+
export interface SheetChartRef {
|
|
4
|
+
readonly chartPartPath: string;
|
|
5
|
+
readonly widthPt: number;
|
|
6
|
+
readonly heightPt: number;
|
|
7
|
+
readonly anchorRow: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseSheetDrawing(drawingXml: Uint8Array, drawingPartPath: string, pkg: OpcPackage, worksheet: ParsedWorksheet): Array<SheetChartRef>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { emuToPt } from "../core/ir/units.js";
|
|
2
|
+
import "./print-model.js";
|
|
3
|
+
import { XMLParser } from "fast-xml-parser";
|
|
4
|
+
//#region src/excel/sheet-drawing.ts
|
|
5
|
+
var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
|
|
6
|
+
var parser = new XMLParser({
|
|
7
|
+
ignoreAttributes: false,
|
|
8
|
+
attributeNamePrefix: "@_",
|
|
9
|
+
removeNSPrefix: true,
|
|
10
|
+
parseTagValue: false
|
|
11
|
+
});
|
|
12
|
+
var TWIPS_PER_PT = 20;
|
|
13
|
+
function parseSheetDrawing(drawingXml, drawingPartPath, pkg, worksheet) {
|
|
14
|
+
const root = parser.parse(new TextDecoder().decode(drawingXml))["wsDr"];
|
|
15
|
+
if (!root || typeof root !== "object") return [];
|
|
16
|
+
const rootObj = root;
|
|
17
|
+
const colWidthPt = makeColWidthPt(worksheet);
|
|
18
|
+
const rowHeightPt = makeRowHeightPt(worksheet);
|
|
19
|
+
const rels = pkg.getPartRelationships(drawingPartPath);
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const kind of [
|
|
22
|
+
"twoCellAnchor",
|
|
23
|
+
"oneCellAnchor",
|
|
24
|
+
"absoluteAnchor"
|
|
25
|
+
]) for (const anchor of asArray(rootObj[kind])) {
|
|
26
|
+
if (!anchor || typeof anchor !== "object") continue;
|
|
27
|
+
const a = anchor;
|
|
28
|
+
const chartRelId = chartRelIdOf(a);
|
|
29
|
+
if (!chartRelId) continue;
|
|
30
|
+
const rel = rels.find((r) => r.id === chartRelId);
|
|
31
|
+
const resolved = rel ? pkg.resolveRelatedPart(drawingPartPath, rel) : void 0;
|
|
32
|
+
if (!resolved) continue;
|
|
33
|
+
const from = cellMarker(a["from"]);
|
|
34
|
+
let widthPt = 0;
|
|
35
|
+
let heightPt = 0;
|
|
36
|
+
if (kind === "twoCellAnchor") {
|
|
37
|
+
const to = cellMarker(a["to"]);
|
|
38
|
+
if (!from || !to) continue;
|
|
39
|
+
widthPt = spanPt(from.col, from.colOffPt, to.col, to.colOffPt, colWidthPt);
|
|
40
|
+
heightPt = spanPt(from.row, from.rowOffPt, to.row, to.rowOffPt, rowHeightPt);
|
|
41
|
+
} else {
|
|
42
|
+
const ext = a["ext"];
|
|
43
|
+
if (!ext || typeof ext !== "object") continue;
|
|
44
|
+
const e = ext;
|
|
45
|
+
widthPt = emuToPt(num(e["@_cx"]) ?? 0);
|
|
46
|
+
heightPt = emuToPt(num(e["@_cy"]) ?? 0);
|
|
47
|
+
}
|
|
48
|
+
if (widthPt <= 0 || heightPt <= 0) continue;
|
|
49
|
+
out.push({
|
|
50
|
+
chartPartPath: resolved.path,
|
|
51
|
+
widthPt,
|
|
52
|
+
heightPt,
|
|
53
|
+
anchorRow: from?.row ?? 0
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return out.sort((x, y) => x.anchorRow - y.anchorRow);
|
|
57
|
+
}
|
|
58
|
+
function chartRelIdOf(anchor) {
|
|
59
|
+
const frame = anchor["graphicFrame"];
|
|
60
|
+
if (!frame || typeof frame !== "object") return void 0;
|
|
61
|
+
const graphic = frame["graphic"];
|
|
62
|
+
if (!graphic || typeof graphic !== "object") return void 0;
|
|
63
|
+
const data = graphic["graphicData"];
|
|
64
|
+
if (!data || typeof data !== "object") return void 0;
|
|
65
|
+
const d = data;
|
|
66
|
+
if (d["@_uri"] !== CHART_URI) return void 0;
|
|
67
|
+
const chart = d["chart"];
|
|
68
|
+
if (!chart || typeof chart !== "object") return void 0;
|
|
69
|
+
const id = chart["@_id"];
|
|
70
|
+
return typeof id === "string" && id !== "" ? id : void 0;
|
|
71
|
+
}
|
|
72
|
+
function cellMarker(node) {
|
|
73
|
+
if (!node || typeof node !== "object") return void 0;
|
|
74
|
+
const m = node;
|
|
75
|
+
const col = num(m["col"]);
|
|
76
|
+
const row = num(m["row"]);
|
|
77
|
+
if (col === void 0 || row === void 0) return void 0;
|
|
78
|
+
return {
|
|
79
|
+
col,
|
|
80
|
+
row,
|
|
81
|
+
colOffPt: emuToPt(num(m["colOff"]) ?? 0),
|
|
82
|
+
rowOffPt: emuToPt(num(m["rowOff"]) ?? 0)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function spanPt(from, fromOffPt, to, toOffPt, trackPt) {
|
|
86
|
+
let span = 0;
|
|
87
|
+
for (let i = from; i < to; i++) span += trackPt(i);
|
|
88
|
+
return span - fromOffPt + toOffPt;
|
|
89
|
+
}
|
|
90
|
+
function makeColWidthPt(ws) {
|
|
91
|
+
return (col) => {
|
|
92
|
+
for (const c of ws.columns) if (col >= c.min - 1 && col <= c.max - 1) return c.widthChars * 105 / TWIPS_PER_PT;
|
|
93
|
+
return 960 / TWIPS_PER_PT;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function makeRowHeightPt(ws) {
|
|
97
|
+
return (row) => {
|
|
98
|
+
for (const r of ws.rowHeights) if (r.row === row) return r.heightPt;
|
|
99
|
+
return 300 / TWIPS_PER_PT;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function num(v) {
|
|
103
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
104
|
+
if (typeof v === "string" && v !== "") {
|
|
105
|
+
const n = Number(v);
|
|
106
|
+
if (Number.isFinite(n)) return n;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function asArray(v) {
|
|
110
|
+
return Array.isArray(v) ? v : v !== void 0 ? [v] : [];
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { parseSheetDrawing };
|
|
@@ -56,5 +56,6 @@ export interface ParsedWorksheet {
|
|
|
56
56
|
readonly printOptions?: XlsxPrintOptions;
|
|
57
57
|
readonly rowBreaks?: ReadonlyArray<number>;
|
|
58
58
|
readonly colBreaks?: ReadonlyArray<number>;
|
|
59
|
+
readonly drawingRelId?: string;
|
|
59
60
|
}
|
|
60
61
|
export declare function parseWorksheet(data: Uint8Array): ParsedWorksheet;
|
|
@@ -32,13 +32,16 @@ function parseWorksheet(data) {
|
|
|
32
32
|
const printOptions = parsePrintOptions(wsObj);
|
|
33
33
|
const rowBreaks = parseBreaks(wsObj, "rowBreaks");
|
|
34
34
|
const colBreaks = parseBreaks(wsObj, "colBreaks");
|
|
35
|
+
const drawingNode = wsObj["drawing"];
|
|
36
|
+
const drawingRelId = drawingNode && typeof drawingNode === "object" ? strAttr(drawingNode, "id") : void 0;
|
|
35
37
|
const printModel = {
|
|
36
38
|
...pageMargins ? { pageMargins } : {},
|
|
37
39
|
...pageSetup ? { pageSetup } : {},
|
|
38
40
|
...fitToPage ? { fitToPage } : {},
|
|
39
41
|
...printOptions ? { printOptions } : {},
|
|
40
42
|
...rowBreaks.length > 0 ? { rowBreaks } : {},
|
|
41
|
-
...colBreaks.length > 0 ? { colBreaks } : {}
|
|
43
|
+
...colBreaks.length > 0 ? { colBreaks } : {},
|
|
44
|
+
...drawingRelId !== void 0 ? { drawingRelId } : {}
|
|
42
45
|
};
|
|
43
46
|
const sheetData = wsObj["sheetData"];
|
|
44
47
|
if (!sheetData || typeof sheetData !== "object") return {
|