reamkit 1.7.0 → 1.10.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 (46) hide show
  1. package/README.md +21 -3
  2. package/dist/esm/core/converter/facade.js +2 -0
  3. package/dist/esm/core/converter/ream.d.ts +1 -0
  4. package/dist/esm/core/converter/ream.js +2 -1
  5. package/dist/esm/core/document-model/types.d.ts +3 -1
  6. package/dist/esm/core/drawingml/shape-render.d.ts +3 -1
  7. package/dist/esm/core/drawingml/shape-render.js +27 -1
  8. package/dist/esm/core/vector.d.ts +10 -0
  9. package/dist/esm/html/html-writer.js +4 -2
  10. package/dist/esm/layout/styled-layout.js +5 -2
  11. package/dist/esm/pdf/shading.d.ts +12 -0
  12. package/dist/esm/pdf/shading.js +152 -0
  13. package/dist/esm/pdf/styled-page-emitter.js +29 -4
  14. package/dist/esm/pdf/vector-graphics.d.ts +1 -1
  15. package/dist/esm/pdf/vector-graphics.js +5 -3
  16. package/dist/esm/pdf-reader/ccitt.d.ts +15 -0
  17. package/dist/esm/pdf-reader/ccitt.js +394 -0
  18. package/dist/esm/pdf-reader/content.d.ts +6 -2
  19. package/dist/esm/pdf-reader/content.js +54 -13
  20. package/dist/esm/pdf-reader/decrypt.d.ts +1 -1
  21. package/dist/esm/pdf-reader/decrypt.js +20 -8
  22. package/dist/esm/pdf-reader/document.d.ts +1 -1
  23. package/dist/esm/pdf-reader/document.js +4 -4
  24. package/dist/esm/pdf-reader/flow-build.js +17 -6
  25. package/dist/esm/pdf-reader/image-decode.js +115 -7
  26. package/dist/esm/pdf-reader/layout.js +45 -7
  27. package/dist/esm/pdf-reader/reader.d.ts +1 -1
  28. package/dist/esm/pdf-reader/reader.js +5 -5
  29. package/dist/esm/pdf-reader/shading.d.ts +3 -0
  30. package/dist/esm/pdf-reader/shading.js +147 -0
  31. package/dist/esm/pdf-reader/text.js +47 -13
  32. package/dist/esm/pdf-reader/vector.d.ts +5 -1
  33. package/dist/esm/pdf-reader/vector.js +15 -6
  34. package/dist/esm/pptx/placeholder-cascade.d.ts +9 -0
  35. package/dist/esm/pptx/placeholder-cascade.js +77 -0
  36. package/dist/esm/pptx/pptx-reader.d.ts +4 -0
  37. package/dist/esm/pptx/pptx-reader.js +213 -0
  38. package/dist/esm/pptx/slide-parser.d.ts +18 -0
  39. package/dist/esm/pptx/slide-parser.js +359 -0
  40. package/dist/esm/pptx/sp-helpers.d.ts +17 -0
  41. package/dist/esm/pptx/sp-helpers.js +60 -0
  42. package/dist/esm/svg/svg-writer.js +12 -5
  43. package/dist/esm/word/docx-writer.js +8 -1
  44. package/dist/esm/word/drawing-parser.d.ts +4 -0
  45. package/dist/esm/word/drawing-parser.js +29 -18
  46. package/package.json +4 -2
@@ -0,0 +1,213 @@
1
+ import { pt } from "../core/ir/units.js";
2
+ import { ResourceStore } from "../core/ir/resources.js";
3
+ import { FEATURES } from "../core/ir/features.js";
4
+ import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
5
+ import "../core/style-cascade/index.js";
6
+ import { bytesInclude } from "../core/bytes.js";
7
+ import { poAttr, poChildren, poIntAttr, poIs } from "../core/po-helpers.js";
8
+ import { DEFAULT_THEME_PALETTE, defaultColorResolver, makeColorResolver } from "../core/drawingml/colors.js";
9
+ import { parseChart, withChartColorStyle } from "../core/drawingml/chart-parser.js";
10
+ import { parseTheme } from "../core/drawingml/theme-parser.js";
11
+ import { OpcPackage } from "../core/opc/package.js";
12
+ import "../core/opc/index.js";
13
+ import { buildPlaceholderCascade } from "./placeholder-cascade.js";
14
+ import { backdropElement, parseBackgroundFill, parseSlideShapes } from "./slide-parser.js";
15
+ import { XMLParser } from "fast-xml-parser";
16
+ //#region src/pptx/pptx-reader.ts
17
+ var EMU_PER_PT = 12700;
18
+ var DEFAULT_CX = 9144e3;
19
+ var DEFAULT_CY = 6858e3;
20
+ var decoder = new TextDecoder();
21
+ var parser = new XMLParser({
22
+ ignoreAttributes: false,
23
+ attributeNamePrefix: "@_",
24
+ preserveOrder: true,
25
+ parseAttributeValue: false,
26
+ parseTagValue: false,
27
+ trimValues: false
28
+ });
29
+ function readPptx(bytes) {
30
+ const losses = [];
31
+ const pkg = OpcPackage.open(bytes);
32
+ const presPath = pkg.getMainDocumentPath();
33
+ const presData = pkg.getPart(presPath);
34
+ const resources = new ResourceStore();
35
+ const charts = /* @__PURE__ */ new Map();
36
+ let cx = DEFAULT_CX;
37
+ let cy = DEFAULT_CY;
38
+ const slideParts = [];
39
+ if (presData) {
40
+ const pres = parser.parse(decoder.decode(presData)).find((n) => poIs(n, "p:presentation"));
41
+ const kids = pres ? poChildren(pres) : [];
42
+ const sldSz = kids.find((c) => poIs(c, "p:sldSz"));
43
+ cx = (sldSz ? poIntAttr(sldSz, "cx") : void 0) || DEFAULT_CX;
44
+ cy = (sldSz ? poIntAttr(sldSz, "cy") : void 0) || DEFAULT_CY;
45
+ const slideRelById = new Map(pkg.getPartRelationships(presPath).filter((r) => r.type.endsWith("/slide")).map((r) => [r.id, r]));
46
+ const lst = kids.find((c) => poIs(c, "p:sldIdLst"));
47
+ const ids = lst ? poChildren(lst).filter((c) => poIs(c, "p:sldId")) : [];
48
+ for (const sldId of ids) {
49
+ const rid = poAttr(sldId, "r:id");
50
+ const rel = rid !== void 0 ? slideRelById.get(rid) : void 0;
51
+ const part = rel ? pkg.resolveRelatedPart(presPath, rel) : void 0;
52
+ if (part) slideParts.push(part);
53
+ }
54
+ }
55
+ if (slideParts.length === 0) losses.push({
56
+ severity: "dropped",
57
+ feature: FEATURES.text,
58
+ detail: "presentation has no slides"
59
+ });
60
+ const slideCount = Math.max(1, slideParts.length);
61
+ const pageW = pt(cx / EMU_PER_PT);
62
+ const pageH = pt(cy / EMU_PER_PT);
63
+ const stylesByLayout = /* @__PURE__ */ new Map();
64
+ const body = [];
65
+ for (let i = 0; i < slideCount; i++) {
66
+ body.push({
67
+ kind: "paragraph",
68
+ paragraph: {
69
+ properties: i > 0 ? { pageBreakBefore: true } : {},
70
+ runs: [{
71
+ text: "​",
72
+ properties: {}
73
+ }]
74
+ }
75
+ });
76
+ const part = slideParts[i];
77
+ if (part) {
78
+ const styles = slideStylesFor(pkg, part.path, stylesByLayout);
79
+ const ctx = {
80
+ ...styles.cascade ? { cascade: styles.cascade } : {},
81
+ colors: styles.colors,
82
+ resolveImage: makeSlideImageResolver(pkg, part.path, resources),
83
+ resolveChart: makeSlideChartResolver(pkg, part.path, charts, styles.colors),
84
+ resolveHyperlink: makeHyperlinkResolver(pkg, part.path)
85
+ };
86
+ body.push(...parseSlide(part.data, ctx, styles.background, pageW, pageH));
87
+ }
88
+ }
89
+ const section = {
90
+ pageSize: {
91
+ width: pageW,
92
+ height: pageH
93
+ },
94
+ margins: {
95
+ top: pt(0),
96
+ right: pt(0),
97
+ bottom: pt(0),
98
+ left: pt(0)
99
+ },
100
+ headers: [],
101
+ footers: []
102
+ };
103
+ return {
104
+ doc: {
105
+ kind: "flow",
106
+ body: resolveBodyStyles([...body], EMPTY_STYLE_SHEET),
107
+ sections: [],
108
+ section,
109
+ styles: EMPTY_STYLE_SHEET,
110
+ resources,
111
+ ...charts.size > 0 ? { charts } : {}
112
+ },
113
+ losses
114
+ };
115
+ }
116
+ function parseXml(data) {
117
+ return parser.parse(decoder.decode(data));
118
+ }
119
+ function parseSlide(data, ctx, inheritedBg, pageW, pageH) {
120
+ const sld = parseXml(data).find((n) => poIs(n, "p:sld"));
121
+ const cSld = sld ? poChildren(sld).find((c) => poIs(c, "p:cSld")) : void 0;
122
+ const colors = ctx.colors ?? defaultColorResolver;
123
+ const bgNode = cSld ? poChildren(cSld).find((c) => poIs(c, "p:bg")) : void 0;
124
+ const bg = (bgNode ? parseBackgroundFill(bgNode, colors) : void 0) ?? inheritedBg;
125
+ const spTree = cSld ? poChildren(cSld).find((c) => poIs(c, "p:spTree")) : void 0;
126
+ const out = [];
127
+ if (bg) out.push(backdropElement(bg, pageW, pageH));
128
+ if (spTree) out.push(...parseSlideShapes(spTree, ctx));
129
+ return out;
130
+ }
131
+ function partBackground(tree, root, colors) {
132
+ const sld = tree.find((n) => poIs(n, root));
133
+ const cSld = sld ? poChildren(sld).find((c) => poIs(c, "p:cSld")) : void 0;
134
+ const bg = cSld ? poChildren(cSld).find((c) => poIs(c, "p:bg")) : void 0;
135
+ return bg ? parseBackgroundFill(bg, colors) : void 0;
136
+ }
137
+ function makeSlideImageResolver(pkg, slidePath, resources) {
138
+ const cache = /* @__PURE__ */ new Map();
139
+ return (relId) => {
140
+ if (cache.has(relId)) return cache.get(relId);
141
+ const rel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
142
+ const resolved = rel ? pkg.resolveRelatedPart(slidePath, rel) : void 0;
143
+ const id = resolved ? resources.put(resolved.data) : void 0;
144
+ cache.set(relId, id);
145
+ return id;
146
+ };
147
+ }
148
+ function makeHyperlinkResolver(pkg, slidePath) {
149
+ return (relId) => {
150
+ const rel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
151
+ return rel && rel.targetMode === "External" ? rel.target : void 0;
152
+ };
153
+ }
154
+ function makeSlideChartResolver(pkg, slidePath, charts, colors) {
155
+ const cache = /* @__PURE__ */ new Map();
156
+ return (relId) => {
157
+ if (cache.has(relId)) return cache.get(relId);
158
+ const rel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
159
+ const resolved = rel ? pkg.resolveRelatedPart(slidePath, rel) : void 0;
160
+ const chart = resolved ? parseChart(resolved.data, colors) : null;
161
+ let key;
162
+ if (chart && resolved) {
163
+ key = `${slidePath}!${relId}`;
164
+ charts.set(key, withChartColorStyle(chart, pkg, resolved.path, colors));
165
+ }
166
+ cache.set(relId, key);
167
+ return key;
168
+ };
169
+ }
170
+ function slideStylesFor(pkg, slidePath, cache) {
171
+ const layoutRel = pkg.getPartRelationships(slidePath).find((r) => r.type.endsWith("/slideLayout"));
172
+ const layout = layoutRel ? pkg.resolveRelatedPart(slidePath, layoutRel) : void 0;
173
+ if (!layout) return { colors: defaultColorResolver };
174
+ const cached = cache.get(layout.path);
175
+ if (cached) return cached;
176
+ const masterRel = pkg.getPartRelationships(layout.path).find((r) => r.type.endsWith("/slideMaster"));
177
+ const master = masterRel ? pkg.resolveRelatedPart(layout.path, masterRel) : void 0;
178
+ const colors = master ? deckColorResolver(pkg, master.path) : defaultColorResolver;
179
+ const layoutTree = parseXml(layout.data);
180
+ const masterTree = master ? parseXml(master.data) : void 0;
181
+ const cascade = buildPlaceholderCascade(layoutTree, masterTree, colors);
182
+ const background = partBackground(layoutTree, "p:sldLayout", colors) ?? (masterTree ? partBackground(masterTree, "p:sldMaster", colors) : void 0);
183
+ const styles = {
184
+ cascade,
185
+ colors,
186
+ ...background ? { background } : {}
187
+ };
188
+ cache.set(layout.path, styles);
189
+ return styles;
190
+ }
191
+ function deckColorResolver(pkg, masterPath) {
192
+ const themeRel = pkg.getPartRelationships(masterPath).find((r) => r.type.endsWith("/theme"));
193
+ const theme = themeRel ? pkg.resolveRelatedPart(masterPath, themeRel) : void 0;
194
+ if (!theme) return defaultColorResolver;
195
+ const palette = new Map(DEFAULT_THEME_PALETTE);
196
+ for (const [slot, hex] of parseTheme(theme.data)) palette.set(slot, hex);
197
+ return makeColorResolver(palette);
198
+ }
199
+ var pptxReader = {
200
+ id: "pptx",
201
+ produces: "flow",
202
+ supports: new Set([
203
+ FEATURES.text,
204
+ FEATURES.images,
205
+ FEATURES.shapes,
206
+ FEATURES.charts,
207
+ FEATURES.tables
208
+ ]),
209
+ sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && bytesInclude(bytes, "ppt/presentation.xml"),
210
+ read: (bytes) => readPptx(bytes)
211
+ };
212
+ //#endregion
213
+ export { pptxReader };
@@ -0,0 +1,18 @@
1
+ import { BodyElement, ShapeFill } from '../core/document-model/index.js';
2
+ import { ColorResolver } from '../core/drawingml/colors.js';
3
+ import { Pt, ResourceId } from '../core/ir/index.js';
4
+ import { PoNode } from '../core/po-helpers.js';
5
+ import { PlaceholderCascade } from './placeholder-cascade.js';
6
+ import { ShapeBoxEmu } from './sp-helpers.js';
7
+ export interface SlideContext {
8
+ readonly cascade?: PlaceholderCascade;
9
+ readonly resolveImage?: (relId: string) => ResourceId | undefined;
10
+ readonly resolveChart?: (relId: string) => string | undefined;
11
+ readonly colors?: ColorResolver;
12
+ readonly resolveHyperlink?: (relId: string) => string | undefined;
13
+ }
14
+ type GroupTransform = (box: ShapeBoxEmu) => ShapeBoxEmu;
15
+ export declare function parseSlideShapes(container: PoNode, ctx?: SlideContext, transform?: GroupTransform): Array<BodyElement>;
16
+ export declare function parseBackgroundFill(bg: PoNode, colors: ColorResolver): ShapeFill | undefined;
17
+ export declare function backdropElement(fill: ShapeFill, widthPt: Pt, heightPt: Pt): BodyElement;
18
+ export {};
@@ -0,0 +1,359 @@
1
+ import { emuToPt } from "../core/ir/units.js";
2
+ import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poText } from "../core/po-helpers.js";
3
+ import { defaultColorResolver, resolveColorNode } from "../core/drawingml/colors.js";
4
+ import { parseCustGeom, parseFill, parseLine, parsePrstGeom } from "../word/drawing-parser.js";
5
+ import { boxFromXfrm, parsePh, parseXfrmBox, rPrToRunProps } from "./sp-helpers.js";
6
+ //#region src/pptx/slide-parser.ts
7
+ var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
8
+ var TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
9
+ var ALGN_TO_ALIGNMENT = {
10
+ l: "left",
11
+ ctr: "center",
12
+ r: "right",
13
+ just: "both",
14
+ dist: "distribute"
15
+ };
16
+ var RECT_GEOMETRY = {
17
+ kind: "preset",
18
+ preset: "rect",
19
+ adjust: /* @__PURE__ */ new Map()
20
+ };
21
+ var IDENTITY_TRANSFORM = (box) => box;
22
+ function parseSlideShapes(container, ctx = {}, transform = IDENTITY_TRANSFORM) {
23
+ const out = [];
24
+ for (const child of poChildren(container)) if (poIs(child, "p:sp")) {
25
+ const shape = parseSp(child, ctx, transform);
26
+ if (shape) out.push({
27
+ kind: "shape",
28
+ shape
29
+ });
30
+ } else if (poIs(child, "p:pic")) {
31
+ const image = parsePic(child, ctx, transform);
32
+ if (image) out.push({
33
+ kind: "image",
34
+ image
35
+ });
36
+ } else if (poIs(child, "p:graphicFrame")) {
37
+ const el = parseGraphicFrame(child, ctx, transform);
38
+ if (el) out.push(el);
39
+ } else if (poIs(child, "p:grpSp")) out.push(...parseSlideShapes(child, ctx, composeGroupTransform(child, transform)));
40
+ return out;
41
+ }
42
+ function composeGroupTransform(grpSp, parent) {
43
+ const grpSpPr = poChildren(grpSp).find((c) => poIs(c, "p:grpSpPr"));
44
+ const xfrm = grpSpPr ? poChildren(grpSpPr).find((c) => poIs(c, "a:xfrm")) : void 0;
45
+ if (!xfrm) return parent;
46
+ const off = poChildren(xfrm).find((c) => poIs(c, "a:off"));
47
+ const ext = poChildren(xfrm).find((c) => poIs(c, "a:ext"));
48
+ const chOff = poChildren(xfrm).find((c) => poIs(c, "a:chOff"));
49
+ const chExt = poChildren(xfrm).find((c) => poIs(c, "a:chExt"));
50
+ const extCx = ext ? poIntAttr(ext, "cx") : void 0;
51
+ const extCy = ext ? poIntAttr(ext, "cy") : void 0;
52
+ const chExtCx = chExt ? poIntAttr(chExt, "cx") : void 0;
53
+ const chExtCy = chExt ? poIntAttr(chExt, "cy") : void 0;
54
+ if (!extCx || !extCy || !chExtCx || !chExtCy) return parent;
55
+ const offX = (off ? poIntAttr(off, "x") : void 0) ?? 0;
56
+ const offY = (off ? poIntAttr(off, "y") : void 0) ?? 0;
57
+ const chOffX = (chOff ? poIntAttr(chOff, "x") : void 0) ?? 0;
58
+ const chOffY = (chOff ? poIntAttr(chOff, "y") : void 0) ?? 0;
59
+ const sx = extCx / chExtCx;
60
+ const sy = extCy / chExtCy;
61
+ return (box) => parent({
62
+ x: offX + (box.x - chOffX) * sx,
63
+ y: offY + (box.y - chOffY) * sy,
64
+ cx: box.cx * sx,
65
+ cy: box.cy * sy
66
+ });
67
+ }
68
+ function floatAt(box) {
69
+ return {
70
+ wrap: "none",
71
+ posH: {
72
+ relativeFrom: "page",
73
+ offsetPt: emuToPt(box.x)
74
+ },
75
+ posV: {
76
+ relativeFrom: "page",
77
+ offsetPt: emuToPt(box.y)
78
+ }
79
+ };
80
+ }
81
+ function parseSp(sp, ctx, transform) {
82
+ const ph = parsePh(sp);
83
+ const colors = ctx.colors ?? defaultColorResolver;
84
+ const spPr = poChildren(sp).find((c) => poIs(c, "p:spPr"));
85
+ let own = parseXfrmBox(spPr);
86
+ if (!own && ph && ctx.cascade) own = ctx.cascade.geometryFor(ph);
87
+ if (!own) return void 0;
88
+ const box = transform(own);
89
+ const txBody = poChildren(sp).find((c) => poIs(c, "p:txBody"));
90
+ const text = txBody ? parseTxBody(txBody, ph, ctx.cascade, colors, ctx.resolveHyperlink) : void 0;
91
+ const geometry = parseGeometry(spPr);
92
+ const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
93
+ const line = spPr ? parseLine(spPr, colors) : void 0;
94
+ const visibleLine = line !== void 0 && line.fill !== "none";
95
+ if (!text && fill.kind === "none" && !visibleLine) return void 0;
96
+ return {
97
+ float: floatAt(box),
98
+ width: emuToPt(box.cx),
99
+ height: emuToPt(box.cy),
100
+ geometry,
101
+ fill,
102
+ ...line ? { line } : {},
103
+ ...text ? { text } : {},
104
+ paragraphProperties: {}
105
+ };
106
+ }
107
+ function parseGraphicFrame(gf, ctx, transform) {
108
+ const own = boxFromXfrm(poChildren(gf).find((c) => poIs(c, "p:xfrm")));
109
+ if (!own) return void 0;
110
+ const box = transform(own);
111
+ const graphicData = poFindDescendant(gf, "a:graphicData");
112
+ const uri = graphicData ? poAttr(graphicData, "uri") : void 0;
113
+ if (uri === CHART_URI) {
114
+ const cChart = poFindDescendant(gf, "c:chart");
115
+ const relId = cChart ? poAttr(cChart, "id") : void 0;
116
+ const key = relId !== void 0 ? ctx.resolveChart?.(relId) : void 0;
117
+ if (key === void 0) return void 0;
118
+ return {
119
+ kind: "chart",
120
+ chart: {
121
+ float: floatAt(box),
122
+ chartRelId: key,
123
+ width: emuToPt(box.cx),
124
+ height: emuToPt(box.cy),
125
+ paragraphProperties: {}
126
+ }
127
+ };
128
+ }
129
+ if (uri === TABLE_URI) {
130
+ const tbl = poFindDescendant(gf, "a:tbl");
131
+ return tbl ? {
132
+ kind: "table",
133
+ table: parseTable(tbl, ctx.colors ?? defaultColorResolver)
134
+ } : void 0;
135
+ }
136
+ }
137
+ function parseBackgroundFill(bg, colors) {
138
+ const bgPr = poChildren(bg).find((c) => poIs(c, "p:bgPr"));
139
+ if (bgPr) {
140
+ const fill = parseFill(bgPr, colors);
141
+ return fill.kind !== "none" ? fill : void 0;
142
+ }
143
+ const bgRef = poChildren(bg).find((c) => poIs(c, "p:bgRef"));
144
+ if (bgRef) for (const c of poChildren(bgRef)) {
145
+ const hex = resolveColorNode(c, colors);
146
+ if (hex) return {
147
+ kind: "solid",
148
+ colorHex: hex
149
+ };
150
+ }
151
+ }
152
+ function backdropElement(fill, widthPt, heightPt) {
153
+ return {
154
+ kind: "shape",
155
+ shape: {
156
+ float: {
157
+ wrap: "none",
158
+ behind: true,
159
+ posH: {
160
+ relativeFrom: "page",
161
+ offsetPt: emuToPt(0)
162
+ },
163
+ posV: {
164
+ relativeFrom: "page",
165
+ offsetPt: emuToPt(0)
166
+ }
167
+ },
168
+ width: widthPt,
169
+ height: heightPt,
170
+ geometry: RECT_GEOMETRY,
171
+ fill,
172
+ paragraphProperties: {}
173
+ }
174
+ };
175
+ }
176
+ function parseGeometry(spPr) {
177
+ if (!spPr) return RECT_GEOMETRY;
178
+ const prst = poChildren(spPr).find((c) => poIs(c, "a:prstGeom"));
179
+ if (prst) return parsePrstGeom(prst);
180
+ const cust = poChildren(spPr).find((c) => poIs(c, "a:custGeom"));
181
+ if (cust) return parseCustGeom(cust);
182
+ return RECT_GEOMETRY;
183
+ }
184
+ function parsePic(pic, ctx, transform) {
185
+ const own = parseXfrmBox(poChildren(pic).find((c) => poIs(c, "p:spPr")));
186
+ if (!own) return void 0;
187
+ const box = transform(own);
188
+ const blipFill = poChildren(pic).find((c) => poIs(c, "p:blipFill"));
189
+ const blip = blipFill ? poChildren(blipFill).find((c) => poIs(c, "a:blip")) : void 0;
190
+ const relId = blip ? poAttr(blip, "embed") : void 0;
191
+ const resource = relId !== void 0 ? ctx.resolveImage?.(relId) : void 0;
192
+ const altText = picAltText(pic);
193
+ return {
194
+ float: floatAt(box),
195
+ ...resource !== void 0 ? { resource } : {},
196
+ width: emuToPt(box.cx),
197
+ height: emuToPt(box.cy),
198
+ paragraphProperties: {},
199
+ ...altText ? { altText } : {}
200
+ };
201
+ }
202
+ function picAltText(pic) {
203
+ const nvPicPr = poChildren(pic).find((c) => poIs(c, "p:nvPicPr"));
204
+ const cNvPr = nvPicPr ? poChildren(nvPicPr).find((c) => poIs(c, "p:cNvPr")) : void 0;
205
+ const descr = cNvPr ? poAttr(cNvPr, "descr") : void 0;
206
+ const title = cNvPr ? poAttr(cNvPr, "title") : void 0;
207
+ return (descr ?? title)?.trim() || void 0;
208
+ }
209
+ function txBodyParagraphs(txBody, ph, cascade, colors, resolveLink) {
210
+ const content = [];
211
+ const counters = [];
212
+ for (const child of poChildren(txBody)) {
213
+ if (!poIs(child, "a:p")) continue;
214
+ content.push({
215
+ kind: "paragraph",
216
+ paragraph: parseSlideParagraph(child, ph, cascade, colors, resolveLink, counters)
217
+ });
218
+ }
219
+ return content;
220
+ }
221
+ function parseTxBody(txBody, ph, cascade, colors, resolveLink) {
222
+ const content = txBodyParagraphs(txBody, ph, cascade, colors, resolveLink);
223
+ if (content.length === 0) return void 0;
224
+ const bodyPr = poChildren(txBody).find((c) => poIs(c, "a:bodyPr"));
225
+ const lIns = bodyPr ? poIntAttr(bodyPr, "lIns") : void 0;
226
+ const tIns = bodyPr ? poIntAttr(bodyPr, "tIns") : void 0;
227
+ const rIns = bodyPr ? poIntAttr(bodyPr, "rIns") : void 0;
228
+ const bIns = bodyPr ? poIntAttr(bodyPr, "bIns") : void 0;
229
+ const a = bodyPr ? poAttr(bodyPr, "anchor") : void 0;
230
+ const anchor = a === "ctr" ? "ctr" : a === "b" ? "b" : a === "t" ? "t" : void 0;
231
+ return {
232
+ content,
233
+ ...lIns !== void 0 ? { insetLeft: emuToPt(lIns) } : {},
234
+ ...tIns !== void 0 ? { insetTop: emuToPt(tIns) } : {},
235
+ ...rIns !== void 0 ? { insetRight: emuToPt(rIns) } : {},
236
+ ...bIns !== void 0 ? { insetBottom: emuToPt(bIns) } : {},
237
+ ...anchor ? { anchor } : {}
238
+ };
239
+ }
240
+ function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters) {
241
+ const pPr = poChildren(aP).find((c) => poIs(c, "a:pPr"));
242
+ const level = (pPr ? poIntAttr(pPr, "lvl") : void 0) ?? 0;
243
+ const defaults = ph && cascade ? cascade.defaultsFor(ph, level) : {};
244
+ const algn = pPr ? poAttr(pPr, "algn") : void 0;
245
+ const alignment = algn !== void 0 ? ALGN_TO_ALIGNMENT[algn] : void 0;
246
+ const runs = [];
247
+ const marker = bulletMarker(pPr, level, counters);
248
+ if (marker !== void 0) runs.push({
249
+ text: marker,
250
+ properties: defaults,
251
+ listMarker: true
252
+ });
253
+ for (const child of poChildren(aP)) if (poIs(child, "a:r") || poIs(child, "a:fld")) {
254
+ const run = parseSlideRun(child, defaults, colors, resolveLink);
255
+ if (run) runs.push(run);
256
+ }
257
+ const marL = pPr ? poIntAttr(pPr, "marL") : void 0;
258
+ const indent = pPr ? poIntAttr(pPr, "indent") : void 0;
259
+ const indentLeft = marL !== void 0 ? emuToPt(marL) : level > 0 ? emuToPt(level * 457200) : void 0;
260
+ return {
261
+ properties: {
262
+ ...alignment ? { alignment } : {},
263
+ ...indentLeft !== void 0 ? { indentLeft } : {},
264
+ ...indent !== void 0 ? { indentFirstLine: emuToPt(indent) } : {}
265
+ },
266
+ runs
267
+ };
268
+ }
269
+ function bulletMarker(pPr, level, counters) {
270
+ if (!pPr) return void 0;
271
+ if (poChildren(pPr).some((c) => poIs(c, "a:buNone"))) return void 0;
272
+ const buChar = poChildren(pPr).find((c) => poIs(c, "a:buChar"));
273
+ if (buChar) return `${poAttr(buChar, "char") ?? "•"} `;
274
+ const buAuto = poChildren(pPr).find((c) => poIs(c, "a:buAutoNum"));
275
+ if (!buAuto) return void 0;
276
+ const type = poAttr(buAuto, "type") ?? "arabicPeriod";
277
+ const startAt = poIntAttr(buAuto, "startAt") ?? 1;
278
+ const prev = counters[level];
279
+ const n = (prev === void 0 ? startAt - 1 : prev) + 1;
280
+ counters[level] = n;
281
+ counters.length = level + 1;
282
+ return `${n}${autoNumSuffix(type)} `;
283
+ }
284
+ function autoNumSuffix(type) {
285
+ if (type.endsWith("ParenR") || type.endsWith("ParenBoth")) return ")";
286
+ if (type.endsWith("Period")) return ".";
287
+ return "";
288
+ }
289
+ function parseSlideRun(node, defaults, colors, resolveLink) {
290
+ const t = poChildren(node).find((c) => poIs(c, "a:t"));
291
+ const text = t ? poText(t) : "";
292
+ if (text.length === 0) return void 0;
293
+ const rPr = poChildren(node).find((c) => poIs(c, "a:rPr"));
294
+ const hlink = rPr ? poChildren(rPr).find((c) => poIs(c, "a:hlinkClick")) : void 0;
295
+ const linkId = hlink ? poAttr(hlink, "id") : void 0;
296
+ const href = linkId !== void 0 ? resolveLink?.(linkId) : void 0;
297
+ return {
298
+ text,
299
+ properties: {
300
+ ...defaults,
301
+ ...rPrToRunProps(rPr, colors)
302
+ },
303
+ ...href ? { href } : {}
304
+ };
305
+ }
306
+ function parseTable(tbl, colors) {
307
+ const grid = [];
308
+ const tblGrid = poChildren(tbl).find((c) => poIs(c, "a:tblGrid"));
309
+ if (tblGrid) {
310
+ for (const col of poChildren(tblGrid)) if (poIs(col, "a:gridCol")) grid.push(emuToPt(poIntAttr(col, "w") ?? 0));
311
+ }
312
+ const rows = [];
313
+ for (const tr of poChildren(tbl)) if (poIs(tr, "a:tr")) rows.push(parseTableRow(tr, colors));
314
+ return {
315
+ properties: {},
316
+ grid,
317
+ rows
318
+ };
319
+ }
320
+ function parseTableRow(tr, colors) {
321
+ const h = poIntAttr(tr, "h");
322
+ const cells = [];
323
+ for (const tc of poChildren(tr)) {
324
+ if (!poIs(tc, "a:tc")) continue;
325
+ if (poAttr(tc, "hMerge") === "1") continue;
326
+ cells.push(parseTableCell(tc, colors));
327
+ }
328
+ return {
329
+ properties: { ...h !== void 0 ? { height: emuToPt(h) } : {} },
330
+ cells
331
+ };
332
+ }
333
+ function parseTableCell(tc, colors) {
334
+ const txBody = poChildren(tc).find((c) => poIs(c, "a:txBody"));
335
+ const content = txBody ? txBodyParagraphs(txBody, void 0, void 0, colors, void 0) : [];
336
+ const gridSpan = poIntAttr(tc, "gridSpan");
337
+ const rowSpan = poIntAttr(tc, "rowSpan");
338
+ const merge = rowSpan !== void 0 && rowSpan > 1 ? "start" : poAttr(tc, "vMerge") === "1" ? "middle" : void 0;
339
+ const tcPr = poChildren(tc).find((c) => poIs(c, "a:tcPr"));
340
+ const shadingHex = tcPr ? cellFillHex(tcPr, colors) : void 0;
341
+ return {
342
+ properties: {
343
+ ...gridSpan !== void 0 && gridSpan > 1 ? { colSpan: gridSpan } : {},
344
+ ...merge ? { merge } : {},
345
+ ...shadingHex ? { shading: { colorHex: shadingHex } } : {}
346
+ },
347
+ content
348
+ };
349
+ }
350
+ function cellFillHex(tcPr, colors) {
351
+ const solidFill = poChildren(tcPr).find((c) => poIs(c, "a:solidFill"));
352
+ if (!solidFill) return void 0;
353
+ for (const c of poChildren(solidFill)) {
354
+ const hex = resolveColorNode(c, colors);
355
+ if (hex) return hex;
356
+ }
357
+ }
358
+ //#endregion
359
+ export { backdropElement, parseBackgroundFill, parseSlideShapes };
@@ -0,0 +1,17 @@
1
+ import { RunProperties } from '../core/document-model/index.js';
2
+ import { ColorResolver } from '../core/drawingml/colors.js';
3
+ import { PoNode } from '../core/po-helpers.js';
4
+ export interface PlaceholderRef {
5
+ readonly type?: string;
6
+ readonly idx?: string;
7
+ }
8
+ export interface ShapeBoxEmu {
9
+ readonly x: number;
10
+ readonly y: number;
11
+ readonly cx: number;
12
+ readonly cy: number;
13
+ }
14
+ export declare function parsePh(sp: PoNode): PlaceholderRef | undefined;
15
+ export declare function boxFromXfrm(xfrm: PoNode | undefined): ShapeBoxEmu | undefined;
16
+ export declare function parseXfrmBox(spPr: PoNode | undefined): ShapeBoxEmu | undefined;
17
+ export declare function rPrToRunProps(rPr: PoNode | undefined, colors: ColorResolver): RunProperties;
@@ -0,0 +1,60 @@
1
+ import { pt } from "../core/ir/units.js";
2
+ import { poAttr, poChildren, poIntAttr, poIs } from "../core/po-helpers.js";
3
+ import { resolveColorNode } from "../core/drawingml/colors.js";
4
+ //#region src/pptx/sp-helpers.ts
5
+ var isTrue = (v) => v === "1" || v === "true" || v === "on";
6
+ function parsePh(sp) {
7
+ const nvSpPr = poChildren(sp).find((c) => poIs(c, "p:nvSpPr"));
8
+ const nvPr = nvSpPr ? poChildren(nvSpPr).find((c) => poIs(c, "p:nvPr")) : void 0;
9
+ const ph = nvPr ? poChildren(nvPr).find((c) => poIs(c, "p:ph")) : void 0;
10
+ if (!ph) return void 0;
11
+ const type = poAttr(ph, "type");
12
+ const idx = poAttr(ph, "idx");
13
+ return {
14
+ ...type !== void 0 ? { type } : {},
15
+ ...idx !== void 0 ? { idx } : {}
16
+ };
17
+ }
18
+ function boxFromXfrm(xfrm) {
19
+ if (!xfrm) return void 0;
20
+ const off = poChildren(xfrm).find((c) => poIs(c, "a:off"));
21
+ const ext = poChildren(xfrm).find((c) => poIs(c, "a:ext"));
22
+ const cx = ext ? poIntAttr(ext, "cx") : void 0;
23
+ const cy = ext ? poIntAttr(ext, "cy") : void 0;
24
+ if (cx === void 0 || cy === void 0 || cx <= 0 || cy <= 0) return void 0;
25
+ return {
26
+ x: (off ? poIntAttr(off, "x") : void 0) ?? 0,
27
+ y: (off ? poIntAttr(off, "y") : void 0) ?? 0,
28
+ cx,
29
+ cy
30
+ };
31
+ }
32
+ function parseXfrmBox(spPr) {
33
+ return boxFromXfrm(spPr ? poChildren(spPr).find((c) => poIs(c, "a:xfrm")) : void 0);
34
+ }
35
+ function rPrToRunProps(rPr, colors) {
36
+ if (!rPr) return {};
37
+ const sz = poIntAttr(rPr, "sz");
38
+ const u = poAttr(rPr, "u");
39
+ const colorHex = solidFillColor(rPr, colors);
40
+ const latin = poChildren(rPr).find((c) => poIs(c, "a:latin"));
41
+ const typeface = latin ? poAttr(latin, "typeface")?.trim() : void 0;
42
+ return {
43
+ ...isTrue(poAttr(rPr, "b")) ? { bold: true } : {},
44
+ ...isTrue(poAttr(rPr, "i")) ? { italic: true } : {},
45
+ ...u !== void 0 && u !== "none" ? { underline: "single" } : {},
46
+ ...sz !== void 0 ? { fontSizePt: pt(sz / 100) } : {},
47
+ ...colorHex ? { colorHex } : {},
48
+ ...typeface ? { fontFamily: { ascii: typeface } } : {}
49
+ };
50
+ }
51
+ function solidFillColor(rPr, colors) {
52
+ const solidFill = poChildren(rPr).find((c) => poIs(c, "a:solidFill"));
53
+ if (!solidFill) return void 0;
54
+ for (const c of poChildren(solidFill)) {
55
+ const hex = resolveColorNode(c, colors);
56
+ if (hex) return hex;
57
+ }
58
+ }
59
+ //#endregion
60
+ export { boxFromXfrm, parsePh, parseXfrmBox, rPrToRunProps };