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

@chartdown/render-svg

v0.9.0

Published

Chartdown SVG renderer — deterministic, seeded, themeable rendering of plain-text TTRPG maps. Runtime-dependency-free beyond @chartdown/core (ADR 0007).

Readme

@chartdown/render-svg

Deterministic, seeded SVG renderer for Chartdown — plain-text TTRPG maps. Same input, same seed, byte-identical SVG. Zero runtime dependencies beyond @chartdown/core.

import { renderSource } from "@chartdown/render-svg";

const { svg, diagnostics } = renderSource(source, { mode: "gm" });
// options: mode ("player" | "gm"), theme (Chartdown theme source), level

Player mode strips GM secrets fail-closed. Themes are themselves Chartdown documents. Try the playground or see the spec.

The resolved scene

render resolves a whole scene per call — positions, outlines, half-planes, organic finishing — and discards it. resolveScene returns it instead, for a host that draws with its own primitives rather than consuming the SVG (ADR 0051).

import { resolveScene } from "@chartdown/render-svg";

const scene = resolveScene(doc, { mode: "gm" });
// { schemaVersion, mapType, mode, unit, extent, levels?, features, walls?, diagnostics }

scene.schema.json sits beside this README and is the normative shape; examples/gumdrop-vale/gumdrop-vale.scene.json is a worked one. The schema versions with this package, not with SPEC_VERSION — a renderer output is not language.

Geometry is in the map's own units. A region's extent: units, cells on a battlemap, hexes on a hexcrawl — never canvas pixels, because a canvas number moves with detail: and ADR 0037 forbids a rendering choice from moving geometry. A grid map's geometry is a cell union rather than an outline: a structure occupies cells, and spec 06 §3 derives the outline from them, so the derived perimeter rides along.

Geometry is what is drawn, after organic finishing — the outline the coast has, not the one the document declared. Your coast therefore agrees with this renderer's coast on the same document, which is the point.

There is no ink in it. No stroke widths, no font sizes, no legibility floor, no zone insets, no glyph scatter. Each feature carries its derivation chain, so you apply your own theme through the same fallback this renderer uses; a theme document is already the interchange format for the rest.

Two exclusions worth knowing before you build on it:

  • Placed labels are not in v1. A feature carries where its label wants to go, not where arbitration put it, so two implementations will put the same things in the same places and label them differently. Arbitration is interleaved with emission and the placer is stateful; hoisting it is its own change.
  • detail: is an input to determinism on a region. A scene is a pure function of (document, seed, renderer version, mode, detail:). Organic finishing runs in canvas space, so a larger canvas grows texture and the dependence propagates through relational placement — examples/vessany's coast has 400 vertices at overview and 665 at reference. Resolve at the detail: you intend to draw, and do not mix scenes from two. Grid maps have no such knob and are unaffected.