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-studio/render-dom

v0.3.7

Published

The live DOM renderer: one element per shape, over the same layout engine as render-svg

Readme

@pptx-studio/render-dom

The live renderer: one <svg> per slide, built as real elements.

Sub-phase 2.10. Every fact about DrawingML this package draws on lives in @pptx-studio/render-svg and was measured against Microsoft PowerPoint in experiment C6.

One tree, two renderers

The plan asks for two renderers "over the same layout engine", so that a thumbnail and the editor cannot disagree about what is on the screen. Sharing a layout is not enough for that on its own: emitting a <linearGradient> twice, once as text and once through createElementNS, is two chances to write the same gradient wrong in two different ways.

So the shared surface goes a level deeper. render-svg builds a node tree and serialises it; this builds the identical tree and instantiates it. The suite asserts that the browser's own XMLSerializer over the mounted nodes returns the string emitter's output character for character.

The namespace

document.createElement('path') makes an HTML element that happens to be spelled path, and it draws nothing at all — silently, with no error anywhere. Every element here goes through createElementNS. Attributes are the mirror image: they belong to no namespace and go through plain setAttribute.

The suite runs in real Chromium rather than jsdom, which is the repository's standing choice and earns it here: the test calls getTotalLength() on the mounted path, which an HTML element cannot answer.

Zoom is a transform, never a re-layout

The mounted <svg> carries a viewBox in EMU and is sized in CSS pixels, so scaling it is one attribute and no arithmetic — resize() writes width and height and nothing else moves. The plan's rule is the reason: font metrics are not linear in point size, so a renderer that re-lays out per zoom level changes its line breaks as the user zooms.

Using it

import { mountSlide } from '@pptx-studio/render-dom';

const mounted = mountSlide(host, slide, { cx: 12192000, cy: 6858000 }, { width: 960, height: 540 });
mounted.element(shape.cNvPrId); // the element drawing one shape, for hit-testing
mounted.resize(1280, 720);
mounted.unmount();

document may be passed explicitly, because this package has to work in a Web Worker with no global one — and because a test that has to stub a global is a test that can pass for the wrong reason.

What it does not do yet

Text (3.8), the overlay canvas and adjust-handle chrome (2.11), selection and gestures (Phase 5), and slide virtualization (12.1). The host is emptied on mount; anything a caller wants beside the slide is a sibling of the host, not a child of it.

The text layer

mountTextLayer builds an HTML layer over the slide from the identical TextBlock @pptx-studio/render-svg emits: one div per shape, one per line, a span per piece, and the same rule rectangles. Real text nodes, so selection, an IME and a screen reader all work on them.

There is one set of line boxes and both renderers read it, which is what stops them drifting. The one place the HTML layer is not exact is the baseline: a browser puts an inline baseline a half-leading plus an ascent below the line box, from font metrics it has rounded to whole pixels, so the line-height that reconciles the two lands within one CSS pixel and no closer. The SVG emitter, where a baseline is a coordinate, is exact — which is the right way round, since that is what thumbnails and export go through.