pptx-viewer-core 1.1.23 → 1.1.26
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/CHANGELOG.md +55 -0
- package/README.md +91 -931
- package/dist/{SvgExporter-D4mBWJHE.d.mts → SvgExporter-BkkVdcN7.d.mts} +1 -1
- package/dist/{SvgExporter-BtZczTlB.d.ts → SvgExporter-MDf-1CNQ.d.ts} +1 -1
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +0 -0
- package/dist/cli/index.mjs +0 -0
- package/dist/converter/index.d.mts +3 -3
- package/dist/converter/index.d.ts +3 -3
- package/dist/index.d.mts +394 -17
- package/dist/index.d.ts +394 -17
- package/dist/index.js +2233 -5872
- package/dist/index.mjs +2203 -5869
- package/dist/{presentation-nZxgWvXq.d.mts → presentation-BWchOWpy.d.mts} +41 -1
- package/dist/{presentation-nZxgWvXq.d.ts → presentation-BWchOWpy.d.ts} +41 -1
- package/dist/{text-operations-DYmhoi7U.d.ts → text-operations-DTlmk6ap.d.ts} +1 -1
- package/dist/{text-operations-DCTGMltY.d.mts → text-operations-Dld03ITU.d.mts} +1 -1
- package/package.json +18 -8
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
[](https://github.com/ChristopherVR/pptx-viewer/blob/main/LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/pptx-viewer-core)
|
|
6
6
|
|
|
7
|
-
>
|
|
7
|
+
> A TypeScript library that **reads, creates, edits, and saves** PowerPoint (`.pptx`) files. It runs in the browser and in Node.js, with no native or system dependencies.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Hand it the bytes of a `.pptx` file and it gives you back a structured, fully typed object that describes every slide: text, shapes, images, charts, tables, and more. Change anything in that object and write it back to a valid `.pptx`. You can also build new presentations from scratch with a simple chainable API, or turn a deck into Markdown.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
There is no UI here: this is the engine on its own. Use it directly when you need to process `.pptx` files without a screen, for example on a server, in a script, or in a build step. The same engine powers the [`pptx-react-viewer`](https://www.npmjs.com/package/pptx-react-viewer), `pptx-vue-viewer`, and `pptx-angular-viewer` UI components.
|
|
12
|
+
|
|
13
|
+
<samp>**[📦 npm](https://www.npmjs.com/package/pptx-viewer-core)** · **[📖 Full docs](https://christophervr.github.io/pptx-viewer/)** · **[▶️ Live demo](https://christophervr.github.io/pptx-viewer/demo/)** · **[⚛️ React UI](https://www.npmjs.com/package/pptx-react-viewer)**</samp>
|
|
12
14
|
|
|
13
15
|
---
|
|
14
16
|
|
|
@@ -16,67 +18,66 @@ This is the headless core SDK. Point it at a `.pptx` `ArrayBuffer` and get back
|
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
20
|
npm install pptx-viewer-core
|
|
19
|
-
#
|
|
21
|
+
# required companions:
|
|
20
22
|
npm install jszip fast-xml-parser
|
|
21
23
|
```
|
|
22
24
|
|
|
23
|
-
>
|
|
24
|
-
|
|
25
|
-
## Overview
|
|
25
|
+
> Two packages are always needed alongside it: **jszip** (a `.pptx` is a ZIP file, and this reads and writes that container) and **fast-xml-parser** (the slides inside are XML, and this reads and writes it). Password protection and digital signatures need a few extra packages (`node-forge`, `xml-crypto`, `@xmldom/xmldom`), but only if you actually use those features.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## What it does
|
|
28
28
|
|
|
29
|
-
| Capability
|
|
30
|
-
|
|
|
31
|
-
| **
|
|
32
|
-
| **Edit**
|
|
33
|
-
| **Save**
|
|
34
|
-
| **Convert**
|
|
35
|
-
| **Export**
|
|
36
|
-
| **
|
|
29
|
+
| Capability | Description |
|
|
30
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
31
|
+
| **Read** | Open a `.pptx` and pull out slides, text, shapes, images, charts, tables, SmartArt, themes, comments, animations, transitions, and document info |
|
|
32
|
+
| **Edit** | Change the data in memory: add, remove, or reorder slides; insert elements; edit text; restyle; switch themes |
|
|
33
|
+
| **Save** | Write the changed data back to a valid `.pptx`, leaving everything you did not touch untouched |
|
|
34
|
+
| **Convert** | Turn a deck into Markdown, optionally pulling the images out alongside it |
|
|
35
|
+
| **Export** | Save individual slides as their own standalone `.pptx` files |
|
|
36
|
+
| **Protect** | Open and save password-protected files (AES-128/256 encryption) |
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Positions and sizes use PowerPoint's own internal unit, the EMU (English Metric Unit): 1 inch = 914,400 EMU, 1 point = 12,700 EMU, and 1 pixel = 9,525 EMU at 96 DPI. You rarely deal with the raw numbers: helpers (`inches`, `cm`, `mm`, `pt`) let you work in familiar units instead.
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
## Quick
|
|
42
|
+
## Quick start
|
|
43
43
|
|
|
44
44
|
```typescript
|
|
45
45
|
import { PptxHandler } from 'pptx-viewer-core';
|
|
46
46
|
|
|
47
|
-
// 1.
|
|
47
|
+
// 1. Open a .pptx file
|
|
48
48
|
const handler = new PptxHandler();
|
|
49
49
|
const buffer = await fetch('presentation.pptx').then((r) => r.arrayBuffer());
|
|
50
50
|
const data = await handler.load(buffer);
|
|
51
51
|
|
|
52
|
-
console.log(
|
|
53
|
-
|
|
52
|
+
console.log(
|
|
53
|
+
`${data.slides.length} slides, canvas ${data.canvasSize.width}×${data.canvasSize.height}`,
|
|
54
|
+
);
|
|
54
55
|
|
|
55
|
-
// 2.
|
|
56
|
+
// 2. Change a slide
|
|
56
57
|
data.slides[0].elements[0].text = 'Updated title';
|
|
57
58
|
|
|
58
|
-
// 3. Save back to .pptx
|
|
59
|
-
const outputBytes = await handler.save(data.slides);
|
|
60
|
-
// => Uint8Array of a valid .pptx file
|
|
59
|
+
// 3. Save it back to .pptx bytes
|
|
60
|
+
const outputBytes = await handler.save(data.slides); // => Uint8Array
|
|
61
61
|
|
|
62
|
-
// 4.
|
|
63
|
-
const exports = await handler.exportSlides(data.slides, {
|
|
64
|
-
slideIndexes: [0, 2],
|
|
65
|
-
});
|
|
66
|
-
// => Map<number, Uint8Array>
|
|
62
|
+
// 4. Or pull out just a few slides as separate files
|
|
63
|
+
const exports = await handler.exportSlides(data.slides, { slideIndexes: [0, 2] }); // => Map<number, Uint8Array>
|
|
67
64
|
```
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
`load()` gives you a `PptxData` object: a plain, fully typed description of the presentation. Read from it, change it, and pass its `slides` back to `save()` to get a valid `.pptx` file as bytes.
|
|
67
|
+
|
|
68
|
+
### Build a presentation from scratch
|
|
69
|
+
|
|
70
|
+
The chainable API lets you create a deck step by step, without touching any file format details:
|
|
70
71
|
|
|
71
72
|
```typescript
|
|
72
|
-
import { Presentation, ThemePresets,
|
|
73
|
+
import { Presentation, ThemePresets, ChartBuilder } from 'pptx-viewer-core';
|
|
73
74
|
|
|
74
75
|
const pptx = await Presentation.create({
|
|
75
76
|
title: 'Sales Report',
|
|
76
77
|
theme: ThemePresets.MODERN_BLUE,
|
|
77
78
|
});
|
|
78
79
|
|
|
79
|
-
//
|
|
80
|
+
// Each slide is added to the deck automatically: no manual .build() or .push() needed
|
|
80
81
|
pptx
|
|
81
82
|
.addSlide('Title Slide')
|
|
82
83
|
.addText('Q4 Sales Report', { fontSize: 44, bold: true, x: 100, y: 200, width: 800, height: 80 });
|
|
@@ -92,932 +93,91 @@ pptx
|
|
|
92
93
|
.bounds(50, 100, 860, 420),
|
|
93
94
|
);
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
pptx.replaceText('2026', 'FY2026');
|
|
96
|
+
pptx.replaceText('2026', 'FY2026'); // find/replace, merge, and templates all chain the same way
|
|
97
97
|
|
|
98
98
|
const bytes = await pptx.save();
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
The builder API comes in three levels, from highest to lowest:
|
|
102
|
+
|
|
103
|
+
1. **`Presentation`**: the whole deck at once (slides, text operations, sections, templates, merging, saving).
|
|
104
|
+
2. **Element builders**: one per element type, for fine-grained control: `TextBuilder`, `ShapeBuilder`, `ChartBuilder`, `TableBuilder`, `ImageBuilder`, `ConnectorBuilder`, `MediaBuilder`, `GroupBuilder`.
|
|
105
|
+
3. **`PptxXmlBuilder`**: raw XML, for the rare cases the higher levels do not cover.
|
|
106
|
+
|
|
107
|
+
It also ships unit helpers (`inches`, `cm`, `mm`, `pt`), common slide sizes (`SlideSizes`), and 8 ready-made themes (`ThemePresets`). The [full docs](https://christophervr.github.io/pptx-viewer/) cover every builder.
|
|
108
|
+
|
|
109
|
+
### Turn a deck into Markdown
|
|
102
110
|
|
|
103
111
|
```typescript
|
|
104
112
|
import { PptxMarkdownConverter } from 'pptx-viewer-core';
|
|
105
113
|
|
|
106
|
-
const converter = new PptxMarkdownConverter({
|
|
107
|
-
|
|
108
|
-
includeSlideNumbers: true,
|
|
109
|
-
imageHandling: 'extract',
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const markdown = await converter.convert(
|
|
114
|
+
const converter = new PptxMarkdownConverter({ includeMetadata: true, imageHandling: 'extract' });
|
|
115
|
+
const result = await converter.convert(
|
|
113
116
|
buffer,
|
|
114
|
-
{
|
|
115
|
-
outputPath: 'output.md',
|
|
116
|
-
mediaFolderName: 'media',
|
|
117
|
-
includeMetadata: true,
|
|
118
|
-
},
|
|
117
|
+
{ outputPath: 'output.md', mediaFolderName: 'media' },
|
|
119
118
|
fileSystemAdapter,
|
|
120
119
|
);
|
|
121
|
-
// =>
|
|
120
|
+
// => the Markdown text, plus stats on any images that were pulled out
|
|
122
121
|
```
|
|
123
122
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
## API Reference
|
|
127
|
-
|
|
128
|
-
### PptxHandler
|
|
129
|
-
|
|
130
|
-
The primary facade for loading, editing, and saving PPTX files.
|
|
131
|
-
|
|
132
|
-
| Method | Signature | Description |
|
|
133
|
-
| -------------------------------- | --------------------------------------------------------------- | ------------------------------------------ |
|
|
134
|
-
| `load` | `(data: ArrayBuffer, options?) => Promise<PptxData>` | Parse a .pptx buffer into structured data |
|
|
135
|
-
| `save` | `(slides: PptxSlide[], options?) => Promise<Uint8Array>` | Serialise slides back to .pptx bytes |
|
|
136
|
-
| `exportSlides` | `(slides, options) => Promise<Map<number, Uint8Array>>` | Export selected slides as standalone files |
|
|
137
|
-
| `getImageData` | `(path: string) => Promise<string \| undefined>` | Get base64 data URL for an embedded image |
|
|
138
|
-
| `getMediaArrayBuffer` | `(path: string) => Promise<ArrayBuffer \| undefined>` | Get raw bytes for an embedded media file |
|
|
139
|
-
| `getChartDataForGraphicFrame` | `(slidePath, xmlObj) => Promise<PptxChartData \| undefined>` | Extract chart data from a graphic frame |
|
|
140
|
-
| `getSmartArtDataForGraphicFrame` | `(slidePath, xmlObj) => Promise<PptxSmartArtData \| undefined>` | Extract SmartArt data from a graphic frame |
|
|
141
|
-
| `getLayoutOptions` | `() => PptxLayoutOption[]` | Get available slide layout options |
|
|
142
|
-
| `getCompatibilityWarnings` | `() => PptxCompatibilityWarning[]` | Get warnings about unsupported features |
|
|
143
|
-
| `createXmlBuilder` / `Builder` | `(data: PptxData) => PptxXmlBuilder` | Create a fluent XML builder |
|
|
144
|
-
| `applyTheme` | `(colors, fonts, name?) => Promise<void>` | Apply a complete theme |
|
|
145
|
-
| `updateThemeColorScheme` | `(scheme) => Promise<void>` | Modify theme colours |
|
|
146
|
-
| `updateThemeFontScheme` | `(scheme) => Promise<void>` | Modify theme fonts |
|
|
147
|
-
| `setPresentationTheme` | `(path, applyToAll?) => Promise<void>` | Load a .thmx theme file |
|
|
148
|
-
|
|
149
|
-
### PptxMarkdownConverter
|
|
150
|
-
|
|
151
|
-
Converts PPTX files to Markdown documents. Extends the abstract `DocumentConverter` base class.
|
|
152
|
-
|
|
153
|
-
| Method | Signature | Description |
|
|
154
|
-
| --------- | ----------------------------------------------------- | ------------------------------- |
|
|
155
|
-
| `convert` | `(buffer, options, fs?) => Promise<ConversionResult>` | Convert PPTX buffer to Markdown |
|
|
156
|
-
|
|
157
|
-
Requires a `FileSystemAdapter` for disk output:
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
interface FileSystemAdapter {
|
|
161
|
-
writeFile(path: string, content: string): Promise<void>;
|
|
162
|
-
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
|
|
163
|
-
createFolder(path: string): Promise<void>;
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### PptxXmlBuilder (Fluent API)
|
|
168
|
-
|
|
169
|
-
A chainable builder for constructing OpenXML nodes directly in the runtime's in-memory ZIP.
|
|
170
|
-
|
|
171
|
-
```typescript
|
|
172
|
-
const builder = handler.Builder(data);
|
|
173
|
-
// Use fluent methods to construct and insert XML elements
|
|
174
|
-
```
|
|
123
|
+
To write files to disk, pass a `FileSystemAdapter` (an object with `writeFile`, `writeBinaryFile`, and `createFolder` methods); this keeps the converter free of any assumptions about where it runs. By default it keeps each element where it sat on the slide (absolutely positioned HTML); set `semanticMode: true` to get clean headings, paragraphs, and lists instead.
|
|
175
124
|
|
|
176
125
|
---
|
|
177
126
|
|
|
178
|
-
##
|
|
179
|
-
|
|
180
|
-
### High-Level Architecture
|
|
181
|
-
|
|
182
|
-
The package follows a layered architecture with clear separation of concerns:
|
|
183
|
-
|
|
184
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
185
|
-
|
|
186
|
-
### Module Map
|
|
187
|
-
|
|
188
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
127
|
+
## `PptxHandler` API
|
|
189
128
|
|
|
190
|
-
|
|
129
|
+
`PptxHandler` is the one class you use to open, change, and save files. Its main methods:
|
|
191
130
|
|
|
192
|
-
|
|
131
|
+
| Method | Signature | What it does |
|
|
132
|
+
| -------------------------- | ------------------------------------------------------- | ------------------------------------------------------ |
|
|
133
|
+
| `load` | `(data, options?) => Promise<PptxData>` | Open a `.pptx` and return the structured data |
|
|
134
|
+
| `save` | `(slides, options?) => Promise<Uint8Array>` | Write slides back to `.pptx` bytes |
|
|
135
|
+
| `exportSlides` | `(slides, options) => Promise<Map<number, Uint8Array>>` | Save chosen slides as standalone files |
|
|
136
|
+
| `getImageData` | `(path) => Promise<string \| undefined>` | Get an embedded image as a base64 data URL |
|
|
137
|
+
| `getMediaArrayBuffer` | `(path) => Promise<ArrayBuffer \| undefined>` | Get the raw bytes of an embedded media file |
|
|
138
|
+
| `getLayoutOptions` | `() => PptxLayoutOption[]` | List the slide layouts available |
|
|
139
|
+
| `getCompatibilityWarnings` | `() => PptxCompatibilityWarning[]` | List features in the file that are not fully supported |
|
|
140
|
+
| `applyTheme` | `(colors, fonts, name?) => Promise<void>` | Apply a complete theme |
|
|
141
|
+
| `setPresentationTheme` | `(path, applyToAll?) => Promise<void>` | Load a `.thmx` theme file |
|
|
193
142
|
|
|
194
|
-
|
|
143
|
+
The `PptxData` you get from `load()` exposes `slides`, `canvasSize`, `theme`, `slideMasters`, `slideLayouts`, `sections`, `coreProperties`, `embeddedFonts`, and more. See the [full docs](https://christophervr.github.io/pptx-viewer/) for the complete `PptxHandler`, chart/SmartArt, and theme APIs.
|
|
195
144
|
|
|
196
|
-
|
|
145
|
+
## What's supported
|
|
197
146
|
|
|
198
|
-
|
|
147
|
+
| Category | Details |
|
|
148
|
+
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
149
|
+
| **Element types** | 16: text, shape, connector, image, picture, table, chart, smartArt, ole, media, group, ink, contentPart, zoom, model3d, unknown |
|
|
150
|
+
| **Preset shapes** | 187+ PowerPoint shapes, including ones with adjustable handles |
|
|
151
|
+
| **Chart types** | 23, including waterfall, funnel, treemap, sunburst, box-whisker, region-map, and combo charts; with trendlines, error bars, and embedded Excel data |
|
|
152
|
+
| **Transitions** | 42 types (including morph, vortex, ripple, and shred) |
|
|
153
|
+
| **Animations** | 40+ presets, including colour animation, motion paths, and text that builds in by word, letter, or paragraph |
|
|
154
|
+
| **SmartArt** | 13 layout types, broken down into editable shapes |
|
|
155
|
+
| **Fills** | Solid, gradient (linear, radial, path), image, and 48 patterns |
|
|
156
|
+
| **Themes** | 8 built-in presets, switchable at runtime, with layout and placeholder remapping |
|
|
157
|
+
| **Security** | AES-128/256 encryption and decryption, modify-password (SHA), and detection of digital signatures |
|
|
158
|
+
| **Preserved** | VBA macros, custom XML, comment authors, and strict-format files are kept intact through a save |
|
|
199
159
|
|
|
200
|
-
|
|
160
|
+
## How it works
|
|
201
161
|
|
|
202
|
-
|
|
162
|
+
You only ever work with one class, `PptxHandler`, and one data object, `PptxData`. The engine takes care of the rest: when you call `load()` it unzips the file, reads the XML, resolves the theme, masters, and layouts, and hands you a clean object. `save()` runs those same steps in reverse.
|
|
203
163
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
207
|
-
|
|
208
|
-
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.
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## Deep Dive: How It Works
|
|
213
|
-
|
|
214
|
-
### 1. OpenXML ZIP Structure
|
|
215
|
-
|
|
216
|
-
A .pptx file is a ZIP archive with this internal structure:
|
|
217
|
-
|
|
218
|
-
```
|
|
219
|
-
presentation.pptx (ZIP)
|
|
220
|
-
+-- [Content_Types].xml <- MIME type registry
|
|
221
|
-
+-- _rels/.rels <- Root relationships
|
|
222
|
-
+-- docProps/
|
|
223
|
-
| +-- app.xml <- Application properties
|
|
224
|
-
| +-- core.xml <- Dublin Core metadata
|
|
225
|
-
| +-- custom.xml <- Custom properties
|
|
226
|
-
+-- ppt/
|
|
227
|
-
+-- presentation.xml <- Slide list, canvas size, slide master refs
|
|
228
|
-
+-- presProps.xml <- Presentation properties (show type, loop, etc.)
|
|
229
|
-
+-- viewProps.xml <- View state (zoom, grid, guides)
|
|
230
|
-
+-- tableStyles.xml <- Table style definitions
|
|
231
|
-
+-- _rels/presentation.xml.rels
|
|
232
|
-
+-- theme/
|
|
233
|
-
| +-- theme1.xml <- Colour scheme, fonts, format scheme
|
|
234
|
-
+-- slideMasters/
|
|
235
|
-
| +-- slideMaster1.xml <- Master slide (background, placeholders)
|
|
236
|
-
+-- slideLayouts/
|
|
237
|
-
| +-- slideLayout1.xml <- Layout templates
|
|
238
|
-
+-- slides/
|
|
239
|
-
| +-- slide1.xml <- Slide content (shape tree)
|
|
240
|
-
| +-- _rels/slide1.xml.rels <- Per-slide relationships
|
|
241
|
-
+-- media/
|
|
242
|
-
| +-- image1.png <- Embedded images
|
|
243
|
-
| +-- video1.mp4 <- Embedded media
|
|
244
|
-
| +-- model1.glb <- 3D models
|
|
245
|
-
+-- charts/
|
|
246
|
-
| +-- chart1.xml <- Chart definitions
|
|
247
|
-
+-- notesSlides/
|
|
248
|
-
| +-- notesSlide1.xml <- Speaker notes
|
|
249
|
-
+-- diagrams/ <- SmartArt data
|
|
250
|
-
+-- embeddings/ <- OLE embedded files
|
|
251
|
-
+-- customXml/ <- Custom XML parts
|
|
252
|
-
+-- vbaProject.bin <- VBA macros (if present)
|
|
253
|
-
```
|
|
164
|
+
A few things worth knowing as you use it:
|
|
254
165
|
|
|
255
|
-
|
|
166
|
+
- **Every element has a `type` field** (`text`, `shape`, `image`, `chart`, `table`, and so on). Check it before reading element-specific properties, for example `if (element.type === 'image')`. TypeScript then knows exactly which fields exist.
|
|
167
|
+
- **Shapes are drawn from a built-in catalogue** of 187+ PowerPoint shapes, so curves, arrows, and callouts come out with the right outlines.
|
|
168
|
+
- **Colours follow PowerPoint's theme rules**, so a colour defined as "accent 1, but 20% lighter" resolves to the correct final value for the active theme.
|
|
256
169
|
|
|
257
|
-
|
|
170
|
+
Under the hood the engine is split into many small, focused modules. If you want the full load and save pipeline, the complete type system, and a module-by-module map, see the [full documentation](https://christophervr.github.io/pptx-viewer/).
|
|
258
171
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
262
|
-
|
|
263
|
-
**Key type modules:**
|
|
264
|
-
|
|
265
|
-
| Module | Types |
|
|
266
|
-
| ----------------- | -------------------------------------------------------------------- |
|
|
267
|
-
| `common.ts` | `XmlObject`, `PptxData`, `PptxSlide`, `PptxCanvasSize` |
|
|
268
|
-
| `elements.ts` | `PptxElement` discriminated union (16 variants) |
|
|
269
|
-
| `element-base.ts` | `PptxElementBase` shared properties |
|
|
270
|
-
| `text.ts` | `TextStyle`, `ParagraphStyle`, `TextSegment`, `TextBody` |
|
|
271
|
-
| `shape-style.ts` | `ShapeStyle`, `FillStyle`, `StrokeStyle`, `ShadowEffect` |
|
|
272
|
-
| `table.ts` | `TableData`, `TableCell`, `TableRow`, `TableBorderStyle` |
|
|
273
|
-
| `chart.ts` | `PptxChartData`, `ChartSeries`, `ChartAxis` (23 chart types) |
|
|
274
|
-
| `theme.ts` | `PptxTheme`, `PptxThemeColorScheme`, `PptxThemeFontScheme` |
|
|
275
|
-
| `animation.ts` | `PptxElementAnimation`, `PptxAnimationPreset` |
|
|
276
|
-
| `transition.ts` | `PptxSlideTransition` (42 transition types) |
|
|
277
|
-
| `masters.ts` | `PptxSlideMaster`, `PptxSlideLayout` |
|
|
278
|
-
| `image.ts` | `ImageEffects`, `ImageCrop` |
|
|
279
|
-
| `geometry.ts` | `PptxCustomGeometry`, `GeometryPath` |
|
|
280
|
-
| `smart-art.ts` | `PptxSmartArtData`, `SmartArtNode` |
|
|
281
|
-
| `media.ts` | `PptxMediaData`, `MediaTiming`, `MediaBookmark`, `MediaCaptionTrack` |
|
|
282
|
-
| `metadata.ts` | `CoreProperties`, `AppProperties` |
|
|
283
|
-
| `three-d.ts` | `ThreeDProperties`, `BevelType` |
|
|
284
|
-
| `type-guards.ts` | Runtime type guard functions for PptxElement variants |
|
|
285
|
-
|
|
286
|
-
### 3. Theme Resolution Chain
|
|
287
|
-
|
|
288
|
-
PowerPoint elements inherit visual styles through a multi-level chain. The runtime resolves styles in this order:
|
|
289
|
-
|
|
290
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
291
|
-
|
|
292
|
-
**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`.
|
|
293
|
-
|
|
294
|
-
The engine ships with **8 built-in theme presets** and supports runtime theme switching with layout switching and placeholder remapping.
|
|
295
|
-
|
|
296
|
-
### 4. Geometry Engine
|
|
297
|
-
|
|
298
|
-
The geometry module (17 files) handles shape path generation and coordinate transforms:
|
|
299
|
-
|
|
300
|
-
| Module | Purpose |
|
|
301
|
-
| ----------------------------- | --------------------------------------------------------- |
|
|
302
|
-
| `shape-geometry.ts` | Main entry -- resolves shape type, clip path, image masks |
|
|
303
|
-
| `connector-geometry.ts` | Connector routing and path generation |
|
|
304
|
-
| `guide-formula.ts` | OOXML DrawingML guide formula evaluator |
|
|
305
|
-
| `guide-formula-eval.ts` | Mathematical expression evaluation engine |
|
|
306
|
-
| `guide-formula-paths.ts` | SVG path generation from guide-computed coordinates |
|
|
307
|
-
| `preset-shape-definitions.ts` | 187+ preset shape definitions (rect, arrow, star, etc.) |
|
|
308
|
-
| `preset-shape-paths.ts` | Pre-computed SVG clip paths for all preset shapes |
|
|
309
|
-
| `transform-utils.ts` | Element position/rotation/flip transforms |
|
|
310
|
-
| `custom-geometry.ts` | Arbitrary OOXML `<a:custGeom>` path parsing |
|
|
311
|
-
|
|
312
|
-
**Guide formula evaluation** implements the OOXML DrawingML formula language:
|
|
313
|
-
|
|
314
|
-
```
|
|
315
|
-
+-----------------------------------------------------+
|
|
316
|
-
| Guide Formula Language |
|
|
317
|
-
| |
|
|
318
|
-
| Operators: +/-, */div, val, abs, sqrt, sin, cos, |
|
|
319
|
-
| tan, at2, min, max, mod, pin, if, ?: |
|
|
320
|
-
| |
|
|
321
|
-
| Built-in variables: |
|
|
322
|
-
| w (shape width), h (shape height) |
|
|
323
|
-
| l, t, r, b (left, top, right, bottom) |
|
|
324
|
-
| wd2, hd2 (half width/height) |
|
|
325
|
-
| cd2, cd4, cd8 (circle division constants) |
|
|
326
|
-
| |
|
|
327
|
-
| Adjustment handles: adj, adj1, adj2, ... |
|
|
328
|
-
| (user-draggable shape parameters) |
|
|
329
|
-
+-----------------------------------------------------+
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### 5. Colour Processing
|
|
333
|
-
|
|
334
|
-
The colour module (4 files) handles OOXML colour parsing and transforms:
|
|
335
|
-
|
|
336
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
337
|
-
|
|
338
|
-
Supported colour transform operations:
|
|
339
|
-
| Transform | Effect |
|
|
340
|
-
|-----------|--------|
|
|
341
|
-
| `lumMod` / `lumOff` | Luminance modulate / offset |
|
|
342
|
-
| `tint` / `shade` | Lighten / darken toward white/black |
|
|
343
|
-
| `satMod` / `satOff` | Saturation modulate / offset |
|
|
344
|
-
| `hueMod` / `hueOff` | Hue rotation |
|
|
345
|
-
| `alpha` | Opacity (0--100000 = 0--100%) |
|
|
346
|
-
| `comp` | Complementary colour |
|
|
347
|
-
| `inv` | Invert colour |
|
|
348
|
-
| `gray` | Grayscale conversion |
|
|
349
|
-
|
|
350
|
-
### 6. Converter System
|
|
351
|
-
|
|
352
|
-
The PPTX-to-Markdown converter uses a registry pattern for element processing:
|
|
353
|
-
|
|
354
|
-
_See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/core/README.md) for visual representations._
|
|
355
|
-
|
|
356
|
-
The converter supports two output modes:
|
|
357
|
-
|
|
358
|
-
- **Positioned mode** (default): HTML `<div>` elements with absolute CSS positioning.
|
|
359
|
-
- **Semantic mode** (`semanticMode: true`): Clean Markdown with headings, paragraphs, and lists.
|
|
360
|
-
|
|
361
|
-
The `MediaContext` class manages image extraction during conversion, mapping data URLs to output file paths and deduplicating identical images.
|
|
362
|
-
|
|
363
|
-
### 7. Services Layer
|
|
364
|
-
|
|
365
|
-
Nine specialised services handle cross-cutting concerns:
|
|
366
|
-
|
|
367
|
-
| Service | Responsibility |
|
|
368
|
-
| ------------------------------- | ------------------------------------------------------------- |
|
|
369
|
-
| `PptxSlideLoaderService` | Coordinate slide XML parsing -- elements, notes, media timing |
|
|
370
|
-
| `PptxNativeAnimationService` | Parse native OOXML animation timing trees (`p:timing`) |
|
|
371
|
-
| `PptxEditorAnimationService` | Map between editor animation presets and OOXML sequences |
|
|
372
|
-
| `PptxAnimationWriteService` | Serialise editor animations back to OOXML timing XML |
|
|
373
|
-
| `PptxSlideTransitionService` | Parse and write slide transition effects (`p:transition`) |
|
|
374
|
-
| `PptxCompatibilityService` | Detect unsupported features and generate warnings |
|
|
375
|
-
| `PptxXmlLookupService` | Cached XML lookups across relationships and parts |
|
|
376
|
-
| `PptxDocumentPropertiesUpdater` | Update `docProps/core.xml` and `docProps/app.xml` |
|
|
377
|
-
| `PptxTemplateBackgroundService` | Manage template/layout background images |
|
|
378
|
-
|
|
379
|
-
### 8. Builder APIs (Fluent SDK)
|
|
380
|
-
|
|
381
|
-
The SDK provides a comprehensive fluent API for creating and manipulating presentations programmatically. Three tiers are available, from highest to lowest level:
|
|
382
|
-
|
|
383
|
-
#### Tier 1 — `Presentation` (highest level)
|
|
384
|
-
|
|
385
|
-
The recommended entry point. Manages slides, text operations, sections, templates, merging, and saving — all with zero boilerplate.
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
import {
|
|
389
|
-
Presentation,
|
|
390
|
-
ThemePresets,
|
|
391
|
-
inches,
|
|
392
|
-
SlideSizes,
|
|
393
|
-
TextBuilder,
|
|
394
|
-
ShapeBuilder,
|
|
395
|
-
ChartBuilder,
|
|
396
|
-
TableBuilder,
|
|
397
|
-
ImageBuilder,
|
|
398
|
-
ConnectorBuilder,
|
|
399
|
-
MediaBuilder,
|
|
400
|
-
GroupBuilder,
|
|
401
|
-
} from 'pptx-viewer-core';
|
|
402
|
-
|
|
403
|
-
// Create a new presentation
|
|
404
|
-
const pptx = await Presentation.create({
|
|
405
|
-
title: 'Quarterly Report',
|
|
406
|
-
creator: 'Sales Team',
|
|
407
|
-
width: SlideSizes.WIDESCREEN_16_9.width,
|
|
408
|
-
height: SlideSizes.WIDESCREEN_16_9.height,
|
|
409
|
-
theme: ThemePresets.MODERN_BLUE,
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
// Add slides — they are auto-tracked, no manual push or .build() needed
|
|
413
|
-
pptx
|
|
414
|
-
.addSlide('Title Slide')
|
|
415
|
-
.addText('Q4 2026 Results', { fontSize: 44, bold: true, x: 100, y: 200, width: 800, height: 80 })
|
|
416
|
-
.addText('Confidential', {
|
|
417
|
-
fontSize: 14,
|
|
418
|
-
color: '#999999',
|
|
419
|
-
x: 100,
|
|
420
|
-
y: 300,
|
|
421
|
-
width: 800,
|
|
422
|
-
height: 30,
|
|
423
|
-
})
|
|
424
|
-
.setBackground({ type: 'solid', color: '#1B2A4A' })
|
|
425
|
-
.setNotes('Open with the revenue highlight')
|
|
426
|
-
.setTransition({ type: 'fade', duration: 500 });
|
|
427
|
-
|
|
428
|
-
pptx
|
|
429
|
-
.addSlide('Blank')
|
|
430
|
-
.addText('Revenue grew 15% YoY', { fontSize: 24, x: 50, y: 50, width: 600, height: 40 })
|
|
431
|
-
.addChart(
|
|
432
|
-
'bar',
|
|
433
|
-
{
|
|
434
|
-
series: [
|
|
435
|
-
{ name: '2025', values: [120, 145, 160, 180], color: '#93C5FD' },
|
|
436
|
-
{ name: '2026', values: [140, 170, 195, 210], color: '#2563EB' },
|
|
437
|
-
],
|
|
438
|
-
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
439
|
-
title: 'Revenue ($M)',
|
|
440
|
-
},
|
|
441
|
-
{ x: 50, y: 100, width: 600, height: 400 },
|
|
442
|
-
)
|
|
443
|
-
.addShape('roundRect', {
|
|
444
|
-
fill: { type: 'solid', color: '#2563EB' },
|
|
445
|
-
text: 'See appendix',
|
|
446
|
-
x: 700,
|
|
447
|
-
y: 450,
|
|
448
|
-
width: 200,
|
|
449
|
-
height: 40,
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// Save to bytes
|
|
453
|
-
const bytes = await pptx.save();
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
**Full `Presentation` API reference:**
|
|
457
|
-
|
|
458
|
-
| Category | Method | Description |
|
|
459
|
-
| --------------- | ------------------------------------------------ | --------------------------------------------- |
|
|
460
|
-
| **Create/Load** | `Presentation.create(options?)` | Create a new blank presentation |
|
|
461
|
-
| | `Presentation.load(buffer)` | Load an existing .pptx file |
|
|
462
|
-
| **Slides** | `addSlide(layoutName?)` | Add a slide (returns `SlideBuilder`) |
|
|
463
|
-
| | `insertSlide(index, layoutName?)` | Insert a slide at position |
|
|
464
|
-
| | `duplicateSlide(slideIndex)` | Deep-clone a slide with new IDs |
|
|
465
|
-
| | `removeSlide(index)` | Remove a slide (chainable) |
|
|
466
|
-
| | `moveSlide(from, to)` | Move a slide (chainable) |
|
|
467
|
-
| | `swapSlides(indexA, indexB)` | Swap two slides (chainable) |
|
|
468
|
-
| | `reorderSlides(newOrder)` | Reorder all slides by index array (chainable) |
|
|
469
|
-
| | `clearSlides()` | Remove all slides (chainable) |
|
|
470
|
-
| | `getSlide(index)` | Get a slide by index |
|
|
471
|
-
| | `forEachSlide(callback)` | Iterate slides (chainable) |
|
|
472
|
-
| | `findSlides(predicate)` | Find slide indices matching a predicate |
|
|
473
|
-
| | `slideCount` | Number of slides |
|
|
474
|
-
| **Text** | `findText(search)` | Search all slides for text (string or RegExp) |
|
|
475
|
-
| | `replaceText(search, replacement)` | Replace text across all slides |
|
|
476
|
-
| | `replaceTextOnSlide(index, search, replacement)` | Replace text on a single slide |
|
|
477
|
-
| **Sections** | `addSection(name, slideIndices)` | Group slides into a section |
|
|
478
|
-
| | `removeSection(sectionId)` | Remove a section |
|
|
479
|
-
| | `reorderSections(sectionIds)` | Reorder sections (chainable) |
|
|
480
|
-
| | `getSectionForSlide(slideIndex)` | Get the section a slide belongs to |
|
|
481
|
-
| | `moveSlidesToSection(indices, targetId)` | Move slides between sections |
|
|
482
|
-
| | `sections` | Get all sections |
|
|
483
|
-
| **Template** | `applyTemplate(data)` | Replace `{{placeholders}}` (chainable) |
|
|
484
|
-
| | `mailMerge(records)` | Generate multiple files from template data |
|
|
485
|
-
| **Merge** | `merge(source, options?)` | Merge another presentation's slides |
|
|
486
|
-
| **Diff** | `diff(other)` | Structured comparison of two presentations |
|
|
487
|
-
| **Save** | `save()` | Serialize to `.pptx` bytes |
|
|
488
|
-
| | `saveEncrypted(password)` | Save with password encryption |
|
|
489
|
-
| **Metadata** | `title` | Presentation title |
|
|
490
|
-
| | `creator` | Author name |
|
|
491
|
-
| | `width` / `height` | Slide dimensions in EMU |
|
|
492
|
-
| **Advanced** | `handler` | Underlying `PptxHandler` |
|
|
493
|
-
| | `data` | Underlying `PptxData` (live reference) |
|
|
494
|
-
| | `slides` | Live slides array |
|
|
495
|
-
| | `xmlBuilder()` | Low-level `PptxXmlBuilder` for mutation |
|
|
496
|
-
| | `dispose()` | Free resources |
|
|
497
|
-
|
|
498
|
-
#### Tier 2 — Element Builders (fluent element construction)
|
|
499
|
-
|
|
500
|
-
Eight builder classes for step-by-step element construction with method chaining. Each builder's `.build()` produces a standard `PptxElement`.
|
|
501
|
-
|
|
502
|
-
**TextBuilder:**
|
|
503
|
-
|
|
504
|
-
```typescript
|
|
505
|
-
const title = TextBuilder.create('Hello World')
|
|
506
|
-
.fontSize(36)
|
|
507
|
-
.bold()
|
|
508
|
-
.italic()
|
|
509
|
-
.underline()
|
|
510
|
-
.strikethrough()
|
|
511
|
-
.color('#2563EB')
|
|
512
|
-
.fontFamily('Inter')
|
|
513
|
-
.alignment('center')
|
|
514
|
-
.verticalAlignment('middle')
|
|
515
|
-
.lineSpacing(1.5)
|
|
516
|
-
.fill({ type: 'solid', color: '#F0F4F8' })
|
|
517
|
-
.stroke({ color: '#2563EB', width: 1 })
|
|
518
|
-
.shadow({ blur: 4, offsetX: 2, offsetY: 2, opacity: 0.3 })
|
|
519
|
-
.position(100, 100)
|
|
520
|
-
.size(600, 80)
|
|
521
|
-
.rotation(0)
|
|
522
|
-
.opacity(1)
|
|
523
|
-
.build();
|
|
524
|
-
|
|
525
|
-
// Rich text with multiple segments
|
|
526
|
-
const richText = TextBuilder.create([
|
|
527
|
-
{ text: 'Bold intro. ', style: { bold: true, fontSize: 18 } },
|
|
528
|
-
{ text: 'Normal body text.', style: { fontSize: 14 } },
|
|
529
|
-
])
|
|
530
|
-
.position(50, 200)
|
|
531
|
-
.size(800, 40)
|
|
532
|
-
.build();
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
**ShapeBuilder:**
|
|
536
|
-
|
|
537
|
-
```typescript
|
|
538
|
-
const shape = ShapeBuilder.create('roundRect')
|
|
539
|
-
.solidFill('#4472C4') // Convenience: solid fill
|
|
540
|
-
.noFill() // Convenience: transparent
|
|
541
|
-
.gradientFill(
|
|
542
|
-
[
|
|
543
|
-
// Convenience: gradient fill
|
|
544
|
-
{ color: '#2563EB', position: 0 },
|
|
545
|
-
{ color: '#60A5FA', position: 1 },
|
|
546
|
-
],
|
|
547
|
-
45,
|
|
548
|
-
)
|
|
549
|
-
.fill({ type: 'pattern', preset: 'dkDnDiag' }) // Full fill input
|
|
550
|
-
.stroke({ color: '#000', width: 2, dash: 'dash' })
|
|
551
|
-
.shadow({ blur: 8, offsetX: 3, offsetY: 3 })
|
|
552
|
-
.text('Click me')
|
|
553
|
-
.textStyle({ fontSize: 14, bold: true, color: '#FFF' })
|
|
554
|
-
.adjustments({ adj1: 16667 }) // Geometry adjustment handles
|
|
555
|
-
.position(200, 200)
|
|
556
|
-
.size(300, 200)
|
|
557
|
-
.rotation(15)
|
|
558
|
-
.opacity(0.9)
|
|
559
|
-
.build();
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
**ImageBuilder:**
|
|
563
|
-
|
|
564
|
-
```typescript
|
|
565
|
-
const logo = ImageBuilder.create('data:image/png;base64,iVBOR...')
|
|
566
|
-
.altText('Company logo')
|
|
567
|
-
.crop(0.1, 0.05, 0.1, 0.05) // Fractional crop from each edge
|
|
568
|
-
.position(50, 50)
|
|
569
|
-
.size(200, 100)
|
|
570
|
-
.rotation(0)
|
|
571
|
-
.opacity(1)
|
|
572
|
-
.build();
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
**TableBuilder:**
|
|
576
|
-
|
|
577
|
-
```typescript
|
|
578
|
-
const table = TableBuilder.create()
|
|
579
|
-
.headerRow(['Name', 'Q1', 'Q2', 'Q3', 'Q4'])
|
|
580
|
-
.addRow(['North', '120', '145', '160', '180'])
|
|
581
|
-
.addRow(['South', '90', '105', '130', '150'])
|
|
582
|
-
.addRow([
|
|
583
|
-
{ text: 'Total', style: { bold: true } },
|
|
584
|
-
{ text: '210', style: { bold: true, color: '#2563EB' } },
|
|
585
|
-
{ text: '250' },
|
|
586
|
-
{ text: '290' },
|
|
587
|
-
{ text: '330' },
|
|
588
|
-
])
|
|
589
|
-
.columnWidths([2, 1, 1, 1, 1]) // Proportional widths
|
|
590
|
-
.bandRows()
|
|
591
|
-
.bandColumns(false)
|
|
592
|
-
.firstCol()
|
|
593
|
-
.lastRow()
|
|
594
|
-
.lastCol(false)
|
|
595
|
-
.style('{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}')
|
|
596
|
-
.position(50, 150)
|
|
597
|
-
.size(860, 250)
|
|
598
|
-
.build();
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
**ChartBuilder:**
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
const chart = ChartBuilder.create('line') // bar, line, pie, doughnut, area, scatter, ...
|
|
605
|
-
.categories(['Jan', 'Feb', 'Mar', 'Apr'])
|
|
606
|
-
.addSeries('Actual', [42, 58, 67, 73], '#2563EB')
|
|
607
|
-
.addSeries('Target', [50, 55, 60, 65], '#E94560')
|
|
608
|
-
.title('Monthly Performance')
|
|
609
|
-
.legend(true, 'b') // Show legend at bottom
|
|
610
|
-
.grouping('clustered') // clustered | stacked | percentStacked
|
|
611
|
-
.position(100, 150)
|
|
612
|
-
.size(600, 400)
|
|
613
|
-
.build();
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
**ConnectorBuilder:**
|
|
617
|
-
|
|
618
|
-
```typescript
|
|
619
|
-
const line = ConnectorBuilder.create()
|
|
620
|
-
.type('curved') // straight | bent | curved
|
|
621
|
-
.stroke({ color: '#333', width: 2, dash: 'dashDot' })
|
|
622
|
-
.startArrow('triangle')
|
|
623
|
-
.endArrow('stealth')
|
|
624
|
-
.from(shape1.id, 2) // Connect from shape1, site index 2
|
|
625
|
-
.to(shape2.id, 0) // Connect to shape2, site index 0
|
|
626
|
-
.position(100, 100)
|
|
627
|
-
.size(300, 0)
|
|
628
|
-
.rotation(0)
|
|
629
|
-
.build();
|
|
630
|
-
```
|
|
631
|
-
|
|
632
|
-
**MediaBuilder:**
|
|
633
|
-
|
|
634
|
-
```typescript
|
|
635
|
-
const video = MediaBuilder.video('data:video/mp4;base64,...')
|
|
636
|
-
.autoPlay()
|
|
637
|
-
.loop()
|
|
638
|
-
.volume(0.8)
|
|
639
|
-
.trim(1000, 5000) // Trim: start at 1s, end at 5s
|
|
640
|
-
.posterFrame('data:image/png;base64,...')
|
|
641
|
-
.position(100, 100)
|
|
642
|
-
.size(480, 270)
|
|
643
|
-
.build();
|
|
644
|
-
|
|
645
|
-
const audio = MediaBuilder.audio('path/to/audio.mp3')
|
|
646
|
-
.autoPlay(false)
|
|
647
|
-
.loop(false)
|
|
648
|
-
.volume(1.0)
|
|
649
|
-
.build();
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
**GroupBuilder:**
|
|
653
|
-
|
|
654
|
-
```typescript
|
|
655
|
-
const group = GroupBuilder.create()
|
|
656
|
-
.addChild(TextBuilder.create('Label').position(0, 0).size(100, 30).build())
|
|
657
|
-
.addChildBuilder(ShapeBuilder.create('rect').solidFill('#EEE').size(100, 100))
|
|
658
|
-
.addChildren([element1, element2])
|
|
659
|
-
.position(200, 200)
|
|
660
|
-
.size(300, 300)
|
|
661
|
-
.rotation(10)
|
|
662
|
-
.build();
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
#### SlideBuilder (returned by `Presentation.addSlide()`)
|
|
666
|
-
|
|
667
|
-
Chainable API for adding elements and setting slide properties:
|
|
668
|
-
|
|
669
|
-
```typescript
|
|
670
|
-
pptx
|
|
671
|
-
.addSlide('Blank')
|
|
672
|
-
// Add elements (all chainable)
|
|
673
|
-
.addText('Title', { fontSize: 36, x: 50, y: 50, width: 860, height: 60 })
|
|
674
|
-
.addShape('ellipse', {
|
|
675
|
-
fill: { type: 'solid', color: '#FF0000' },
|
|
676
|
-
x: 50,
|
|
677
|
-
y: 150,
|
|
678
|
-
width: 100,
|
|
679
|
-
height: 100,
|
|
680
|
-
})
|
|
681
|
-
.addImage('data:image/png;base64,...', { x: 200, y: 150, width: 300, height: 200 })
|
|
682
|
-
.addTable({ rows: [{ cells: [{ text: 'A' }, { text: 'B' }] }] })
|
|
683
|
-
.addChart('pie', { series: [{ name: 'S1', values: [60, 40] }], categories: ['Yes', 'No'] })
|
|
684
|
-
.addConnector({ type: 'straight', stroke: { color: '#000', width: 1 } })
|
|
685
|
-
.addMedia('video', 'data:video/mp4;base64,...', { autoPlay: true })
|
|
686
|
-
.addGroup([element1, element2], { x: 0, y: 0, width: 960, height: 540 })
|
|
687
|
-
.addFreeform('M 0 0 L 100 50 L 50 100 Z', { stroke: { color: '#F00', width: 2 } })
|
|
688
|
-
.addElement(anyPptxElement) // Add any pre-built element
|
|
689
|
-
.addBuilderElement(TextBuilder.create('X').bold()) // Accept any builder
|
|
690
|
-
// Slide properties
|
|
691
|
-
.setBackground({
|
|
692
|
-
type: 'gradient',
|
|
693
|
-
angle: 135,
|
|
694
|
-
stops: [
|
|
695
|
-
{ color: '#000', position: 0 },
|
|
696
|
-
{ color: '#333', position: 1 },
|
|
697
|
-
],
|
|
698
|
-
})
|
|
699
|
-
.setTransition({ type: 'morph', duration: 800 })
|
|
700
|
-
.addAnimation(elementId, { preset: 'fadeIn', trigger: 'afterPrevious', duration: 500 })
|
|
701
|
-
.setNotes('Speaker notes here')
|
|
702
|
-
.setHidden(false)
|
|
703
|
-
.setSection('Introduction')
|
|
704
|
-
.setName('Intro Slide')
|
|
705
|
-
// Query methods
|
|
706
|
-
.getElements() // Readonly array of current elements
|
|
707
|
-
.getLastElement() // Last element (for animation IDs)
|
|
708
|
-
.elementCount // Number of elements
|
|
709
|
-
.removeElement(elementId) // Remove by ID (chainable)
|
|
710
|
-
.build(); // Get the PptxSlide object
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
#### Unit Helpers and Theme Presets
|
|
714
|
-
|
|
715
|
-
```typescript
|
|
716
|
-
import { inches, cm, mm, pt, inchesToEmu, SlideSizes, ThemePresets } from 'pptx-viewer-core';
|
|
717
|
-
|
|
718
|
-
// Unit conversions (all return pixels at 96 DPI)
|
|
719
|
-
inches(1); // => 96
|
|
720
|
-
cm(2.54); // => 96
|
|
721
|
-
mm(25.4); // => 96
|
|
722
|
-
pt(72); // => 96
|
|
723
|
-
|
|
724
|
-
// EMU conversions (for PresentationOptions width/height)
|
|
725
|
-
inchesToEmu(10); // => 9144000
|
|
726
|
-
|
|
727
|
-
// Standard slide sizes (EMU values)
|
|
728
|
-
SlideSizes.WIDESCREEN_16_9; // { width: 12192000, height: 6858000 }
|
|
729
|
-
SlideSizes.STANDARD_4_3; // { width: 9144000, height: 6858000 }
|
|
730
|
-
SlideSizes.A4_LANDSCAPE; // { width: 10692000, height: 7560937 }
|
|
731
|
-
|
|
732
|
-
// Theme presets (8 built-in themes)
|
|
733
|
-
ThemePresets.OFFICE; // Default Office theme
|
|
734
|
-
ThemePresets.MODERN_BLUE; // Clean blue professional
|
|
735
|
-
ThemePresets.CORPORATE; // Professional corporate
|
|
736
|
-
ThemePresets.DARK; // Dark mode
|
|
737
|
-
ThemePresets.VIBRANT; // Energetic colours
|
|
738
|
-
ThemePresets.EARTH; // Warm earth tones
|
|
739
|
-
ThemePresets.MONOCHROME; // High contrast B&W
|
|
740
|
-
ThemePresets.MINIMAL; // Soft pastels
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
#### Tier 3 — Low-Level APIs
|
|
744
|
-
|
|
745
|
-
**PptxXmlBuilder** — Fluent in-place mutation of an existing `PptxData`:
|
|
746
|
-
|
|
747
|
-
```typescript
|
|
748
|
-
PptxXmlBuilder.from(data)
|
|
749
|
-
.slide(0)
|
|
750
|
-
.elements()
|
|
751
|
-
.add(createTextElement('New text'))
|
|
752
|
-
.removeById('old_id')
|
|
753
|
-
.updateById('el_id', (el) => ({ ...el, x: 200 }))
|
|
754
|
-
.done()
|
|
755
|
-
.notes()
|
|
756
|
-
.set('Updated notes')
|
|
757
|
-
.done()
|
|
758
|
-
.done()
|
|
759
|
-
.project(); // => mutated PptxData
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
**SDK Operations** — Pure functions for batch operations:
|
|
763
|
-
|
|
764
|
-
| Category | Functions |
|
|
765
|
-
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
766
|
-
| **Text** | `findText`, `replaceText`, `replaceTextInSlide` |
|
|
767
|
-
| **Charts** | `setChartType`, `addChartSeries`, `removeChartSeries`, `setChartCategories`, `updateChartSeriesValues`, `setChartTitle`, `setChartGrouping`, `updateChartDataPoint`, `addChartCategory`, `removeChartCategory` |
|
|
768
|
-
| **Shapes** | `replaceShapeGeometry`, `replaceWithCustomGeometry`, `interpolateShapeGeometry`, `parseSvgPath`, `serializeSvgPath` |
|
|
769
|
-
| **Slides** | `duplicateSlide`, `duplicateElement` |
|
|
770
|
-
| **Sections** | `addSection`, `removeSection`, `reorderSections`, `getSectionForSlide`, `moveSlidesToSection` |
|
|
771
|
-
| **Merge** | `mergePresentation` |
|
|
772
|
-
| **Diff** | `diffPresentations`, `diffSlides` |
|
|
773
|
-
| **Template** | `applyTemplate`, `findPlaceholders`, `mailMerge` |
|
|
774
|
-
| **Layout** | `createLayout`, `createLayouts`, `findLayoutByName`, `findLayoutByType`, `generateLayoutXml` |
|
|
775
|
-
|
|
776
|
-
**PptxElementXmlBuilder** — Low-level element XML construction:
|
|
777
|
-
|
|
778
|
-
- Builds `<p:sp>`, `<p:pic>`, `<p:cxnSp>`, `<p:graphicFrame>` nodes
|
|
779
|
-
- Factory per element type: `TextShapeXmlFactory`, `PictureXmlFactory`, `ConnectorXmlFactory`, `MediaGraphicFrameXmlFactory`
|
|
780
|
-
|
|
781
|
-
### 9. Encryption and Security
|
|
782
|
-
|
|
783
|
-
The engine handles several security-related PPTX features:
|
|
784
|
-
|
|
785
|
-
| Feature | Description |
|
|
786
|
-
| ------------------------------ | ------------------------------------------------------------------------------------------- |
|
|
787
|
-
| **PPTX Encryption/Decryption** | AES-128/256 Agile encryption per [MS-OFFCRYPTO]. Reads and writes password-protected files. |
|
|
788
|
-
| **Modify Password** | SHA-based hash verifier for write-protection (does not prevent opening). |
|
|
789
|
-
| **Digital Signatures** | Detects and can strip XML digital signatures (`_xmlsignatures` parts). |
|
|
790
|
-
| **Encrypted File Detection** | Identifies OLE compound file format (CFB) wrapping encrypted PPTX content. |
|
|
791
|
-
|
|
792
|
-
---
|
|
793
|
-
|
|
794
|
-
## Type System Reference
|
|
795
|
-
|
|
796
|
-
The core type system uses **EMU (English Metric Units)** as the native coordinate system, matching PowerPoint's internal representation:
|
|
797
|
-
|
|
798
|
-
```
|
|
799
|
-
1 inch = 914,400 EMU
|
|
800
|
-
1 cm = 360,000 EMU
|
|
801
|
-
1 point = 12,700 EMU
|
|
802
|
-
1 pixel = 9,525 EMU (at 96 DPI)
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
**PptxData** -- the top-level parsed result:
|
|
806
|
-
|
|
807
|
-
```typescript
|
|
808
|
-
interface PptxData {
|
|
809
|
-
slides: PptxSlide[];
|
|
810
|
-
canvasSize: PptxCanvasSize;
|
|
811
|
-
theme?: PptxTheme;
|
|
812
|
-
slideMasters: PptxSlideMaster[];
|
|
813
|
-
slideLayouts: PptxSlideLayout[];
|
|
814
|
-
sections: PptxSection[];
|
|
815
|
-
customShows: PptxCustomShow[];
|
|
816
|
-
presentationProperties: PresentationProperties;
|
|
817
|
-
coreProperties: CoreProperties;
|
|
818
|
-
appProperties: AppProperties;
|
|
819
|
-
customProperties: CustomProperty[];
|
|
820
|
-
embeddedFonts: EmbeddedFont[];
|
|
821
|
-
// ...
|
|
822
|
-
}
|
|
823
|
-
```
|
|
824
|
-
|
|
825
|
-
**PptxSlide** -- a single slide:
|
|
826
|
-
|
|
827
|
-
```typescript
|
|
828
|
-
interface PptxSlide {
|
|
829
|
-
id: string;
|
|
830
|
-
elements: PptxElement[];
|
|
831
|
-
background?: SlideBackground;
|
|
832
|
-
transition?: PptxSlideTransition;
|
|
833
|
-
notes?: string;
|
|
834
|
-
hidden?: boolean;
|
|
835
|
-
layoutPath?: string;
|
|
836
|
-
// ...
|
|
837
|
-
}
|
|
838
|
-
```
|
|
839
|
-
|
|
840
|
-
---
|
|
841
|
-
|
|
842
|
-
## Feature Summary
|
|
843
|
-
|
|
844
|
-
| Category | Details |
|
|
845
|
-
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
846
|
-
| **Element Types** | 16: text, shape, connector, image, picture, table, chart, smartArt, ole, media, group, ink, contentPart, zoom, model3d, unknown |
|
|
847
|
-
| **Preset Shapes** | 187+ with guide formula evaluation and adjustment handles |
|
|
848
|
-
| **Chart Types** | 23: bar, column, line, area, pie, doughnut, scatter, bubble, radar, stock, surface/3D, histogram, waterfall, funnel, treemap, sunburst, boxWhisker, regionMap, combo |
|
|
849
|
-
| **Chart Features** | Display units, logarithmic axes, chart color styles, embedded Excel data, pivot sources, trendlines, error bars, data tables |
|
|
850
|
-
| **Transitions** | 42 types including morph, vortex, ripple, shred, and p14 extensions |
|
|
851
|
-
| **Animations** | 40+ presets with color animations, motion path auto-rotation, text build (by word/letter/paragraph) |
|
|
852
|
-
| **SmartArt** | 13 layout types (list, process, cycle, hierarchy, matrix, gear, etc.) |
|
|
853
|
-
| **Fills** | Solid, gradient (linear/radial/path), image, 48 pattern presets |
|
|
854
|
-
| **Text Features** | Warp (24+ presets), inline math (OMML to MathML), multi-column, text field substitution |
|
|
855
|
-
| **Themes** | 8 built-in presets, runtime switching, layout/placeholder remapping |
|
|
856
|
-
| **3D** | ThreeDProperties for shapes and text, extrusion, bevel, material, lighting |
|
|
857
|
-
| **Security** | AES-128/256 encryption/decryption, modify password (SHA), digital signature detection |
|
|
858
|
-
| **Preservation** | VBA macros, custom XML parts, comment authors, OOXML Strict namespaces |
|
|
859
|
-
| **Other** | Kiosk mode, custom shows, sections, tags, print settings, photo album, guide lines, embedded font deobfuscation |
|
|
860
|
-
|
|
861
|
-
---
|
|
862
|
-
|
|
863
|
-
## File Structure Reference
|
|
172
|
+
## Limitations
|
|
864
173
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
+-- core/ # Core PPTX engine (247 files)
|
|
870
|
-
| +-- index.ts # Core barrel export
|
|
871
|
-
| +-- PptxHandler.ts # Public facade class
|
|
872
|
-
| +-- PptxHandlerCore.ts # Facade over IPptxHandlerRuntime
|
|
873
|
-
| +-- constants.ts # EMU conversion, XML namespaces
|
|
874
|
-
| +-- constants-colors.ts # Named colour constants
|
|
875
|
-
| |
|
|
876
|
-
| +-- types/ # Type system (22 files)
|
|
877
|
-
| | +-- index.ts # Barrel re-export
|
|
878
|
-
| | +-- common.ts # PptxData, PptxSlide, XmlObject
|
|
879
|
-
| | +-- elements.ts # PptxElement discriminated union (16 variants)
|
|
880
|
-
| | +-- element-base.ts # PptxElementBase shared props
|
|
881
|
-
| | +-- text.ts # TextStyle, Paragraph, TextSegment
|
|
882
|
-
| | +-- shape-style.ts # ShapeStyle, FillStyle, StrokeStyle
|
|
883
|
-
| | +-- table.ts # TableData, TableCell, TableRow
|
|
884
|
-
| | +-- chart.ts # PptxChartData, ChartSeries (23 types)
|
|
885
|
-
| | +-- theme.ts # PptxTheme, colour/font schemes
|
|
886
|
-
| | +-- animation.ts # PptxElementAnimation
|
|
887
|
-
| | +-- transition.ts # PptxSlideTransition (42 types)
|
|
888
|
-
| | +-- masters.ts # PptxSlideMaster, PptxSlideLayout
|
|
889
|
-
| | +-- image.ts # ImageEffects, ImageCrop
|
|
890
|
-
| | +-- geometry.ts # PptxCustomGeometry
|
|
891
|
-
| | +-- smart-art.ts # PptxSmartArtData
|
|
892
|
-
| | +-- media.ts # PptxMediaData, MediaTiming
|
|
893
|
-
| | +-- metadata.ts # CoreProperties, AppProperties
|
|
894
|
-
| | +-- presentation.ts # PresentationProperties
|
|
895
|
-
| | +-- view-properties.ts # ViewProperties
|
|
896
|
-
| | +-- three-d.ts # ThreeDProperties
|
|
897
|
-
| | +-- actions.ts # ElementAction, hyperlinks
|
|
898
|
-
| | +-- type-guards.ts # isShape(), isImage(), etc.
|
|
899
|
-
| |
|
|
900
|
-
| +-- core/ # Runtime engine (128 files)
|
|
901
|
-
| | +-- index.ts # Runtime barrel export
|
|
902
|
-
| | +-- PptxHandlerRuntime.ts # Sealed final class
|
|
903
|
-
| | +-- PptxHandlerRuntimeFactory.ts # DI factory + interface
|
|
904
|
-
| | +-- types.ts # IPptxHandlerRuntime interface
|
|
905
|
-
| | |
|
|
906
|
-
| | +-- runtime/ # Mixin modules (84 files)
|
|
907
|
-
| | | +-- PptxHandlerRuntimeState.ts # Base state (fields, ZIP, parser)
|
|
908
|
-
| | | +-- PptxHandlerRuntimeThemeLoading.ts
|
|
909
|
-
| | | +-- PptxHandlerRuntimeThemeProcessing.ts
|
|
910
|
-
| | | +-- PptxHandlerRuntimeSlideParsing.ts
|
|
911
|
-
| | | +-- PptxHandlerRuntimeElementParsing.ts
|
|
912
|
-
| | | +-- PptxHandlerRuntimeShapeParsing.ts
|
|
913
|
-
| | | +-- PptxHandlerRuntimeShapeTextParsing.ts
|
|
914
|
-
| | | +-- PptxHandlerRuntimeChartParsing.ts
|
|
915
|
-
| | | +-- PptxHandlerRuntimeSmartArtParsing.ts
|
|
916
|
-
| | | +-- PptxHandlerRuntimeLoadPipeline.ts # load() entry point
|
|
917
|
-
| | | +-- PptxHandlerRuntimeSavePipeline.ts # save() entry point
|
|
918
|
-
| | | +-- PptxHandlerRuntimeSaveElementWriter.ts
|
|
919
|
-
| | | +-- PptxHandlerRuntimeSaveTextWriter.ts
|
|
920
|
-
| | | +-- PptxHandlerRuntimeImplementation.ts # Top of chain
|
|
921
|
-
| | | +-- ...40+ more mixin modules
|
|
922
|
-
| | |
|
|
923
|
-
| | +-- builders/ # Runtime builders (40 files)
|
|
924
|
-
| | | +-- PptxColorStyleCodec.ts
|
|
925
|
-
| | | +-- PptxConnectorParser.ts
|
|
926
|
-
| | | +-- PptxContentTypesBuilder.ts
|
|
927
|
-
| | | +-- PptxGraphicFrameParser.ts
|
|
928
|
-
| | | +-- PptxTableDataParser.ts
|
|
929
|
-
| | | +-- PptxShapeStyleExtractor.ts
|
|
930
|
-
| | | +-- PptxShapeEffectXmlBuilder.ts
|
|
931
|
-
| | | +-- ...33 more builders
|
|
932
|
-
| | |
|
|
933
|
-
| | +-- factories/ # DI factories (4 files)
|
|
934
|
-
| | +-- PptxRuntimeDependencyFactory.ts
|
|
935
|
-
| | +-- PptxSaveConstantsFactory.ts
|
|
936
|
-
| | +-- types.ts
|
|
937
|
-
| |
|
|
938
|
-
| +-- geometry/ # Shape geometry (17 files)
|
|
939
|
-
| | +-- shape-geometry.ts # Shape type -> clip path resolution
|
|
940
|
-
| | +-- connector-geometry.ts # Connector path generation
|
|
941
|
-
| | +-- guide-formula.ts # OOXML guide formula API
|
|
942
|
-
| | +-- guide-formula-eval.ts # Expression evaluation
|
|
943
|
-
| | +-- preset-shape-definitions.ts # 187+ preset shapes
|
|
944
|
-
| | +-- preset-shape-paths.ts # Pre-computed clip paths
|
|
945
|
-
| | +-- custom-geometry.ts # Custom geometry parsing
|
|
946
|
-
| | +-- transform-utils.ts # Position/rotation transforms
|
|
947
|
-
| |
|
|
948
|
-
| +-- color/ # Colour processing (4 files)
|
|
949
|
-
| | +-- color-utils.ts # Main API (parseDrawingColor, etc.)
|
|
950
|
-
| | +-- color-primitives.ts # Hex <-> RGB <-> HSL conversions
|
|
951
|
-
| | +-- color-transforms.ts # OOXML colour transform application
|
|
952
|
-
| |
|
|
953
|
-
| +-- builders/ # XML builder APIs (11 files)
|
|
954
|
-
| | +-- PptxElementXmlBuilder.ts # Low-level element XML builder
|
|
955
|
-
| | +-- fluent/
|
|
956
|
-
| | | +-- PptxXmlBuilder.ts # Fluent chainable builder
|
|
957
|
-
| | +-- factories/
|
|
958
|
-
| | +-- TextShapeXmlFactory.ts
|
|
959
|
-
| | +-- PictureXmlFactory.ts
|
|
960
|
-
| | +-- ConnectorXmlFactory.ts
|
|
961
|
-
| | +-- MediaGraphicFrameXmlFactory.ts
|
|
962
|
-
| |
|
|
963
|
-
| +-- services/ # Service classes (21 files)
|
|
964
|
-
| | +-- PptxSlideLoaderService.ts
|
|
965
|
-
| | +-- PptxNativeAnimationService.ts
|
|
966
|
-
| | +-- PptxEditorAnimationService.ts
|
|
967
|
-
| | +-- PptxAnimationWriteService.ts
|
|
968
|
-
| | +-- PptxSlideTransitionService.ts
|
|
969
|
-
| | +-- PptxCompatibilityService.ts
|
|
970
|
-
| | +-- PptxXmlLookupService.ts
|
|
971
|
-
| | +-- PptxDocumentPropertiesUpdater.ts
|
|
972
|
-
| | +-- PptxTemplateBackgroundService.ts
|
|
973
|
-
| |
|
|
974
|
-
| +-- utils/ # Utility functions (32 files)
|
|
975
|
-
| +-- clone-utils.ts # Deep clone for slides, elements, styles
|
|
976
|
-
| +-- element-utils.ts # Element labels, text content, actions
|
|
977
|
-
| +-- stroke-utils.ts # Dash styles, border rendering
|
|
978
|
-
| +-- data-url-utils.ts # Data URL <-> byte conversions
|
|
979
|
-
| +-- encryption-detection.ts # CFB/OLE format detection
|
|
980
|
-
| +-- ooxml-crypto.ts # AES-128/256 encryption/decryption
|
|
981
|
-
| +-- signature-detection.ts # Digital signature detection
|
|
982
|
-
| +-- font-deobfuscation.ts # OOXML font deobfuscation
|
|
983
|
-
| +-- smartart-decompose.ts # SmartArt -> individual shapes
|
|
984
|
-
| +-- smartart-editing.ts # SmartArt node CRUD operations
|
|
985
|
-
| +-- chart-advanced-parser.ts # Trendlines, error bars, data tables
|
|
986
|
-
| +-- chart-axis-parser.ts # Axis parsing (value, category, date)
|
|
987
|
-
| +-- chart-cx-parser.ts # ChartEx (cx:chart) parsing
|
|
988
|
-
| +-- ole-utils.ts # OLE object type detection
|
|
989
|
-
| +-- guide-utils.ts # Drawing guide EMU <-> px conversions
|
|
990
|
-
| +-- theme-override-utils.ts # Theme colour map override handling
|
|
991
|
-
| +-- vml-parser.ts # VML (Vector Markup Language) parsing
|
|
992
|
-
| +-- strict-namespace-map.ts # Strict OOXML namespace normalisation
|
|
993
|
-
|
|
|
994
|
-
+-- converter/ # PPTX -> Markdown (20 files)
|
|
995
|
-
+-- index.ts # Converter barrel export
|
|
996
|
-
+-- PptxMarkdownConverter.ts # Main converter orchestrator
|
|
997
|
-
+-- SlideProcessor.ts # Per-slide markdown generation
|
|
998
|
-
+-- base.ts # Abstract DocumentConverter base
|
|
999
|
-
+-- types.ts # FileSystemAdapter, ConversionOptions
|
|
1000
|
-
+-- media-context.ts # Media extraction & deduplication
|
|
1001
|
-
+-- elements/ # Element processors (11 files)
|
|
1002
|
-
+-- ElementProcessor.ts # Abstract base processor
|
|
1003
|
-
+-- TextElementProcessor.ts # Shapes -> markdown text
|
|
1004
|
-
+-- ImageElementProcessor.ts # Images -> 
|
|
1005
|
-
+-- TableElementProcessor.ts # Tables -> markdown tables
|
|
1006
|
-
+-- ChartElementProcessor.ts # Charts -> data summaries
|
|
1007
|
-
+-- SmartArtElementProcessor.ts # SmartArt -> structured text
|
|
1008
|
-
+-- GroupElementProcessor.ts # Groups -> recursive processing
|
|
1009
|
-
+-- MediaElementProcessor.ts # Audio/video -> link references
|
|
1010
|
-
+-- OleElementProcessor.ts # OLE objects -> descriptions
|
|
1011
|
-
+-- InkElementProcessor.ts # Ink annotations -> descriptions
|
|
1012
|
-
+-- FallbackElementProcessor.ts # Unknown elements -> placeholder
|
|
1013
|
-
```
|
|
174
|
+
- **OLE objects** (embedded Word docs, spreadsheets, and similar) are read-only: you get their preview image, not their contents.
|
|
175
|
+
- **SmartArt** is broken into editable shapes using the drawing data PowerPoint already saved in the file. There is no engine that re-flows the layout if you change it.
|
|
176
|
+
- **Chart editing is data-only**: you can change series, data points, categories, and the chart type. Other chart properties are read for display but cannot be edited.
|
|
177
|
+
- **Strict-format files** (ISO/IEC 29500 Strict) are converted to the more common Transitional form when opened and converted back when saved.
|
|
1014
178
|
|
|
1015
|
-
|
|
179
|
+
See the [full docs](https://christophervr.github.io/pptx-viewer/) for the details behind each of these.
|
|
1016
180
|
|
|
1017
|
-
##
|
|
181
|
+
## License
|
|
1018
182
|
|
|
1019
|
-
-
|
|
1020
|
-
- **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.
|
|
1021
|
-
- **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.
|
|
1022
|
-
- **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.
|
|
1023
|
-
- **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.
|
|
183
|
+
[Apache-2.0](LICENSE). Please keep the [`NOTICE`](NOTICE) file with redistributions.
|