Skip to content

Latest commit

 

History

182 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gum

Gum is a JSX language for vector graphics: plots, diagrams, mathematical figures, and slides. Compose shapes, text, and TeX with measured layouts, then export SVG, PNG, PDF, or PPTX, or display the result directly in an image-capable terminal.

Use Gum as a command-line tool, a TypeScript library, or through its browser editor and React bindings. JSX figures use ordinary JavaScript functions and data; they do not require React.

Start with the CLI · Documentation and gallery

Get started

Use Node.js 24 or newer and install the bundled CLI:

npm install -g @gum-jsx/cli

The CLI includes the core renderer, math, maps, and PNG/PDF/PPTX exporters. It provides the gum command. Bun 1.4.2 or newer works equally well as an alternative runtime and is required for CLI plugins.

Save this as figure.jsx:

<Plot
  width={px(640)}
  aspect={2}
  font-size={px(18)}
  title="Sine wave"
  xlabel="x"
  ylabel="sin(x)"
  xlim={[0, tau]}
  ylim={[-1.5, 1.5]}
  background="white"
>
  <SymLine
    fy={sin}
    xlim={[0, tau]}
    samples={161}
    stroke={blue}
    stroke-width={px(2)}
  />
</Plot>

Render it:

gum figure.jsx -o figure.svg
gum figure.jsx -o figure.png --ratio 2
gum figure.jsx -o figure.pdf

Sine wave rendered from the JSX above

Elements, units, and helpers such as Plot, px, sin, and tau are already in scope. Use px(24) for pixels, em(1.5) for font-relative lengths, and fractions such as 0.5 for relative sizes. Gum measures text and composes layouts with boxes, stacks, and positioned canvases. Start with the units and sizing guides.

Ways to use Gum

Command line. Omit -o to display a figure in a terminal supporting the kitty graphics protocol. Use -f svg for SVG on stdout, or -f tree --stats to inspect layout. The CLI includes math bindings:

gum figure.jsx
gum figure.jsx -f tree --stats
gum slides/ -o talk.pdf

PNG and terminal rendering use tiny-skia WebAssembly without native addons or install scripts. Raster output uses outlined text; emoji without outlines and external SVG images are unsupported. PDF output preserves vector paths and embedded PNG images; text is outlined and is not searchable or selectable. See the CLI, PDF, and PPTX references for format support and limits.

Browser editor. From a development checkout, run bun --filter @gum-jsx/edit dev and open the printed URL to edit JSX with a live SVG preview. The /docs page provides searchable, editable examples.

Library. Evaluate JSX and render it to SVG from a Bun script:

import { evaluate, render_element } from '@gum-jsx/core'

const source = await Bun.file('figure.jsx').text()
const result = render_element(evaluate(source))
if (result.kind === 'svg') {
  await Bun.write('figure.svg', result.svg)
}

You can also construct elements directly in TypeScript. The core and math renderers support browser hosts with preloaded font resources. Use @gum-jsx/math for TeX or @gum-jsx/react to compose figures as React components. Evaluated JSX executes JavaScript in the host environment; use trusted source or an application-provided isolation boundary.

Coding agents. From the workspace root, bun run plugin:build generates the plugin's authoring skill from the maintained documentation. bun run plugin:pack rebuilds it and packages the plugin ZIP.

To install the plugin from GitHub:

codex plugin marketplace add CompendiumLabs/gum-jsx
codex plugin add gum-jsx@gum-jsx

Start a new task after installation. Rendering uses the Gum CLI described above.

Packages

Each package is a separate repository, developed together through Git submodules.

Package Purpose
@gum-jsx/core JSX evaluation, layout, shapes, text, plots, networks, and SVG output.
@gum-jsx/math TeX parsing, math layout, and standalone formula exports.
@gum-jsx/png Fragment rasterization to PNG or RGBA through WebAssembly.
@gum-jsx/pdf Vector PDF export from laid-out fragments.
@gum-jsx/pptx Native PowerPoint shapes and images from laid-out fragments.
@gum-jsx/react React bindings, headless rendering, and the gum-react command.
@gum-jsx/mark Markdown terminal rendering with figures and math.
@gum-jsx/cli The gum command.
@gum-jsx/edit Browser editor and interactive documentation viewer.
@gum-jsx/docs Guides, element references, gallery sources, and skill generation.

Development

Clone the workspace and its package submodules:

git clone https://github.com/CompendiumLabs/gum-jsx.git
cd gum-jsx
git -c url."https://github.com/".insteadOf=git@github.com: submodule update --init --recursive
bun install
bun --filter @gum-jsx/png build

The submodule command uses HTTPS for the repository's SSH remotes, so a public checkout does not require a GitHub SSH key.

Run shared commands from the workspace root:

bun run test          # Every package's suite, sequentially
bun run typecheck     # TypeScript checks across all packages
bun run build        # Build PNG assets, then the bundled CLI
bun run perf          # Core, math, maps, and demos benchmarks, sequentially
bun --filter @gum-jsx/edit build # Production browser editor and docs viewer
bun run visual-test   # Searchable HTML report of rendered examples
bun run rehearse      # Publish to a temporary local registry and check fresh installs
bun run --cwd gum-jsx-cli test # Includes isolated npm CLI installation checks

To work on one package, use its scripts, for example bun --filter @gum-jsx/core test. Package READMEs cover additional checks and dependencies. The design, roadmap, and feature map describe implementation decisions and planned work. The release checklist covers packaging and publication checks.

Performance

bun run perf                 # All suites, measured sequentially
bun run perf:core            # Core only
bun run perf:math            # Math only
bun run perf:maps            # Maps only
bun run perf:demos           # Full JSX demos, split by rendering stage
bun run perf --list          # List case names without preparing fixtures
bun run perf --smoke         # Exercise every case twice without timing
bun run perf --filter '^core/layout/'
bun run perf --json > /tmp/gum-perf.json

Each of these packages also exposes bun run perf from its own directory, with the same options. The suites use Mitata for warmup, sampling, and latency statistics. Inputs are deterministic and maps use bundled atlases. Construction, fresh-pass layout, SVG serialization, full renders, and cache hits have separate cases so their costs can be compared. Fonts are warmed except in explicitly named fresh-provider cases.

See the core, math, maps, and demos workload notes for exact timing boundaries. Run on an idle machine, save JSON reports before and after a change, and compare the same case names on the same hardware and Bun version. JSON timings are in nanoseconds. Record Git revisions with reports and repeat runs to check noise; performance results are separate from correctness tests.

Compare freezing modes with the regular benchmark commands:

GUM_FREEZE=1 bun run perf --json > /tmp/gum-freeze.json
GUM_FREEZE=0 bun run perf --json > /tmp/gum-no-freeze.json
GUM_FREEZE=0 bun run perf:demos

Run modes sequentially and alternate their order across repeats.

For production rendering, NODE_ENV=production disables runtime freezing while retaining input snapshots and validation. GUM_FREEZE=1 or 0 overrides the default before Gum loads. Browser builds use __GUM_FREEZE__; Studio and the MCP viewer configure this automatically. See the immutability policy. bun run test:immutability runs the workspace tests with freezing both enabled and disabled.

For a CPU profile of selected cases:

bun --cpu-prof --cpu-prof-dir=/tmp test/perf.ts --filter '^core/layout/'

About

Gum meta-repo

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages