@mkabatek/pptx-viewer 1.5.4 → 1.5.5

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 (43) hide show
  1. package/package.json +2 -9
  2. package/node_modules/emf-converter/LICENSE +0 -21
  3. package/node_modules/emf-converter/README.md +0 -629
  4. package/node_modules/emf-converter/dist/index.d.mts +0 -86
  5. package/node_modules/emf-converter/dist/index.d.ts +0 -86
  6. package/node_modules/emf-converter/dist/index.js +0 -4257
  7. package/node_modules/emf-converter/dist/index.mjs +0 -4253
  8. package/node_modules/emf-converter/package.json +0 -53
  9. package/node_modules/mtx-decompressor/LICENSE +0 -373
  10. package/node_modules/mtx-decompressor/README.md +0 -271
  11. package/node_modules/mtx-decompressor/dist/index.d.mts +0 -84
  12. package/node_modules/mtx-decompressor/dist/index.d.ts +0 -84
  13. package/node_modules/mtx-decompressor/dist/index.js +0 -1532
  14. package/node_modules/mtx-decompressor/dist/index.mjs +0 -1528
  15. package/node_modules/mtx-decompressor/package.json +0 -44
  16. package/node_modules/pptx-viewer-core/LICENSE +0 -21
  17. package/node_modules/pptx-viewer-core/NOTICE +0 -16
  18. package/node_modules/pptx-viewer-core/README.md +0 -1294
  19. package/node_modules/pptx-viewer-core/dist/SvgExporter-BtZczTlB.d.ts +0 -557
  20. package/node_modules/pptx-viewer-core/dist/SvgExporter-D4mBWJHE.d.mts +0 -557
  21. package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +0 -150
  22. package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +0 -150
  23. package/node_modules/pptx-viewer-core/dist/cli/index.js +0 -0
  24. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +0 -0
  25. package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +0 -48
  26. package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +0 -48
  27. package/node_modules/pptx-viewer-core/dist/converter/index.js +0 -0
  28. package/node_modules/pptx-viewer-core/dist/converter/index.mjs +0 -0
  29. package/node_modules/pptx-viewer-core/dist/index.d.mts +0 -12744
  30. package/node_modules/pptx-viewer-core/dist/index.d.ts +0 -12744
  31. package/node_modules/pptx-viewer-core/dist/index.js +0 -66894
  32. package/node_modules/pptx-viewer-core/dist/index.mjs +0 -66420
  33. package/node_modules/pptx-viewer-core/dist/presentation-nZxgWvXq.d.mts +0 -5645
  34. package/node_modules/pptx-viewer-core/dist/presentation-nZxgWvXq.d.ts +0 -5645
  35. package/node_modules/pptx-viewer-core/dist/signature-inspection-status-BCUpfCQh.d.mts +0 -220
  36. package/node_modules/pptx-viewer-core/dist/signature-inspection-status-BCUpfCQh.d.ts +0 -220
  37. package/node_modules/pptx-viewer-core/dist/signature-node/index.d.mts +0 -177
  38. package/node_modules/pptx-viewer-core/dist/signature-node/index.d.ts +0 -177
  39. package/node_modules/pptx-viewer-core/dist/signature-node/index.js +0 -1206
  40. package/node_modules/pptx-viewer-core/dist/signature-node/index.mjs +0 -1143
  41. package/node_modules/pptx-viewer-core/dist/text-operations-DCTGMltY.d.mts +0 -134
  42. package/node_modules/pptx-viewer-core/dist/text-operations-DYmhoi7U.d.ts +0 -134
  43. package/node_modules/pptx-viewer-core/package.json +0 -96
@@ -1,1294 +0,0 @@
1
- # pptx-viewer-core
2
-
3
- A framework-agnostic TypeScript engine for **parsing**, **editing**, **serialising**, and **converting** PowerPoint (.pptx) files. Operates entirely in-memory on the OpenXML ZIP archive with no native dependencies.
4
-
5
- ## Table of Contents
6
-
7
- - [pptx-viewer-core](#pptx-viewer-core)
8
- - [Table of Contents](#table-of-contents)
9
- - [Overview](#overview)
10
- - [Quick Start](#quick-start)
11
- - [API Reference](#api-reference)
12
- - [PptxHandler](#pptxhandler)
13
- - [PptxMarkdownConverter](#pptxmarkdownconverter)
14
- - [PptxXmlBuilder (Fluent API)](#pptxxmlbuilder-fluent-api)
15
- - [Architecture](#architecture)
16
- - [High-Level Architecture](#high-level-architecture)
17
- - [Module Map](#module-map)
18
- - [Load Pipeline](#load-pipeline)
19
- - [Save Pipeline](#save-pipeline)
20
- - [Runtime Mixin Composition](#runtime-mixin-composition)
21
- - [Deep Dive: How It Works](#deep-dive-how-it-works)
22
- - [1. OpenXML ZIP Structure](#1-openxml-zip-structure)
23
- - [2. Type System](#2-type-system)
24
- - [3. Theme Resolution Chain](#3-theme-resolution-chain)
25
- - [4. Geometry Engine](#4-geometry-engine)
26
- - [5. Colour Processing](#5-colour-processing)
27
- - [6. Converter System](#6-converter-system)
28
- - [7. Services Layer](#7-services-layer)
29
- - [8. Builder APIs (Fluent SDK)](#8-builder-apis-fluent-sdk)
30
- - [9. Encryption and Security](#9-encryption-and-security)
31
- - [Type System Reference](#type-system-reference)
32
- - [Feature Summary](#feature-summary)
33
- - [File Structure Reference](#file-structure-reference)
34
- - [Limitations](#limitations)
35
-
36
- ---
37
-
38
- ## Overview
39
-
40
- PowerPoint files (.pptx) are ZIP archives containing XML documents conforming to the [Office Open XML (OOXML)](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/) specification. This package provides a complete TypeScript SDK for working with those files:
41
-
42
- | Capability | Description |
43
- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
44
- | **Parse** | Unzip, parse XML, and extract slides, elements, themes, masters, layouts, media, charts, SmartArt, comments, animations, transitions, and document properties |
45
- | **Edit** | Mutate the in-memory data model (add/remove/reorder slides, insert elements, modify text, change styles, update themes) |
46
- | **Save** | Serialise the modified data model back into a valid .pptx ZIP archive with full round-trip fidelity |
47
- | **Convert** | Transform parsed PPTX data into Markdown with optional media extraction |
48
- | **Export** | Export individual slides as standalone .pptx files |
49
- | **Encrypt/Decrypt** | Handle password-protected PPTX files using AES-128/256 Agile encryption |
50
-
51
- The library has only two peer dependencies: **jszip** (ZIP handling) and **fast-xml-parser** (XML parse/build).
52
-
53
- ---
54
-
55
- ## Quick Start
56
-
57
- ```typescript
58
- import { PptxHandler } from 'pptx-viewer-core';
59
-
60
- // 1. Parse a PPTX file
61
- const handler = new PptxHandler();
62
- const buffer = await fetch('presentation.pptx').then((r) => r.arrayBuffer());
63
- const data = await handler.load(buffer);
64
-
65
- console.log(`${data.slides.length} slides loaded`);
66
- console.log(`Canvas: ${data.canvasSize.width} x ${data.canvasSize.height}`);
67
-
68
- // 2. Modify slides
69
- data.slides[0].elements[0].text = 'Updated title';
70
-
71
- // 3. Save back to .pptx
72
- const outputBytes = await handler.save(data.slides);
73
- // => Uint8Array of a valid .pptx file
74
-
75
- // 4. Export individual slides
76
- const exports = await handler.exportSlides(data.slides, {
77
- slideIndexes: [0, 2],
78
- });
79
- // => Map<number, Uint8Array>
80
- ```
81
-
82
- ### Create from scratch (Fluent API)
83
-
84
- ```typescript
85
- import { Presentation, ThemePresets, TextBuilder, ChartBuilder } from 'pptx-viewer-core';
86
-
87
- const pptx = await Presentation.create({
88
- title: 'Sales Report',
89
- theme: ThemePresets.MODERN_BLUE,
90
- });
91
-
92
- // Slides are auto-tracked — no manual .build() or .push() needed
93
- pptx
94
- .addSlide('Title Slide')
95
- .addText('Q4 Sales Report', { fontSize: 44, bold: true, x: 100, y: 200, width: 800, height: 80 });
96
-
97
- pptx
98
- .addSlide('Blank')
99
- .addText('Revenue by Region', { fontSize: 28, x: 50, y: 30, width: 600, height: 50 })
100
- .addBuilderElement(
101
- ChartBuilder.create('bar')
102
- .categories(['North', 'South', 'East', 'West'])
103
- .addSeries('2026', [210, 150, 180, 120], '#2563EB')
104
- .title('Revenue ($M)')
105
- .bounds(50, 100, 860, 420),
106
- );
107
-
108
- // Find and replace, merge, template — all fluent
109
- pptx.replaceText('2026', 'FY2026');
110
-
111
- const bytes = await pptx.save();
112
- ```
113
-
114
- ### PPTX to Markdown conversion
115
-
116
- ```typescript
117
- import { PptxMarkdownConverter } from 'pptx-viewer-core';
118
-
119
- const converter = new PptxMarkdownConverter({
120
- includeMetadata: true,
121
- includeSlideNumbers: true,
122
- imageHandling: 'extract',
123
- });
124
-
125
- const markdown = await converter.convert(
126
- buffer,
127
- {
128
- outputPath: 'output.md',
129
- mediaFolderName: 'media',
130
- includeMetadata: true,
131
- },
132
- fileSystemAdapter,
133
- );
134
- // => ConversionResult with markdown string + extracted media stats
135
- ```
136
-
137
- ---
138
-
139
- ## API Reference
140
-
141
- ### PptxHandler
142
-
143
- The primary facade for loading, editing, and saving PPTX files.
144
-
145
- | Method | Signature | Description |
146
- | -------------------------------- | --------------------------------------------------------------- | ------------------------------------------ |
147
- | `load` | `(data: ArrayBuffer, options?) => Promise<PptxData>` | Parse a .pptx buffer into structured data |
148
- | `save` | `(slides: PptxSlide[], options?) => Promise<Uint8Array>` | Serialise slides back to .pptx bytes |
149
- | `exportSlides` | `(slides, options) => Promise<Map<number, Uint8Array>>` | Export selected slides as standalone files |
150
- | `getImageData` | `(path: string) => Promise<string \| undefined>` | Get base64 data URL for an embedded image |
151
- | `getMediaArrayBuffer` | `(path: string) => Promise<ArrayBuffer \| undefined>` | Get raw bytes for an embedded media file |
152
- | `getChartDataForGraphicFrame` | `(slidePath, xmlObj) => Promise<PptxChartData \| undefined>` | Extract chart data from a graphic frame |
153
- | `getSmartArtDataForGraphicFrame` | `(slidePath, xmlObj) => Promise<PptxSmartArtData \| undefined>` | Extract SmartArt data from a graphic frame |
154
- | `getLayoutOptions` | `() => PptxLayoutOption[]` | Get available slide layout options |
155
- | `getCompatibilityWarnings` | `() => PptxCompatibilityWarning[]` | Get warnings about unsupported features |
156
- | `createXmlBuilder` / `Builder` | `(data: PptxData) => PptxXmlBuilder` | Create a fluent XML builder |
157
- | `applyTheme` | `(colors, fonts, name?) => Promise<void>` | Apply a complete theme |
158
- | `updateThemeColorScheme` | `(scheme) => Promise<void>` | Modify theme colours |
159
- | `updateThemeFontScheme` | `(scheme) => Promise<void>` | Modify theme fonts |
160
- | `setPresentationTheme` | `(path, applyToAll?) => Promise<void>` | Load a .thmx theme file |
161
-
162
- ### PptxMarkdownConverter
163
-
164
- Converts PPTX files to Markdown documents. Extends the abstract `DocumentConverter` base class.
165
-
166
- | Method | Signature | Description |
167
- | --------- | ----------------------------------------------------- | ------------------------------- |
168
- | `convert` | `(buffer, options, fs?) => Promise<ConversionResult>` | Convert PPTX buffer to Markdown |
169
-
170
- Requires a `FileSystemAdapter` for disk output:
171
-
172
- ```typescript
173
- interface FileSystemAdapter {
174
- writeFile(path: string, content: string): Promise<void>;
175
- writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
176
- createFolder(path: string): Promise<void>;
177
- }
178
- ```
179
-
180
- ### PptxXmlBuilder (Fluent API)
181
-
182
- A chainable builder for constructing OpenXML nodes directly in the runtime's in-memory ZIP.
183
-
184
- ```typescript
185
- const builder = handler.Builder(data);
186
- // Use fluent methods to construct and insert XML elements
187
- ```
188
-
189
- ---
190
-
191
- ## Architecture
192
-
193
- ### High-Level Architecture
194
-
195
- The package follows a layered architecture with clear separation of concerns:
196
-
197
- ```mermaid
198
- flowchart TB
199
- subgraph "Public API"
200
- A[PptxHandler]
201
- B[PptxMarkdownConverter]
202
- end
203
-
204
- subgraph "Facade Layer"
205
- C[PptxHandlerCore]
206
- end
207
-
208
- subgraph "Runtime Engine"
209
- D["IPptxHandlerRuntime<br/>(interface)"]
210
- E["PptxHandlerRuntime<br/>(50+ mixin modules)"]
211
- end
212
-
213
- subgraph "Supporting Modules"
214
- F[Types -- 22 modules]
215
- G[Geometry -- 17 modules]
216
- H[Colour -- 4 modules]
217
- I[Services -- 21 modules]
218
- J[Builders -- 11 modules]
219
- K[Utils -- 32 modules]
220
- end
221
-
222
- subgraph "Converter System"
223
- L[DocumentConverter base]
224
- M[SlideProcessor]
225
- N["Element Processors<br/>(11 types)"]
226
- O[MediaContext]
227
- end
228
-
229
- A --> C
230
- C --> D
231
- D -.->|implemented by| E
232
- E --> F
233
- E --> G
234
- E --> H
235
- E --> I
236
- E --> J
237
- E --> K
238
-
239
- B --> L
240
- L --> M
241
- M --> N
242
- M --> O
243
- ```
244
-
245
- ### Module Map
246
-
247
- ```mermaid
248
- graph TB
249
- subgraph "Entry Points"
250
- IDX["src/index.ts<br/>Package entry"]
251
- CIDX["src/core/index.ts<br/>Core barrel"]
252
- VIDX["src/converter/index.ts<br/>Converter barrel"]
253
- end
254
-
255
- subgraph "Handler Facade"
256
- PH["PptxHandler.ts<br/>Public class"]
257
- PHC["PptxHandlerCore.ts<br/>Facade over runtime"]
258
- end
259
-
260
- subgraph "Runtime (core/core/)"
261
- RT["PptxHandlerRuntime.ts<br/>Sealed final class"]
262
- RTF["PptxHandlerRuntimeFactory.ts<br/>DI factory"]
263
- RTI["PptxHandlerRuntimeImplementation.ts<br/>Top of mixin chain"]
264
- RTLP["...LoadPipeline.ts"]
265
- RTSP["...SavePipeline.ts"]
266
- RTMS["...50+ mixin modules"]
267
- end
268
-
269
- subgraph "Types (core/types/)"
270
- TE["elements.ts -- PptxElement union"]
271
- TT["text.ts -- TextStyle, Paragraph"]
272
- TS["shape-style.ts -- ShapeStyle"]
273
- TC["chart.ts -- PptxChartData"]
274
- TH["theme.ts -- PptxTheme"]
275
- TMORE["...17 more type modules"]
276
- end
277
-
278
- subgraph "Geometry (core/geometry/)"
279
- SG["shape-geometry.ts"]
280
- CG["connector-geometry.ts"]
281
- GF["guide-formula.ts"]
282
- PS["preset-shape-definitions.ts"]
283
- end
284
-
285
- subgraph "Services (core/services/)"
286
- SL["PptxSlideLoaderService"]
287
- AN["PptxNativeAnimationService"]
288
- AW["PptxAnimationWriteService"]
289
- TR["PptxSlideTransitionService"]
290
- CP["PptxCompatibilityService"]
291
- end
292
-
293
- IDX --> CIDX
294
- IDX --> VIDX
295
- CIDX --> PH
296
- PH --> PHC
297
- PHC --> RT
298
- RT --> RTI
299
- RTI --> RTLP
300
- RTLP --> RTSP
301
- RTSP --> RTMS
302
- ```
303
-
304
- ### Load Pipeline
305
-
306
- When `handler.load(buffer)` is called, the following sequence occurs:
307
-
308
- ```mermaid
309
- sequenceDiagram
310
- participant C as Caller
311
- participant H as PptxHandler
312
- participant R as Runtime
313
- participant Z as JSZip
314
- participant X as fast-xml-parser
315
-
316
- C->>H: load(arrayBuffer)
317
- H->>H: detectFileFormat(buffer)
318
- alt Encrypted
319
- H->>H: decryptOoxml(buffer, password)
320
- end
321
- H->>R: load(buffer, options)
322
- R->>Z: loadAsync(buffer)
323
- Note over R: ZIP opened in memory
324
-
325
- R->>R: Parse [Content_Types].xml
326
- R->>R: Parse ppt/presentation.xml
327
- R->>X: Parse XML -> JS objects
328
-
329
- loop For each slide master
330
- R->>R: Parse theme, colour map, layouts
331
- end
332
-
333
- loop For each slide
334
- R->>R: Parse slide XML
335
- R->>R: Resolve layout -> master -> theme chain
336
- R->>R: Parse elements (shapes, images, charts, tables, SmartArt, OLE, 3D models, zoom)
337
- R->>R: Parse text with style inheritance
338
- R->>R: Parse animations & transitions
339
- R->>R: Extract media relationships
340
- end
341
-
342
- R->>R: Parse comments, doc properties, embedded fonts
343
- R-->>C: PptxData { slides, canvasSize, theme, masters, ... }
344
- ```
345
-
346
- ### Save Pipeline
347
-
348
- When `handler.save(slides)` is called:
349
-
350
- ```mermaid
351
- sequenceDiagram
352
- participant C as Caller
353
- participant H as PptxHandler
354
- participant R as Runtime
355
- participant Z as JSZip
356
-
357
- C->>H: save(slides, options)
358
- H->>R: save(slides, options)
359
-
360
- R->>R: Reconcile slide list (added/removed/reordered)
361
- R->>R: Update ppt/presentation.xml
362
-
363
- loop For each slide
364
- R->>R: Build slide XML from element data
365
- R->>R: Serialise text paragraphs + run properties
366
- R->>R: Write shape styles, effects, transforms
367
- R->>R: Update relationships (images, charts, media)
368
- R->>R: Write animation timing trees
369
- R->>R: Update slide notes
370
- end
371
-
372
- R->>R: Update [Content_Types].xml
373
- R->>R: Write doc properties, comments
374
- R->>R: Preserve VBA macros, custom XML parts
375
- R->>Z: Generate ZIP (compression: DEFLATE)
376
- R-->>C: Uint8Array (.pptx bytes)
377
- ```
378
-
379
- ### Runtime Mixin Composition
380
-
381
- The runtime is assembled from 50+ mixin modules using a linear inheritance chain. Each module adds a focused set of capabilities:
382
-
383
- ```mermaid
384
- graph LR
385
- A["State<br/>(base fields)"] --> B["ThemeLoading"]
386
- B --> C["ThemeProcessing"]
387
- C --> D["ThemeOverrides"]
388
- D --> E["SlideMasters"]
389
- E --> F["BackgroundParsing"]
390
- F --> G["ElementParsing"]
391
- G --> H["ShapeParsing"]
392
- H --> I["TextParsing"]
393
- I --> J["ChartParsing"]
394
- J --> K["...30+ more"]
395
- K --> L["SavePipeline"]
396
- L --> M["LoadPipeline"]
397
- M --> N["Implementation<br/>(top of chain)"]
398
- ```
399
-
400
- Each file exports a class named `PptxHandlerRuntime` that extends the previous module's export, adding its own methods. The final `PptxHandlerRuntimeImplementation` aggregates all functionality into the complete runtime.
401
-
402
- ---
403
-
404
- ## Deep Dive: How It Works
405
-
406
- ### 1. OpenXML ZIP Structure
407
-
408
- A .pptx file is a ZIP archive with this internal structure:
409
-
410
- ```
411
- presentation.pptx (ZIP)
412
- +-- [Content_Types].xml <- MIME type registry
413
- +-- _rels/.rels <- Root relationships
414
- +-- docProps/
415
- | +-- app.xml <- Application properties
416
- | +-- core.xml <- Dublin Core metadata
417
- | +-- custom.xml <- Custom properties
418
- +-- ppt/
419
- +-- presentation.xml <- Slide list, canvas size, slide master refs
420
- +-- presProps.xml <- Presentation properties (show type, loop, etc.)
421
- +-- viewProps.xml <- View state (zoom, grid, guides)
422
- +-- tableStyles.xml <- Table style definitions
423
- +-- _rels/presentation.xml.rels
424
- +-- theme/
425
- | +-- theme1.xml <- Colour scheme, fonts, format scheme
426
- +-- slideMasters/
427
- | +-- slideMaster1.xml <- Master slide (background, placeholders)
428
- +-- slideLayouts/
429
- | +-- slideLayout1.xml <- Layout templates
430
- +-- slides/
431
- | +-- slide1.xml <- Slide content (shape tree)
432
- | +-- _rels/slide1.xml.rels <- Per-slide relationships
433
- +-- media/
434
- | +-- image1.png <- Embedded images
435
- | +-- video1.mp4 <- Embedded media
436
- | +-- model1.glb <- 3D models
437
- +-- charts/
438
- | +-- chart1.xml <- Chart definitions
439
- +-- notesSlides/
440
- | +-- notesSlide1.xml <- Speaker notes
441
- +-- diagrams/ <- SmartArt data
442
- +-- embeddings/ <- OLE embedded files
443
- +-- customXml/ <- Custom XML parts
444
- +-- vbaProject.bin <- VBA macros (if present)
445
- ```
446
-
447
- The runtime uses **jszip** to read/write this archive and **fast-xml-parser** to parse/build the XML documents.
448
-
449
- ### 2. Type System
450
-
451
- The type system is organised into 22 domain-specific modules with a discriminated union pattern for elements:
452
-
453
- ```mermaid
454
- graph TB
455
- subgraph "PptxElement (discriminated union -- 16 types)"
456
- direction LR
457
- TX["type: 'text'"]
458
- SH["type: 'shape'"]
459
- CN["type: 'connector'"]
460
- IM["type: 'image'"]
461
- PC["type: 'picture'"]
462
- TB["type: 'table'"]
463
- CH["type: 'chart'"]
464
- SA["type: 'smartArt'"]
465
- OL["type: 'ole'"]
466
- MD["type: 'media'"]
467
- GR["type: 'group'"]
468
- IK["type: 'ink'"]
469
- CP["type: 'contentPart'"]
470
- ZM["type: 'zoom'"]
471
- M3["type: 'model3d'"]
472
- UK["type: 'unknown'"]
473
- end
474
-
475
- subgraph "Shared Properties (PptxElementBase)"
476
- ID["id, name, type"]
477
- POS["x, y, width, height, rotation"]
478
- STY["shapeStyle?: ShapeStyle"]
479
- ACT["action?: ElementAction"]
480
- ANI["animations?: PptxElementAnimation[]"]
481
- end
482
-
483
- SH --> SHARED["+ text, paragraphs, textBody, geometry"]
484
- IM --> IPROPS["+ imagePath, imageData, imageEffects, crop"]
485
- TB --> TPROPS["+ tableData (rows, columns, cells, styles)"]
486
- CH --> CPROPS["+ chartData (type, series, axes, legend)"]
487
- CN --> CNPROPS["+ connectorType, startConnection, endConnection"]
488
- M3 --> MPROPS["+ modelPath, modelData, modelMimeType"]
489
- ```
490
-
491
- **Key type modules:**
492
-
493
- | Module | Types |
494
- | ----------------- | -------------------------------------------------------------------- |
495
- | `common.ts` | `XmlObject`, `PptxData`, `PptxSlide`, `PptxCanvasSize` |
496
- | `elements.ts` | `PptxElement` discriminated union (16 variants) |
497
- | `element-base.ts` | `PptxElementBase` shared properties |
498
- | `text.ts` | `TextStyle`, `ParagraphStyle`, `TextSegment`, `TextBody` |
499
- | `shape-style.ts` | `ShapeStyle`, `FillStyle`, `StrokeStyle`, `ShadowEffect` |
500
- | `table.ts` | `TableData`, `TableCell`, `TableRow`, `TableBorderStyle` |
501
- | `chart.ts` | `PptxChartData`, `ChartSeries`, `ChartAxis` (23 chart types) |
502
- | `theme.ts` | `PptxTheme`, `PptxThemeColorScheme`, `PptxThemeFontScheme` |
503
- | `animation.ts` | `PptxElementAnimation`, `PptxAnimationPreset` |
504
- | `transition.ts` | `PptxSlideTransition` (42 transition types) |
505
- | `masters.ts` | `PptxSlideMaster`, `PptxSlideLayout` |
506
- | `image.ts` | `ImageEffects`, `ImageCrop` |
507
- | `geometry.ts` | `PptxCustomGeometry`, `GeometryPath` |
508
- | `smart-art.ts` | `PptxSmartArtData`, `SmartArtNode` |
509
- | `media.ts` | `PptxMediaData`, `MediaTiming`, `MediaBookmark`, `MediaCaptionTrack` |
510
- | `metadata.ts` | `CoreProperties`, `AppProperties` |
511
- | `three-d.ts` | `ThreeDProperties`, `BevelType` |
512
- | `type-guards.ts` | Runtime type guard functions for PptxElement variants |
513
-
514
- ### 3. Theme Resolution Chain
515
-
516
- PowerPoint elements inherit visual styles through a multi-level chain. The runtime resolves styles in this order:
517
-
518
- ```mermaid
519
- flowchart TD
520
- A["Element Direct Formatting<br/>(inline styles in shape XML)"] --> B{"Has property?"}
521
- B -->|Yes| Z["Use element value"]
522
- B -->|No| C["Placeholder on Layout<br/>(matching idx + type)"]
523
- C --> D{"Has property?"}
524
- D -->|Yes| Z
525
- D -->|No| E["Placeholder on Master<br/>(matching idx + type)"]
526
- E --> F{"Has property?"}
527
- F -->|Yes| Z
528
- F -->|No| G["Theme Defaults<br/>(a:objectDefaults / lstStyle)"]
529
- G --> H{"Has property?"}
530
- H -->|Yes| Z
531
- H -->|No| I["Hardcoded Fallback<br/>(black text, no fill)"]
532
- I --> Z
533
- ```
534
-
535
- **Theme colour references** (e.g. `accent1`, `dk1`, `lt2`) are resolved through the theme's `a:clrScheme`, optionally overridden by the slide master's `p:clrMap` and the layout's `p:clrMapOvr`.
536
-
537
- The engine ships with **8 built-in theme presets** and supports runtime theme switching with layout switching and placeholder remapping.
538
-
539
- ### 4. Geometry Engine
540
-
541
- The geometry module (17 files) handles shape path generation and coordinate transforms:
542
-
543
- | Module | Purpose |
544
- | ----------------------------- | --------------------------------------------------------- |
545
- | `shape-geometry.ts` | Main entry -- resolves shape type, clip path, image masks |
546
- | `connector-geometry.ts` | Connector routing and path generation |
547
- | `guide-formula.ts` | OOXML DrawingML guide formula evaluator |
548
- | `guide-formula-eval.ts` | Mathematical expression evaluation engine |
549
- | `guide-formula-paths.ts` | SVG path generation from guide-computed coordinates |
550
- | `preset-shape-definitions.ts` | 187+ preset shape definitions (rect, arrow, star, etc.) |
551
- | `preset-shape-paths.ts` | Pre-computed SVG clip paths for all preset shapes |
552
- | `transform-utils.ts` | Element position/rotation/flip transforms |
553
- | `custom-geometry.ts` | Arbitrary OOXML `<a:custGeom>` path parsing |
554
-
555
- **Guide formula evaluation** implements the OOXML DrawingML formula language:
556
-
557
- ```
558
- +-----------------------------------------------------+
559
- | Guide Formula Language |
560
- | |
561
- | Operators: +/-, */div, val, abs, sqrt, sin, cos, |
562
- | tan, at2, min, max, mod, pin, if, ?: |
563
- | |
564
- | Built-in variables: |
565
- | w (shape width), h (shape height) |
566
- | l, t, r, b (left, top, right, bottom) |
567
- | wd2, hd2 (half width/height) |
568
- | cd2, cd4, cd8 (circle division constants) |
569
- | |
570
- | Adjustment handles: adj, adj1, adj2, ... |
571
- | (user-draggable shape parameters) |
572
- +-----------------------------------------------------+
573
- ```
574
-
575
- ### 5. Colour Processing
576
-
577
- The colour module (4 files) handles OOXML colour parsing and transforms:
578
-
579
- ```mermaid
580
- flowchart LR
581
- A["OOXML Colour Node<br/>(srgbClr / schemeClr /<br/>sysClr / prstClr)"] --> B["parseDrawingColor()"]
582
- B --> C["Resolve base hex"]
583
- C --> D{"Has transforms?"}
584
- D -->|Yes| E["applyDrawingColorTransforms()<br/>lumMod, lumOff, tint, shade,<br/>satMod, alpha, hueMod, etc."]
585
- D -->|No| F["Return #RRGGBB"]
586
- E --> F
587
- ```
588
-
589
- Supported colour transform operations:
590
- | Transform | Effect |
591
- |-----------|--------|
592
- | `lumMod` / `lumOff` | Luminance modulate / offset |
593
- | `tint` / `shade` | Lighten / darken toward white/black |
594
- | `satMod` / `satOff` | Saturation modulate / offset |
595
- | `hueMod` / `hueOff` | Hue rotation |
596
- | `alpha` | Opacity (0--100000 = 0--100%) |
597
- | `comp` | Complementary colour |
598
- | `inv` | Invert colour |
599
- | `gray` | Grayscale conversion |
600
-
601
- ### 6. Converter System
602
-
603
- The PPTX-to-Markdown converter uses a registry pattern for element processing:
604
-
605
- ```mermaid
606
- flowchart TD
607
- A["PptxMarkdownConverter<br/>(extends DocumentConverter)"] --> B["Parse PPTX via PptxHandler"]
608
- B --> C["SlideProcessor<br/>(per-slide orchestration)"]
609
- C --> D{"Element Type?"}
610
-
611
- D -->|shape| E["TextElementProcessor"]
612
- D -->|image| F["ImageElementProcessor"]
613
- D -->|table| G["TableElementProcessor"]
614
- D -->|chart| H["ChartElementProcessor"]
615
- D -->|smartArt| I["SmartArtElementProcessor"]
616
- D -->|group| J["GroupElementProcessor"]
617
- D -->|media| K["MediaElementProcessor"]
618
- D -->|ole| L["OleElementProcessor"]
619
- D -->|ink| M["InkElementProcessor"]
620
- D -->|unknown| N["FallbackElementProcessor"]
621
-
622
- E --> O["Markdown Output"]
623
- F --> O
624
- G --> O
625
- ```
626
-
627
- The converter supports two output modes:
628
-
629
- - **Positioned mode** (default): HTML `<div>` elements with absolute CSS positioning.
630
- - **Semantic mode** (`semanticMode: true`): Clean Markdown with headings, paragraphs, and lists.
631
-
632
- The `MediaContext` class manages image extraction during conversion, mapping data URLs to output file paths and deduplicating identical images.
633
-
634
- ### 7. Services Layer
635
-
636
- Nine specialised services handle cross-cutting concerns:
637
-
638
- | Service | Responsibility |
639
- | ------------------------------- | ------------------------------------------------------------- |
640
- | `PptxSlideLoaderService` | Coordinate slide XML parsing -- elements, notes, media timing |
641
- | `PptxNativeAnimationService` | Parse native OOXML animation timing trees (`p:timing`) |
642
- | `PptxEditorAnimationService` | Map between editor animation presets and OOXML sequences |
643
- | `PptxAnimationWriteService` | Serialise editor animations back to OOXML timing XML |
644
- | `PptxSlideTransitionService` | Parse and write slide transition effects (`p:transition`) |
645
- | `PptxCompatibilityService` | Detect unsupported features and generate warnings |
646
- | `PptxXmlLookupService` | Cached XML lookups across relationships and parts |
647
- | `PptxDocumentPropertiesUpdater` | Update `docProps/core.xml` and `docProps/app.xml` |
648
- | `PptxTemplateBackgroundService` | Manage template/layout background images |
649
-
650
- ### 8. Builder APIs (Fluent SDK)
651
-
652
- The SDK provides a comprehensive fluent API for creating and manipulating presentations programmatically. Three tiers are available, from highest to lowest level:
653
-
654
- #### Tier 1 — `Presentation` (highest level)
655
-
656
- The recommended entry point. Manages slides, text operations, sections, templates, merging, and saving — all with zero boilerplate.
657
-
658
- ```typescript
659
- import {
660
- Presentation,
661
- ThemePresets,
662
- inches,
663
- SlideSizes,
664
- TextBuilder,
665
- ShapeBuilder,
666
- ChartBuilder,
667
- TableBuilder,
668
- ImageBuilder,
669
- ConnectorBuilder,
670
- MediaBuilder,
671
- GroupBuilder,
672
- } from 'pptx-viewer-core';
673
-
674
- // Create a new presentation
675
- const pptx = await Presentation.create({
676
- title: 'Quarterly Report',
677
- creator: 'Sales Team',
678
- width: SlideSizes.WIDESCREEN_16_9.width,
679
- height: SlideSizes.WIDESCREEN_16_9.height,
680
- theme: ThemePresets.MODERN_BLUE,
681
- });
682
-
683
- // Add slides — they are auto-tracked, no manual push or .build() needed
684
- pptx
685
- .addSlide('Title Slide')
686
- .addText('Q4 2026 Results', { fontSize: 44, bold: true, x: 100, y: 200, width: 800, height: 80 })
687
- .addText('Confidential', {
688
- fontSize: 14,
689
- color: '#999999',
690
- x: 100,
691
- y: 300,
692
- width: 800,
693
- height: 30,
694
- })
695
- .setBackground({ type: 'solid', color: '#1B2A4A' })
696
- .setNotes('Open with the revenue highlight')
697
- .setTransition({ type: 'fade', duration: 500 });
698
-
699
- pptx
700
- .addSlide('Blank')
701
- .addText('Revenue grew 15% YoY', { fontSize: 24, x: 50, y: 50, width: 600, height: 40 })
702
- .addChart(
703
- 'bar',
704
- {
705
- series: [
706
- { name: '2025', values: [120, 145, 160, 180], color: '#93C5FD' },
707
- { name: '2026', values: [140, 170, 195, 210], color: '#2563EB' },
708
- ],
709
- categories: ['Q1', 'Q2', 'Q3', 'Q4'],
710
- title: 'Revenue ($M)',
711
- },
712
- { x: 50, y: 100, width: 600, height: 400 },
713
- )
714
- .addShape('roundRect', {
715
- fill: { type: 'solid', color: '#2563EB' },
716
- text: 'See appendix',
717
- x: 700,
718
- y: 450,
719
- width: 200,
720
- height: 40,
721
- });
722
-
723
- // Save to bytes
724
- const bytes = await pptx.save();
725
- ```
726
-
727
- **Full `Presentation` API reference:**
728
-
729
- | Category | Method | Description |
730
- | --------------- | ------------------------------------------------ | --------------------------------------------- |
731
- | **Create/Load** | `Presentation.create(options?)` | Create a new blank presentation |
732
- | | `Presentation.load(buffer)` | Load an existing .pptx file |
733
- | **Slides** | `addSlide(layoutName?)` | Add a slide (returns `SlideBuilder`) |
734
- | | `insertSlide(index, layoutName?)` | Insert a slide at position |
735
- | | `duplicateSlide(slideIndex)` | Deep-clone a slide with new IDs |
736
- | | `removeSlide(index)` | Remove a slide (chainable) |
737
- | | `moveSlide(from, to)` | Move a slide (chainable) |
738
- | | `swapSlides(indexA, indexB)` | Swap two slides (chainable) |
739
- | | `reorderSlides(newOrder)` | Reorder all slides by index array (chainable) |
740
- | | `clearSlides()` | Remove all slides (chainable) |
741
- | | `getSlide(index)` | Get a slide by index |
742
- | | `forEachSlide(callback)` | Iterate slides (chainable) |
743
- | | `findSlides(predicate)` | Find slide indices matching a predicate |
744
- | | `slideCount` | Number of slides |
745
- | **Text** | `findText(search)` | Search all slides for text (string or RegExp) |
746
- | | `replaceText(search, replacement)` | Replace text across all slides |
747
- | | `replaceTextOnSlide(index, search, replacement)` | Replace text on a single slide |
748
- | **Sections** | `addSection(name, slideIndices)` | Group slides into a section |
749
- | | `removeSection(sectionId)` | Remove a section |
750
- | | `reorderSections(sectionIds)` | Reorder sections (chainable) |
751
- | | `getSectionForSlide(slideIndex)` | Get the section a slide belongs to |
752
- | | `moveSlidesToSection(indices, targetId)` | Move slides between sections |
753
- | | `sections` | Get all sections |
754
- | **Template** | `applyTemplate(data)` | Replace `{{placeholders}}` (chainable) |
755
- | | `mailMerge(records)` | Generate multiple files from template data |
756
- | **Merge** | `merge(source, options?)` | Merge another presentation's slides |
757
- | **Diff** | `diff(other)` | Structured comparison of two presentations |
758
- | **Save** | `save()` | Serialize to `.pptx` bytes |
759
- | | `saveEncrypted(password)` | Save with password encryption |
760
- | **Metadata** | `title` | Presentation title |
761
- | | `creator` | Author name |
762
- | | `width` / `height` | Slide dimensions in EMU |
763
- | **Advanced** | `handler` | Underlying `PptxHandler` |
764
- | | `data` | Underlying `PptxData` (live reference) |
765
- | | `slides` | Live slides array |
766
- | | `xmlBuilder()` | Low-level `PptxXmlBuilder` for mutation |
767
- | | `dispose()` | Free resources |
768
-
769
- #### Tier 2 — Element Builders (fluent element construction)
770
-
771
- Eight builder classes for step-by-step element construction with method chaining. Each builder's `.build()` produces a standard `PptxElement`.
772
-
773
- **TextBuilder:**
774
-
775
- ```typescript
776
- const title = TextBuilder.create('Hello World')
777
- .fontSize(36)
778
- .bold()
779
- .italic()
780
- .underline()
781
- .strikethrough()
782
- .color('#2563EB')
783
- .fontFamily('Inter')
784
- .alignment('center')
785
- .verticalAlignment('middle')
786
- .lineSpacing(1.5)
787
- .fill({ type: 'solid', color: '#F0F4F8' })
788
- .stroke({ color: '#2563EB', width: 1 })
789
- .shadow({ blur: 4, offsetX: 2, offsetY: 2, opacity: 0.3 })
790
- .position(100, 100)
791
- .size(600, 80)
792
- .rotation(0)
793
- .opacity(1)
794
- .build();
795
-
796
- // Rich text with multiple segments
797
- const richText = TextBuilder.create([
798
- { text: 'Bold intro. ', style: { bold: true, fontSize: 18 } },
799
- { text: 'Normal body text.', style: { fontSize: 14 } },
800
- ])
801
- .position(50, 200)
802
- .size(800, 40)
803
- .build();
804
- ```
805
-
806
- **ShapeBuilder:**
807
-
808
- ```typescript
809
- const shape = ShapeBuilder.create('roundRect')
810
- .solidFill('#4472C4') // Convenience: solid fill
811
- .noFill() // Convenience: transparent
812
- .gradientFill(
813
- [
814
- // Convenience: gradient fill
815
- { color: '#2563EB', position: 0 },
816
- { color: '#60A5FA', position: 1 },
817
- ],
818
- 45,
819
- )
820
- .fill({ type: 'pattern', preset: 'dkDnDiag' }) // Full fill input
821
- .stroke({ color: '#000', width: 2, dash: 'dash' })
822
- .shadow({ blur: 8, offsetX: 3, offsetY: 3 })
823
- .text('Click me')
824
- .textStyle({ fontSize: 14, bold: true, color: '#FFF' })
825
- .adjustments({ adj1: 16667 }) // Geometry adjustment handles
826
- .position(200, 200)
827
- .size(300, 200)
828
- .rotation(15)
829
- .opacity(0.9)
830
- .build();
831
- ```
832
-
833
- **ImageBuilder:**
834
-
835
- ```typescript
836
- const logo = ImageBuilder.create('data:image/png;base64,iVBOR...')
837
- .altText('Company logo')
838
- .crop(0.1, 0.05, 0.1, 0.05) // Fractional crop from each edge
839
- .position(50, 50)
840
- .size(200, 100)
841
- .rotation(0)
842
- .opacity(1)
843
- .build();
844
- ```
845
-
846
- **TableBuilder:**
847
-
848
- ```typescript
849
- const table = TableBuilder.create()
850
- .headerRow(['Name', 'Q1', 'Q2', 'Q3', 'Q4'])
851
- .addRow(['North', '120', '145', '160', '180'])
852
- .addRow(['South', '90', '105', '130', '150'])
853
- .addRow([
854
- { text: 'Total', style: { bold: true } },
855
- { text: '210', style: { bold: true, color: '#2563EB' } },
856
- { text: '250' },
857
- { text: '290' },
858
- { text: '330' },
859
- ])
860
- .columnWidths([2, 1, 1, 1, 1]) // Proportional widths
861
- .bandRows()
862
- .bandColumns(false)
863
- .firstCol()
864
- .lastRow()
865
- .lastCol(false)
866
- .style('{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}')
867
- .position(50, 150)
868
- .size(860, 250)
869
- .build();
870
- ```
871
-
872
- **ChartBuilder:**
873
-
874
- ```typescript
875
- const chart = ChartBuilder.create('line') // bar, line, pie, doughnut, area, scatter, ...
876
- .categories(['Jan', 'Feb', 'Mar', 'Apr'])
877
- .addSeries('Actual', [42, 58, 67, 73], '#2563EB')
878
- .addSeries('Target', [50, 55, 60, 65], '#E94560')
879
- .title('Monthly Performance')
880
- .legend(true, 'b') // Show legend at bottom
881
- .grouping('clustered') // clustered | stacked | percentStacked
882
- .position(100, 150)
883
- .size(600, 400)
884
- .build();
885
- ```
886
-
887
- **ConnectorBuilder:**
888
-
889
- ```typescript
890
- const line = ConnectorBuilder.create()
891
- .type('curved') // straight | bent | curved
892
- .stroke({ color: '#333', width: 2, dash: 'dashDot' })
893
- .startArrow('triangle')
894
- .endArrow('stealth')
895
- .from(shape1.id, 2) // Connect from shape1, site index 2
896
- .to(shape2.id, 0) // Connect to shape2, site index 0
897
- .position(100, 100)
898
- .size(300, 0)
899
- .rotation(0)
900
- .build();
901
- ```
902
-
903
- **MediaBuilder:**
904
-
905
- ```typescript
906
- const video = MediaBuilder.video('data:video/mp4;base64,...')
907
- .autoPlay()
908
- .loop()
909
- .volume(0.8)
910
- .trim(1000, 5000) // Trim: start at 1s, end at 5s
911
- .posterFrame('data:image/png;base64,...')
912
- .position(100, 100)
913
- .size(480, 270)
914
- .build();
915
-
916
- const audio = MediaBuilder.audio('path/to/audio.mp3')
917
- .autoPlay(false)
918
- .loop(false)
919
- .volume(1.0)
920
- .build();
921
- ```
922
-
923
- **GroupBuilder:**
924
-
925
- ```typescript
926
- const group = GroupBuilder.create()
927
- .addChild(TextBuilder.create('Label').position(0, 0).size(100, 30).build())
928
- .addChildBuilder(ShapeBuilder.create('rect').solidFill('#EEE').size(100, 100))
929
- .addChildren([element1, element2])
930
- .position(200, 200)
931
- .size(300, 300)
932
- .rotation(10)
933
- .build();
934
- ```
935
-
936
- #### SlideBuilder (returned by `Presentation.addSlide()`)
937
-
938
- Chainable API for adding elements and setting slide properties:
939
-
940
- ```typescript
941
- pptx
942
- .addSlide('Blank')
943
- // Add elements (all chainable)
944
- .addText('Title', { fontSize: 36, x: 50, y: 50, width: 860, height: 60 })
945
- .addShape('ellipse', {
946
- fill: { type: 'solid', color: '#FF0000' },
947
- x: 50,
948
- y: 150,
949
- width: 100,
950
- height: 100,
951
- })
952
- .addImage('data:image/png;base64,...', { x: 200, y: 150, width: 300, height: 200 })
953
- .addTable({ rows: [{ cells: [{ text: 'A' }, { text: 'B' }] }] })
954
- .addChart('pie', { series: [{ name: 'S1', values: [60, 40] }], categories: ['Yes', 'No'] })
955
- .addConnector({ type: 'straight', stroke: { color: '#000', width: 1 } })
956
- .addMedia('video', 'data:video/mp4;base64,...', { autoPlay: true })
957
- .addGroup([element1, element2], { x: 0, y: 0, width: 960, height: 540 })
958
- .addFreeform('M 0 0 L 100 50 L 50 100 Z', { stroke: { color: '#F00', width: 2 } })
959
- .addElement(anyPptxElement) // Add any pre-built element
960
- .addBuilderElement(TextBuilder.create('X').bold()) // Accept any builder
961
- // Slide properties
962
- .setBackground({
963
- type: 'gradient',
964
- angle: 135,
965
- stops: [
966
- { color: '#000', position: 0 },
967
- { color: '#333', position: 1 },
968
- ],
969
- })
970
- .setTransition({ type: 'morph', duration: 800 })
971
- .addAnimation(elementId, { preset: 'fadeIn', trigger: 'afterPrevious', duration: 500 })
972
- .setNotes('Speaker notes here')
973
- .setHidden(false)
974
- .setSection('Introduction')
975
- .setName('Intro Slide')
976
- // Query methods
977
- .getElements() // Readonly array of current elements
978
- .getLastElement() // Last element (for animation IDs)
979
- .elementCount // Number of elements
980
- .removeElement(elementId) // Remove by ID (chainable)
981
- .build(); // Get the PptxSlide object
982
- ```
983
-
984
- #### Unit Helpers and Theme Presets
985
-
986
- ```typescript
987
- import { inches, cm, mm, pt, inchesToEmu, SlideSizes, ThemePresets } from 'pptx-viewer-core';
988
-
989
- // Unit conversions (all return pixels at 96 DPI)
990
- inches(1); // => 96
991
- cm(2.54); // => 96
992
- mm(25.4); // => 96
993
- pt(72); // => 96
994
-
995
- // EMU conversions (for PresentationOptions width/height)
996
- inchesToEmu(10); // => 9144000
997
-
998
- // Standard slide sizes (EMU values)
999
- SlideSizes.WIDESCREEN_16_9; // { width: 12192000, height: 6858000 }
1000
- SlideSizes.STANDARD_4_3; // { width: 9144000, height: 6858000 }
1001
- SlideSizes.A4_LANDSCAPE; // { width: 10692000, height: 7560937 }
1002
-
1003
- // Theme presets (8 built-in themes)
1004
- ThemePresets.OFFICE; // Default Office theme
1005
- ThemePresets.MODERN_BLUE; // Clean blue professional
1006
- ThemePresets.CORPORATE; // Professional corporate
1007
- ThemePresets.DARK; // Dark mode
1008
- ThemePresets.VIBRANT; // Energetic colours
1009
- ThemePresets.EARTH; // Warm earth tones
1010
- ThemePresets.MONOCHROME; // High contrast B&W
1011
- ThemePresets.MINIMAL; // Soft pastels
1012
- ```
1013
-
1014
- #### Tier 3 — Low-Level APIs
1015
-
1016
- **PptxXmlBuilder** — Fluent in-place mutation of an existing `PptxData`:
1017
-
1018
- ```typescript
1019
- PptxXmlBuilder.from(data)
1020
- .slide(0)
1021
- .elements()
1022
- .add(createTextElement('New text'))
1023
- .removeById('old_id')
1024
- .updateById('el_id', (el) => ({ ...el, x: 200 }))
1025
- .done()
1026
- .notes()
1027
- .set('Updated notes')
1028
- .done()
1029
- .done()
1030
- .project(); // => mutated PptxData
1031
- ```
1032
-
1033
- **SDK Operations** — Pure functions for batch operations:
1034
-
1035
- | Category | Functions |
1036
- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1037
- | **Text** | `findText`, `replaceText`, `replaceTextInSlide` |
1038
- | **Charts** | `setChartType`, `addChartSeries`, `removeChartSeries`, `setChartCategories`, `updateChartSeriesValues`, `setChartTitle`, `setChartGrouping`, `updateChartDataPoint`, `addChartCategory`, `removeChartCategory` |
1039
- | **Shapes** | `replaceShapeGeometry`, `replaceWithCustomGeometry`, `interpolateShapeGeometry`, `parseSvgPath`, `serializeSvgPath` |
1040
- | **Slides** | `duplicateSlide`, `duplicateElement` |
1041
- | **Sections** | `addSection`, `removeSection`, `reorderSections`, `getSectionForSlide`, `moveSlidesToSection` |
1042
- | **Merge** | `mergePresentation` |
1043
- | **Diff** | `diffPresentations`, `diffSlides` |
1044
- | **Template** | `applyTemplate`, `findPlaceholders`, `mailMerge` |
1045
- | **Layout** | `createLayout`, `createLayouts`, `findLayoutByName`, `findLayoutByType`, `generateLayoutXml` |
1046
-
1047
- **PptxElementXmlBuilder** — Low-level element XML construction:
1048
-
1049
- - Builds `<p:sp>`, `<p:pic>`, `<p:cxnSp>`, `<p:graphicFrame>` nodes
1050
- - Factory per element type: `TextShapeXmlFactory`, `PictureXmlFactory`, `ConnectorXmlFactory`, `MediaGraphicFrameXmlFactory`
1051
-
1052
- ### 9. Encryption and Security
1053
-
1054
- The engine handles several security-related PPTX features:
1055
-
1056
- | Feature | Description |
1057
- | ------------------------------ | ------------------------------------------------------------------------------------------- |
1058
- | **PPTX Encryption/Decryption** | AES-128/256 Agile encryption per [MS-OFFCRYPTO]. Reads and writes password-protected files. |
1059
- | **Modify Password** | SHA-based hash verifier for write-protection (does not prevent opening). |
1060
- | **Digital Signatures** | Detects and can strip XML digital signatures (`_xmlsignatures` parts). |
1061
- | **Encrypted File Detection** | Identifies OLE compound file format (CFB) wrapping encrypted PPTX content. |
1062
-
1063
- ---
1064
-
1065
- ## Type System Reference
1066
-
1067
- The core type system uses **EMU (English Metric Units)** as the native coordinate system, matching PowerPoint's internal representation:
1068
-
1069
- ```
1070
- 1 inch = 914,400 EMU
1071
- 1 cm = 360,000 EMU
1072
- 1 point = 12,700 EMU
1073
- 1 pixel = 9,525 EMU (at 96 DPI)
1074
- ```
1075
-
1076
- **PptxData** -- the top-level parsed result:
1077
-
1078
- ```typescript
1079
- interface PptxData {
1080
- slides: PptxSlide[];
1081
- canvasSize: PptxCanvasSize;
1082
- theme?: PptxTheme;
1083
- slideMasters: PptxSlideMaster[];
1084
- slideLayouts: PptxSlideLayout[];
1085
- sections: PptxSection[];
1086
- customShows: PptxCustomShow[];
1087
- presentationProperties: PresentationProperties;
1088
- coreProperties: CoreProperties;
1089
- appProperties: AppProperties;
1090
- customProperties: CustomProperty[];
1091
- embeddedFonts: EmbeddedFont[];
1092
- // ...
1093
- }
1094
- ```
1095
-
1096
- **PptxSlide** -- a single slide:
1097
-
1098
- ```typescript
1099
- interface PptxSlide {
1100
- id: string;
1101
- elements: PptxElement[];
1102
- background?: SlideBackground;
1103
- transition?: PptxSlideTransition;
1104
- notes?: string;
1105
- hidden?: boolean;
1106
- layoutPath?: string;
1107
- // ...
1108
- }
1109
- ```
1110
-
1111
- ---
1112
-
1113
- ## Feature Summary
1114
-
1115
- | Category | Details |
1116
- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1117
- | **Element Types** | 16: text, shape, connector, image, picture, table, chart, smartArt, ole, media, group, ink, contentPart, zoom, model3d, unknown |
1118
- | **Preset Shapes** | 187+ with guide formula evaluation and adjustment handles |
1119
- | **Chart Types** | 23: bar, column, line, area, pie, doughnut, scatter, bubble, radar, stock, surface/3D, histogram, waterfall, funnel, treemap, sunburst, boxWhisker, regionMap, combo |
1120
- | **Chart Features** | Display units, logarithmic axes, chart color styles, embedded Excel data, pivot sources, trendlines, error bars, data tables |
1121
- | **Transitions** | 42 types including morph, vortex, ripple, shred, and p14 extensions |
1122
- | **Animations** | 40+ presets with color animations, motion path auto-rotation, text build (by word/letter/paragraph) |
1123
- | **SmartArt** | 13 layout types (list, process, cycle, hierarchy, matrix, gear, etc.) |
1124
- | **Fills** | Solid, gradient (linear/radial/path), image, 48 pattern presets |
1125
- | **Text Features** | Warp (24+ presets), inline math (OMML to MathML), multi-column, text field substitution |
1126
- | **Themes** | 8 built-in presets, runtime switching, layout/placeholder remapping |
1127
- | **3D** | ThreeDProperties for shapes and text, extrusion, bevel, material, lighting |
1128
- | **Security** | AES-128/256 encryption/decryption, modify password (SHA), digital signature detection |
1129
- | **Preservation** | VBA macros, custom XML parts, comment authors, OOXML Strict namespaces |
1130
- | **Other** | Kiosk mode, custom shows, sections, tags, print settings, photo album, guide lines, embedded font deobfuscation |
1131
-
1132
- ---
1133
-
1134
- ## File Structure Reference
1135
-
1136
- ```
1137
- src/
1138
- +-- index.ts # Package entry -- re-exports core + converter
1139
- |
1140
- +-- core/ # Core PPTX engine (247 files)
1141
- | +-- index.ts # Core barrel export
1142
- | +-- PptxHandler.ts # Public facade class
1143
- | +-- PptxHandlerCore.ts # Facade over IPptxHandlerRuntime
1144
- | +-- constants.ts # EMU conversion, XML namespaces
1145
- | +-- constants-colors.ts # Named colour constants
1146
- | |
1147
- | +-- types/ # Type system (22 files)
1148
- | | +-- index.ts # Barrel re-export
1149
- | | +-- common.ts # PptxData, PptxSlide, XmlObject
1150
- | | +-- elements.ts # PptxElement discriminated union (16 variants)
1151
- | | +-- element-base.ts # PptxElementBase shared props
1152
- | | +-- text.ts # TextStyle, Paragraph, TextSegment
1153
- | | +-- shape-style.ts # ShapeStyle, FillStyle, StrokeStyle
1154
- | | +-- table.ts # TableData, TableCell, TableRow
1155
- | | +-- chart.ts # PptxChartData, ChartSeries (23 types)
1156
- | | +-- theme.ts # PptxTheme, colour/font schemes
1157
- | | +-- animation.ts # PptxElementAnimation
1158
- | | +-- transition.ts # PptxSlideTransition (42 types)
1159
- | | +-- masters.ts # PptxSlideMaster, PptxSlideLayout
1160
- | | +-- image.ts # ImageEffects, ImageCrop
1161
- | | +-- geometry.ts # PptxCustomGeometry
1162
- | | +-- smart-art.ts # PptxSmartArtData
1163
- | | +-- media.ts # PptxMediaData, MediaTiming
1164
- | | +-- metadata.ts # CoreProperties, AppProperties
1165
- | | +-- presentation.ts # PresentationProperties
1166
- | | +-- view-properties.ts # ViewProperties
1167
- | | +-- three-d.ts # ThreeDProperties
1168
- | | +-- actions.ts # ElementAction, hyperlinks
1169
- | | +-- type-guards.ts # isShape(), isImage(), etc.
1170
- | |
1171
- | +-- core/ # Runtime engine (128 files)
1172
- | | +-- index.ts # Runtime barrel export
1173
- | | +-- PptxHandlerRuntime.ts # Sealed final class
1174
- | | +-- PptxHandlerRuntimeFactory.ts # DI factory + interface
1175
- | | +-- types.ts # IPptxHandlerRuntime interface
1176
- | | |
1177
- | | +-- runtime/ # Mixin modules (84 files)
1178
- | | | +-- PptxHandlerRuntimeState.ts # Base state (fields, ZIP, parser)
1179
- | | | +-- PptxHandlerRuntimeThemeLoading.ts
1180
- | | | +-- PptxHandlerRuntimeThemeProcessing.ts
1181
- | | | +-- PptxHandlerRuntimeSlideParsing.ts
1182
- | | | +-- PptxHandlerRuntimeElementParsing.ts
1183
- | | | +-- PptxHandlerRuntimeShapeParsing.ts
1184
- | | | +-- PptxHandlerRuntimeShapeTextParsing.ts
1185
- | | | +-- PptxHandlerRuntimeChartParsing.ts
1186
- | | | +-- PptxHandlerRuntimeSmartArtParsing.ts
1187
- | | | +-- PptxHandlerRuntimeLoadPipeline.ts # load() entry point
1188
- | | | +-- PptxHandlerRuntimeSavePipeline.ts # save() entry point
1189
- | | | +-- PptxHandlerRuntimeSaveElementWriter.ts
1190
- | | | +-- PptxHandlerRuntimeSaveTextWriter.ts
1191
- | | | +-- PptxHandlerRuntimeImplementation.ts # Top of chain
1192
- | | | +-- ...40+ more mixin modules
1193
- | | |
1194
- | | +-- builders/ # Runtime builders (40 files)
1195
- | | | +-- PptxColorStyleCodec.ts
1196
- | | | +-- PptxConnectorParser.ts
1197
- | | | +-- PptxContentTypesBuilder.ts
1198
- | | | +-- PptxGraphicFrameParser.ts
1199
- | | | +-- PptxTableDataParser.ts
1200
- | | | +-- PptxShapeStyleExtractor.ts
1201
- | | | +-- PptxShapeEffectXmlBuilder.ts
1202
- | | | +-- ...33 more builders
1203
- | | |
1204
- | | +-- factories/ # DI factories (4 files)
1205
- | | +-- PptxRuntimeDependencyFactory.ts
1206
- | | +-- PptxSaveConstantsFactory.ts
1207
- | | +-- types.ts
1208
- | |
1209
- | +-- geometry/ # Shape geometry (17 files)
1210
- | | +-- shape-geometry.ts # Shape type -> clip path resolution
1211
- | | +-- connector-geometry.ts # Connector path generation
1212
- | | +-- guide-formula.ts # OOXML guide formula API
1213
- | | +-- guide-formula-eval.ts # Expression evaluation
1214
- | | +-- preset-shape-definitions.ts # 187+ preset shapes
1215
- | | +-- preset-shape-paths.ts # Pre-computed clip paths
1216
- | | +-- custom-geometry.ts # Custom geometry parsing
1217
- | | +-- transform-utils.ts # Position/rotation transforms
1218
- | |
1219
- | +-- color/ # Colour processing (4 files)
1220
- | | +-- color-utils.ts # Main API (parseDrawingColor, etc.)
1221
- | | +-- color-primitives.ts # Hex <-> RGB <-> HSL conversions
1222
- | | +-- color-transforms.ts # OOXML colour transform application
1223
- | |
1224
- | +-- builders/ # XML builder APIs (11 files)
1225
- | | +-- PptxElementXmlBuilder.ts # Low-level element XML builder
1226
- | | +-- fluent/
1227
- | | | +-- PptxXmlBuilder.ts # Fluent chainable builder
1228
- | | +-- factories/
1229
- | | +-- TextShapeXmlFactory.ts
1230
- | | +-- PictureXmlFactory.ts
1231
- | | +-- ConnectorXmlFactory.ts
1232
- | | +-- MediaGraphicFrameXmlFactory.ts
1233
- | |
1234
- | +-- services/ # Service classes (21 files)
1235
- | | +-- PptxSlideLoaderService.ts
1236
- | | +-- PptxNativeAnimationService.ts
1237
- | | +-- PptxEditorAnimationService.ts
1238
- | | +-- PptxAnimationWriteService.ts
1239
- | | +-- PptxSlideTransitionService.ts
1240
- | | +-- PptxCompatibilityService.ts
1241
- | | +-- PptxXmlLookupService.ts
1242
- | | +-- PptxDocumentPropertiesUpdater.ts
1243
- | | +-- PptxTemplateBackgroundService.ts
1244
- | |
1245
- | +-- utils/ # Utility functions (32 files)
1246
- | +-- clone-utils.ts # Deep clone for slides, elements, styles
1247
- | +-- element-utils.ts # Element labels, text content, actions
1248
- | +-- stroke-utils.ts # Dash styles, border rendering
1249
- | +-- data-url-utils.ts # Data URL <-> byte conversions
1250
- | +-- encryption-detection.ts # CFB/OLE format detection
1251
- | +-- ooxml-crypto.ts # AES-128/256 encryption/decryption
1252
- | +-- signature-detection.ts # Digital signature detection
1253
- | +-- font-deobfuscation.ts # OOXML font deobfuscation
1254
- | +-- smartart-decompose.ts # SmartArt -> individual shapes
1255
- | +-- smartart-editing.ts # SmartArt node CRUD operations
1256
- | +-- chart-advanced-parser.ts # Trendlines, error bars, data tables
1257
- | +-- chart-axis-parser.ts # Axis parsing (value, category, date)
1258
- | +-- chart-cx-parser.ts # ChartEx (cx:chart) parsing
1259
- | +-- ole-utils.ts # OLE object type detection
1260
- | +-- guide-utils.ts # Drawing guide EMU <-> px conversions
1261
- | +-- theme-override-utils.ts # Theme colour map override handling
1262
- | +-- vml-parser.ts # VML (Vector Markup Language) parsing
1263
- | +-- strict-namespace-map.ts # Strict OOXML namespace normalisation
1264
- |
1265
- +-- converter/ # PPTX -> Markdown (20 files)
1266
- +-- index.ts # Converter barrel export
1267
- +-- PptxMarkdownConverter.ts # Main converter orchestrator
1268
- +-- SlideProcessor.ts # Per-slide markdown generation
1269
- +-- base.ts # Abstract DocumentConverter base
1270
- +-- types.ts # FileSystemAdapter, ConversionOptions
1271
- +-- media-context.ts # Media extraction & deduplication
1272
- +-- elements/ # Element processors (11 files)
1273
- +-- ElementProcessor.ts # Abstract base processor
1274
- +-- TextElementProcessor.ts # Shapes -> markdown text
1275
- +-- ImageElementProcessor.ts # Images -> ![alt](path)
1276
- +-- TableElementProcessor.ts # Tables -> markdown tables
1277
- +-- ChartElementProcessor.ts # Charts -> data summaries
1278
- +-- SmartArtElementProcessor.ts # SmartArt -> structured text
1279
- +-- GroupElementProcessor.ts # Groups -> recursive processing
1280
- +-- MediaElementProcessor.ts # Audio/video -> link references
1281
- +-- OleElementProcessor.ts # OLE objects -> descriptions
1282
- +-- InkElementProcessor.ts # Ink annotations -> descriptions
1283
- +-- FallbackElementProcessor.ts # Unknown elements -> placeholder
1284
- ```
1285
-
1286
- ---
1287
-
1288
- ## Limitations
1289
-
1290
- - **Embedded OLE objects are read-only** -- OLE objects (embedded Excel, Word, etc.) are recognised and their preview images are displayed, but their internal content cannot be edited. OLE2 is an opaque binary container format -- deserialising and re-serialising the internal object structure (e.g. an embedded Excel workbook) would require embedding the full application runtime.
1291
- - **SmartArt uses static shape decomposition** -- SmartArt diagrams are decomposed into individual positioned shapes using PowerPoint's own pre-computed drawing data (13 layout types). The shapes are fully editable, but there is no live SmartArt reflow engine -- moving or reordering shapes won't automatically recalculate the layout the way PowerPoint's built-in SmartArt engine does.
1292
- - **3D effects** -- 3D properties are fully parsed into `ThreeDProperties` (extrusion, bevel, material, lighting). Rendering uses CSS 3D transforms in the React viewer. 3D model elements (GLB/GLTF) require Three.js as an optional peer dependency.
1293
- - **Chart editing is data-level only** -- You can add/remove series, edit data points, add/remove categories, and change chart type. However, structural chart properties (axis formatting, legend placement, data labels, trendlines, error bars) are parsed for display but not exposed for programmatic editing.
1294
- - **Strict OOXML conformance is normalised** -- Office 365 can save files in ISO/IEC 29500 Strict mode, which uses different namespace URIs than the more common Transitional (ECMA-376) format. The engine maps 46+ namespace URI pairs on load (Strict -> Transitional) and converts back on save. Features that rely on strict-only extensions outside these mapped namespaces may not round-trip.