Render a deck to SVG in the browser
Read a .pptx from a file input and draw every slide as an SVG string, entirely in the tab.
Goal
Turn a .pptx the visitor chose into one SVG per slide, with pictures and text, without a server.
You need
npm install @pptx-studio/opc @pptx-studio/model @pptx-studio/render-svgSteps
1. Read the bytes
A File from an input or a drop gives you an ArrayBuffer; the packages take a Uint8Array.
const input = document.querySelector<HTMLInputElement>('input[type=file]');
const file = input?.files?.[0];
if (file === undefined) throw new Error('choose a .pptx');
const bytes = new Uint8Array(await file.arrayBuffer());2. Open the package and load the document
PartStore.open inflates the archive under safety limits; loadDocument parses every slide, layout, master and theme and binds them through their relationships.
import { PartStore } from '@pptx-studio/opc';
import { loadDocument } from '@pptx-studio/model';
const store = PartStore.open(bytes);
const doc = loadDocument(store);
console.log(doc.slides.length, doc.slideSize); // slides, and the size in EMU3. Draw a slide
renderSlide returns a string. mediaFromStore resolves each picture through the part it was written in; the text option takes the presentation's default text style so the tenth source of the cascade is there.
import { mediaFromStore, renderSlide } from '@pptx-studio/render-svg';
const media = mediaFromStore(store);
const svg = renderSlide(doc.slides[0]!, doc.slideSize, {
width: 960,
media,
text: { defaultTextStyle: doc.defaultTextStyle },
});
document.querySelector('#stage')!.innerHTML = svg;4. Every slide
The text engine is created inside renderSlide unless you pass one. For a whole deck, make one once so the measurer and the font probe are shared.
import { createTextEngine } from '@pptx-studio/render-svg';
const text = createTextEngine({ defaultTextStyle: doc.defaultTextStyle });
const svgs = doc.slides.map((slide) =>
renderSlide(slide, doc.slideSize, { width: 960, media, text }),
);What can go wrong
OpcErrorwithERR_NOT_A_ZIP- The file is not a.pptx- a.pptfrom PowerPoint 2003 is not a ZIP.OpcErrorwithERR_ENCRYPTED_PACKAGE- The deck is password-protected; remove the password in PowerPoint first.ModelErrorwithMODEL_NO_PRESENTATION- A ZIP with no presentation part: a Word or Excel file with the wrong extension.RenderErrorwithRENDER_UNKNOWN_PRESET- A shape names a preset geometry outside the 187; the deck was written by something other than PowerPoint.
Try it
Reading the deck…