npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pptx-browser

v4.1.5

Published

Render, edit, and export PowerPoint (PPTX) slides. Canvas rendering, SVG export, PDF export, PPTX writer/template engine, slide show, text extraction, animations. Zero dependencies.

Readme

pptx-browser

Render PowerPoint (.pptx) slides directly onto an HTML <canvas> element — zero dependencies, no server required.

Uses only native browser/Node APIs: DecompressionStream for ZIP decompression, DOMParser for XML, and the Canvas 2D API for rendering.

Browser support

Chrome 80+ · Firefox 113+ · Safari 16.4+ · Node 18+ (with node-canvas)


Installation

npm install pptx-browser

No JSZip, no pptxjs, no other dependencies.


Quick start

import { PptxRenderer } from 'pptx-browser';

const renderer = new PptxRenderer();

// Load from a <input type="file"> element
const [file] = fileInput.files;
await renderer.load(file, (progress, msg) => console.log(progress, msg));

console.log(renderer.slideCount); // number of slides

// Render slide 0 onto a canvas
const canvas = document.getElementById('my-canvas');
await renderer.renderSlide(0, canvas, 1280); // 1280px wide

// Clean up blob URLs when done
renderer.destroy();

API

new PptxRenderer()

Creates a new renderer instance. Each instance is independent and can load one PPTX at a time.


renderer.load(source, onProgress?)

Load a PPTX file.

| Parameter | Type | Description | |--------------|----------------------------------------------|-------------------------------------| | source | File \| Blob \| ArrayBuffer \| Uint8Array | The PPTX data | | onProgress | (progress: number, message: string) => void| Optional. Called with 0–1 progress |

Returns: Promise<void>


renderer.renderSlide(index, canvas, width?)

Render a single slide.

| Parameter | Type | Default | Description | |-----------|----------------------|---------|--------------------------| | index | number | — | 0-based slide index | | canvas | HTMLCanvasElement | — | Target canvas element | | width | number | 1280 | Output width in pixels |

Canvas height is set automatically to maintain the correct aspect ratio.

Returns: Promise<void>


renderer.renderAllSlides(width?)

Render all slides and return an array of canvas elements. Useful for thumbnail strips.

const canvases = await renderer.renderAllSlides(320);
canvases.forEach((c, i) => document.body.appendChild(c));

Returns: Promise<HTMLCanvasElement[]>


renderer.slideCount

number — total number of slides. Available after load() resolves.


renderer.destroy()

Releases all blob: URLs created during rendering. Call this when you're done with the renderer or loading a new file.


React example

import { useRef, useState } from 'react';
import { PptxRenderer } from 'pptx-browser';

export function PptxViewer() {
  const canvasRef = useRef(null);
  const [renderer] = useState(() => new PptxRenderer());
  const [slideCount, setSlideCount] = useState(0);
  const [current, setCurrent] = useState(0);

  async function onFile(e) {
    const file = e.target.files[0];
    if (!file) return;
    renderer.destroy();
    await renderer.load(file);
    setSlideCount(renderer.slideCount);
    await renderer.renderSlide(0, canvasRef.current, 1280);
    setCurrent(0);
  }

  async function goTo(i) {
    await renderer.renderSlide(i, canvasRef.current, 1280);
    setCurrent(i);
  }

  return (
    <div>
      <input type="file" accept=".pptx" onChange={onFile} />
      <p>Slide {current + 1} / {slideCount}</p>
      <canvas ref={canvasRef} style={{ maxWidth: '100%' }} />
      <div>
        {current > 0 && <button onClick={() => goTo(current - 1)}>←</button>}
        {current < slideCount - 1 && <button onClick={() => goTo(current + 1)}>→</button>}
      </div>
    </div>
  );
}

What's rendered

| Feature | Status | |----------------------------|---------| | Theme colours (all 12) | ✅ | | Colour transforms (lumMod, lumOff, tint, shade, sat, hue, alpha…) | ✅ | | Gradient fills (linear + radial) | ✅ | | Image fills + cropping | ✅ | | Pattern fills | ✅ (simplified) | | 50+ preset shapes | ✅ | | Custom geometry (custGeom) | ✅ | | Drop shadows + glow | ✅ | | Text rendering (wrapping, alignment, superscript/subscript) | ✅ | | Font mapping MS→Google Fonts | ✅ (80+ fonts) | | normAutoFit text scaling | ✅ | | Tables | ✅ | | Images in shapes/backgrounds | ✅ | | Slide master & layout inheritance | ✅ | | Placeholder position inheritance | ✅ | | Rotation & flip | ✅ | | Group shapes | ✅ | | Charts/SmartArt | Placeholder box |


How ZIP decompression works (no JSZip)

PPTX files are ZIP archives. Instead of bundling JSZip (~100KB), this library uses the browser-native DecompressionStream('deflate-raw') API, available since:

  • Chrome 80 (Apr 2020)
  • Firefox 113 (May 2023)
  • Safari 16.4 (Mar 2023)
  • Node.js 18 (Apr 2022)

The custom ZIP parser is ~80 lines of code vs JSZip's 3,000+.


Font handling

Microsoft Office fonts (Calibri, Cambria, Franklin Gothic, etc.) aren't available in browsers. This library automatically maps them to the nearest metric-compatible Google Font and loads it via the Google Fonts API before rendering. Key mappings:

| Office font | Web substitute | Notes | |--------------------|-------------------------|------------------------------------| | Calibri | Carlito | Metric-compatible (identical widths) | | Calibri Light | Carlito Light | Metric-compatible | | Cambria | Caladea | Metric-compatible | | Aptos (new default)| Inter | | | Franklin Gothic | Libre Franklin | | | Gill Sans | Quattrocento Sans | | | Segoe UI | Inter | |

Fonts are loaded once and cached for the session.


License

MIT