Skip to content

coroboros/sparkline

Repository files navigation

@coroboros/sparkline

@coroboros/sparkline

Lightweight, zero-dependency SVG sparkline generator for Node.js.

Calculates polyline points from a numeric series and returns a pure SVG string. Tune width, height, stroke, coordinate precision, and accessibility metadata.

npm ci license stars coroboros.com

Contents

Requirements

  • Node.js >=22 LTS. Use fnm for version management — Rust-based, faster than nvm.
  • Any of the following package managers: pnpm, npm, yarn, bun.

Install

pnpm add @coroboros/sparkline
npm install @coroboros/sparkline
yarn add @coroboros/sparkline
bun add @coroboros/sparkline

Usage

// ESM (recommended)
import { sparkline } from '@coroboros/sparkline';
// CommonJS
const { sparkline } = require('@coroboros/sparkline');
import { sparkline, SparklineError } from '@coroboros/sparkline';

const values = [10, 50, 50, 200, 0];

try {
  const svg = sparkline(values, {
    width: 135,
    height: 50,
    stroke: '#C9A96E',
    strokeWidth: 1.25,
    strokeOpacity: 1,
    precision: 2,
    title: 'Price (24h)',
    ariaLabel: 'Price trend over the last 24 hours',
    description: 'Hourly close for the last 24 hours.',
  });
  // svg is a string containing <svg>…<polyline/>…</svg>
} catch (err) {
  if (err instanceof SparklineError) {
    console.error(err.code, err.message);
  }
}

API

Types

SparklineOptions

Style and accessibility options for sparkline. Every field is optional. Invalid style options (width, height, stroke, strokeWidth, strokeOpacity, precision) fall back silently to their defaults.

Option Type Default Description
width number 135 SVG width, in pixels. Must be > 0.
height number 50 SVG height, in pixels. Must be > 0.
stroke string #C9A96E Stroke color — CSS named color, hex (#rgb, #rgba, #rrggbb, #rrggbbaa), or functional notation (rgb(), rgba(), hsl(), oklch(), …).
strokeWidth number 1.25 Stroke width, in pixels. Must be >= 0. 0 produces an invisible polyline.
strokeOpacity number 1 Stroke opacity, in [0, 1].
precision integer 2 Decimal places kept on every coordinate. Integer in [0, 6]. Lower values produce smaller SVGs.
title string (optional) Adds a <title> element and sets role="img" plus aria-label on the root <svg> (when ariaLabel is omitted).
ariaLabel string (optional) Explicit aria-label on the root <svg>. Takes precedence over title for the accessible name.
description string (optional) Adds a <desc> element for screen-reader long-form context.
SparklineError

Thrown by sparkline. Inherits from Error. See Errors for the code list.

class SparklineError extends Error {
  readonly name: 'SparklineError';
  readonly code: SparklineErrorCode;
  readonly message: string;
}
SparklineErrorCode
type SparklineErrorCode = 'MISSING_VALUES' | 'INVALID_VALUES' | 'EMPTY_VALUES';
sparkline(values, options?)

Generate an SVG sparkline from an array of numeric values.

Parameters

Option Type Default Description
values ReadonlyArray<number> (required) Finite numbers used to draw the sparkline. Must contain at least one element.
options? SparklineOptions {} Style and accessibility overrides.

Returnsstring. The SVG markup including <polyline>.

ThrowsSparklineError. Invalid values throw with one of MISSING_VALUES, INVALID_VALUES, EMPTY_VALUES. Invalid style options fall back silently to their defaults.

Notes — See bench/baseline.md for SVG-render timings.

Examples

sparkline([10, 50, 50, 200, 0]);
// → <svg viewBox="0 0 135 50" ...><polyline .../></svg>

sparkline([1, 2, 3, 2, 1], {
  width: 200,
  height: 60,
  strokeWidth: 2,
  ariaLabel: 'Trend',
});
// → accessible SVG with role="img" and aria-label="Trend"

try {
  sparkline([]);
} catch (err) {
  if (err instanceof SparklineError) {
    err.code; // 'EMPTY_VALUES'
  }
}

Accessibility

The polyline is inset by strokeWidth / 2 so stroke caps never clip the viewBox edges.

When none of title, ariaLabel, or description are provided, the SVG is marked aria-hidden="true" — treat it as decorative. Pass any of them to opt into an accessible image: the root gets role="img" plus aria-label (from ariaLabel or title), and <title> / <desc> nest inside the SVG.

Gallery

Rendered examples live in assets/examples.

Bitcoin Ethereum Chainlink Kusama Tether

Errors

Code Description
MISSING_VALUES The values option is missing.
INVALID_VALUES values is not an array, or contains non-finite numbers.
EMPTY_VALUES values is an empty array.

Debugging

The library uses Node's built-in util.debuglog. Enable it with:

NODE_DEBUG=sparkline node your-script.js

Compared to alternatives

Feature sparkline (shiwano) node-sparkline @fnando/sparkline react-sparklines @coroboros/sparkline
Output ASCII SVG string SVG (mutates DOM) React (JSX → SVG) SVG string
Runs in Node without DOM or React yes yes no no yes
Zero runtime dependencies no yes yes no yes
Accessibility (title, aria-label, <desc>) n/a no no no yes
Tunable coordinate precision no no no (fixed) no yes
Built-in TypeScript types no no no no yes
ESM + CJS dual build no no no no yes

The gap is accessibility-aware SVG output rendered in Node. sparkline (shiwano) returns Unicode block characters — fine in a terminal, off-limits in an <img> tag or a generated PDF. @fnando/sparkline mutates a passed <svg> DOM element; react-sparklines renders through a React tree. node-sparkline is the closest peer with an SVG string and zero deps, but ships no ARIA support, no precision control, no types, and CJS only. @coroboros/sparkline fills the rest: opt-in title / aria-label / <desc>, coordinate precision for wire-size control, built-in types, and a dual ESM/CJS build.

Contributing

Bug reports and PRs welcome.

  • Open an issue before submitting non-trivial PRs.
  • Commits follow Conventional Commits.
  • Run pnpm lint && pnpm typecheck && pnpm test before pushing.
  • Target the main branch.

License

MIT

About

Lightweight, zero-dependency SVG sparkline generator for Node.js.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors