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

@xrn07/figure-renderer

v0.2.2

Published

Zero-dependency pure TypeScript figure renderer - pure SVG string generation

Readme

@xrn07/figure-renderer

Zero-dependency pure TypeScript figure renderer - pure SVG string generation.

✨ Version 0.2.2 - Truly Generic Figure Renderer Now supports ANY figure type without errors - physics, chemistry, math, biology, and more. No more "unknown figure type" errors!

✨ Version 0.2.1 - Enhanced API Format Support Real-world API responses with flexible parsing, numeric magnitudes, and automatic field normalization.

⚠️ Version 0.2.0 Breaking Change New flexible DSL format. See MIGRATION_V0.2.0.md for details.

Features

  • Zero runtime dependencies - Only ~8KB minified
  • Universal - Works in Node.js, browser, Next.js SSR, PDF export
  • Type-safe - Full TypeScript support
  • Truly Generic - Works with ANY figure type (physics, chemistry, math, biology, etc.)
  • No Errors - Renders placeholder SVG for unknown types instead of crashing
  • Testable - SVG strings are easily snapshot-able
  • Accessible - React component with proper ARIA labels
  • International - Localization support via alt field
  • API-friendly - Handles both JSON strings and objects, numeric or string magnitudes

Installation

npm install @xrn07/figure-renderer

Quick Start

Server-side (Node.js)

import { renderFigure, parseFigureDSL } from "@xrn07/figure-renderer";

const dsl = parseFigureDSL(jsonString);
const svg = renderFigure(dsl);
console.log(svg); // <svg>...</svg>

React/Next.js

import { FigureView } from "@xrn07/figure-renderer/react";
import { parseFigureDSL } from "@xrn07/figure-renderer";

// Parse DSL from API response (can be JSON string or object)
const dsl = parseFigureDSL(question.figure_dsl);
return <FigureView dsl={dsl} alt={question.figure_alt_bn} className='w-full' />;

Real-World API Format (v0.2.1+)

The parser now handles real API responses directly:

// API returns object with numeric magnitude
const apiResponse = {
  type: "force_diagram",
  alt_bn: "বস্তুর উপর ক্রিয়াশীল বল",
  arrows: [
    {
      direction: "right",
      label: "10 N",
      magnitude: 10, // Number instead of string
      unit: "N",
    },
  ],
};

// Parse from object (not just JSON string)
const dsl = parseFigureDSL(apiResponse);
const svg = renderFigure(dsl);

API

renderFigure(dsl: FigureDSL): string

Main rendering function that converts DSL to SVG string.

const svg = renderFigure({
  type: 'circuit',
  width: 400,
  height: 300,
  components: [...]
});

parseFigureDSL(str: string | object): FigureDSL | null

Safe JSON parser with Zod validation. Accepts both JSON strings and objects. Returns null for invalid input.

New in v0.2.1:

  • ✅ Accepts objects directly (not just JSON strings)
  • ✅ Handles alt_bn field (automatically maps to alt)
  • ✅ Supports numeric or string magnitudes
  • ✅ Automatic field normalization for API responses
// Parse from JSON string
const dsl = parseFigureDSL(jsonString);

// Parse from object (NEW!)
const dsl = parseFigureDSL(apiResponseObject);

if (dsl) {
  // Valid DSL with normalized fields
}

<FigureView /> (React component)

React wrapper component for rendering figures.

<FigureView dsl={dsl} alt='Description of figure' className='w-full h-auto' />

Supported Figure Types

The package is truly generic and supports ANY figure type:

  • force_diagram - Force vector diagrams with compass directions (full renderer)
  • ANY custom type - Renders placeholder SVG for unknown types (physics, chemistry, math, biology diagrams)

No more errors! If you try to render an unsupported type like circuit_diagram, graph, geometry, etc., the package will render a nice placeholder instead of crashing.

Registering Custom Renderers

For specialized rendering of specific types, you can register custom renderers:

import { registerRenderer } from "@xrn07/figure-renderer";

registerRenderer("circuit_diagram", (dsl) => {
  // Your custom rendering logic
  return `<svg>...</svg>`;
});

DSL Schema (v0.2.0)

The DSL is now generic and flexible. All figures share common base properties:

interface FigureDSL {
  type: string; // Generic - any figure type supported
  width?: number; // Optional - defaults to 400
  height?: number; // Optional - defaults to 300
  title?: string;
  alt?: string; // Localization support
  [key: string]: any; // Additional properties per figure type
}

Force Diagram DSL

{
  "type": "force_diagram",
  "alt": "বস্তুটির উপর ক্রিয়াশীল বলগুলোর চিত্র",
  "width": 400,
  "height": 300,
  "arrows": [
    {
      "direction": "down",
      "label": "মাধ্যাকর্ষণ",
      "magnitude": "100 N",
      "unit": "N",
      "color": "#dc2626"
    },
    {
      "direction": "up",
      "label": "সমতলের প্রতিক্রিয়া বল",
      "magnitude": 100,
      "unit": "N",
      "color": "#2563eb"
    }
  ]
}

Compass Directions: up, down, left, right, up-left, up-right, down-left, down-right

New in v0.2.1: Magnitude can be string ("100 N") or number (100). The parser handles both formats automatically.

Optional Object:

{
  "type": "force_diagram",
  "object": {
    "type": "box",
    "x": 200,
    "y": 150,
    "width": 60,
    "height": 60,
    "label": "5kg"
  },
  "arrows": [...]
}

See src/types.ts for complete type definitions.

Examples

Circuit Diagram

const circuitDSL = {
  type: "circuit",
  width: 400,
  height: 300,
  components: [
    { type: "battery", x: 100, y: 150, label: "12V" },
    { type: "resistor", x: 200, y: 100, label: "R1" },
    // ... more components
  ],
};

Force Diagram (v0.2.0+ Format)

const forceDSL = {
  type: "force_diagram", // NEW: snake_case
  width: 400, // Optional
  height: 300, // Optional
  arrows: [
    // NEW: compass-based arrows
    {
      direction: "down", // Instead of angle: -90
      label: "মাধ্যাকর্ষণ",
      magnitude: "100 N", // Can be number or string
      unit: "N",
      color: "#dc2626",
    },
    {
      direction: "up",
      label: "Normal Force",
      magnitude: 100, // Number works too
      unit: "N",
      color: "#2563eb",
    },
  ],
};

Force Diagram (Old v0.1.x Format - Deprecated)

const forceDSL = {
  type: "forceDiagram",
  width: 400,
  height: 300,
  object: { type: "box", x: 200, y: 150, width: 60, height: 60 },
  forces: [
    {
      originX: 200,
      originY: 150,
      magnitude: 50,
      angle: -90,
      label: "F₁",
      color: "#e53e3e",
    },
    // ... more forces
  ],
};

Testing

import { renderFigure } from '@xrn07/figure-renderer';

test('renders circuit diagram', () => {
  const dsl = { type: 'circuit', ... };
  const svg = renderFigure(dsl);
  expect(svg).toMatchSnapshot();
});

Bundle Size

  • Minified: ~8KB
  • Gzipped: ~3KB
  • Tree-shakeable: Unused renderers can be excluded

Changelog

v0.2.2 (2026-06-XX)

Major Enhancement:

  • 🎉 Truly Generic Package - Now supports ANY figure type without errors
  • ✨ No more "unknown figure type" crashes
  • ✨ Renders placeholder SVG for unregistered types (physics, chemistry, math, biology, etc.)
  • ✨ Graceful degradation instead of errors
  • 🐛 Fixed arrow overlap for multiple arrows in same direction
  • ✨ Automatic arrow stacking with proper spacing

Improvements:

  • 📦 Package now works out-of-the-box for any educational content
  • 🎯 Better developer experience - no need to pre-register every type

v0.2.1 (2026-06-XX)

Enhancements:

  • ✨ Accept objects directly in parseFigureDSL() (not just JSON strings)
  • ✨ Support numeric magnitudes (e.g., magnitude: 100 instead of magnitude: "100 N")
  • ✨ Automatic field normalization (e.g., alt_bnalt)
  • ✨ Flexible magnitude parsing with automatic unit handling
  • 📝 Updated tests to verify real API format compatibility

Bug Fixes:

  • 🐛 Fixed parsing of real-world API responses with numeric values

v0.2.0 (2025-01-XX)

Breaking Changes:

  • 🔴 Migrated from rigid enum types to generic string-based type system
  • 🔴 Changed force diagram format from angle-based to compass directions
  • 🔴 Renamed forceDiagramforce_diagram
  • 🔴 Replaced forces array with arrows array

New Features:

  • ✨ Compass direction system (up, down, left, right, etc.)
  • ✨ Optional dimensions with sensible defaults
  • ✨ Bengali and multilingual support via alt field
  • ✨ Renderer registry for custom figure types
  • ✨ Props customization system

License

MIT