How @openmaic/importer Converts PPTX to OpenMAIC Slides: Complete Pipeline Explained
@openmaic/importer transforms PowerPoint files into structured JSON by parsing the PPTX zip archive, extracting slide XML, theme data, and media resources, then converting each element into OpenMAIC's native slide format through a 10-stage pipeline.
The @openmaic/importer package is the official conversion engine for the OpenMAIC project (THU-MAIC/OpenMAIC). It reads binary .pptx files and outputs a JSON representation that the OpenMAIC renderer can display natively. This article breaks down the complete conversion pipeline implemented in packages/@openmaic/importer/src1/pptxtojson.js.
Stage 1: Loading and Parsing the PPTX Archive
The entry point parse accepts an ArrayBuffer and initializes JSZip to read the zip-packed PPTX structure.
import { parse } from '@openmaic/importer'
async function convertPptx(file) {
const arrayBuffer = await file.arrayBuffer()
const result = await parse(arrayBuffer, { mediaMode: 'base64' })
return result
}
In [pptxtojson.js lines 33-38](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/importer/src1/pptxtojson.js#L33-L38), the parse function creates the zip instance and begins the extraction process.
Stage 2: Discovering Slide Files via Content Types
The getContentTypes helper parses _rels/[Content_Types].xml to locate all slide XML paths (slides/slide*.xml), layout files, and other document parts. This establishes the manifest of content to process.
Stage 3: Extracting Global Slide Information
getSlideInfo reads ppt/presentation.xml to obtain:
- Slide dimensions — converted from EMUs (English Metric Units) to points
- Default text style — applied when no explicit formatting exists
Stage 4: Loading the Theme
getTheme follows relationships in presentation.xml.rels to find the theme file, then builds an array of accent colors used throughout the presentation.
Stage 5: Processing Each Individual Slide
For every slide file, processSingleSlide orchestrates resource resolution:
- Reads the slide's
.relsfile to map images, charts, diagrams, notes, and master/layout references - Retrieves the corresponding layout, master, and theme resources
- Builds a warp object containing all required data:
zip,slideResObj,layoutResObj,masterResObj,themeContent, and more
Stage 6: Background and Layout Elements
Two specialized functions prepare the slide canvas:
getSlideBackgroundFill— creates the slide's background fillgetLayoutElements— extracts non-placeholder shapes from layout and master that become part of the slide background
Stage 7: Walking the Slide XML Tree
The slide's spTree node contains all visible objects. processNodesInSlide dispatches each node type to its specific handler:
| Node Type | Handler Function |
|---|---|
p:sp (shape) |
processSpNode |
p:cxnSp (connector) |
processSpNode |
p:pic (picture) |
processPicNode |
p:graphicFrame (chart/table/diagram) |
processGraphicFrameNode |
p:grpSp (group) |
processNodesInSlide (recursive) |
Stage 8: Shape and Text Processing
processSpNode resolves placeholder inheritance (layout → master) and delegates to genShape. This function:
- Computes geometry: position, size, rotation, flips
- Extracts fill/border via
fill.js - Applies shadow effects via
shadow.js - Processes text content via
text.js
The result is either a shape or text element in the OpenMAIC JSON schema.
Stage 9: Media Extraction (Images, Video, Audio)
processPicNode handles embedded media:
// Simplified flow from processPicNode
const mediaBuffer = await zip.file(mediaPath).async('arraybuffer')
const mimeType = getMimeType(mediaExtension) // from utils.js
const dataUrl = buildDataUrl(mediaBuffer, mimeType, mediaMode)
// Returns: { type: 'image' | 'video' | 'audio', ... }
The mediaMode option controls whether media is embedded as base64 data URLs or blob URLs.
Stage 10: Charts, Tables, Diagrams, and Math
processGraphicFrameNode inspects the graphicData URI and delegates to specialized parsers:
genChart— parses chart XML, extracts series data, colors, and chart typegenTable— converts tables to 2D JSON with cell spans, borders, and stylinggenDiagram— handles SmartArt diagrams with shape elements and fallback textprocessMathNode— parses OMML MathML, outputs LaTeX plus optional preview images
Notes, Transitions, and Final Assembly
Per-slide metadata is extracted via:
getNote— fetches speaker notesfindTransitionNodeandparseTransition— locate and interpret slide transition data
processSingleSlide returns a complete slide object:
{
fill, // background fill
elements, // processed shapes, text, media
layoutElements, // master/layout background elements
note, // speaker notes
transition // transition effect
}
The top-level parse function aggregates all slides and attaches theme colors and presentation size.
Node.js Usage Example
import fs from 'fs'
import { parse } from '@openmaic/importer'
async function run() {
const buffer = fs.readFileSync('example.pptx')
const { slides, themeColors, size } = await parse(buffer, { mediaMode: 'blob' })
console.log(JSON.stringify({ slides, themeColors, size }, null, 2))
}
run()
Key Source Files in the Pipeline
| File | Responsibility |
|---|---|
src1/pptxtojson.js |
Core orchestration pipeline |
src1/readXmlFile.js |
XML extraction via fast-xml-parser |
src1/utils.js |
EMU→point conversion, MIME lookup, base64 encoding |
src1/shape.js |
Geometry, custom shapes, fills/borders |
src1/text.js |
PowerPoint text runs → HTML strings |
src1/fill.js |
Solid, picture, gradient, pattern fills |
src1/chart.js |
Chart parsing (series, types, colors) |
src1/table.js |
Table structure with spans and styling |
src1/diagram.js |
SmartArt diagram extraction |
src1/math.js |
OMML MathML → LaTeX conversion |
Summary
-
@openmaic/importerconverts PPTX to JSON through a 10-stage pipeline starting with zip extraction and ending with structured slide objects. -
Resource resolution follows PowerPoint's relationship files (
.rels) to locate themes, layouts, masters, and embedded media. -
Node dispatch in
processNodesInSlideroutes shapes, pictures, charts, tables, diagrams, and math to specialized handlers. -
Media handling supports both base64 embedding and blob URL generation via the
mediaModeoption. -
The output JSON matches OpenMAIC's renderer schema exactly, enabling faithful reproduction of slides, shapes, text, media, charts, tables, diagrams, and formulas.
Frequently Asked Questions
What input formats does @openmaic/importer accept?
The parse function accepts an ArrayBuffer or Buffer. In browsers, use file.arrayBuffer() on a File object. In Node.js, read the file into a Buffer with fs.readFileSync(). The importer does not accept file paths directly.
How are PowerPoint themes and colors preserved?
getTheme extracts accent colors from the theme XML referenced in presentation.xml.rels. These colors are aggregated into a themeColors array returned at the top level of the parse result, allowing the OpenMAIC renderer to apply consistent color schemes.
What happens to embedded videos and audio files?
processPicNode detects media types by extension and MIME type lookup in utils.js. The binary content is extracted from the zip and converted to either base64 data URLs or blob URLs depending on the mediaMode option. The resulting element specifies type: 'video' or type: 'audio' with the appropriate source reference.
Can the importer handle complex SmartArt diagrams?
Yes. processGraphicFrameNode delegates SmartArt content to genDiagram in src1/diagram.js. This module extracts the hierarchical shape structure and fallback text from the diagram's data model, producing a JSON representation that preserves the visual arrangement.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →