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

@markdy/renderer-dom

v1.5.0

Published

Browser renderer for diagram-native animated MarkdyScript architecture diagrams, built on the Web Animations API.

Readme

@markdy/renderer-dom

Web Animations API renderer for MarkdyScript scenes. Translates a parsed AST into 60fps GPU-accelerated DOM elements and drives the animation timeline with interactive analytical capabilities (Blast Radius, Route Pathfinder, and SVG/GIF export).

🚀 Try it live: Test MarkdyScript in the browser at markdy.com/playground
📚 Documentation: Complete syntax guide and examples at markdy.com/docs
💼 Enterprise & Commercial: Free under MIT. To support development or request custom architecture blueprints, explore GitHub Sponsors.

Features

  • Browser-native — Web Animations API + CSS transforms, no Canvas or GSAP (~24 KB minzipped)
  • Blast Radius & Upstream Impact Lens — compute and highlight transitive inward callers and outward impact chains dynamically
  • Route Pathfinder — discover and animate the shortest topological communication route between any two services
  • Dynamic Port Multiplexing & Fillet Connectors — renders balanced parallel connection lanes with smooth rounded corner paths
  • 17 Diagram Layout Topologiesarchitecture, flowchart, tree, sequence, state, layers, nested, swimlane, timeline, gantt, medallion, flywheel, constellation, quadrant, pyramid, radar, venn
  • Dynamic Theme Switching — live runtime switching across 10 semantic themes (paper, editorial, midnight, blueprint, graphite, nebula, terminal, sketchy, ink, doodle)
  • Flow edges-> request, <- response, ~> event, -- dependency, each with its own stroke, plus animated traveling pulse
  • Beat-driven cuesshow, hide, glow, focus, and frame camera zooms, sequenced by named beats
  • Media Exporters — zero-dep animated GIF89a exporter with LZW compression and Figma-ready vector SVG export
  • Seek-safe — manual currentTime control enables reliable seek() in any direction
  • Playback-rate controls — set normalized timeline speed to slow down or speed up diagrams without rebuilding animations
  • Interactive viewport — wheel zoom, drag pan, and double-click reset with responsive auto-fit
  • Single dependency — only @markdy/core

Installation

pnpm add @markdy/core @markdy/renderer-dom

Package Position

@markdy/core -> @markdy/renderer-dom -> browser scene playback & impact lens

Usage

import { createDiagram, calculateBlastRadius, findShortestRoute } from "@markdy/renderer-dom";
import { parse } from "@markdy/core";

const code = `
scene "FinTech Checkout" theme=paper
layout LR

browser Client "Web Client"
gateway Gateway "API Gateway"
service PaymentSvc "Payment Service" @src="src/pay/index.ts#L10"
database LedgerDb "Ledger DB" icon=postgresql

beat checkout:
  show $nodes stagger=60ms
  Client -> Gateway "POST /checkout" -> PaymentSvc "Process" -> LedgerDb "Commit"
`;

const diagram = createDiagram({
  container: document.getElementById("scene")!,
  code,
  autoplay: true,
});

// Calculate Blast Radius
const ast = parse(code);
const impact = calculateBlastRadius("PaymentSvc", ast);
console.log("Upstream callers:", impact.upstreamNodeIds);     // ['Gateway', 'Client']
console.log("Downstream blast:", impact.downstreamNodeIds);   // ['LedgerDb']

// Shortest Route Pathfinder
const shortestPath = findShortestRoute("Client", "LedgerDb", ast);
console.log("Route:", shortestPath); // ['Client', 'Gateway', 'PaymentSvc', 'LedgerDb']

Responsive Playback

Animations run on the browser's Web Animations timeline. JavaScript synchronizes them on play, pause, seek, speed changes, and layout changes, not on every frame.

responsiveLayout controls whether the renderer may change orientation:

  • "auto" (default): adapt diagrams without an explicit layout directive.
  • true: also adapt diagrams that declare a direction, as in the playground.
  • false: keep the source layout fixed and only scale the scene.

With fitMode: "auto" (default), automatically sized architecture, flowchart, state, and tree diagrams compare cached horizontal and vertical layouts against the available width and height. Orientation changes only when the alternative improves the fitted scale by more than 20%. Other cases use a width breakpoint around 640px with a 32px margin on either side. Reverse flow stays BT/RL, and explicit scene dimensions are preserved, including partially specified sizes.

Auto fitting uses width-first framing in natural-height embeds and contain framing in height-constrained hosts. If fitting requires a scale below minReadableScale (default 0.9, valid range 0 to 1), the viewport scrolls instead of shrinking further. Set it to 0 to disable the readability floor. The Fit control toggles between a contained overview and readable framing. Scrollable framing starts horizontally centered and pins storyboard camera motion so frame cues do not compete with manual scrolling; other animations keep playing. Explicit fitMode: "width" and fitMode: "contain" keep their original scaling behavior without a readability floor.

Bounds include routed paths and label rectangles, even outside the estimated scene dimensions, and are cached after mounting or re-layout. Container resizing preserves playback time and state. ResizeObserver handles split panes as well as window resizing; hosts can call diagram.resize() after revealing a hidden preview.

Animated GIF Export

const gif = await diagram.exportGif({
  fps: 12,
  pixelRatio: 1,
  maxFrames: 120,
  maxWidth: 1600,
  holdEndMs: 1400,
  loop: true,
  onProgress: (progress) => console.log(Math.round(progress * 100)),
});

GIF export captures the rendered DOM, including node styling, shadows, and the current animation state. Use mode: "pure" for the previous vector-based rasterization path. PNG and SVG exports keep their existing defaults.

fps and pixelRatio are targets. Long scenes are sampled evenly across the complete timeline, with at most maxFrames frames including the final hold. Output width is capped by maxWidth; resolution is reduced further when needed to keep captured frames within a 48-megapixel budget. Repeated frames are merged without losing their delays, so compression preserves playback duration.

Playback time and playing/paused state are restored after export, including when capture fails. Browser font and cross-origin image restrictions still apply.

API Exports

| Export | Type | Description | |---|---|---| | createDiagram(options) | Function | Mounts and drives an animated diagram in a DOM container | | calculateBlastRadius(nodeId, ast) | Function | Computes upstream dependency callers and downstream blast radius | | findShortestRoute(fromId, toId, ast) | Function | Finds the shortest topological message path between two nodes | | applyImpactHighlight(container, impact) | Function | Highlights affected subgraph and dims non-impacted nodes | | clearImpactHighlight(container) | Function | Resets all impact highlighting | | exportDiagramAsVectorSvg(container, opts?) | Function | Export pure SVG vector snapshot of active scene frame | | exportDiagramAsPng(container, opts?) | Function | Export high-DPI rasterized PNG Blob | | exportDiagramAsGif(container, timeline, opts?) | Function | Export animated GIF89a recording |

Development & Visual Harness

To inspect the renderer visually during local development:

pnpm --filter @markdy/renderer-dom run harness

The harness runs on http://127.0.0.1:4325 (port 4325 is decoupled from Astro's default port 4321 to avoid collisions with documentation previews). It serves canonical test fixtures, live theme switching, and real-time interactive DOM rendering.

Ecosystem & Documentation

License

MIT