@imgly/pptx-importer
v0.3.0
Published
Import PowerPoint (PPTX) presentations into IMG.LY's Creative Engine SDK. Platform-agnostic TypeScript library for converting PPTX slides to CE.SDK scenes.
Readme
PPTX Importer for CE.SDK
A TypeScript library for importing PowerPoint (PPTX) presentations into IMG.LY's Creative Engine SDK. Converts PPTX slides into CE.SDK scenes with full support for text, shapes, images, and formatting.
Features
✨ Comprehensive PPTX Support
- Text Elements: Full text formatting including font families, sizes, colors, bold, italic, character spacing, and line height
- Shapes: Rectangles, ellipses, and custom vector shapes with fills and strokes
- Gradient Fills: Linear and radial gradients on shapes (70% of presentations)
- Shadow Effects: Outer drop shadows with blur, offset, and transparency (60% of presentations)
- Gradient Backgrounds: Linear and radial gradients on slide backgrounds
- Images: Embedded images with proper positioning and dimensions
- Groups: Grouped elements with preserved hierarchy
- Layout: Accurate positioning, sizing, and rotation
- Z-Order: Maintains element stacking order from PowerPoint
- Theme Colors: Resolves PowerPoint theme color references
🌐 Platform-Agnostic
Works in both browser and Node.js environments:
- No file system dependencies
- Pure ArrayBuffer/Uint8Array handling
- Platform-neutral base64 encoding
- ESM module format
🎯 Production-Ready
- TypeScript-first with full type definitions
- Comprehensive test suite with golden screenshot tests
- Visual regression testing with golden screenshots
- Font resolution via Google Fonts integration
- Error handling with detailed warnings for unsupported features
Installation
npm install @imgly/pptx-importerPeer Dependencies
You'll need CE.SDK in your project:
# For browser
npm install @cesdk/engine
# For Node.js
npm install @cesdk/node@imgly/pptx-importer uses JSZip and fast-xml-parser internally to read PPTX archives. They are installed automatically as dependencies of this package.
Quick Start
Browser
import CreativeEngine from '@cesdk/engine';
import { PPTXParser } from '@imgly/pptx-importer';
// Initialize CE.SDK engine
const config = {
license: 'your-license-key',
userId: 'your-user-id',
};
const engine = await CreativeEngine.init(config);
// Load PPTX file
const response = await fetch('presentation.pptx');
const arrayBuffer = await response.arrayBuffer();
// Parse PPTX and create CE.SDK scene (automatically parses all slides)
const parser = await PPTXParser.fromFile(engine, arrayBuffer);
const result = await parser.parse();
// Get created pages
const pages = engine.block.findByType('//ly.img.ubq/page');
console.log(`Imported ${pages.length} slides`);
// Check for any warnings
const messages = result.logger.getMessages();
const warnings = messages.filter(m => m.type === 'warning');
if (warnings.length > 0) {
console.warn('Unsupported features:', warnings);
}
// Export first slide
const blob = await engine.block.export(pages[0], 'image/png');Node.js
import CreativeEngine from '@cesdk/node';
import { PPTXParser } from '@imgly/pptx-importer';
import { readFileSync } from 'fs';
// Initialize CE.SDK engine
const engine = await CreativeEngine.init({
license: process.env.CESDK_LICENSE,
});
// Load PPTX file
const fileBuffer = readFileSync('presentation.pptx');
const arrayBuffer = fileBuffer.buffer.slice(
fileBuffer.byteOffset,
fileBuffer.byteOffset + fileBuffer.byteLength
);
// Parse PPTX (automatically parses all slides and attaches to scene)
const parser = await PPTXParser.fromFile(engine, arrayBuffer);
const result = await parser.parse();
// Get created pages
const pages = engine.block.findByType('//ly.img.ubq/page');
// Export first slide
const blob = await engine.block.export(pages[0], 'image/png');API Reference
PPTXParser
Static Methods
PPTXParser.fromFile(engine, fileBuffer, options?)
Creates a parser instance from a PPTX file.
Parameters:
engine: CreativeEngine- CE.SDK engine instancefileBuffer: ArrayBuffer- PPTX file as ArrayBufferoptions?: Partial<PPTXParserOptions>- Optional configuration
Returns: Promise<PPTXParser>
Example:
const parser = await PPTXParser.fromFile(engine, arrayBuffer, {
tolerancePercent: 5,
logWarnings: true,
strictMode: false,
});Instance Methods
parser.parse()
Parses all slides in the PPTX file and automatically attaches them to the scene.
Parameters: None
Returns: Promise<ParseResult> - Contains logger with warnings and messages
Example:
// Parse all slides
const result = await parser.parse();
// Get created pages
const pages = engine.block.findByType('//ly.img.ubq/page');
console.log(`Imported ${pages.length} slides`);
// Access individual pages
pages.forEach((pageId, index) => {
console.log(`Slide ${index + 1}: block ID ${pageId}`);
});Note: This API matches the PSD importer pattern for consistency across IMG.LY importers. All slides are parsed and attached to the scene automatically. Use
engine.block.findByType()to retrieve page block IDs.
parser.getSlideCount()
Returns the total number of slides in the PPTX file.
Returns: number
ParseResult
The result returned by parser.parse() contains a logger with warnings and messages.
Example:
const result = await parser.parse();
// Get all messages
const messages = result.logger.getMessages();
// Filter by type
const warnings = messages.filter(m => m.type === 'warning');
const errors = messages.filter(m => m.type === 'error');
warnings.forEach(w => {
console.log(`Warning: ${w.message}`);
});PPTXParserOptions
Configuration options for the parser.
interface PPTXParserOptions {
/**
* Tolerance percentage for numeric property validation in tests
* @default 5
*/
tolerancePercent?: number;
/**
* Apply font metrics-based vertical position correction for text blocks
* @default true
*/
applyFontMetricsCorrection?: boolean;
/**
* Auto-correct text blocks that overflow their bounds
* @default true
*/
autoCorrectTextOverflow?: boolean;
}Supported Features
✅ Fully Supported
Text Blocks
- Font family, size, color
- Bold, italic formatting
- Character spacing
- Line height
- Multiple text runs with different formatting
- Vertical alignment
Shapes
- Rectangles (with corner radius)
- Ellipses/circles
- Custom vector shapes (via SVG path conversion)
- Fill colors (solid, theme colors)
- Stroke colors and widths
Images
- PNG, JPEG, GIF, BMP, WebP
- Embedded images
- Proper sizing and positioning
Backgrounds
- Solid colors (RGB, theme colors)
- Linear and radial gradients
Layout
- Absolute positioning
- Rotation
- Z-order preservation
- Groups and nested elements
⚠️ Partially Supported
Gradients
- ✅ Linear gradients (fully supported)
- ✅ Radial gradients (fully supported)
- ⚠️ Path gradients (falls back to radial with warning)
- ⚠️ Rectangular gradients (falls back to radial with warning)
Shadow Effects
- ✅ Outer drop shadows (fully supported)
- ⚠️ Inner shadows (converted to outer shadows with warning)
Colors
- ✅ RGB colors
- ✅ Theme colors (with fallback)
- ⚠️ Transparency (basic support)
Text
- ✅ Basic formatting
- ⚠️ Bullets and numbering (basic)
❌ Not Supported
- Tables (
<a:tbl>) - Table content is skipped; workaround: ungroup table in PowerPoint before export - Charts - Chart visualizations are not imported
- SmartArt - Diagram graphics are not imported
- Animations and transitions
- Slide masters and layouts
- Audio and video
- Comments and notes
- Background images (solid colors and gradients ARE supported)
Font Loading
The importer resolves fonts using Google Fonts and substitutes common proprietary fonts (Helvetica, Arial, Times New Roman, etc.) with visually-similar Google Fonts equivalents. The font catalog and fallback aliases are served as two CE.SDK asset sources from the IMG.LY CDN:
| Asset source | Contents | Size (gzipped) |
|--------------|----------|----------------|
| ly.img.gfonts | 1,394 Google Fonts typefaces with all variants | ~127 KB |
| ly.img.gfonts-fallbacks | 16 proprietary-font aliases (Helvetica→Roboto, Arial→Arimo, …) | ~3 KB |
PPTXParser.fromFile(...) automatically calls addGfontsAssetLibrary(engine) during initialization, which registers both sources via engine.asset.addLocalAssetSourceFromJSONURI(...). The files are fetched from https://staticimgly.com/imgly/gfonts/<version>/dist/ at registration time and CE.SDK caches the font files once resolved.
No extra pnpm install is required. The sources are internal to IMG.LY and loaded from the CDN; you do not install an additional package. An active internet connection is required during parser setup.
Customizing font resolution
The addGfontsAssetLibrary helper and the default fontResolver function are exported from the public API so you can:
- Pre-register the gfonts asset sources yourself (for example, early in your app boot to pre-warm the CDN fetch):
import { addGfontsAssetLibrary } from '@imgly/pptx-importer'; await addGfontsAssetLibrary(engine); - Register your own typeface asset source with the same ID (
ly.img.gfontsorly.img.gfonts-fallbacks) before callingPPTXParser.fromFile—addGfontsAssetLibraryskips sources that are already registered, so your override wins. - Reuse the default
fontResolveras a building block inside your own logger / substitution logic:import { fontResolver } from '@imgly/pptx-importer'; const result = await fontResolver({ family: 'Helvetica', weight: 'bold', style: 'normal' }, engine);
Unit System
PowerPoint uses EMUs (English Metric Units) for measurements:
- 1 inch = 914,400 EMUs
- 1 cm = 360,000 EMUs
CE.SDK scenes use Pixels at 96 DPI (standard screen resolution, matching Canva and PowerPoint). The importer automatically converts:
// EMUs to CE.SDK pixels at 96 DPI
pixels = (emus / 914400) * 96
// Simplified: pixels = emus / 9525Font sizes use points (72 points = 1 inch), which are DPI-independent and don't require conversion.
Platform Compatibility
Browser Requirements
- Modern browsers with ES2022 support
- Chrome 94+, Firefox 93+, Safari 15+, Edge 94+
Node.js Requirements
- Node.js 22+
- Works with Bun, Deno (with Node.js compatibility)
Build Targets
The package is built with platform: 'neutral' to work in any JavaScript environment.
Troubleshooting
Font Substitution Warnings
Font 'CustomFont' substituted with 'Arial' for block 42The importer uses Google Fonts for font resolution via the ly.img.gfonts and ly.img.gfonts-fallbacks asset sources (see Font Loading below). If a font isn't available, it falls back to a similar font. To add custom fonts:
// Add custom font to CE.SDK asset library before parsing
await engine.asset.addAssetToSource('my-fonts', {
id: 'custom-font',
meta: { name: 'Custom Font' },
payload: {
typeface: {
name: 'Custom Font',
fonts: [{ uri: 'https://example.com/font.ttf' }]
}
}
});Missing Theme Colors
Color scheme not found in theme XMLSome PPTX files have corrupted or missing theme data. The parser falls back to default colors. To fix, re-save the PPTX in PowerPoint.
Visual Differences in Regression Tests
Regression renders may differ from committed baselines because of:
- Font rendering differences across platforms
- CE.SDK version updates
- Intentional parser improvements
Update baselines only after verifying via the dashboard that the diff is intentional:
pnpm test:regression:updateChangelog
See CHANGELOG.md for release notes.
License
ISC
