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-renderer

v2.1.1

Published

Framework-free DOM/SVG renderer for PPTX presentations

Readme

@s8fy/pptx-renderer

Framework-free DOM/SVG/CSS renderer and viewer controller for parsed PPTX presentations.

Animation tests

pnpm --filter @s8fy/pptx-renderer test runs the renderer/controller regressions without compiling MoonBit. pnpm --filter @s8fy/pptx-renderer test:integration additionally requires MoonBit and the workspace dependencies. It builds the generator and parser incrementally in the workspace build directory, then tests generated PPTX through the JS parser, source-built WASM, bundled WASM, core model, and actual controller CSS. CI requires both suites; missing build tools fail the integration suite.

pnpm smoke:transitions <fresh-output-dir> runs Chromium composition and lifecycle checks, including CSS/Viewer equivalence for all seven legacy basic effects and overlapping-content midpoint frames for both window orientations. It writes PNGs and a report to the new directory; CI retains these artifacts for 15 days.

pnpm --filter @s8fy/pptx-renderer test:transitions runs the focused transition/Morph regressions. pnpm smoke:transition-composition <fresh-output-dir> checks two-page composition and interrupted snapshots for 28 effect/direction pairs in Chromium, plus root opacity and natural GSAP completion. It compares actual pixels against independent endpoint colors and captured frames, rather than the old CSS behavior. Install Chromium with pnpm exec playwright install chromium before running locally.

The separate Visual CI workflow (.github/workflows/visual-ci.yml) owns browser, DOM and rendering checks, using Node 24 and Nushell. Its Ubuntu job runs type checks, focused DOM tests and composition pixels without MoonBit, retaining evidence for seven days. Its parallel macOS job runs release:visual and smoke:transitions, preserving the existing snapshot platform and retaining frames/traces for 15 days. That job builds source parser/authorization WASM without the native CLI or PDFium. Relevant source, dependency, fixture and baseline changes trigger it on pushes and PRs; superseded runs are cancelled. The main CI retains general SDK/engine tests.

Install

pnpm add @s8fy/pptx-renderer

Import the stylesheet once in the browser entry. It includes package-relative, cacheable KaTeX WOFF2 assets for formula rendering.

Usage

import { createPptxViewer } from '@s8fy/pptx-renderer'
import '@s8fy/pptx-renderer/style.css'

export async function mountPresentation(container: HTMLElement, file: File) {
  const viewer = createPptxViewer(container)
  try {
    await viewer.load(await file.arrayBuffer(), file.name)
    return viewer
  } catch (error) {
    viewer.destroy()
    throw error
  }
}

Call viewer.destroy() when the host view is removed. It releases owned media/font resources and event listeners. load() accepts an ArrayBuffer and resolves after authorization, parsing, font preparation (with fallback/timeout), and the first DOM commit.

The controller defaults to the WASM parser/unzip engine, a 960 px viewer width, enabled PDF export and presenter mode, and disabled PPTX download. It also accepts source: { kind: 'file', file, fileName? } or source: { kind: 'presentation', presentation }. Omit source for an empty viewer; top-level file / fileName / presentation options are rejected.

Animation and Morph playback

Animations and slide transitions run in fullscreen or presenter mode by default. Set animationScope: 'always' for embedded playback. animationScope: 'never', animationMode: 'static', or animate: false disables playback; reduced-motion preferences are respected unless animate: true is explicit. Thumbnails stay static.

The runtime plays relative grow/shrink and signed spin, including zero and multiple turns, finite repeat, auto-reverse, and click/with-previous/after-previous timing. Authored acceleration/deceleration fractions control each forward and reverse leg. Consecutive emphasis preserves the preceding held transform. Native fly enters or exits at the specified slide edge; legacy slide(...) filters keep their object-local clipping.

Morph connects consecutive rendered slides using drawing identity and exact !! names. byObject moves matched objects and groups, while byWord and byChar move matching text units between text boxes. Character mode keeps Unicode graphemes intact. Position, size, rotation, compatible vector paths and paint interpolate; replaced or incompatible visual content crossfades. Duplicate forced names remain unmatched, charts/tables/media crossfade, and unknown Morph modes use a slide fade. Text stays in its original drawing when the host cannot measure or segment it. Paragraphs containing inline math or media also stay intact so their non-text graphics are preserved.

During controlled slide transitions, next() or nextAnimation() finishes the transition before advancing page animations. completeAnimations() also completes destination animations; resetAnimations(), navigation, resize and destruction cancel the current transition. Destination animation initial states are prepared before the transition, keeping click entrances hidden; automatic animations and timed slide advance start after it completes. Reset restores page animation initial states and stops automatic animations and timed advance, including across asynchronous preparation and rerenders. Manual animation commands remain available; navigating to another slide or accepting a new source resumes automatic playback. GSAP and its optional geometry/path plugins load on demand.

The Viewer plays limited variants of 8 of the 19 P14 types:

| P14 effect | Web profile | | ----------------- | ------------------------------------------------------------ | | flash | No effect parameters; empirical brightness curve | | reveal | Left/right; throughBlack true or false | | flip | Left/right | | prism | Left/right/up/down; isContent=false and isInverted=false | | doors, window | Horizontal/vertical | | pan | Left/right/up/down | | wheel-reverse | Integer spokes from 1 through 16 |

The ECMA wheel effect also plays 1–16 spokes. Geometric profiles require a previous visible slide; DOM/SVG content and the profile's CSS features must be available. Live canvas, media and embedded documents use a basic/static fallback.

A recognized P14 profile uses its source timing, including when an unsupported variant or unavailable visual capability selects a basic fallback. Unenabled or uninterpretable P14 effects use the MC-selected branch and its timing. Zero duration and playback policy can settle the page immediately; advClick is preserved but does not restrict public navigation commands.

Generation and reading cover more variants than Web playback; see the generated capability matrix for those axes. These Web profiles approximate selected macOS PowerPoint samples. Parameter tests and Chromium composition checks do not certify Office pixel parity or cross-browser visual equivalence.

Controller methods

| API | Behavior | | ------------------------------------------------------------------ | --------------------------------------------------------------------------------- | | slide, total | Current zero-based index and slide count | | setSlide(index), next(), prev() | Navigate; next() may first advance an animation segment | | load(buffer, fileName?), setData(model) | Async document replacement; setData removes original-file export capability | | toPdf(options?) | Return PDF bytes without downloading | | downloadPdf(options?), downloadPptx(fileName?) | Async conversion/download initiation; require a successfully loaded original file | | enterFullscreen(), enterPresenterMode(), exitPresenterMode() | Browser presentation modes | | nextAnimation(), completeAnimations(), resetAnimations() | Control supported slide animations | | destroy() | Dispose the controller |

Use onLoad, onSlideChange, onLicenseStateChange, and onError callbacks for notifications. Source changes and destruction reject pending operations with ViewerOperationError; always handle returned promises. enablePdfExport and enablePptxDownload control UI availability, not license entitlements.

Render a slide without the controller

renderSlide(slide, { width, height, scale?, watermarks?, onSlideLink?, animate? }) returns an HTMLElement. renderElement(element, scale?, onSlideLink?) returns a Node. Both consume normalized core model types, not the raw parser result.

For a prepared Slide, a minimal static host can use:

import { renderSlide } from '@s8fy/pptx-renderer'
import type { RenderOptions } from '@s8fy/pptx-renderer'
import type { Slide } from '@s8fy/pptx-core'
import '@s8fy/pptx-renderer/style.css'

export function mountSlide(host: HTMLElement, slide: Slide, options: RenderOptions) {
  const node = renderSlide(slide, options)
  host.append(node)
  return () => node.remove()
}

Install @s8fy/pptx-core directly if your application imports its model types. Set width/height to the presentation's unscaled pixel dimensions; scale defaults to 1.

These low-level functions do not parse files, resolve authorization, load fonts, own media cleanup, or install the controller's animation/navigation runtime. The caller supplies resolved watermark layers and owns those responsibilities. Prefer createPptxViewer for a complete viewer.

Runtime

Rendering requires a browser DOM. ESM/CJS module imports are SSR-safe; create the viewer after client mount. The package declares Node.js 22.12+, ships both ESM/CJS TypeScript declarations, and exports ./style.css. WASM/Worker/font assets must remain accessible in the deployed application; browser PDF export requires Web Workers.

Framework adapters import the @s8fy/pptx-viewer facade, which delegates to this renderer, instead of maintaining separate rendering implementations.

License

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