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.
- package/dist/esm/core/bidi/segments.js +1 -2
- package/dist/esm/core/converter/facade.d.ts +5 -0
- package/dist/esm/core/converter/project.js +5 -1
- package/dist/esm/core/converter/ream.d.ts +6 -0
- package/dist/esm/core/converter/ream.js +34 -8
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +659 -7
- package/dist/esm/core/drawingml/chart-geometry.d.ts +34 -10
- package/dist/esm/core/drawingml/chart-geometry.js +424 -92
- package/dist/esm/core/drawingml/chart-parser.js +301 -11
- package/dist/esm/core/drawingml/colors.d.ts +7 -7
- package/dist/esm/core/drawingml/colors.js +84 -18
- package/dist/esm/core/drawingml/preset-geometry.js +240 -6
- 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/sparkline-geometry.js +6 -4
- package/dist/esm/core/drawingml/theme-parser.d.ts +51 -0
- package/dist/esm/core/drawingml/theme-parser.js +92 -1
- package/dist/esm/core/font/measure.d.ts +5 -0
- package/dist/esm/core/font/measure.js +21 -1
- package/dist/esm/core/font/ttf-subset.js +26 -1
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +353 -43
- package/dist/esm/core/indexed-colors.d.ts +11 -0
- package/dist/esm/core/indexed-colors.js +81 -0
- package/dist/esm/core/ir/flow.d.ts +23 -1
- package/dist/esm/core/ir/sheet.d.ts +61 -0
- package/dist/esm/{excel → core}/number-format.d.ts +37 -0
- package/dist/esm/core/number-format.js +800 -0
- 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/opc/alternate-content.d.ts +13 -0
- package/dist/esm/core/opc/alternate-content.js +72 -0
- package/dist/esm/core/opc/core-properties.js +1 -0
- package/dist/esm/core/opc/package.d.ts +14 -1
- package/dist/esm/core/opc/package.js +43 -4
- package/dist/esm/core/opc/relationships.js +1 -0
- package/dist/esm/core/opc/xml-entities.d.ts +12 -0
- package/dist/esm/core/opc/xml-entities.js +91 -0
- package/dist/esm/core/po-helpers.js +16 -1
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +137 -0
- 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 +30 -0
- package/dist/esm/excel/activex-parser.js +1 -0
- package/dist/esm/excel/column-bands.d.ts +26 -1
- package/dist/esm/excel/column-bands.js +156 -20
- package/dist/esm/excel/comments-parser.js +5 -3
- package/dist/esm/excel/conditional-format.d.ts +25 -2
- package/dist/esm/excel/conditional-format.js +63 -19
- package/dist/esm/excel/escaped-text.d.ts +9 -0
- package/dist/esm/excel/escaped-text.js +20 -0
- package/dist/esm/excel/form-control-parser.js +1 -0
- package/dist/esm/excel/formula/dates.js +1 -1
- package/dist/esm/excel/header-footer.d.ts +9 -1
- package/dist/esm/excel/header-footer.js +162 -14
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/index.js +2 -2
- package/dist/esm/excel/pivot-table-parser.js +1 -0
- package/dist/esm/excel/print-model.d.ts +75 -0
- package/dist/esm/excel/print-model.js +899 -77
- package/dist/esm/excel/printer-settings.d.ts +16 -0
- package/dist/esm/excel/printer-settings.js +36 -0
- package/dist/esm/excel/rich-value.d.ts +13 -0
- package/dist/esm/excel/rich-value.js +120 -0
- package/dist/esm/excel/shared-strings-parser.js +11 -7
- package/dist/esm/excel/sheet-drawing.d.ts +11 -0
- package/dist/esm/excel/sheet-drawing.js +26 -3
- package/dist/esm/excel/sheet-shape-parser.d.ts +53 -1
- package/dist/esm/excel/sheet-shape-parser.js +461 -32
- package/dist/esm/excel/sheet-to-flow.d.ts +23 -2
- package/dist/esm/excel/sheet-to-flow.js +553 -36
- package/dist/esm/excel/slicer-parser.js +1 -0
- package/dist/esm/excel/styles-parser.d.ts +30 -2
- package/dist/esm/excel/styles-parser.js +177 -40
- package/dist/esm/excel/table-parser.js +1 -0
- package/dist/esm/excel/vml-drawing.d.ts +68 -0
- package/dist/esm/excel/vml-drawing.js +158 -0
- package/dist/esm/excel/workbook-parser.d.ts +5 -0
- package/dist/esm/excel/workbook-parser.js +5 -1
- package/dist/esm/excel/worksheet-parser.d.ts +2 -1
- package/dist/esm/excel/worksheet-parser.js +150 -61
- package/dist/esm/excel/xlsx-reader.js +242 -11
- package/dist/esm/excel/xlsx-to-pdf.js +12 -1
- package/dist/esm/html/html-writer.js +29 -6
- package/dist/esm/layout/page-doc.d.ts +87 -1
- package/dist/esm/layout/styled-layout.d.ts +46 -2
- package/dist/esm/layout/styled-layout.js +2345 -274
- package/dist/esm/pdf/cid-font.js +20 -9
- package/dist/esm/pdf/objects.d.ts +13 -0
- package/dist/esm/pdf/objects.js +18 -1
- package/dist/esm/pdf/shading.js +76 -6
- package/dist/esm/pdf/styled-page-emitter.js +355 -49
- package/dist/esm/pdf/text-page-renderer.js +1 -0
- package/dist/esm/pdf/vector-graphics.d.ts +31 -2
- package/dist/esm/pdf/vector-graphics.js +103 -3
- package/dist/esm/pptx/pptx-reader.js +2 -0
- package/dist/esm/pptx/slide-parser.d.ts +21 -4
- package/dist/esm/pptx/slide-parser.js +98 -24
- package/dist/esm/svg/svg-writer.js +23 -4
- package/dist/esm/word/document-parser.d.ts +96 -7
- package/dist/esm/word/document-parser.js +538 -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 +86 -5
- package/dist/esm/word/drawing-parser.js +1590 -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 +108 -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 +32 -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 +9 -2
- package/dist/esm/word/table-parser.d.ts +9 -1
- package/dist/esm/word/table-parser.js +182 -30
- package/package.json +7 -3
- package/dist/esm/excel/number-format.js +0 -476
|
@@ -10,12 +10,84 @@ import "../core/vector.js";
|
|
|
10
10
|
* @param patternName When set, the fill is this named shading pattern from the
|
|
11
11
|
* page's `/Pattern` resources (a gradient, EP16b) rather than a solid colour;
|
|
12
12
|
* only used if the shape actually carries a `fillGradient`.
|
|
13
|
+
* @param alphaStateName When set, the shape's shadow is drawn first, under this
|
|
14
|
+
* named `/ExtGState` (its constant alpha) from the page's resources.
|
|
13
15
|
* @returns The content-stream operator lines.
|
|
14
16
|
*/
|
|
15
|
-
|
|
17
|
+
/**
|
|
18
|
+
* §20.1.8.40 `blurRad` — how a blurred shadow is drawn: as `count` copies of
|
|
19
|
+
* the silhouette, each at `alpha` transparency, growing through the blur's
|
|
20
|
+
* width. Shared with the emitter that registers the /ExtGState for it, so the
|
|
21
|
+
* alpha it registers is the one the layers are drawn at.
|
|
22
|
+
*
|
|
23
|
+
* @param shadow The shadow (its `blurPt` and `alpha` are read).
|
|
24
|
+
* @returns The number of layers and the transparency of each.
|
|
25
|
+
*/
|
|
26
|
+
function shadowBlurLayers(shadow) {
|
|
27
|
+
if (!(shadow.blurPt > 0)) return {
|
|
28
|
+
count: 1,
|
|
29
|
+
alpha: shadow.alpha
|
|
30
|
+
};
|
|
31
|
+
const count = Math.min(8, Math.max(2, Math.round(shadow.blurPt / 2)));
|
|
32
|
+
return {
|
|
33
|
+
count,
|
|
34
|
+
alpha: shadow.alpha / count
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function shadowBbox(shape) {
|
|
38
|
+
let minX = Infinity;
|
|
39
|
+
let minY = Infinity;
|
|
40
|
+
let maxX = -Infinity;
|
|
41
|
+
let maxY = -Infinity;
|
|
42
|
+
for (const path of shape.paths) for (const seg of path.segments) {
|
|
43
|
+
if (seg.op === "close") continue;
|
|
44
|
+
minX = Math.min(minX, seg.x);
|
|
45
|
+
minY = Math.min(minY, seg.y);
|
|
46
|
+
maxX = Math.max(maxX, seg.x);
|
|
47
|
+
maxY = Math.max(maxY, seg.y);
|
|
48
|
+
}
|
|
49
|
+
return Number.isFinite(minX) && maxX > minX && maxY > minY ? {
|
|
50
|
+
minX,
|
|
51
|
+
minY,
|
|
52
|
+
maxX,
|
|
53
|
+
maxY
|
|
54
|
+
} : void 0;
|
|
55
|
+
}
|
|
56
|
+
function emitVectorShape(shape, patternName, alphaStateName) {
|
|
16
57
|
const out = [];
|
|
17
|
-
out.push("q");
|
|
18
58
|
const [a, b, c, d, e, f] = shape.transform;
|
|
59
|
+
const shadow = shape.shadow;
|
|
60
|
+
if (shadow) {
|
|
61
|
+
const [sr, sg, sb] = hexToRgb01(shadow.colorHex);
|
|
62
|
+
const bbox = shadowBbox(shape);
|
|
63
|
+
const scale = Math.sqrt(Math.abs(a * d - b * c)) || 1;
|
|
64
|
+
const { count } = shadowBlurLayers(shadow);
|
|
65
|
+
for (let i = 0; i < count; i++) {
|
|
66
|
+
out.push("q");
|
|
67
|
+
if (alphaStateName !== void 0) out.push(`/${alphaStateName} gs`);
|
|
68
|
+
out.push(`${num(a)} ${num(b)} ${num(c)} ${num(d)} ${num(e + shadow.dxPt)} ${num(f - shadow.dyPt)} cm`);
|
|
69
|
+
if (count > 1 && bbox) {
|
|
70
|
+
const local = shadow.blurPt / scale;
|
|
71
|
+
const grow = -local / 2 + (i + .5) * local / count;
|
|
72
|
+
const halfW = Math.max((bbox.maxX - bbox.minX) / 2, 1e-6);
|
|
73
|
+
const halfH = Math.max((bbox.maxY - bbox.minY) / 2, 1e-6);
|
|
74
|
+
const cx = (bbox.minX + bbox.maxX) / 2;
|
|
75
|
+
const cy = (bbox.minY + bbox.maxY) / 2;
|
|
76
|
+
const sx = Math.max((halfW + grow) / halfW, 0);
|
|
77
|
+
const sy = Math.max((halfH + grow) / halfH, 0);
|
|
78
|
+
out.push(`${num(sx)} 0 0 ${num(sy)} ${num(cx * (1 - sx))} ${num(cy * (1 - sy))} cm`);
|
|
79
|
+
}
|
|
80
|
+
out.push(`${num(sr)} ${num(sg)} ${num(sb)} rg`);
|
|
81
|
+
let shadowEvenodd = false;
|
|
82
|
+
for (const path of shape.paths) {
|
|
83
|
+
if (path.fillRule === "evenodd") shadowEvenodd = true;
|
|
84
|
+
for (const seg of path.segments) out.push(emitSegment(seg));
|
|
85
|
+
}
|
|
86
|
+
out.push(shadowEvenodd ? "f*" : "f");
|
|
87
|
+
out.push("Q");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
out.push("q");
|
|
19
91
|
out.push(`${num(a)} ${num(b)} ${num(c)} ${num(d)} ${num(e)} ${num(f)} cm`);
|
|
20
92
|
const stroke = shape.stroke;
|
|
21
93
|
if (stroke) {
|
|
@@ -41,6 +113,34 @@ function emitVectorShape(shape, patternName) {
|
|
|
41
113
|
out.push("Q");
|
|
42
114
|
return out;
|
|
43
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* The operators that make `paths` the current CLIP, under `transform` — the
|
|
118
|
+
* same local→y-up-page matrix {@link emitVectorShape} takes. Emitted inside the
|
|
119
|
+
* caller's own `q`…`Q`, and followed by the inverse matrix so what comes after
|
|
120
|
+
* is back in page coordinates.
|
|
121
|
+
*
|
|
122
|
+
* @param paths The clip outline, in the shape's local frame.
|
|
123
|
+
* @param transform The local→page matrix.
|
|
124
|
+
* @returns The operators: `cm`, the path, `W n`, and the inverse `cm`.
|
|
125
|
+
*/
|
|
126
|
+
function emitClipPath(paths, transform) {
|
|
127
|
+
const [a, b, c, d, e, f] = transform;
|
|
128
|
+
const det = a * d - b * c;
|
|
129
|
+
if (det === 0) return [];
|
|
130
|
+
const out = [`${num(a)} ${num(b)} ${num(c)} ${num(d)} ${num(e)} ${num(f)} cm`];
|
|
131
|
+
let evenodd = false;
|
|
132
|
+
for (const path of paths) {
|
|
133
|
+
if (path.fillRule === "evenodd") evenodd = true;
|
|
134
|
+
for (const seg of path.segments) out.push(emitSegment(seg));
|
|
135
|
+
}
|
|
136
|
+
out.push(evenodd ? "W* n" : "W n");
|
|
137
|
+
const ia = d / det;
|
|
138
|
+
const ib = -b / det;
|
|
139
|
+
const ic = -c / det;
|
|
140
|
+
const id = a / det;
|
|
141
|
+
out.push(`${num(ia)} ${num(ib)} ${num(ic)} ${num(id)} ${num(-(e * ia + f * ic))} ${num(-(e * ib + f * id))} cm`);
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
44
144
|
function emitSegment(seg) {
|
|
45
145
|
switch (seg.op) {
|
|
46
146
|
case "move": return `${num(seg.x)} ${num(seg.y)} m`;
|
|
@@ -70,4 +170,4 @@ function hexToRgb01(hex) {
|
|
|
70
170
|
];
|
|
71
171
|
}
|
|
72
172
|
//#endregion
|
|
73
|
-
export { emitVectorShape };
|
|
173
|
+
export { emitClipPath, emitVectorShape, shadowBlurLayers };
|
|
@@ -19,8 +19,10 @@ var DEFAULT_CX = 9144e3;
|
|
|
19
19
|
var DEFAULT_CY = 6858e3;
|
|
20
20
|
var decoder = new TextDecoder();
|
|
21
21
|
var parser = new XMLParser({
|
|
22
|
+
htmlEntities: true,
|
|
22
23
|
ignoreAttributes: false,
|
|
23
24
|
attributeNamePrefix: "@_",
|
|
25
|
+
maxNestedTags: 1e3,
|
|
24
26
|
preserveOrder: true,
|
|
25
27
|
parseAttributeValue: false,
|
|
26
28
|
parseTagValue: false,
|
|
@@ -73,16 +73,33 @@ export declare function diagramTransform(spTree: PoNode, frame: ShapeBoxEmu): Gr
|
|
|
73
73
|
* @param where Optional location tag for the loss report (e.g. `slide 3`).
|
|
74
74
|
*/
|
|
75
75
|
export declare function noDiagramOverrideLoss(where?: string): Loss;
|
|
76
|
+
/** One SmartArt node: the box it occupies in the target space, and its shape. */
|
|
77
|
+
export interface DiagramNode {
|
|
78
|
+
readonly box: ShapeBoxEmu;
|
|
79
|
+
readonly shape: ShapeBlock;
|
|
80
|
+
}
|
|
76
81
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
82
|
+
* Read a SmartArt drawing override (a `dsp:spTree`) into its nodes. The `dsp:`
|
|
83
|
+
* wrapper holds an ordinary `a:` `spPr`/`txBody`, so the shared DrawingML
|
|
79
84
|
* readers apply unchanged. Shared by pptx and docx (E-SMARTART); diagrams carry
|
|
80
85
|
* no placeholder cascade.
|
|
81
86
|
*
|
|
87
|
+
* @param spTree The diagram drawing's `dsp:spTree`.
|
|
88
|
+
* @param transform Maps each shape's diagram-space box to the target space.
|
|
89
|
+
* @param colors The colour resolver for the shapes' fills/strokes/text.
|
|
90
|
+
* @param resolveLink A run hyperlink resolver, or `undefined`.
|
|
91
|
+
* @param resolveImage Resolves a picture fill's `r:embed` against the DRAWING
|
|
92
|
+
* part's own relationships, or `undefined`.
|
|
93
|
+
* @returns The diagram's visible nodes, in drawing order.
|
|
94
|
+
*/
|
|
95
|
+
export declare function parseDiagramNodes(spTree: PoNode, transform: GroupTransform, colors: ColorResolver, resolveLink: LinkResolver, resolveImage?: (relId: string) => ResourceId | undefined): Array<DiagramNode>;
|
|
96
|
+
/**
|
|
97
|
+
* The same nodes as free-standing floating shapes — what a slide wants, where
|
|
98
|
+
* every shape is anchored to the page.
|
|
99
|
+
*
|
|
82
100
|
* @param spTree The diagram drawing's `dsp:spTree`.
|
|
83
101
|
* @param transform Maps each shape's diagram-space box to the target space.
|
|
84
|
-
* @param makeFloat Anchors a box
|
|
85
|
-
* relative for an inline docx diagram.
|
|
102
|
+
* @param makeFloat Anchors a node's box.
|
|
86
103
|
* @param colors The colour resolver for the shapes' fills/strokes/text.
|
|
87
104
|
* @param resolveLink A run hyperlink resolver, or `undefined`.
|
|
88
105
|
* @returns The diagram's visible shapes as positioned {@link ShapeBlock}s.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { emuToPt } from "../core/ir/units.js";
|
|
1
|
+
import { emuToPt, pt } from "../core/ir/units.js";
|
|
2
2
|
import { FEATURES } from "../core/ir/features.js";
|
|
3
|
-
import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poText } from "../core/po-helpers.js";
|
|
3
|
+
import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poTag, poText } from "../core/po-helpers.js";
|
|
4
4
|
import { defaultColorResolver, resolveColorNode } from "../core/drawingml/colors.js";
|
|
5
5
|
import { boxFromXfrm, parsePh, parseXfrmBox, rPrToRunProps } from "./sp-helpers.js";
|
|
6
|
-
import { parseCustGeom, parseFill, parseLine, parsePrstGeom } from "../word/drawing-parser.js";
|
|
6
|
+
import { parseCustGeom, parseFill, parseLine, parsePrstGeom, parseShadow, parseXfrm } from "../word/drawing-parser.js";
|
|
7
7
|
//#region src/pptx/slide-parser.ts
|
|
8
8
|
var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
|
|
9
9
|
var TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
|
|
@@ -206,20 +206,20 @@ function noDiagramOverrideLoss(where) {
|
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
208
|
/**
|
|
209
|
-
*
|
|
210
|
-
*
|
|
209
|
+
* Read a SmartArt drawing override (a `dsp:spTree`) into its nodes. The `dsp:`
|
|
210
|
+
* wrapper holds an ordinary `a:` `spPr`/`txBody`, so the shared DrawingML
|
|
211
211
|
* readers apply unchanged. Shared by pptx and docx (E-SMARTART); diagrams carry
|
|
212
212
|
* no placeholder cascade.
|
|
213
213
|
*
|
|
214
|
-
* @param spTree
|
|
215
|
-
* @param transform
|
|
216
|
-
* @param
|
|
217
|
-
*
|
|
218
|
-
* @param
|
|
219
|
-
*
|
|
220
|
-
* @returns The diagram's visible
|
|
214
|
+
* @param spTree The diagram drawing's `dsp:spTree`.
|
|
215
|
+
* @param transform Maps each shape's diagram-space box to the target space.
|
|
216
|
+
* @param colors The colour resolver for the shapes' fills/strokes/text.
|
|
217
|
+
* @param resolveLink A run hyperlink resolver, or `undefined`.
|
|
218
|
+
* @param resolveImage Resolves a picture fill's `r:embed` against the DRAWING
|
|
219
|
+
* part's own relationships, or `undefined`.
|
|
220
|
+
* @returns The diagram's visible nodes, in drawing order.
|
|
221
221
|
*/
|
|
222
|
-
function
|
|
222
|
+
function parseDiagramNodes(spTree, transform, colors, resolveLink, resolveImage) {
|
|
223
223
|
const out = [];
|
|
224
224
|
for (const sp of poChildren(spTree)) {
|
|
225
225
|
if (!poIs(sp, "dsp:sp")) continue;
|
|
@@ -228,26 +228,89 @@ function parseDiagramDrawing(spTree, transform, makeFloat, colors, resolveLink)
|
|
|
228
228
|
if (!own) continue;
|
|
229
229
|
const box = transform(own);
|
|
230
230
|
const txBody = poChildren(sp).find((c) => poIs(c, "dsp:txBody"));
|
|
231
|
-
const
|
|
231
|
+
const parsed = txBody ? parseTxBody(txBody, void 0, void 0, colors, resolveLink) : void 0;
|
|
232
|
+
const text = parsed ? withDiagramFontColor(parsed, sp, colors) : void 0;
|
|
232
233
|
const geometry = parseGeometry(spPr);
|
|
233
|
-
const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
|
|
234
|
+
const fill = spPr ? parseFill(spPr, colors, resolveImage) : { kind: "none" };
|
|
234
235
|
const line = spPr ? parseLine(spPr, colors) : void 0;
|
|
236
|
+
const shadow = spPr ? parseShadow(spPr, colors) : void 0;
|
|
235
237
|
const visibleLine = line !== void 0 && line.fill !== "none";
|
|
236
238
|
if (!text && fill.kind === "none" && !visibleLine) continue;
|
|
239
|
+
const xfrm = spPr ? poChildren(spPr).find((c) => poIs(c, "a:xfrm")) : void 0;
|
|
240
|
+
const spin = xfrm ? parseXfrm(xfrm) : void 0;
|
|
241
|
+
const txBox = (spin?.rotation60k ?? 0) % 216e5 !== 0 ? boxFromXfrm(poChildren(sp).find((c) => poIs(c, "dsp:txXfrm"))) : void 0;
|
|
237
242
|
out.push({
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
box,
|
|
244
|
+
shape: {
|
|
245
|
+
width: emuToPt(box.cx),
|
|
246
|
+
height: emuToPt(box.cy),
|
|
247
|
+
geometry,
|
|
248
|
+
fill,
|
|
249
|
+
...line ? { line } : {},
|
|
250
|
+
...text && !txBox ? { text } : {},
|
|
251
|
+
...spin && Object.keys(spin).length > 0 ? { transform: spin } : {},
|
|
252
|
+
...shadow ? { shadow } : {},
|
|
253
|
+
paragraphProperties: {}
|
|
254
|
+
}
|
|
246
255
|
});
|
|
256
|
+
if (text && txBox) {
|
|
257
|
+
const placed = transform(txBox);
|
|
258
|
+
out.push({
|
|
259
|
+
box: placed,
|
|
260
|
+
shape: {
|
|
261
|
+
width: emuToPt(placed.cx),
|
|
262
|
+
height: emuToPt(placed.cy),
|
|
263
|
+
geometry: RECT_GEOMETRY,
|
|
264
|
+
fill: { kind: "none" },
|
|
265
|
+
text,
|
|
266
|
+
paragraphProperties: {}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
247
270
|
}
|
|
248
271
|
return out;
|
|
249
272
|
}
|
|
250
273
|
/**
|
|
274
|
+
* The same nodes as free-standing floating shapes — what a slide wants, where
|
|
275
|
+
* every shape is anchored to the page.
|
|
276
|
+
*
|
|
277
|
+
* @param spTree The diagram drawing's `dsp:spTree`.
|
|
278
|
+
* @param transform Maps each shape's diagram-space box to the target space.
|
|
279
|
+
* @param makeFloat Anchors a node's box.
|
|
280
|
+
* @param colors The colour resolver for the shapes' fills/strokes/text.
|
|
281
|
+
* @param resolveLink A run hyperlink resolver, or `undefined`.
|
|
282
|
+
* @returns The diagram's visible shapes as positioned {@link ShapeBlock}s.
|
|
283
|
+
*/
|
|
284
|
+
function parseDiagramDrawing(spTree, transform, makeFloat, colors, resolveLink) {
|
|
285
|
+
return parseDiagramNodes(spTree, transform, colors, resolveLink).map(({ box, shape }) => ({
|
|
286
|
+
...shape,
|
|
287
|
+
float: makeFloat(box)
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
function withDiagramFontColor(text, sp, colors) {
|
|
291
|
+
const style = poChildren(sp).find((c) => poIs(c, "dsp:style"));
|
|
292
|
+
const ref = style ? poChildren(style).find((c) => poIs(c, "a:fontRef")) : void 0;
|
|
293
|
+
const child = ref ? poChildren(ref).find((c) => poTag(c) !== void 0) : void 0;
|
|
294
|
+
const colorHex = child ? resolveColorNode(child, colors) : void 0;
|
|
295
|
+
if (colorHex === void 0) return text;
|
|
296
|
+
return {
|
|
297
|
+
...text,
|
|
298
|
+
content: text.content.map((block) => block.kind === "paragraph" ? {
|
|
299
|
+
...block,
|
|
300
|
+
paragraph: {
|
|
301
|
+
...block.paragraph,
|
|
302
|
+
runs: block.paragraph.runs.map((run) => run.properties.colorHex === void 0 ? {
|
|
303
|
+
...run,
|
|
304
|
+
properties: {
|
|
305
|
+
...run.properties,
|
|
306
|
+
colorHex
|
|
307
|
+
}
|
|
308
|
+
} : run)
|
|
309
|
+
}
|
|
310
|
+
} : block)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
251
314
|
* `p:bg` → the background fill, or `undefined` when none/unsupported. `p:bgPr`
|
|
252
315
|
* carries the fill directly (`a:solidFill`/`a:gradFill` — the same children
|
|
253
316
|
* `parseFill` reads; a picture background is not yet supported); `p:bgRef` (a
|
|
@@ -400,6 +463,17 @@ function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters) {
|
|
|
400
463
|
const run = parseSlideRun(child, defaults, colors, resolveLink);
|
|
401
464
|
if (run) runs.push(run);
|
|
402
465
|
}
|
|
466
|
+
if (runs.length === 0) {
|
|
467
|
+
const endRPr = poChildren(aP).find((c) => poIs(c, "a:endParaRPr"));
|
|
468
|
+
const sz = endRPr ? poIntAttr(endRPr, "sz") : void 0;
|
|
469
|
+
if (sz !== void 0 && sz > 0) runs.push({
|
|
470
|
+
text: "",
|
|
471
|
+
properties: {
|
|
472
|
+
...defaults,
|
|
473
|
+
fontSizePt: pt(sz / 100)
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
}
|
|
403
477
|
const marL = pPr ? poIntAttr(pPr, "marL") : void 0;
|
|
404
478
|
const indent = pPr ? poIntAttr(pPr, "indent") : void 0;
|
|
405
479
|
const indentLeft = marL !== void 0 ? emuToPt(marL) : level > 0 ? emuToPt(level * 457200) : void 0;
|
|
@@ -502,4 +576,4 @@ function cellFillHex(tcPr, colors) {
|
|
|
502
576
|
}
|
|
503
577
|
}
|
|
504
578
|
//#endregion
|
|
505
|
-
export { backdropElement, diagramTransform, noDiagramOverrideLoss, parseBackgroundFill,
|
|
579
|
+
export { backdropElement, diagramTransform, noDiagramOverrideLoss, parseBackgroundFill, parseDiagramNodes, parseGeometry, parseSlideShapes, parseTxBody };
|
|
@@ -87,14 +87,20 @@ function emitPage(out, page, laid, losses, idc) {
|
|
|
87
87
|
x2,
|
|
88
88
|
yBottom
|
|
89
89
|
];
|
|
90
|
-
out.push(`<line x1="${fmt(ax)}" y1="${fmt(ay)}" x2="${fmt(bx)}" y2="${fmt(by)}" stroke="#${b.borderColorHex}" stroke-width="${fmt(b.borderSizePt)}"/>`);
|
|
90
|
+
out.push(`<line x1="${fmt(ax)}" y1="${fmt(ay)}" x2="${fmt(bx)}" y2="${fmt(by)}" stroke="#${b.borderColorHex}" stroke-width="${fmt(b.borderSizePt)}"${b.borderStyle === "dashed" ? " stroke-dasharray=\"8 2.5\"" : b.borderStyle === "dashSmallGap" ? " stroke-dasharray=\"3 1\"" : b.borderStyle === "dotted" ? " stroke-dasharray=\"0.5 1\"" : ""}/>`);
|
|
91
91
|
}
|
|
92
92
|
for (const sh of plan.shapes) emitShape(out, sh.shape, idc);
|
|
93
|
-
for (const t of plan.lines) emitTextLine(out, t, losses);
|
|
93
|
+
for (const t of plan.lines) emitTextLine(out, t, losses, idc);
|
|
94
94
|
}
|
|
95
|
-
function emitTextLine(out, item, losses) {
|
|
95
|
+
function emitTextLine(out, item, losses, idc) {
|
|
96
|
+
const clip = item.clip;
|
|
97
|
+
if (clip) {
|
|
98
|
+
const id = `clip${idc.n++}`;
|
|
99
|
+
out.push(`<clipPath id="${id}"><rect x="${fmt(clip.x)}" y="${fmt(clip.y)}" width="${fmt(clip.width)}" height="${fmt(clip.height)}"/></clipPath>`, `<g clip-path="url(#${id})">`);
|
|
100
|
+
}
|
|
96
101
|
const y = item.baselineY;
|
|
97
102
|
let x = item.originX;
|
|
103
|
+
const rot = item.rotationDeg ? ` transform="rotate(${fmt(-item.rotationDeg)} ${fmt(item.originX)} ${fmt(item.baselineY)})"` : "";
|
|
98
104
|
for (const tok of item.line.tokens) {
|
|
99
105
|
if (tok.kind === "image") {
|
|
100
106
|
x += tok.widthPt;
|
|
@@ -109,9 +115,10 @@ function emitTextLine(out, item, losses) {
|
|
|
109
115
|
x += tok.widthPt;
|
|
110
116
|
continue;
|
|
111
117
|
}
|
|
112
|
-
if (tok.text.trim().length > 0) out.push(`<text x="${fmt(x)}" y="${fmt(y)}" font-family="sans-serif" font-size="${fmt(tok.fontSizePt)}" fill="#${tok.resolvedRun.colorHex}">${escapeXml(tok.text)}</text>`);
|
|
118
|
+
if (tok.text.trim().length > 0) out.push(`<text x="${fmt(x)}" y="${fmt(y)}"${rot} font-family="sans-serif" font-size="${fmt(tok.fontSizePt)}" fill="#${tok.resolvedRun.colorHex}">${escapeXml(tok.text)}</text>`);
|
|
113
119
|
x += tok.widthPt;
|
|
114
120
|
}
|
|
121
|
+
if (clip) out.push("</g>");
|
|
115
122
|
}
|
|
116
123
|
function emitShape(out, shape, idc) {
|
|
117
124
|
const [a, b, c, d, e, f] = shape.transform;
|
|
@@ -123,6 +130,18 @@ function emitShape(out, shape, idc) {
|
|
|
123
130
|
fill = `url(#${id})`;
|
|
124
131
|
} else fill = shape.fillColorHex ? `#${shape.fillColorHex}` : "none";
|
|
125
132
|
const stroke = shape.stroke ? ` stroke="#${shape.stroke.colorHex}" stroke-width="${fmt(shape.stroke.widthPt)}"` : "";
|
|
133
|
+
const shadow = shape.shadow;
|
|
134
|
+
if (shadow) {
|
|
135
|
+
const id = `shadow${idc.n++}`;
|
|
136
|
+
if (shadow.blurPt > 0) out.push(`<filter id="${id}" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="${fmt(shadow.blurPt / 2)}"/></filter>`);
|
|
137
|
+
const shTransform = `matrix(${fmt(a)} ${fmt(b)} ${fmt(c)} ${fmt(d)} ${fmt(e + shadow.dxPt)} ${fmt(f + shadow.dyPt)})`;
|
|
138
|
+
out.push(`<g opacity="${fmt(shadow.alpha)}"${shadow.blurPt > 0 ? ` filter="url(#${id})"` : ""}>`);
|
|
139
|
+
for (const path of shape.paths) {
|
|
140
|
+
const rule = path.fillRule === "evenodd" ? " fill-rule=\"evenodd\"" : "";
|
|
141
|
+
out.push(`<path d="${pathData(path.segments)}" fill="#${shadow.colorHex}"${rule} transform="${shTransform}"/>`);
|
|
142
|
+
}
|
|
143
|
+
out.push("</g>");
|
|
144
|
+
}
|
|
126
145
|
for (const path of shape.paths) {
|
|
127
146
|
const d2 = pathData(path.segments);
|
|
128
147
|
const rule = path.fillRule === "evenodd" ? " fill-rule=\"evenodd\"" : "";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { BodyElement, Comment, Section, SectionProperties } from '../core/document-model/index.js';
|
|
1
|
+
import { BodyElement, Comment, RunProperties, Section, SectionProperties, ShapeFill } from '../core/document-model/index.js';
|
|
2
2
|
import { ColorResolver } from '../core/drawingml/colors.js';
|
|
3
3
|
import { Loss, ResourceId } from '../core/ir/index.js';
|
|
4
4
|
import { PoNode } from '../core/po-helpers.js';
|
|
5
|
+
import { ThemeStyles } from './drawing-parser.js';
|
|
5
6
|
/**
|
|
6
7
|
* Resolves a drawing relationship id to a content-addressed `ResourceId` —
|
|
7
8
|
* supplied by the converter (which owns the OPC package and the `ResourceStore`).
|
|
@@ -9,6 +10,15 @@ import { PoNode } from '../core/po-helpers.js';
|
|
|
9
10
|
export type ImageResolver = (relId: string) => ResourceId | undefined;
|
|
10
11
|
/** Resolves a `w:hyperlink` `r:id` to its external target URL. */
|
|
11
12
|
export type HyperlinkResolver = (relId: string) => string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* A SmartArt diagram's pre-rendered drawing override: its `dsp:spTree`, plus a
|
|
15
|
+
* resolver for the picture fills its nodes name — those relationships belong to
|
|
16
|
+
* the drawing part, not to the part that references the diagram.
|
|
17
|
+
*/
|
|
18
|
+
export interface ResolvedDiagram {
|
|
19
|
+
readonly spTree: PoNode;
|
|
20
|
+
readonly resolveImage?: ImageResolver;
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Document-wide resolvers every nested parser needs — one context object instead
|
|
14
24
|
* of threading a parameter pair through ten signatures (oop-design §8).
|
|
@@ -25,10 +35,28 @@ export interface ParseContext {
|
|
|
25
35
|
readonly resolveHyperlink?: HyperlinkResolver;
|
|
26
36
|
/**
|
|
27
37
|
* SmartArt: a data relationship id (`dgm:relIds` `@r:dm`) → the diagram's
|
|
28
|
-
* pre-rendered drawing override
|
|
29
|
-
*
|
|
38
|
+
* pre-rendered drawing override, or `undefined` when the file ships none
|
|
39
|
+
* (E-SMARTART SA2).
|
|
40
|
+
*/
|
|
41
|
+
readonly resolveDiagram?: (relId: string) => ResolvedDiagram | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* §21.2 a `c:chart` `@r:id` → the chart part's path, the key the reader files
|
|
44
|
+
* parsed charts under. Relationship ids are scoped to their owning part, so a
|
|
45
|
+
* footer's `rId1` and the body's `rId1` are different charts. Absent ⇒ the
|
|
46
|
+
* raw rel id is kept.
|
|
47
|
+
*/
|
|
48
|
+
readonly resolveChartPart?: (relId: string) => string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* §20.1.4.2.19 — the theme's `a:lnStyleLst` widths in points, which a
|
|
51
|
+
* gallery-styled shape's `a:lnRef idx` indexes for its outline weight.
|
|
30
52
|
*/
|
|
31
|
-
readonly
|
|
53
|
+
readonly themeLineWidths?: ReadonlyArray<number>;
|
|
54
|
+
/**
|
|
55
|
+
* §20.1.4.1.14/§20.1.4.1.15 — the theme's format scheme: the fill, background
|
|
56
|
+
* fill and effect styles a `<wps:style>` reference indexes for the fill and
|
|
57
|
+
* the shadow a gallery-drawn shape wears.
|
|
58
|
+
*/
|
|
59
|
+
readonly themeStyles?: ThemeStyles;
|
|
32
60
|
/**
|
|
33
61
|
* Sink for graceful-degradation notices (E-SMARTART SA3): a SmartArt with no
|
|
34
62
|
* drawing override records a dropped-feature {@link Loss} rather than vanishing.
|
|
@@ -41,6 +69,12 @@ export interface ParseContext {
|
|
|
41
69
|
* reference is readonly; its contents mutate during the walk (CM2c).
|
|
42
70
|
*/
|
|
43
71
|
readonly openCommentRanges?: Set<string>;
|
|
72
|
+
/**
|
|
73
|
+
* §17.3.1.1/§17.3.1.3 — what `w:beforeAutospacing`/`w:afterAutospacing`
|
|
74
|
+
* resolve to for THIS document: 14pt when it states no compatibility mode,
|
|
75
|
+
* and nothing (the default) for every Word 2007-or-later one.
|
|
76
|
+
*/
|
|
77
|
+
readonly autoSpacingPt?: number;
|
|
44
78
|
}
|
|
45
79
|
/** The default {@link ParseContext} — just the default colour resolver. */
|
|
46
80
|
export declare const DEFAULT_PARSE_CONTEXT: ParseContext;
|
|
@@ -53,8 +87,55 @@ export declare const DEFAULT_PARSE_CONTEXT: ParseContext;
|
|
|
53
87
|
* @param ctx The document-wide parse context.
|
|
54
88
|
* @returns The body elements; empty when the `w:body` is absent.
|
|
55
89
|
*/
|
|
56
|
-
export declare function parseDocument(documentXml: Uint8Array, ctx?: ParseContext): Array<BodyElement>;
|
|
57
|
-
/**
|
|
90
|
+
export declare function parseDocument(documentXml: Uint8Array, ctx?: ParseContext, blocks?: BlockCounter): Array<BodyElement>;
|
|
91
|
+
/**
|
|
92
|
+
* §17.2.1 `w:background` — the colour the whole page is painted, as a six-digit
|
|
93
|
+
* hex. Read from `@w:color` (Word's own attribute), falling back to the VML
|
|
94
|
+
* `v:background @fillcolor` beside it. `auto` and a gradient-only background
|
|
95
|
+
* (which carries no flat colour of its own) both come back undefined.
|
|
96
|
+
*
|
|
97
|
+
* @param documentXml The raw `document.xml` bytes.
|
|
98
|
+
* @returns The colour, or undefined when the document names none.
|
|
99
|
+
*/
|
|
100
|
+
export declare function parseBackgroundColor(documentXml: Uint8Array): string | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* §17.2.1 — the page background as the FILL it is. `@w:color` is only the flat
|
|
103
|
+
* fallback: the `v:background` beside it carries the gradient or the picture
|
|
104
|
+
* Word actually paints, and both references draw those. fill.docx runs a
|
|
105
|
+
* five-stop radial sweep where we painted its fallback navy, and
|
|
106
|
+
* tdf126533_pageBitmap.docx papers the page with an image.
|
|
107
|
+
*
|
|
108
|
+
* @param documentXml The raw `document.xml` bytes.
|
|
109
|
+
* @param resolveImage Resolver for a picture background's `r:id`.
|
|
110
|
+
* @returns The fill, or undefined when the document names no background.
|
|
111
|
+
*/
|
|
112
|
+
export declare function parseBackgroundFill(documentXml: Uint8Array, resolveImage?: (relId: string) => ResourceId | undefined): ShapeFill | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Lines a parsed body up with anything counted in SOURCE blocks. `index[i]` is
|
|
115
|
+
* the ordinal of the `w:p`/`w:tbl` that produced body element `i`; `next` is the
|
|
116
|
+
* running count. A paragraph carrying anchored drawings produces several
|
|
117
|
+
* elements, so the two counts diverge — and {@link parseSections} counts blocks.
|
|
118
|
+
*/
|
|
119
|
+
export interface BlockCounter {
|
|
120
|
+
readonly index: Array<number>;
|
|
121
|
+
next: number;
|
|
122
|
+
}
|
|
123
|
+
/** A fresh {@link BlockCounter}. */
|
|
124
|
+
export declare function newBlockCounter(): BlockCounter;
|
|
125
|
+
/**
|
|
126
|
+
* Translate a section boundary counted in source blocks into one counted in body
|
|
127
|
+
* elements: the number of elements that came from a block before `blockEnd`.
|
|
128
|
+
*
|
|
129
|
+
* @param blocks The counter filled while parsing the body.
|
|
130
|
+
* @param blockEnd The section's `endIndex`, in source blocks.
|
|
131
|
+
* @returns The matching body-element index.
|
|
132
|
+
*/
|
|
133
|
+
export declare function bodyIndexForBlock(blocks: BlockCounter, blockEnd: number): number;
|
|
134
|
+
/**
|
|
135
|
+
* The empty {@link SectionProperties} fallback (no headers/footers). §17.6.13 —
|
|
136
|
+
* on the page a document with no `w:sectPr` of its own is made on, which is the
|
|
137
|
+
* same US Letter a section with no `w:pgSz` gets.
|
|
138
|
+
*/
|
|
58
139
|
export declare const EMPTY_SECTION: SectionProperties;
|
|
59
140
|
/**
|
|
60
141
|
* Parse the document's final section properties (ECMA-376 Part 1 §17.6.17 — the
|
|
@@ -96,7 +177,15 @@ export declare function parseHeaderFooter(xml: Uint8Array, ctx?: ParseContext):
|
|
|
96
177
|
* @param ctx The document-wide parse context.
|
|
97
178
|
* @returns The parsed body elements.
|
|
98
179
|
*/
|
|
99
|
-
export declare function parseBodyElements(children: ReadonlyArray<PoNode>, ctx?: ParseContext): Array<BodyElement>;
|
|
180
|
+
export declare function parseBodyElements(children: ReadonlyArray<PoNode>, ctx?: ParseContext, blocks?: BlockCounter, sdtRunProps?: RunProperties): Array<BodyElement>;
|
|
181
|
+
/**
|
|
182
|
+
* §17.5.2.28 `w:sdt/w:sdtPr/w:rPr` — the run properties a content control
|
|
183
|
+
* lends what it holds, when it states any.
|
|
184
|
+
*
|
|
185
|
+
* @param sdt The `w:sdt` element.
|
|
186
|
+
* @returns The properties, or `undefined` when the control states none.
|
|
187
|
+
*/
|
|
188
|
+
export declare function sdtRunProperties(sdt: PoNode): RunProperties | undefined;
|
|
100
189
|
/**
|
|
101
190
|
* Parse `footnotes.xml` / `endnotes.xml` (§17.11) into note content by id. The
|
|
102
191
|
* separator / continuationSeparator / continuationNotice stubs (negative ids or
|