reamkit 1.20.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/esm/core/bytes.d.ts +22 -4
  2. package/dist/esm/core/bytes.js +73 -5
  3. package/dist/esm/core/crypto/offcrypto.d.ts +1 -0
  4. package/dist/esm/core/crypto/offcrypto.js +2 -1
  5. package/dist/esm/core/document-model/types.d.ts +60 -0
  6. package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
  7. package/dist/esm/core/drawingml/chart-parser.js +23 -1
  8. package/dist/esm/core/drawingml/colors.d.ts +27 -3
  9. package/dist/esm/core/drawingml/colors.js +30 -6
  10. package/dist/esm/core/drawingml/preset-geometry.js +236 -0
  11. package/dist/esm/core/metafile/emf.js +2 -1
  12. package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
  13. package/dist/esm/core/metafile/symbol-fonts.js +154 -0
  14. package/dist/esm/core/metafile/wmf.js +35 -2
  15. package/dist/esm/core/vector.d.ts +5 -0
  16. package/dist/esm/excel/sheet-shape-parser.js +1 -12
  17. package/dist/esm/excel/xlsx-reader.d.ts +1 -1
  18. package/dist/esm/excel/xlsx-reader.js +3 -3
  19. package/dist/esm/index.d.ts +1 -0
  20. package/dist/esm/index.js +2 -1
  21. package/dist/esm/layout/page-doc.d.ts +38 -0
  22. package/dist/esm/layout/page-doc.js +34 -18
  23. package/dist/esm/layout/styled-layout.js +174 -49
  24. package/dist/esm/pdf/shading.d.ts +19 -0
  25. package/dist/esm/pdf/shading.js +84 -11
  26. package/dist/esm/pdf/styled-page-emitter.js +614 -444
  27. package/dist/esm/pptx/ole-preview.d.ts +10 -0
  28. package/dist/esm/pptx/ole-preview.js +52 -0
  29. package/dist/esm/pptx/placeholder-cascade.d.ts +69 -5
  30. package/dist/esm/pptx/placeholder-cascade.js +162 -25
  31. package/dist/esm/pptx/pptx-reader.js +247 -39
  32. package/dist/esm/pptx/slide-parser.d.ts +72 -10
  33. package/dist/esm/pptx/slide-parser.js +310 -82
  34. package/dist/esm/pptx/sp-helpers.js +19 -4
  35. package/dist/esm/pptx/table-style.d.ts +56 -0
  36. package/dist/esm/pptx/table-style.js +161 -0
  37. package/dist/esm/svg/svg-writer.js +53 -5
  38. package/dist/esm/word/docx-reader.js +2 -2
  39. package/dist/esm/word/drawing-parser.d.ts +34 -0
  40. package/dist/esm/word/drawing-parser.js +159 -13
  41. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shape id → the relationship id of its `v:imagedata`, for every shape in a
3
+ * legacy VML drawing part that has one.
4
+ *
5
+ * @param data The raw `vmlDrawing#.vml` bytes.
6
+ * @returns The map, keyed by shape id with the `_x0000_s` prefix stripped.
7
+ */
8
+ export declare function parseVmlImageRels(data: Uint8Array): Map<string, string>;
9
+ /** Strip the `_x0000_s` prefix a VML shape id carries, so both spellings meet. */
10
+ export declare function normalizeSpid(id: string): string;
@@ -0,0 +1,52 @@
1
+ import { XMLParser } from "fast-xml-parser";
2
+ //#region src/pptx/ole-preview.ts
3
+ var decoder = new TextDecoder("utf-8");
4
+ var parser = new XMLParser({
5
+ ignoreAttributes: false,
6
+ attributeNamePrefix: "@_",
7
+ parseAttributeValue: false,
8
+ parseTagValue: false,
9
+ removeNSPrefix: true
10
+ });
11
+ var SPID_PREFIX = /^_x0000_s/u;
12
+ /**
13
+ * Shape id → the relationship id of its `v:imagedata`, for every shape in a
14
+ * legacy VML drawing part that has one.
15
+ *
16
+ * @param data The raw `vmlDrawing#.vml` bytes.
17
+ * @returns The map, keyed by shape id with the `_x0000_s` prefix stripped.
18
+ */
19
+ function parseVmlImageRels(data) {
20
+ const out = /* @__PURE__ */ new Map();
21
+ walk(parser.parse(decoder.decode(data)), out);
22
+ return out;
23
+ }
24
+ /** Strip the `_x0000_s` prefix a VML shape id carries, so both spellings meet. */
25
+ function normalizeSpid(id) {
26
+ return id.replace(SPID_PREFIX, "");
27
+ }
28
+ function walk(node, out) {
29
+ if (node === null || typeof node !== "object") return;
30
+ if (Array.isArray(node)) {
31
+ for (const item of node) walk(item, out);
32
+ return;
33
+ }
34
+ const rec = node;
35
+ const shape = rec["shape"];
36
+ if (shape !== void 0) for (const s of Array.isArray(shape) ? shape : [shape]) collect(s, out);
37
+ for (const value of Object.values(rec)) walk(value, out);
38
+ }
39
+ function collect(shape, out) {
40
+ if (shape === null || typeof shape !== "object") return;
41
+ const rec = shape;
42
+ const id = rec["@_id"];
43
+ const imagedata = rec["imagedata"];
44
+ if (typeof id !== "string" || imagedata === void 0) return;
45
+ const first = Array.isArray(imagedata) ? imagedata[0] : imagedata;
46
+ if (first === null || typeof first !== "object") return;
47
+ const img = first;
48
+ const rel = img["@_relid"] ?? img["@_id"];
49
+ if (typeof rel === "string") out.set(normalizeSpid(id), rel);
50
+ }
51
+ //#endregion
52
+ export { normalizeSpid, parseVmlImageRels };
@@ -1,4 +1,4 @@
1
- import { RunProperties } from '../core/document-model/index.js';
1
+ import { ParagraphProperties, RunProperties } 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
4
  import { PlaceholderRef, ShapeBoxEmu } from './sp-helpers.js';
@@ -12,11 +12,63 @@ export interface PlaceholderCascade {
12
12
  /** The inherited EMU box for a slide placeholder without its own `a:xfrm`. */
13
13
  readonly geometryFor: (ph: PlaceholderRef) => ShapeBoxEmu | undefined;
14
14
  /**
15
- * The master's default run formatting for a placeholder's paragraph at the
16
- * given 0-based outline level (empty when no master text styles apply).
15
+ * The inherited run formatting for a paragraph at the given 0-based outline
16
+ * level. Without a placeholder this is the presentation's default text style
17
+ * — what an ordinary text box on a slide is written in.
17
18
  */
18
- readonly defaultsFor: (ph: PlaceholderRef, level: number) => RunProperties;
19
+ readonly defaultsFor: (ph: PlaceholderRef | undefined, level: number) => RunProperties;
20
+ /** The inherited paragraph shape at that level: alignment, indent, spacing. */
21
+ readonly paragraphDefaultsFor: (ph: PlaceholderRef | undefined, level: number) => ParagraphProperties;
22
+ /** The bullet that level inherits, which a paragraph states only to change. */
23
+ readonly bulletFor: (ph: PlaceholderRef | undefined, level: number) => LevelBullet | undefined;
24
+ /**
25
+ * The vertical anchor the placeholder's prototype states (`a:bodyPr@anchor`),
26
+ * the layout's before the master's, for a shape that states none itself.
27
+ */
28
+ readonly anchorFor: (ph: PlaceholderRef) => 't' | 'ctr' | 'b' | undefined;
29
+ /**
30
+ * The prototype's own `p:spPr`, for the properties a slide placeholder
31
+ * inherits rather than states: its fill, its outline, its geometry. The
32
+ * layout's before the master's.
33
+ */
34
+ readonly shapePropsFor: (ph: PlaceholderRef) => PoNode | undefined;
35
+ }
36
+ /** One level of a text style: how its paragraphs sit and how their runs read. */
37
+ interface LevelStyle {
38
+ readonly run: RunProperties;
39
+ readonly paragraph: ParagraphProperties;
40
+ readonly bullet?: LevelBullet;
41
+ }
42
+ /**
43
+ * §21.1.2.4.4/.5/.6 — the bullet a level declares: none at all, a literal
44
+ * character, or a number that counts. A slide paragraph states one only where
45
+ * it differs from this: themes.pptx's second slide writes one bare line, and
46
+ * the dot in front of it is the master's body style, nine levels up.
47
+ */
48
+ export interface LevelBullet {
49
+ /** What it draws: nothing at all, a character, or a number that counts. */
50
+ readonly kind?: 'none' | 'char' | 'autoNum';
51
+ /** `a:buChar` — the character, already read out of the face that states it. */
52
+ readonly char?: string;
53
+ /** `a:buAutoNum @type`/`@startAt` — the numbering and where it starts. */
54
+ readonly type?: string;
55
+ readonly startAt?: number;
56
+ /** §21.1.2.4.2/.3 — its size, as a fraction of the text or in points. */
57
+ readonly sizePct?: number;
58
+ readonly sizePts?: number;
59
+ /** §21.1.2.4.1 `a:buClr` — the colour it is drawn in, when it has its own. */
60
+ readonly colorHex?: string;
19
61
  }
62
+ /**
63
+ * What an `a:pPr` (or an `a:lvlNpPr`, the same vocabulary) says about its
64
+ * bullet — each part on its own, because a paragraph may restate the SIZE and
65
+ * leave the character to its level.
66
+ *
67
+ * @param pPr The paragraph-properties node.
68
+ * @param colors The colour resolver, for `a:buClr`.
69
+ * @returns What it states, or `undefined` when it says nothing about bullets.
70
+ */
71
+ export declare function parseBullet(pPr: PoNode | undefined, colors?: ColorResolver): LevelBullet | undefined;
20
72
  /**
21
73
  * Build a {@link PlaceholderCascade} from a slide's already-parsed layout and
22
74
  * master trees: it resolves a placeholder's inherited geometry (the layout's
@@ -27,4 +79,16 @@ export interface PlaceholderCascade {
27
79
  * @param masterTree The parsed `p:sldMaster` part, when present.
28
80
  * @param colors The deck's colour resolver, for scheme colours in the text styles.
29
81
  */
30
- export declare function buildPlaceholderCascade(layoutTree: ReadonlyArray<PoNode>, masterTree: ReadonlyArray<PoNode> | undefined, colors: ColorResolver): PlaceholderCascade;
82
+ export declare function buildPlaceholderCascade(layoutTree: ReadonlyArray<PoNode>, masterTree: ReadonlyArray<PoNode> | undefined, colors: ColorResolver, deckDefaults?: ReadonlyArray<LevelStyle>): PlaceholderCascade;
83
+ /**
84
+ * `a:lstStyle` (or a `p:txStyles` family) → its nine levels. Shared by the
85
+ * deck's default text style, the master's families and a prototype's own list,
86
+ * which are the same vocabulary written in different places.
87
+ *
88
+ * @param list The `a:lstStyle` / `p:titleStyle` / … node.
89
+ * @param colors The deck's colour resolver.
90
+ * @param prefix The level element prefix: `a:lvl` here, always.
91
+ * @returns The nine levels, or an empty list when there is no such node.
92
+ */
93
+ export declare function parseLevelStyles(list: PoNode | undefined, colors: ColorResolver): Array<LevelStyle>;
94
+ export {};
@@ -1,6 +1,46 @@
1
- import { poChildren, poIs } from "../core/po-helpers.js";
1
+ import { emuToPt, pt } from "../core/ir/units.js";
2
+ import { fromSymbolFont } from "../core/metafile/symbol-fonts.js";
3
+ import { poAttr, poChildren, poIntAttr, poIs } from "../core/po-helpers.js";
4
+ import { resolveColorNode } from "../core/drawingml/colors.js";
2
5
  import { parsePh, parseXfrmBox, rPrToRunProps } from "./sp-helpers.js";
3
6
  //#region src/pptx/placeholder-cascade.ts
7
+ /**
8
+ * What an `a:pPr` (or an `a:lvlNpPr`, the same vocabulary) says about its
9
+ * bullet — each part on its own, because a paragraph may restate the SIZE and
10
+ * leave the character to its level.
11
+ *
12
+ * @param pPr The paragraph-properties node.
13
+ * @param colors The colour resolver, for `a:buClr`.
14
+ * @returns What it states, or `undefined` when it says nothing about bullets.
15
+ */
16
+ function parseBullet(pPr, colors) {
17
+ if (!pPr) return void 0;
18
+ const child = (tag) => poChildren(pPr).find((c) => poIs(c, tag));
19
+ const pct = poIntAttr(child("a:buSzPct"), "val");
20
+ const pts = poIntAttr(child("a:buSzPts"), "val");
21
+ const clr = child("a:buClr");
22
+ const colorHex = clr && colors ? poChildren(clr).map((c) => resolveColorNode(c, colors)).find((hex) => hex !== void 0) : void 0;
23
+ const size = {
24
+ ...pct !== void 0 ? { sizePct: pct / 1e5 } : {},
25
+ ...pts !== void 0 ? { sizePts: pts / 100 } : {},
26
+ ...colorHex !== void 0 ? { colorHex } : {}
27
+ };
28
+ const buChar = child("a:buChar");
29
+ const buAuto = child("a:buAutoNum");
30
+ const kind = poChildren(pPr).some((c) => poIs(c, "a:buNone")) ? { kind: "none" } : buChar ? {
31
+ kind: "char",
32
+ char: fromSymbolFont(poAttr(buChar, "char") ?? "•", poAttr(child("a:buFont"), "typeface"))
33
+ } : buAuto ? {
34
+ kind: "autoNum",
35
+ type: poAttr(buAuto, "type") ?? "arabicPeriod",
36
+ startAt: poIntAttr(buAuto, "startAt") ?? 1
37
+ } : void 0;
38
+ const out = {
39
+ ...size,
40
+ ...kind
41
+ };
42
+ return Object.keys(out).length > 0 ? out : void 0;
43
+ }
4
44
  function categoryOf(type) {
5
45
  if (type === "title" || type === "ctrTitle") return "title";
6
46
  if (type === void 0 || type === "body" || type === "subTitle" || type === "obj") return "body";
@@ -16,26 +56,124 @@ function categoryOf(type) {
16
56
  * @param masterTree The parsed `p:sldMaster` part, when present.
17
57
  * @param colors The deck's colour resolver, for scheme colours in the text styles.
18
58
  */
19
- function buildPlaceholderCascade(layoutTree, masterTree, colors) {
20
- const layoutPhs = collectPlaceholders(layoutTree, "p:sldLayout");
21
- const masterPhs = masterTree ? collectPlaceholders(masterTree, "p:sldMaster") : [];
59
+ function buildPlaceholderCascade(layoutTree, masterTree, colors, deckDefaults = []) {
60
+ const layoutPhs = collectPlaceholders(layoutTree, "p:sldLayout", colors);
61
+ const masterPhs = masterTree ? collectPlaceholders(masterTree, "p:sldMaster", colors) : [];
22
62
  const txStyles = masterTree ? collectTxStyles(masterTree, colors) : {
23
63
  title: [],
24
64
  body: [],
25
65
  other: []
26
66
  };
67
+ const styleAt = (ph, level) => {
68
+ const layers = [at(deckDefaults, level)];
69
+ if (ph) layers.push(at(txStyles[categoryOf(ph.type)], level), at(matchPlaceholder(masterPhs, ph)?.levels ?? [], level), at(matchPlaceholder(layoutPhs, ph)?.levels ?? [], level));
70
+ return layers.reduce(mergeLevels, EMPTY_LEVEL);
71
+ };
27
72
  return {
28
73
  geometryFor(ph) {
29
74
  return matchPlaceholder(layoutPhs, ph)?.box ?? matchPlaceholder(masterPhs, ph)?.box;
30
75
  },
31
76
  defaultsFor(ph, level) {
32
- const levels = txStyles[categoryOf(ph.type)];
33
- if (levels.length === 0) return {};
34
- return levels[Math.min(Math.max(level, 0), levels.length - 1)] ?? {};
77
+ return styleAt(ph, level).run;
78
+ },
79
+ paragraphDefaultsFor(ph, level) {
80
+ return styleAt(ph, level).paragraph;
81
+ },
82
+ bulletFor(ph, level) {
83
+ return styleAt(ph, level).bullet;
84
+ },
85
+ anchorFor(ph) {
86
+ return matchPlaceholder(layoutPhs, ph)?.anchor ?? matchPlaceholder(masterPhs, ph)?.anchor;
87
+ },
88
+ shapePropsFor(ph) {
89
+ return matchPlaceholder(layoutPhs, ph)?.spPr ?? matchPlaceholder(masterPhs, ph)?.spPr;
35
90
  }
36
91
  };
37
92
  }
38
- function collectPlaceholders(tree, root) {
93
+ var EMPTY_LEVEL = {
94
+ run: {},
95
+ paragraph: {}
96
+ };
97
+ /** The style at `level`, clamped to the list — a deeper level keeps the last. */
98
+ function at(levels, level) {
99
+ if (levels.length === 0) return EMPTY_LEVEL;
100
+ return levels[Math.min(Math.max(level, 0), levels.length - 1)] ?? EMPTY_LEVEL;
101
+ }
102
+ /** `next` over `base` — a layer states only what it changes. */
103
+ function mergeLevels(base, next) {
104
+ const bullet = base.bullet || next.bullet ? {
105
+ ...base.bullet,
106
+ ...next.bullet
107
+ } : void 0;
108
+ return {
109
+ run: {
110
+ ...base.run,
111
+ ...next.run
112
+ },
113
+ paragraph: {
114
+ ...base.paragraph,
115
+ ...next.paragraph
116
+ },
117
+ ...bullet ? { bullet } : {}
118
+ };
119
+ }
120
+ /**
121
+ * `a:lstStyle` (or a `p:txStyles` family) → its nine levels. Shared by the
122
+ * deck's default text style, the master's families and a prototype's own list,
123
+ * which are the same vocabulary written in different places.
124
+ *
125
+ * @param list The `a:lstStyle` / `p:titleStyle` / … node.
126
+ * @param colors The deck's colour resolver.
127
+ * @param prefix The level element prefix: `a:lvl` here, always.
128
+ * @returns The nine levels, or an empty list when there is no such node.
129
+ */
130
+ function parseLevelStyles(list, colors) {
131
+ if (!list) return [];
132
+ const out = [];
133
+ for (let lvl = 1; lvl <= 9; lvl++) {
134
+ const lvlPr = poChildren(list).find((c) => poIs(c, `a:lvl${String(lvl)}pPr`));
135
+ const defRPr = lvlPr ? poChildren(lvlPr).find((c) => poIs(c, "a:defRPr")) : void 0;
136
+ const bullet = parseBullet(lvlPr, colors);
137
+ out.push({
138
+ run: rPrToRunProps(defRPr, colors),
139
+ paragraph: pPrToParagraphProps(lvlPr),
140
+ ...bullet ? { bullet } : {}
141
+ });
142
+ }
143
+ return out;
144
+ }
145
+ var ALGN = {
146
+ l: "left",
147
+ ctr: "center",
148
+ r: "right",
149
+ just: "both",
150
+ dist: "distribute"
151
+ };
152
+ /**
153
+ * A level's paragraph shape — §21.1.2.2.7 `@algn`, `@marL`/`@indent`, and the
154
+ * space around it. `a:spcPct` is a fraction of the line rather than a distance,
155
+ * which this model has no room for, so only the stated POINTS are read.
156
+ */
157
+ function pPrToParagraphProps(lvlPr) {
158
+ if (!lvlPr) return {};
159
+ const algn = poAttr(lvlPr, "algn");
160
+ const marL = poIntAttr(lvlPr, "marL");
161
+ const indent = poIntAttr(lvlPr, "indent");
162
+ return {
163
+ ...algn !== void 0 && ALGN[algn] ? { alignment: ALGN[algn] } : {},
164
+ ...marL !== void 0 ? { indentLeft: emuToPt(marL) } : {},
165
+ ...indent !== void 0 ? { indentFirstLine: emuToPt(indent) } : {},
166
+ ...spacingPt(lvlPr, "a:spcBef", "spacingBefore"),
167
+ ...spacingPt(lvlPr, "a:spcAft", "spacingAfter")
168
+ };
169
+ }
170
+ function spacingPt(lvlPr, tag, key) {
171
+ const holder = poChildren(lvlPr).find((c) => poIs(c, tag));
172
+ const pts = holder ? poChildren(holder).find((c) => poIs(c, "a:spcPts")) : void 0;
173
+ const val = pts ? poIntAttr(pts, "val") : void 0;
174
+ return val === void 0 ? {} : { [key]: pt(val / 100) };
175
+ }
176
+ function collectPlaceholders(tree, root, colors) {
39
177
  const sld = tree.find((n) => poIs(n, root));
40
178
  const cSld = sld ? poChildren(sld).find((c) => poIs(c, "p:cSld")) : void 0;
41
179
  const spTree = cSld ? poChildren(cSld).find((c) => poIs(c, "p:spTree")) : void 0;
@@ -45,10 +183,19 @@ function collectPlaceholders(tree, root) {
45
183
  if (!poIs(sp, "p:sp")) continue;
46
184
  const ref = parsePh(sp);
47
185
  if (!ref) continue;
48
- const box = parseXfrmBox(poChildren(sp).find((c) => poIs(c, "p:spPr")));
186
+ const spPr = poChildren(sp).find((c) => poIs(c, "p:spPr"));
187
+ const box = parseXfrmBox(spPr);
188
+ const txBody = poChildren(sp).find((c) => poIs(c, "p:txBody"));
189
+ const lstStyle = txBody ? poChildren(txBody).find((c) => poIs(c, "a:lstStyle")) : void 0;
190
+ const bodyPr = txBody ? poChildren(txBody).find((c) => poIs(c, "a:bodyPr")) : void 0;
191
+ const a = bodyPr ? poAttr(bodyPr, "anchor") : void 0;
192
+ const anchor = a === "ctr" || a === "b" || a === "t" ? a : void 0;
49
193
  out.push({
50
194
  ref,
51
- ...box ? { box } : {}
195
+ ...box ? { box } : {},
196
+ ...spPr ? { spPr } : {},
197
+ levels: parseLevelStyles(lstStyle, colors),
198
+ ...anchor ? { anchor } : {}
52
199
  });
53
200
  }
54
201
  return out;
@@ -66,22 +213,12 @@ function matchPlaceholder(list, ph) {
66
213
  function collectTxStyles(masterTree, colors) {
67
214
  const sld = masterTree.find((n) => poIs(n, "p:sldMaster"));
68
215
  const txStyles = sld ? poChildren(sld).find((c) => poIs(c, "p:txStyles")) : void 0;
216
+ const family = (tag) => parseLevelStyles(txStyles ? poChildren(txStyles).find((c) => poIs(c, tag)) : void 0, colors);
69
217
  return {
70
- title: levelStyles(txStyles, "p:titleStyle", colors),
71
- body: levelStyles(txStyles, "p:bodyStyle", colors),
72
- other: levelStyles(txStyles, "p:otherStyle", colors)
218
+ title: family("p:titleStyle"),
219
+ body: family("p:bodyStyle"),
220
+ other: family("p:otherStyle")
73
221
  };
74
222
  }
75
- function levelStyles(txStyles, tag, colors) {
76
- const style = txStyles ? poChildren(txStyles).find((c) => poIs(c, tag)) : void 0;
77
- if (!style) return [];
78
- const out = [];
79
- for (let lvl = 1; lvl <= 9; lvl++) {
80
- const lvlPr = poChildren(style).find((c) => poIs(c, `a:lvl${lvl}pPr`));
81
- const defRPr = lvlPr ? poChildren(lvlPr).find((c) => poIs(c, "a:defRPr")) : void 0;
82
- out.push(rPrToRunProps(defRPr, colors));
83
- }
84
- return out;
85
- }
86
223
  //#endregion
87
- export { buildPlaceholderCascade };
224
+ export { buildPlaceholderCascade, parseBullet, parseLevelStyles };