@mkabatek/pptx-viewer 1.5.4 → 1.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -1
- package/dist/index.mjs +3 -1
- package/dist/viewer/index.js +3 -1
- package/dist/viewer/index.mjs +3 -1
- package/package.json +2 -9
- package/node_modules/emf-converter/LICENSE +0 -21
- package/node_modules/emf-converter/README.md +0 -629
- package/node_modules/emf-converter/dist/index.d.mts +0 -86
- package/node_modules/emf-converter/dist/index.d.ts +0 -86
- package/node_modules/emf-converter/dist/index.js +0 -4257
- package/node_modules/emf-converter/dist/index.mjs +0 -4253
- package/node_modules/emf-converter/package.json +0 -53
- package/node_modules/mtx-decompressor/LICENSE +0 -373
- package/node_modules/mtx-decompressor/README.md +0 -271
- package/node_modules/mtx-decompressor/dist/index.d.mts +0 -84
- package/node_modules/mtx-decompressor/dist/index.d.ts +0 -84
- package/node_modules/mtx-decompressor/dist/index.js +0 -1532
- package/node_modules/mtx-decompressor/dist/index.mjs +0 -1528
- package/node_modules/mtx-decompressor/package.json +0 -44
- package/node_modules/pptx-viewer-core/LICENSE +0 -21
- package/node_modules/pptx-viewer-core/NOTICE +0 -16
- package/node_modules/pptx-viewer-core/README.md +0 -1294
- package/node_modules/pptx-viewer-core/dist/SvgExporter-BtZczTlB.d.ts +0 -557
- package/node_modules/pptx-viewer-core/dist/SvgExporter-D4mBWJHE.d.mts +0 -557
- package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +0 -150
- package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +0 -150
- package/node_modules/pptx-viewer-core/dist/cli/index.js +0 -0
- package/node_modules/pptx-viewer-core/dist/cli/index.mjs +0 -0
- package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +0 -48
- package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +0 -48
- package/node_modules/pptx-viewer-core/dist/converter/index.js +0 -0
- package/node_modules/pptx-viewer-core/dist/converter/index.mjs +0 -0
- package/node_modules/pptx-viewer-core/dist/index.d.mts +0 -12744
- package/node_modules/pptx-viewer-core/dist/index.d.ts +0 -12744
- package/node_modules/pptx-viewer-core/dist/index.js +0 -66894
- package/node_modules/pptx-viewer-core/dist/index.mjs +0 -66420
- package/node_modules/pptx-viewer-core/dist/presentation-nZxgWvXq.d.mts +0 -5645
- package/node_modules/pptx-viewer-core/dist/presentation-nZxgWvXq.d.ts +0 -5645
- package/node_modules/pptx-viewer-core/dist/signature-inspection-status-BCUpfCQh.d.mts +0 -220
- package/node_modules/pptx-viewer-core/dist/signature-inspection-status-BCUpfCQh.d.ts +0 -220
- package/node_modules/pptx-viewer-core/dist/signature-node/index.d.mts +0 -177
- package/node_modules/pptx-viewer-core/dist/signature-node/index.d.ts +0 -177
- package/node_modules/pptx-viewer-core/dist/signature-node/index.js +0 -1206
- package/node_modules/pptx-viewer-core/dist/signature-node/index.mjs +0 -1143
- package/node_modules/pptx-viewer-core/dist/text-operations-DCTGMltY.d.mts +0 -134
- package/node_modules/pptx-viewer-core/dist/text-operations-DYmhoi7U.d.ts +0 -134
- 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 -> 
|
|
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.
|