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

@gum-jsx/core

v1.9.0

Published

Language for vector graphics generation.

Downloads

661

Readme

@gum-jsx/core

The core of gum.jsx: the evaluator that turns gum's JSX dialect into SVG, the element library behind it (layout, geometry, text, plots, networks, symbolic curves), and the fonts (IBM Plex) it measures text with. A pure, platform-neutral library with no CLI and no node-only dependencies — it runs the same in a browser and on a server. The batteries-included gum-jsx package wraps it together with the add-ons and ships the gum command; install that instead if you want the whole stack.

Installation

npm install @gum-jsx/core

Usage

evaluateGum evaluates a string of gum.jsx and returns the root Svg element; .svg() serializes it:

import { evaluateGum } from '@gum-jsx/core/eval'

const jsx = `
<Plot xlim={[0, 2*pi]} ylim={[-1.5, 1.5]} grid margin={[0.2, 0.1]} aspect={2}>
  <SymLine fy={sin} stroke={blue} stroke-width={2} />
</Plot>
`
const elem = evaluateGum(jsx, { size: 800, theme: 'light' })
const svg = elem.svg()

The code runs with every element, constant (pi, blue, sans, …) and utility (linspace, zip, random, …) in scope, so most files are a single JSX expression; a file can also declare things and return an element. Options: size (a number or [width, height]), theme (light or dark), bindings (extra names to bind), prelude (code or the bindings of code evaluated first, see evaluatePrelude), seed (for random/uniform/normal/integer), strict (throw on rendering fallbacks instead of drawing them), loadFile (how loadTable(path) and <LoadImage id={path} /> in the code read files), debug, plus any Svg argument such as padding, unit_size or bare.

evaluateGum is the default Env's evaluate. An Env is everything code evaluates against — the elements and names in scope, the fonts, the theme, strict mode and the random streams — and every element carries the Env it was built with, so nothing about a render is global: a dark evaluation leaves no dark theme behind, and two Envs with different settings or element sets can be used side by side. The default Env is gum; make your own for other defaults or an isolated element set:

import { gum, Env } from '@gum-jsx/core'
import { math } from '@gum-jsx/math'

gum.use(math)                                   // <Latex> in the default Env (what gum-jsx does for you)
const dark = new Env({ theme: 'dark' }).use(math)
const elem = dark.evaluate(jsx, { size: 800 })  // or gum.with({ theme: 'dark' }).evaluate(...)

new Env({ theme, strict, seed, plugins }) starts with core's elements, names and text fonts; use(plugin) adds an add-on's (a plugin is { elems, bindings, fonts }, and registerElements/registerBindings/registerFonts add one kind); with(settings) derives an Env with other settings (its registries are copied, so use on either leaves the other alone); evaluate and prelude run code. The evaluation scope also binds env itself.

The elements are plain classes and can be used from JavaScript directly, with props in snake_case; an element built this way uses the default Env unless it is given one (new Plot({ env, ... })):

import { Plot, SymLine, pi, sin, blue } from '@gum-jsx/core'

const elem = new Plot({
  children: [ new SymLine({ fy: sin, stroke: blue, stroke_width: 2 }) ],
  xlim: [0, 2*pi], ylim: [-1.5, 1.5], grid: true, margin: [0.2, 0.1], aspect: 2,
})
const svg = elem.svg()

The documentation has a page and an example per element; the same pages ship in @gum-jsx/docs.

Fonts

Text is measured against real font metrics, so the faces have to be loaded before anything with text is rendered. In node they are read from disk on first use and nothing more is needed. In a browser, fetch them first — await loadTextFonts() for IBM Plex (the faces every Env starts with), or await gum.loadFonts() for everything the Env knows, including a plugin's — otherwise rendering throws FontNotLoadedError. Each Env has a font registry (env.fonts, a FontRegistry: register, names, face, load, loaded, get, data); env.registerFont(name, path, face) adds a face of your own and loads it, and env.fonts.data(name) holds the fetched bytes for handing to FontFace so the page can draw the same glyphs the layout measured. Loaded files are cached process-wide by path, so Envs sharing a family share one copy. Emoji are measured with a fixed advance and left to the host's emoji font.

Extending

An add-on is a plugin: an object { elems, bindings, fonts } (EnvPlugin) that an Env applies with use, so a host that never uses it gets only core's names, and importing the add-on does nothing on its own; @gum-jsx/math exports math this way for <Latex> and the KaTeX faces. An add-on's elements subclass core's and take env in their args like every element (see Element.env), so they read the theme, strict mode and fonts of the Env they are built in. Internals are reachable through the subpath exports @gum-jsx/core/env (Env, defaultEnv, resolveEnv), @gum-jsx/core/lib/* (Context, types, theme, strict, utils, …), @gum-jsx/core/elems/* (the element modules), and @gum-jsx/core/fonts (the font registry) — that is the surface add-ons are written against.

Strict mode (strict: true on an Env or an evaluation) turns the permissive fallbacks — unparseable input, unknown tags or commands, glyphs missing from a face — into thrown StrictErrors, which is how the gum-jsx test suite renders every example.