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

@s8fy/pptx-core

v1.5.0

Published

Framework-agnostic PPTX parsing, types, font lifecycle, and PDF export helpers

Readme

@s8fy/pptx-core

Framework-free PPTX parsing, shared slide types, font lifecycle helpers, Blob URL cleanup, and PDF export facade used by the viewer SDK packages.

Install

pnpm add @s8fy/pptx-core

Use this package when you need the normalized PptxPresentation model without the built-in viewer UI. Most applications should install the higher-level @s8fy/pptx-viewer facade instead.

Parse a presentation

import { parsePptx, revokeBlobUrls } from '@s8fy/pptx-core'

const response = await fetch('/slides.pptx')
if (!response.ok) throw new Error(`PPTX request failed: ${response.status}`)
const deck = await parsePptx(await response.arrayBuffer())
try {
  console.log(deck.width, deck.height, deck.slides.length)
  // Consume the model here; keep it alive while its media is displayed.
} finally {
  revokeBlobUrls(deck)
}

parsePptx(buffer, options?) returns Promise<PptxPresentation>. Input must be an ArrayBuffer, not a URL or File; use await file.arrayBuffer() for browser files. The normalized model has width, height, slides, themeColors, optional fonts, and optional referencedFonts. Dimensions are in pixels. This is different from the low-level parser's ParseResult, whose dimensions live under size.

| Parse option | Default | Meaning | | -------------- | ---------------- | ----------------------------------------------------------------------- | | parser | 'wasm' | 'wasm' or 'js'; the low-level parser package instead defaults to JS | | unzipMode | 'wasm' | ZIP engine for WASM parsing | | extractFonts | false | Extract embedded font data; parsing does not install browser fonts | | wasmUrl | Package-relative | Optional parser WASM URL, not the PDF engine URL | | signal | None | AbortSignal for cancelling this request |

revokeBlobUrls(deck) releases media URLs owned by the returned model. Call it on the original model object after its last consumer finishes; cloning or serializing the model does not transfer cleanup ownership. Blob URLs are not portable persistent data.

Export PDF

import { pptxToPdf, downloadPdf } from '@s8fy/pptx-core'

export async function downloadPresentation(file: File): Promise<void> {
  const bytes = await pptxToPdf(await file.arrayBuffer(), {
    unicodeFallbackFont: { url: '/fonts/NotoSansSC-Regular.ttf' },
  })
  downloadPdf(bytes, file.name)
}

Provide the example font at that URL, or omit the fallback for documents that do not need it. PDF conversion needs the original PPTX bytes, not just a PptxPresentation. pptxToPdf returns Promise<Uint8Array>; downloadPdf(bytes, fileName) only initiates a browser download and changes the extension to .pdf.

PptxToPdfOptions accepts signal, PDF wasmUrl, PDF workerUrl, license, watermark, regularFonts, unicodeFallbackFont, emojiFallbackFont, emojiBitmapFallback, mathFallbackFont, and officeFontFallbacks. Parser and PDF wasmUrl settings refer to different binaries. Unlike the low-level parser PDF API, this facade does not expose wasmBytes; unlike the viewer controller, it does not accept fontResolver directly.

For model-aware font resolution, call await createPdfFontOptions({ presentation: deck, resolver: { cacheBaseUrl: '/fonts/', remoteFonts: false } }) and spread the result into pptxToPdf options. Browser preview fonts and PDF font bytes are separate; an installed CSS font alone does not supply PDF glyph data.

Browser font lifecycle

Custom renderers can use injectEmbeddedFonts(deck.fonts ?? []) and loadReferencedFonts(deck.referencedFonts ?? [], deck.fonts?.map(font => font.typeface), options). Both return cleanup functions; the latter also exposes a ready Promise and a pending flag. Release both when the view is disposed. The viewer controller handles this lifecycle automatically.

Referenced-font loading enables Google Fonts fallback by default. For self-hosted assets, use families or cacheBaseUrl with remoteFonts: false; explicit configured assets can still be fetched. See the exported BrowserFontResolverOptions and PdfFontSources types for the separate preview and PDF configurations.

Authorization and errors

Core parsing normalizes data; it does not itself authorize display. Applications implementing a custom display should resolve authorization with resolveViewerPresentationAuthorization and apply its result, or use the viewer controller, which handles this automatically. PDF conversion resolves the bundled policy before conversion. Pass an issued license through license: { signedLicense }; missing or invalid licenses are evaluated under the applicable output rules, never assumed licensed.

Useful exported errors include AuthorizationDeniedError (reason), PptxFileSizeLimitError (code, sizeBytes, limitBytes), and ResourcePolicyError (details.reason, details.stage). Resource limits are independent of commercial entitlement. Catch rejected promises in parsing/export handlers.

Runtime and package entrypoints

Node.js 22.12+ is declared in the package. ESM and CommonJS entrypoints include their corresponding TypeScript declarations. Parsing and PDF conversion can run in Node; DOM rendering, browser font injection, and download helpers require a browser. WASM parsing/export requires WebAssembly GC support.

Bundled WASM assets use package-relative URLs by default. Keep deployed WASM/Worker files accessible, and serve WASM bytes rather than an HTML fallback page. Browser PDF export requires a working Web Worker. No framework dependency or viewer stylesheet is required just to parse or export.

License

The default license is the PolyForm Noncommercial License. Commercial use requires a separate commercial license.