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:

  1. Reads the slide's .rels file to map images, charts, diagrams, notes, and master/layout references
  2. Retrieves the corresponding layout, master, and theme resources
  3. 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 fill
  • getLayoutElements — 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 type
  • genTable — converts tables to 2D JSON with cell spans, borders, and styling
  • genDiagram — handles SmartArt diagrams with shape elements and fallback text
  • processMathNode — parses OMML MathML, outputs LaTeX plus optional preview images

Notes, Transitions, and Final Assembly

Per-slide metadata is extracted via:

  • getNote — fetches speaker notes
  • findTransitionNode and parseTransition — 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/importer converts 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 processNodesInSlide routes shapes, pictures, charts, tables, diagrams, and math to specialized handlers.

  • Media handling supports both base64 embedding and blob URL generation via the mediaMode option.

  • 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →