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

@thi.ng/hiccup-svg

v5.6.8

Published

SVG element functions for @thi.ng/hiccup & related tooling

Readme

@thi.ng/hiccup-svg

npm version npm downloads Mastodon Follow

[!NOTE] This is one of 214 standalone projects, maintained as part of the @thi.ng/umbrella monorepo and anti-framework.

🚀 Please help me to work full-time on these projects by sponsoring me on GitHub. Thank you! ❤️

About

SVG element functions for @thi.ng/hiccup & related tooling.

Important

The functions provided here do produce valid hiccup elements, but since none of them make use of (or support) the global hiccup / hdom context object, they can ONLY be invoked directly, i.e. they MUST be called like:

import { circle, svg } from "@thi.ng/hiccup-svg";

// correct (direct invocation)
svg({}, circle([0, 0], 100, { fill: "red" }));

// incorrect / unsupported (lazy evaluation)
[svg, {}, [circle, [0, 0], 100, { fill: "red" }]]

SVG conversion of @thi.ng/geom & @thi.ng/hiccup-canvas shape trees

Since v2.0.0 this package provides a conversion utility to translate the more compact syntax used by @thi.ng/geom and @thi.ng/hiccup-canvas shape trees (designed for more performant realtime / canvas drawing) into a SVG serializable hiccup format.

The convertTree() function takes a pre-normalized hiccup tree of geom/hiccup-canvas shape definitions and recursively converts it into an hiccup flavor which is ready for SVG serialization (i.e. using stringified geometry attribs). This conversion also involves translation & re-organization of various attributes. This function returns a new tree. The original remains untouched, as will any unrecognized tree / shape nodes (those will be transferred as-is to the result tree). Conversion can be explicitly disabled for individual elements (tree branches) by setting the __convert: false control attribute. See example below.

Tree conversion can be implicitly triggered by providing a __convert: true attribute to the root svg() element. This conversion also supports the __prec control attribute which can be used (on a per-shape basis) to control the formatting used for various floating point values (except color conversions). Child shapes (of a group) inherit the precision setting of their parent.

import { svg } from "@thi.ng/hiccup-svg";

// create SVG root element and convert body
svg(
    { width: 100, height: 100, __convert: true, __prec: 3 },
    ["rect", { fill: [1, 0, 0] }, [1.2345, -1.2345], 100, 100]
)
// [
//   'svg',
//   {
//     version: '1.1',
//     xmlns: 'http://www.w3.org/2000/svg',
//     'xmlns:xlink': 'http://www.w3.org/1999/xlink',
//     width: 100,
//     height: 100
//   },
//   ['rect', { fill: '#ff0000', x: '1.234', y: '-1.234', width: '100', height: '100' }]
// ]

Automatic attribute conversions

Colors

Since v3.1.0:

Color conversions are only applied to fill and stroke attributes and color stops provided to linearGradient(), radialGradient()

String

String color attribs prefixed with $ are replaced with url(#...) refs (e.g. to refer to gradients), else used as is (untransformed)

Number

Interpreted as ARGB hex value:

{ fill: 0xffaabbcc } => { fill: "#aabbcc" }

Array

Interpreted as float RGB(A):

{ fill: [1, 0.8, 0.6, 0.4] } => { fill: "rgba(255,204,153,0.40)" }

@thi.ng/color values

Converted to CSS color strings:

{ fill: hcya(0.1666, 1, 0.8859) } => { fill: "#ffff00" }

Transforms

(i.e. transform, rotate, scale, translate)

If an element has a transform attrib, conversion of the other transformation attribs will be skipped, else the values are assumed to be either strings or:

  • transform: 6-element numeric array (2x3 matrix in column major order)
  • translate: 2-element array
  • rotate: number (angle in radians)
  • scale: number (uniform scale) or 2-elem array

If no transform, but others are given, the resulting transformation order will always be TRS. Any string values will be used as-is and therefore need to be complete, e.g. { rotate: "rotate(60)" }

Status

STABLE - used in production

Search or submit any issues for this package

Installation

yarn add @thi.ng/hiccup-svg

ESM import:

import * as svg from "@thi.ng/hiccup-svg";

Browser ESM import:

<script type="module" src="https://esm.run/@thi.ng/hiccup-svg"></script>

JSDelivr documentation

For Node.js REPL:

const svg = await import("@thi.ng/hiccup-svg");

Package sizes (brotli'd, pre-treeshake): ESM: 2.53 KB

Dependencies

Note: @thi.ng/api is in most cases a type-only import (not used at runtime)

Usage examples

17 projects in this repo's /examples directory are using this package:

| Screenshot | Description | Live demo | Source | |:-------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|:---------------------------------------------------------|:--------------------------------------------------------------------------------------| | | Tool to interactively compute & visualize color contrasts against WCAG threshold | Demo | Source | | | Probabilistic color theme generator | Demo | Source | | | Heatmap visualization of this mono-repo's commits | | Source | | | Basic crypto-currency candle chart with multiple moving averages plots | Demo | Source | | | Color palette generation via dominant color extraction from uploaded images | Demo | Source | | | Mouse gesture / stroke analysis, simplification, corner detection | Demo | Source | | | Various hdom-canvas shape drawing examples & SVG conversion / export | Demo | Source | | | CLI util to visualize umbrella pkg stats | | Source | | | Generate SVG using pointfree DSL | | Source | | | Polygon to cubic curve conversion & visualization | Demo | Source | | | Animated SVG elements with reactive attributes | Demo | Source | | | rdom powered SVG graph with draggable nodes | Demo | Source | | | Interactive grid generator, SVG generation & export, undo/redo support | Demo | Source | | | SVG path parsing & dynamic resampling | Demo | Source | | | Additive waveform synthesis & SVG visualization with undo/redo | Demo | Source | | | Interactive ridge-line plot | Demo | Source | | | Interactive scatter & line plot of low-discrepancy samples | Demo | Source |

API

Generated API docs

import * as svg from "@thi.ng/hiccup-svg";
import { serialize } from "@thi.ng/hiccup";
import * as fs "node:fs";

fs.writeFileSync(
    "hello.svg",
    serialize(
        svg.svg(
            { width: 100, height: 100 },
            svg.defs(svg.linearGradient("grad", [0, 0], [0, 1], [[0, "red"], [1, "blue"]])),
            svg.circle([50, 50], 50, { fill: "url(#grad)" }),
            svg.text([50, 55], "Hello", { fill: "white", "text-anchor": "middle" })
        )
    ));

Minimal example showing SVG conversion of a hiccup-canvas scene (also see @thi.ng/geom for another compatible approach):

import { svg } from "@thi.ng/hiccup-svg";
import { serialize } from "@thi.ng/hiccup";
import { writeFileSync } from "node:fs";

// scene tree defined for hiccup-canvas
const scene = [
    ["defs", {},
        ["radialGradient",
            { id: "bg", from: [150, 280], to: [150, 300], r1: 300, r2: 100 },
            [[0, "#07f"], [0.5, "#0ef"], [0.8, "#efe"], [1, "#af0"]]],
        ["radialGradient",
            { id: "sun", from: [110, 120], to: [110, 120], r1: 5, r2: 50 },
            [[0, "#fff"], [1, "rgba(255,255,192,0)"]]]
    ],
    ["circle", { fill: "$bg" }, [150, 150], 130],
    ["circle", { fill: "$sun" }, [110, 120], 50],
];

writeFileSync(
    "radialgradient.svg",
    serialize(
        svg({ width: 300, height: 300, __convert: true }, scene)
    )
);

Result:

<svg version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="300">
    <defs>
        <radialGradient id="bg" fx="150.00" fy="280.00" cx="150.00" cy="300.00" fr="300.00" r="100.00" gradientUnits="userSpaceOnUse">
            <stop offset="0" stop-color="#07f"/>
            <stop offset="0.5" stop-color="#0ef"/>
            <stop offset="0.8" stop-color="#efe"/>
            <stop offset="1" stop-color="#af0"/>
        </radialGradient>
        <radialGradient id="sun" fx="110.00" fy="120.00" cx="110.00" cy="120.00" fr="5.00" r="50.00" gradientUnits="userSpaceOnUse">
            <stop offset="0" stop-color="#fff"/>
            <stop offset="1" stop-color="rgb(255,255,192)" stop-opacity="0"/>
        </radialGradient>
    </defs>
    <circle cx="150.00" cy="150.00" r="130.00" fill="url(#bg)"/>
    <circle cx="110.00" cy="120.00" r="50.00" fill="url(#sun)"/>
</svg>

Authors

If this project contributes to an academic publication, please cite it as:

@misc{thing-hiccup-svg,
  title = "@thi.ng/hiccup-svg",
  author = "Karsten Schmidt",
  note = "https://thi.ng/hiccup-svg",
  year = 2016
}

License

© 2016 - 2026 Karsten Schmidt // Apache License 2.0