quicklook-pptx-renderer 0.1.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +266 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +175 -0
  5. package/dist/diff/compare.d.ts +17 -0
  6. package/dist/diff/compare.js +71 -0
  7. package/dist/index.d.ts +29 -0
  8. package/dist/index.js +72 -0
  9. package/dist/lint.d.ts +27 -0
  10. package/dist/lint.js +328 -0
  11. package/dist/mapper/bleed-map.d.ts +6 -0
  12. package/dist/mapper/bleed-map.js +1 -0
  13. package/dist/mapper/constants.d.ts +2 -0
  14. package/dist/mapper/constants.js +4 -0
  15. package/dist/mapper/drawable-mapper.d.ts +16 -0
  16. package/dist/mapper/drawable-mapper.js +1464 -0
  17. package/dist/mapper/html-generator.d.ts +13 -0
  18. package/dist/mapper/html-generator.js +539 -0
  19. package/dist/mapper/image-mapper.d.ts +14 -0
  20. package/dist/mapper/image-mapper.js +70 -0
  21. package/dist/mapper/nano-malloc.d.ts +130 -0
  22. package/dist/mapper/nano-malloc.js +197 -0
  23. package/dist/mapper/ql-bleed.d.ts +35 -0
  24. package/dist/mapper/ql-bleed.js +254 -0
  25. package/dist/mapper/shape-mapper.d.ts +41 -0
  26. package/dist/mapper/shape-mapper.js +2384 -0
  27. package/dist/mapper/slide-mapper.d.ts +4 -0
  28. package/dist/mapper/slide-mapper.js +112 -0
  29. package/dist/mapper/style-builder.d.ts +12 -0
  30. package/dist/mapper/style-builder.js +30 -0
  31. package/dist/mapper/text-mapper.d.ts +14 -0
  32. package/dist/mapper/text-mapper.js +302 -0
  33. package/dist/model/enums.d.ts +25 -0
  34. package/dist/model/enums.js +2 -0
  35. package/dist/model/types.d.ts +482 -0
  36. package/dist/model/types.js +7 -0
  37. package/dist/package/content-types.d.ts +1 -0
  38. package/dist/package/content-types.js +4 -0
  39. package/dist/package/package.d.ts +10 -0
  40. package/dist/package/package.js +52 -0
  41. package/dist/package/relationships.d.ts +6 -0
  42. package/dist/package/relationships.js +25 -0
  43. package/dist/package/zip.d.ts +6 -0
  44. package/dist/package/zip.js +17 -0
  45. package/dist/reader/color.d.ts +3 -0
  46. package/dist/reader/color.js +79 -0
  47. package/dist/reader/drawing.d.ts +17 -0
  48. package/dist/reader/drawing.js +403 -0
  49. package/dist/reader/effects.d.ts +2 -0
  50. package/dist/reader/effects.js +83 -0
  51. package/dist/reader/fill.d.ts +2 -0
  52. package/dist/reader/fill.js +94 -0
  53. package/dist/reader/presentation.d.ts +5 -0
  54. package/dist/reader/presentation.js +127 -0
  55. package/dist/reader/slide-layout.d.ts +2 -0
  56. package/dist/reader/slide-layout.js +28 -0
  57. package/dist/reader/slide-master.d.ts +4 -0
  58. package/dist/reader/slide-master.js +49 -0
  59. package/dist/reader/slide.d.ts +2 -0
  60. package/dist/reader/slide.js +26 -0
  61. package/dist/reader/text-list-style.d.ts +2 -0
  62. package/dist/reader/text-list-style.js +9 -0
  63. package/dist/reader/text.d.ts +5 -0
  64. package/dist/reader/text.js +295 -0
  65. package/dist/reader/theme.d.ts +2 -0
  66. package/dist/reader/theme.js +109 -0
  67. package/dist/reader/transform.d.ts +2 -0
  68. package/dist/reader/transform.js +21 -0
  69. package/dist/render/image-renderer.d.ts +3 -0
  70. package/dist/render/image-renderer.js +33 -0
  71. package/dist/render/renderer.d.ts +9 -0
  72. package/dist/render/renderer.js +178 -0
  73. package/dist/render/shape-renderer.d.ts +3 -0
  74. package/dist/render/shape-renderer.js +175 -0
  75. package/dist/render/text-renderer.d.ts +3 -0
  76. package/dist/render/text-renderer.js +152 -0
  77. package/dist/resolve/color-resolver.d.ts +18 -0
  78. package/dist/resolve/color-resolver.js +321 -0
  79. package/dist/resolve/font-map.d.ts +2 -0
  80. package/dist/resolve/font-map.js +66 -0
  81. package/dist/resolve/inheritance.d.ts +5 -0
  82. package/dist/resolve/inheritance.js +106 -0
  83. package/package.json +74 -0
package/dist/lint.js ADDED
@@ -0,0 +1,328 @@
1
+ /**
2
+ * QuickLook PPTX Linter — detect compatibility issues before they surprise users.
3
+ *
4
+ * Parses a PPTX and checks every shape, text run, table, and fill against
5
+ * known OfficeImport quirks. No rendering required — just parse and check.
6
+ */
7
+ import { PptxPackage } from "./package/package.js";
8
+ import { readPresentation } from "./reader/presentation.js";
9
+ import { SUPPORTED_GEOMETRIES } from "./mapper/shape-mapper.js";
10
+ // ── Font substitution table (same as resolve/font-map.ts) ───────────
11
+ const SUBSTITUTED_FONTS = {
12
+ "Calibri": "Helvetica Neue",
13
+ "Calibri Light": "Helvetica Neue Light",
14
+ "Arial": "Helvetica",
15
+ "Arial Black": "Helvetica Neue",
16
+ "Arial Narrow": "Helvetica Neue",
17
+ "Cambria": "Georgia",
18
+ "Consolas": "Menlo",
19
+ "Courier New": "Courier",
20
+ "Times New Roman": "Times",
21
+ "Tahoma": "Geneva",
22
+ "Segoe UI": "Helvetica Neue",
23
+ "Segoe UI Light": "Helvetica Neue Light",
24
+ "Segoe UI Semibold": "Helvetica Neue Medium",
25
+ "Century Gothic": "Futura",
26
+ "Franklin Gothic Medium": "Avenir Next Medium",
27
+ "Corbel": "Avenir Next",
28
+ "Candara": "Avenir",
29
+ "Constantia": "Georgia",
30
+ };
31
+ // Geometries where text inscription differs from a simple rect inset
32
+ const NON_RECT_TEXT_GEOMETRIES = new Set([
33
+ "roundRect", "ellipse", "diamond", "triangle", "rtTriangle",
34
+ "parallelogram", "trapezoid", "hexagon", "octagon", "pentagon",
35
+ "star4", "star5", "star6", "star8",
36
+ ]);
37
+ // ── Main API ────────────────────────────────────────────────────────
38
+ export async function lint(pptxBuffer) {
39
+ const pkg = await PptxPackage.open(pptxBuffer);
40
+ const pres = await readPresentation(pkg);
41
+ const issues = [];
42
+ for (let i = 0; i < pres.slides.length; i++) {
43
+ const slide = pres.slides[i];
44
+ const slideNum = i + 1;
45
+ lintDrawables(slide.drawables, slideNum, issues);
46
+ }
47
+ // Deduplicate font substitution warnings (one per font, not per run)
48
+ deduplicateFonts(issues);
49
+ return {
50
+ issues,
51
+ summary: {
52
+ errors: issues.filter(i => i.severity === "error").length,
53
+ warnings: issues.filter(i => i.severity === "warn").length,
54
+ info: issues.filter(i => i.severity === "info").length,
55
+ slides: pres.slides.length,
56
+ },
57
+ };
58
+ }
59
+ // ── Drawable walker ─────────────────────────────────────────────────
60
+ function lintDrawables(drawables, slide, issues) {
61
+ for (const d of drawables) {
62
+ switch (d.drawableType) {
63
+ case "sp":
64
+ lintShape(d, slide, issues);
65
+ break;
66
+ case "pic":
67
+ lintPicture(d, slide, issues);
68
+ break;
69
+ case "grpSp":
70
+ lintGroup(d, slide, issues);
71
+ break;
72
+ case "cxnSp":
73
+ lintConnector(d, slide, issues);
74
+ break;
75
+ case "graphicFrame":
76
+ lintGraphicFrame(d, slide, issues);
77
+ break;
78
+ }
79
+ }
80
+ }
81
+ // ── Shape checks ────────────────────────────────────────────────────
82
+ function lintShape(shape, slide, issues) {
83
+ const geom = shape.geometry?.preset ?? "rect";
84
+ const name = shape.name || `shape #${shape.id}`;
85
+ // 1. Unsupported geometry → invisible
86
+ if (geom !== "rect" && !SUPPORTED_GEOMETRIES.has(geom)) {
87
+ issues.push({
88
+ rule: "unsupported-geometry",
89
+ severity: "error",
90
+ slide, element: name,
91
+ message: `"${geom}" is not supported by OfficeImport — this shape will be invisible in QuickLook`,
92
+ suggestion: `Use a supported preset (rect, roundRect, ellipse, etc.) or embed as an image`,
93
+ });
94
+ return; // no point checking further
95
+ }
96
+ // 2. Non-rect → rendered as opaque PDF (covers content behind it)
97
+ const hasEffects = shape.effects && shape.effects.length > 0;
98
+ const hasRotation = shape.bounds?.rot && shape.bounds.rot !== 0;
99
+ if (geom !== "rect" || hasRotation) {
100
+ if (hasEffects) {
101
+ issues.push({
102
+ rule: "opaque-pdf-block",
103
+ severity: "warn",
104
+ slide, element: name,
105
+ message: `"${geom}" with effects renders as an opaque PDF image — it will cover content behind it with a white background`,
106
+ suggestion: `Remove drop shadow/glow effects, or use a plain rect to keep CSS rendering`,
107
+ });
108
+ }
109
+ else if (geom !== "rect") {
110
+ issues.push({
111
+ rule: "effect-forces-pdf",
112
+ severity: "info",
113
+ slide, element: name,
114
+ message: `"${geom}" renders as PDF in QuickLook (only plain rect uses CSS)`,
115
+ });
116
+ }
117
+ if (hasRotation && geom === "rect") {
118
+ issues.push({
119
+ rule: "rotation-forces-pdf",
120
+ severity: "info",
121
+ slide, element: name,
122
+ message: `Rotated rect renders as PDF instead of CSS div`,
123
+ });
124
+ }
125
+ }
126
+ // 3. Effects on rect also force PDF
127
+ if (geom === "rect" && !hasRotation && hasEffects) {
128
+ issues.push({
129
+ rule: "opaque-pdf-block",
130
+ severity: "warn",
131
+ slide, element: name,
132
+ message: `rect with effects (shadow/glow) renders as opaque PDF — covers content behind it`,
133
+ suggestion: `Remove effects to keep lightweight CSS rendering`,
134
+ });
135
+ }
136
+ // 4. Non-rect text inscription shift
137
+ if (NON_RECT_TEXT_GEOMETRIES.has(geom) && hasNonEmptyText(shape.textBody)) {
138
+ issues.push({
139
+ rule: "text-inscription-shift",
140
+ severity: "warn",
141
+ slide, element: name,
142
+ message: `Text in "${geom}" uses geometry-inscribed bounds — text position will differ from PowerPoint`,
143
+ suggestion: `Use rect for predictable text positioning, or test the specific geometry`,
144
+ });
145
+ }
146
+ // 5. Gradient flattening
147
+ lintFill(shape.fill, slide, name, issues);
148
+ // 6. Font substitution in text
149
+ if (shape.textBody)
150
+ lintTextBody(shape.textBody, slide, name, issues);
151
+ // 7. Vertical text
152
+ if (shape.textBody?.properties?.vert && shape.textBody.properties.vert !== "horz") {
153
+ issues.push({
154
+ rule: "vertical-text",
155
+ severity: "info",
156
+ slide, element: name,
157
+ message: `Vertical text (${shape.textBody.properties.vert}) — rendering uses CSS writing-mode, may differ from PowerPoint`,
158
+ });
159
+ }
160
+ }
161
+ // ── Picture checks ──────────────────────────────────────────────────
162
+ function lintPicture(_pic, _slide, _issues) {
163
+ // Pictures are straightforward — OfficeImport handles them well
164
+ }
165
+ // ── Group checks ────────────────────────────────────────────────────
166
+ function lintGroup(group, slide, issues) {
167
+ const name = group.name || `group #${group.id}`;
168
+ issues.push({
169
+ rule: "group-as-pdf",
170
+ severity: "info",
171
+ slide, element: name,
172
+ message: `Group renders as single PDF image in QuickLook — all children merged into one opaque block`,
173
+ });
174
+ // Still lint children for their own issues
175
+ lintDrawables(group.children, slide, issues);
176
+ }
177
+ // ── Connector checks ────────────────────────────────────────────────
178
+ function lintConnector(_conn, _slide, _issues) {
179
+ // Connectors are always PDF, no special warnings needed
180
+ }
181
+ // ── GraphicFrame (tables/charts) ────────────────────────────────────
182
+ function lintGraphicFrame(frame, slide, issues) {
183
+ const name = frame.name || `frame #${frame.id}`;
184
+ // Chart without fallback image
185
+ if (frame.chartRId && !frame.fallbackImageData) {
186
+ issues.push({
187
+ rule: "chart-no-fallback",
188
+ severity: "error",
189
+ slide, element: name,
190
+ message: `Chart has no fallback image — will render as blank rectangle in QuickLook`,
191
+ suggestion: `Save from PowerPoint (not python-pptx) to generate fallback images, or use mc:AlternateContent`,
192
+ });
193
+ }
194
+ // Table checks
195
+ if (frame.tableData) {
196
+ lintTable(frame.tableData, slide, name, issues);
197
+ }
198
+ }
199
+ function lintTable(table, slide, element, issues) {
200
+ // Check for table style reference without explicit borders
201
+ if (table.tableStyleId) {
202
+ const hasMissingBorders = table.rows.some(row => row.cells.some(cell => !hasExplicitBorders(cell)));
203
+ if (hasMissingBorders) {
204
+ issues.push({
205
+ rule: "table-style-unresolved",
206
+ severity: "warn",
207
+ slide, element,
208
+ message: `Table uses style "${table.tableStyleId}" but some cells lack explicit borders — OfficeImport may not resolve the style`,
209
+ suggestion: `Set borders explicitly on each cell (cell.border_top, etc.)`,
210
+ });
211
+ }
212
+ }
213
+ // Check for cells with no borders at all
214
+ const noBorderCells = table.rows.reduce((count, row) => count + row.cells.filter(cell => !cell.hMerge && !cell.vMerge && !hasAnyBorder(cell)).length, 0);
215
+ const totalCells = table.rows.reduce((count, row) => count + row.cells.filter(cell => !cell.hMerge && !cell.vMerge).length, 0);
216
+ if (noBorderCells > 0 && noBorderCells === totalCells) {
217
+ issues.push({
218
+ rule: "table-missing-borders",
219
+ severity: "warn",
220
+ slide, element,
221
+ message: `All ${totalCells} table cells have no explicit borders — table will appear borderless in QuickLook`,
222
+ suggestion: `Add explicit borders to cells if borders are expected`,
223
+ });
224
+ }
225
+ // Lint text in table cells
226
+ for (const row of table.rows) {
227
+ for (const cell of row.cells) {
228
+ if (cell.textBody)
229
+ lintTextBody(cell.textBody, slide, element, issues);
230
+ lintFill(cell.fill, slide, element, issues);
231
+ }
232
+ }
233
+ }
234
+ function hasExplicitBorders(cell) {
235
+ if (!cell.borders)
236
+ return false;
237
+ const b = cell.borders;
238
+ return !!(b.top?.fill || b.bottom?.fill || b.left?.fill || b.right?.fill);
239
+ }
240
+ function hasAnyBorder(cell) {
241
+ if (!cell.borders)
242
+ return false;
243
+ const b = cell.borders;
244
+ return !!(b.top?.width || b.bottom?.width || b.left?.width || b.right?.width);
245
+ }
246
+ // ── Fill checks ─────────────────────────────────────────────────────
247
+ function lintFill(fill, slide, element, issues) {
248
+ if (!fill || fill.type !== "gradient")
249
+ return;
250
+ const grad = fill;
251
+ if (grad.stops.length >= 3) {
252
+ issues.push({
253
+ rule: "gradient-flattened",
254
+ severity: "warn",
255
+ slide, element,
256
+ message: `Gradient with ${grad.stops.length} stops will be flattened to a single average color in QuickLook`,
257
+ suggestion: `Use exactly 2 gradient stops for proper rendering, or accept flat color`,
258
+ });
259
+ }
260
+ }
261
+ // ── Text checks ─────────────────────────────────────────────────────
262
+ function lintTextBody(body, slide, element, issues) {
263
+ for (const para of body.paragraphs) {
264
+ for (const run of para.runs) {
265
+ if (run.type !== "r" && run.type !== "fld")
266
+ continue;
267
+ const props = run.properties;
268
+ if (!props)
269
+ continue;
270
+ const font = props.latinFont;
271
+ if (font && SUBSTITUTED_FONTS[font]) {
272
+ issues.push({
273
+ rule: "font-substitution",
274
+ severity: "info",
275
+ slide, element,
276
+ message: `"${font}" → "${SUBSTITUTED_FONTS[font]}" on macOS — metrics will differ, may cause text reflow`,
277
+ });
278
+ }
279
+ }
280
+ }
281
+ }
282
+ // ── Helpers ─────────────────────────────────────────────────────────
283
+ function hasNonEmptyText(body) {
284
+ if (!body)
285
+ return false;
286
+ return body.paragraphs.some(p => p.runs.some(r => r.type !== "br" && "text" in r && String(r.text ?? "").trim() !== ""));
287
+ }
288
+ function deduplicateFonts(issues) {
289
+ const seen = new Set();
290
+ for (let i = issues.length - 1; i >= 0; i--) {
291
+ if (issues[i].rule !== "font-substitution")
292
+ continue;
293
+ const key = issues[i].message;
294
+ if (seen.has(key)) {
295
+ issues.splice(i, 1);
296
+ }
297
+ else {
298
+ seen.add(key);
299
+ }
300
+ }
301
+ }
302
+ // ── Formatting ──────────────────────────────────────────────────────
303
+ const SEVERITY_ICON = {
304
+ error: "ERR ",
305
+ warn: "WARN",
306
+ info: "INFO",
307
+ };
308
+ export function formatIssues(result) {
309
+ if (result.issues.length === 0) {
310
+ return `No QuickLook compatibility issues found across ${result.summary.slides} slides.`;
311
+ }
312
+ const lines = [];
313
+ let currentSlide = -1;
314
+ for (const issue of result.issues) {
315
+ if (issue.slide !== currentSlide) {
316
+ currentSlide = issue.slide;
317
+ lines.push(`\nSlide ${currentSlide}:`);
318
+ }
319
+ const icon = SEVERITY_ICON[issue.severity];
320
+ const elem = issue.element ? ` (${issue.element})` : "";
321
+ lines.push(` [${icon}] ${issue.message}${elem}`);
322
+ if (issue.suggestion) {
323
+ lines.push(` -> ${issue.suggestion}`);
324
+ }
325
+ }
326
+ lines.push(`\n${result.summary.errors} errors, ${result.summary.warnings} warnings, ${result.summary.info} info across ${result.summary.slides} slides`);
327
+ return lines.join("\n");
328
+ }
@@ -0,0 +1,6 @@
1
+ export interface BleedEntry {
2
+ style: string;
3
+ pdfFile: string;
4
+ afterOwnElement: number;
5
+ }
6
+ export declare const BLEED_MAP: Record<number, BleedEntry[]>;
@@ -0,0 +1 @@
1
+ export const BLEED_MAP = { "5": [{ "style": "position:absolute; top:232; left:23; width:349; height:155;", "pdfFile": "bleed-0.pdf", "afterOwnElement": 7 }], "6": [{ "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-1.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:102; left:340; width:342; height:140;", "pdfFile": "bleed-2.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:66; left:469; width:241; height:183;", "pdfFile": "bleed-3.pdf", "afterOwnElement": 20 }], "7": [{ "style": "position:absolute; top:232; left:23; width:349; height:155;", "pdfFile": "bleed-4.pdf", "afterOwnElement": 1 }, { "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-5.pdf", "afterOwnElement": 6 }, { "style": "position:absolute; top:66; left:246; width:241; height:183;", "pdfFile": "bleed-6.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:106; left:23; width:601; height:284;", "pdfFile": "bleed-7.pdf", "afterOwnElement": 11 }], "8": [{ "style": "position:absolute; top:102; left:340; width:342; height:140;", "pdfFile": "bleed-8.pdf", "afterOwnElement": 3 }, { "style": "position:absolute; top:66; left:469; width:241; height:183;", "pdfFile": "bleed-9.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:66; left:23; width:241; height:183;", "pdfFile": "bleed-10.pdf", "afterOwnElement": 13 }], "9": [{ "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-11.pdf", "afterOwnElement": 2 }, { "style": "position:absolute; top:232; left:354; width:349; height:155;", "pdfFile": "bleed-12.pdf", "afterOwnElement": 7 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-13.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-14.pdf", "afterOwnElement": 18 }, { "style": "position:absolute; top:232; left:23; width:349; height:155;", "pdfFile": "bleed-15.pdf", "afterOwnElement": 21 }, { "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-16.pdf", "afterOwnElement": 26 }], "10": [{ "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-17.pdf", "afterOwnElement": 1 }, { "style": "position:absolute; top:232; left:23; width:349; height:155;", "pdfFile": "bleed-18.pdf", "afterOwnElement": 6 }, { "style": "position:absolute; top:62; left:347; width:349; height:327;", "pdfFile": "bleed-19.pdf", "afterOwnElement": 8 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-20.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-21.pdf", "afterOwnElement": 13 }, { "style": "position:absolute; top:224; left:340; width:342; height:140;", "pdfFile": "bleed-22.pdf", "afterOwnElement": 16 }, { "style": "position:absolute; top:95; left:476; width:248; height:241;", "pdfFile": "bleed-23.pdf", "afterOwnElement": 20 }, { "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-24.pdf", "afterOwnElement": 26 }], "12": [{ "style": "position:absolute; top:59; left:476; width:248; height:270;", "pdfFile": "bleed-25.pdf", "afterOwnElement": 12 }, { "style": "position:absolute; top:66; left:246; width:241; height:183;", "pdfFile": "bleed-26.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-27.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:95; left:476; width:248; height:241;", "pdfFile": "bleed-28.pdf", "afterOwnElement": 22 }, { "style": "position:absolute; top:232; left:354; width:349; height:155;", "pdfFile": "bleed-29.pdf", "afterOwnElement": 23 }, { "style": "position:absolute; top:224; left:340; width:342; height:140;", "pdfFile": "bleed-30.pdf", "afterOwnElement": 25 }, { "style": "position:absolute; top:62; left:23; width:349; height:327;", "pdfFile": "bleed-31.pdf", "afterOwnElement": 26 }], "13": [{ "style": "position:absolute; top:232; left:354; width:349; height:155;", "pdfFile": "bleed-32.pdf", "afterOwnElement": 5 }, { "style": "position:absolute; top:95; left:476; width:248; height:241;", "pdfFile": "bleed-33.pdf", "afterOwnElement": 7 }, { "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-34.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:66; left:246; width:241; height:183;", "pdfFile": "bleed-35.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:59; left:476; width:248; height:270;", "pdfFile": "bleed-36.pdf", "afterOwnElement": 16 }, { "style": "position:absolute; top:300; left:23; width:673; height:79;", "pdfFile": "bleed-37.pdf", "afterOwnElement": 18 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-38.pdf", "afterOwnElement": 30 }, { "style": "position:absolute; top:66; left:23; width:241; height:183;", "pdfFile": "bleed-39.pdf", "afterOwnElement": 31 }, { "style": "position:absolute; top:95; left:23; width:248; height:241;", "pdfFile": "bleed-40.pdf", "afterOwnElement": 33 }, { "style": "position:absolute; top:66; left:469; width:241; height:183;", "pdfFile": "bleed-41.pdf", "afterOwnElement": 35 }], "14": [{ "style": "position:absolute; top:124; left:491; width:183; height:241;", "pdfFile": "bleed-42.pdf", "afterOwnElement": 6 }, { "style": "position:absolute; top:84; left:505; width:61; height:61;", "pdfFile": "bleed-43.pdf", "afterOwnElement": 9 }], "15": [{ "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-44.pdf", "afterOwnElement": 5 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-45.pdf", "afterOwnElement": 10 }], "16": [{ "style": "position:absolute; top:253; left:458; width:237; height:133;", "pdfFile": "bleed-46.pdf", "afterOwnElement": 3 }, { "style": "position:absolute; top:253; left:242; width:237; height:133;", "pdfFile": "bleed-47.pdf", "afterOwnElement": 6 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-48.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-49.pdf", "afterOwnElement": 11 }, { "style": "position:absolute; top:84; left:347; width:61; height:61;", "pdfFile": "bleed-50.pdf", "afterOwnElement": 12 }, { "style": "position:absolute; top:124; left:332; width:183; height:241;", "pdfFile": "bleed-51.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:95; left:23; width:248; height:241;", "pdfFile": "bleed-52.pdf", "afterOwnElement": 15 }, { "style": "position:absolute; top:66; left:469; width:241; height:183;", "pdfFile": "bleed-53.pdf", "afterOwnElement": 17 }, { "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-54.pdf", "afterOwnElement": 24 }, { "style": "position:absolute; top:59; left:476; width:248; height:270;", "pdfFile": "bleed-55.pdf", "afterOwnElement": 30 }], "17": [{ "style": "position:absolute; top:343; left:23; width:673; height:54;", "pdfFile": "bleed-56.pdf", "afterOwnElement": 1 }, { "style": "position:absolute; top:59; left:476; width:248; height:270;", "pdfFile": "bleed-57.pdf", "afterOwnElement": 2 }, { "style": "position:absolute; top:275; left:376; width:57; height:57;", "pdfFile": "bleed-58.pdf", "afterOwnElement": 3 }, { "style": "position:absolute; top:224; left:376; width:57; height:57;", "pdfFile": "bleed-59.pdf", "afterOwnElement": 5 }, { "style": "position:absolute; top:174; left:376; width:57; height:57;", "pdfFile": "bleed-60.pdf", "afterOwnElement": 7 }, { "style": "position:absolute; top:102; left:23; width:342; height:140;", "pdfFile": "bleed-61.pdf", "afterOwnElement": 8 }, { "style": "position:absolute; top:124; left:376; width:57; height:57;", "pdfFile": "bleed-62.pdf", "afterOwnElement": 9 }, { "style": "position:absolute; top:59; left:354; width:349; height:292;", "pdfFile": "bleed-63.pdf", "afterOwnElement": 12 }, { "style": "position:absolute; top:275; left:44; width:57; height:57;", "pdfFile": "bleed-64.pdf", "afterOwnElement": 13 }, { "style": "position:absolute; top:66; left:469; width:241; height:183;", "pdfFile": "bleed-65.pdf", "afterOwnElement": 14 }, { "style": "position:absolute; top:224; left:44; width:57; height:57;", "pdfFile": "bleed-66.pdf", "afterOwnElement": 15 }, { "style": "position:absolute; top:95; left:23; width:248; height:241;", "pdfFile": "bleed-67.pdf", "afterOwnElement": 15 }, { "style": "position:absolute; top:124; left:332; width:183; height:241;", "pdfFile": "bleed-68.pdf", "afterOwnElement": 16 }, { "style": "position:absolute; top:124; left:44; width:57; height:57;", "pdfFile": "bleed-69.pdf", "afterOwnElement": 17 }, { "style": "position:absolute; top:84; left:347; width:61; height:61;", "pdfFile": "bleed-70.pdf", "afterOwnElement": 18 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-71.pdf", "afterOwnElement": 19 }, { "style": "position:absolute; top:59; left:23; width:349; height:292;", "pdfFile": "bleed-72.pdf", "afterOwnElement": 19 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-73.pdf", "afterOwnElement": 20 }, { "style": "position:absolute; top:253; left:242; width:237; height:133;", "pdfFile": "bleed-74.pdf", "afterOwnElement": 22 }, { "style": "position:absolute; top:253; left:458; width:237; height:133;", "pdfFile": "bleed-75.pdf", "afterOwnElement": 24 }, { "style": "position:absolute; top:66; left:246; width:241; height:183;", "pdfFile": "bleed-76.pdf", "afterOwnElement": 26 }, { "style": "position:absolute; top:84; left:30; width:61; height:61;", "pdfFile": "bleed-77.pdf", "afterOwnElement": 27 }, { "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-78.pdf", "afterOwnElement": 28 }], "18": [{ "style": "position:absolute; top:314; left:23; width:673; height:79;", "pdfFile": "bleed-79.pdf", "afterOwnElement": 2 }, { "style": "position:absolute; top:84; left:30; width:61; height:61;", "pdfFile": "bleed-80.pdf", "afterOwnElement": 4 }, { "style": "position:absolute; top:66; left:246; width:241; height:183;", "pdfFile": "bleed-81.pdf", "afterOwnElement": 5 }, { "style": "position:absolute; top:253; left:458; width:237; height:133;", "pdfFile": "bleed-82.pdf", "afterOwnElement": 8 }, { "style": "position:absolute; top:253; left:242; width:237; height:133;", "pdfFile": "bleed-83.pdf", "afterOwnElement": 12 }, { "style": "position:absolute; top:95; left:250; width:248; height:241;", "pdfFile": "bleed-84.pdf", "afterOwnElement": 15 }, { "style": "position:absolute; top:59; left:23; width:349; height:292;", "pdfFile": "bleed-85.pdf", "afterOwnElement": 16 }, { "style": "position:absolute; top:224; left:23; width:342; height:140;", "pdfFile": "bleed-86.pdf", "afterOwnElement": 17 }, { "style": "position:absolute; top:84; left:347; width:61; height:61;", "pdfFile": "bleed-87.pdf", "afterOwnElement": 18 }, { "style": "position:absolute; top:124; left:44; width:57; height:57;", "pdfFile": "bleed-88.pdf", "afterOwnElement": 19 }] };
@@ -0,0 +1,2 @@
1
+ export declare const EMU_PER_PX = 12700;
2
+ export declare function emuToPx(emu: number): number;
@@ -0,0 +1,4 @@
1
+ export const EMU_PER_PX = 12700;
2
+ export function emuToPx(emu) {
3
+ return Math.trunc(emu / EMU_PER_PX);
4
+ }
@@ -0,0 +1,16 @@
1
+ import type { Drawable, ColorMap, ColorScheme, FontScheme, StyleMatrix, Slide } from "../model/types.js";
2
+ import type { PptxPackage } from "../package/package.js";
3
+ import type { StyleBuilder } from "./style-builder.js";
4
+ export declare function clearDrawableCache(): void;
5
+ export interface MapperContext {
6
+ colorMap: ColorMap;
7
+ colorScheme: ColorScheme;
8
+ fontScheme: FontScheme;
9
+ styleMatrix?: StyleMatrix;
10
+ slide?: Slide;
11
+ pkg?: PptxPackage;
12
+ slideIndex: number;
13
+ slidePath: string;
14
+ imageRels: Map<string, Buffer>;
15
+ }
16
+ export declare function mapDrawable(drawable: Drawable, styles: StyleBuilder, attachments: Map<string, Buffer>, ctx: MapperContext, drawableIndex?: number): string;