Loading & Parsing
Loading turns raw .pptx, legacy .ppt, or pptx-viewer-json bytes into a fully resolved, typed PptxData object. All parsing happens in memory - no temporary files, no native code.
Construct a handler and load
import { PptxHandler } from 'pptx-viewer-core';
const handler = new PptxHandler();
const data = await handler.load(arrayBuffer);
console.log(`${data.slides.length} slides loaded`);
console.log(`Canvas: ${data.width} x ${data.height}`);handler.load(data, options?) accepts an ArrayBuffer and returns Promise<PptxData>. It recognizes OpenXML ZIP packages, legacy OLE2 PowerPoint files, and a JSON object carrying the "format": "pptx-viewer-json" marker.
Keep the handler
The handler holds the in-memory ZIP. Use the same handler instance to later save() or fetch media via getImageData() / getMediaArrayBuffer().
Getting an ArrayBuffer
The engine is environment-agnostic; you just need bytes.
const buffer = await fetch('presentation.pptx').then((r) => r.arrayBuffer());
const data = await handler.load(buffer);const file = input.files[0]; // File from <input type="file">
const buffer = await file.arrayBuffer();
const data = await handler.load(buffer);import { readFile } from 'node:fs/promises';
const node = await readFile('presentation.pptx'); // Buffer
const buffer = node.buffer.slice(node.byteOffset, node.byteOffset + node.byteLength);
const data = await handler.load(buffer as ArrayBuffer);What the load pipeline does
When you call load(), the runtime:
- Detects the file format. Portable JSON is validated and overlaid on a generated blank archive. Encrypted OpenXML OLE2/CFB files are decrypted first when a password is supplied, and legacy binary PowerPoint files are converted to the model.
- Opens the ZIP with JSZip and parses
[Content_Types].xmlandppt/presentation.xml. - Parses each slide master, its theme, colour map, and layouts.
- For each slide, parses the shape tree and resolves the layout → master → theme style chain (see /guide/architecture).
- Parses text with style inheritance, animations, transitions, and media relationships.
- Parses comments, document properties, and embedded fonts.
The result is a single PptxData object holding everything needed to render, edit, or convert the deck.
Portable deck JSON
PptxJsonConverter produces a versioned, self-contained pptx-viewer-json document. It carries the presentation model and binary model fields as tagged base64, so it can be transferred without the original archive. load() recognizes its format marker automatically and prepares a minimal archive so ordinary editing and save() continue to work.
import { PptxHandler, PptxJsonConverter } from 'pptx-viewer-core';
const json = PptxJsonConverter.toJson(data, { pretty: true, generator: 'my-app' });
const imported = new PptxHandler();
const restored = await imported.load(new TextEncoder().encode(json).buffer);
const bytes = await imported.save(restored.slides); // valid .pptx bytesThe current format is version 1. Use PptxJsonConverter.parse() when you need validation without rebuilding PptxData, or fromJson() when you only need the model.
Load options
const data = await handler.load(buffer, {
password: 'secret', // decrypt an encrypted file (see below)
allowExternalImages: false, // default false - http(s) image URLs are dropped
maxUncompressedBytes: 500 * 1024 * 1024, // zip-bomb guard, 500 MiB default
});| Option | Default | Purpose |
|---|---|---|
password | - | Decrypts an encrypted package before parsing. |
allowExternalImages | false | When false, relationship targets resolving to http:///https:// are dropped from rendered slides (SSRF / privacy mitigation). Set true to allow them through. |
maxUncompressedBytes | 500 MiB | Total uncompressed budget. Exceeding it (or 65,536 entries) rejects with ZipBombError. |
eagerDecodeImages | false | Decode embedded images during load rather than lazily. |
Accessing slides, theme, and metadata
const data = await handler.load(buffer);
// Slides
const first = data.slides[0];
console.log(first.id, first.elements.length, first.notes);
// Canvas / dimensions
console.log(data.width, data.height); // pixels
// Theme
console.log(data.theme?.name);
console.log(data.theme?.fontScheme?.majorFont?.latin);
// Document metadata
console.log(data.coreProperties?.title, data.coreProperties?.creator);
// Structure
console.log(data.sections, data.slideMasters, data.slideLayouts);See /guide/data-model for the full shape of PptxData, PptxSlide, and friends.
Iterating elements and narrowing by type
Every slide's elements array is a list of PptxElement - a discriminated union of 16 variants. Always narrow with the type discriminant before touching variant-specific fields:
for (const slide of data.slides) {
for (const el of slide.elements) {
switch (el.type) {
case 'shape':
case 'text':
console.log('text:', el.text);
break;
case 'image':
console.log('image at', el.imagePath);
break;
case 'table':
console.log('table rows:', el.tableData?.rows.length);
break;
case 'chart':
console.log('chart type:', el.chartData?.type);
break;
case 'group':
// groups nest child elements recursively
console.log('group children:', el.children.length);
break;
}
}
}Narrow before access
TypeScript only exposes variant fields (like imagePath or tableData) after you've narrowed on el.type. This is the intended pattern - see /guide/data-model.
Embedded media
To pull bytes for an embedded image or media file referenced by an element:
const dataUrl = await handler.getImageData(element.imagePath); // base64 data URL
const bytes = await handler.getMediaArrayBuffer(mediaPath); // ArrayBufferEncrypted files
If the file is password-protected and you call load() without a password, the engine throws EncryptedFileError. Provide options.password to decrypt before parsing:
const data = await handler.load(buffer, { password: 'secret' });See /core/encryption for the full encryption and write-back API.