Skip to content

angrymouse/svgcmp

Repository files navigation

svgcmp

A JavaScript library and CLI for compiling SVG into compact bytecode and executing that bytecode back into SVG markup.

Goals

  • compile SVG documents into compact bytecode
  • minimize string usage wherever possible
  • encode paths as binary command/value sequences
  • encode colors as binary values instead of CSS strings where possible
  • keep execution simple and deterministic
  • reconstruct full SVG output from bytecode
  • expose both a reusable JS API and a CLI

Current scope

The current v1 scope is frozen in code at src/ast/feature-scope.ts:1-45.

Supported element set

  • svg
  • g
  • defs
  • symbol
  • use
  • path
  • rect
  • circle
  • ellipse
  • line
  • polyline
  • polygon
  • clipPath
  • mask
  • linearGradient
  • radialGradient
  • stop
  • text
  • tspan

Supported attribute/value families

  • geometry
  • paint
  • opacity
  • path data
  • points data
  • transforms
  • gradient references
  • viewBox
  • ids and href-style references
  • raw-string fallback for unsupported static attributes

How it works

The main pipeline is:

  1. Parse SVG into a normalized document tree.
  2. Convert known elements and attributes to numeric codes.
  3. Encode numbers using fixed-point + variable-length integer encoding.
  4. Encode path d values as binary path commands and numeric operands.
  5. Encode paint values as typed binary values where possible.
  6. Store remaining uncommon strings in a compact string table.
  7. Decode bytecode back into the normalized SVG tree.
  8. Serialize the reconstructed tree into SVG markup.

Relevant implementation files:

  • normalized model: src/ast/model.ts:1-110
  • feature scope: src/ast/feature-scope.ts:1-45
  • bytecode constants: src/bytecode/constants.ts:1-148
  • binary primitives: src/bytecode/binary.ts:1-125
  • parser: src/parser/svg.ts:1-379
  • compiler/decoder: src/compiler/codec.ts:1-468
  • serializer: src/serializer/svg.ts:1-125
  • VM API: src/vm/api.ts:1-126
  • CLI: src/cli/bin.ts:1-129

Installation

npm install

Development

Build

npm run build

Test

npm run test

Full verification

npm run check

Project scripts are defined in package.json:20-23.

CLI usage

The CLI binary is exposed as svgcmp via package.json:14-16.

Commands

svgcmp compile <input.svg> <output.bin>
svgcmp render <input.bin> <output.svg>
svgcmp inspect <input.bin>
svgcmp roundtrip <input.svg> <output.svg>
svgcmp stats <input.svg|input.bin>
svgcmp scope

Examples

Compile SVG into bytecode:

node dist/cli/bin.js compile input.svg output.bin

Render bytecode back into SVG:

node dist/cli/bin.js render output.bin restored.svg

Inspect bytecode structure:

node dist/cli/bin.js inspect output.bin

Measure compression and structure:

node dist/cli/bin.js stats input.svg

Print supported scope:

node dist/cli/bin.js scope

CLI command handling is implemented in src/cli/bin.ts:9-129.

JavaScript API

Public exports are re-exported from src/index.ts:1-6.

High-level API

Defined in src/vm/api.ts:20-80.

import {
  compileSvg,
  compileSvgDetailed,
  decodeBytecode,
  executeBytecode,
  inspectBytecode,
  roundtripSvg
} from 'svgcmp';

compileSvg(svgText)

Compiles SVG text into bytecode.

const bytecode = compileSvg(svgText);

compileSvgDetailed(svgText)

Compiles SVG and returns the normalized document plus inspection metadata.

const result = compileSvgDetailed(svgText);
console.log(result.bytecode);
console.log(result.inspection);

decodeBytecode(bytecode)

Decodes bytecode back into the normalized SVG document model.

const document = decodeBytecode(bytecode);

executeBytecode(bytecode, options?)

Executes bytecode into final SVG markup.

const svg = executeBytecode(bytecode, { xmlDeclaration: true });

inspectBytecode(bytecode)

Returns structural metadata such as byte length, string table size, node counts, and path count.

const inspection = inspectBytecode(bytecode);

roundtripSvg(svgText, options?)

Compiles SVG and immediately serializes the reconstructed document back into SVG.

const { bytecode, svg, inspection } = roundtripSvg(svgText, { xmlDeclaration: true });

Bytecode design summary

The current bytecode format is defined in src/bytecode/constants.ts:1-148 and encoded/decoded in src/compiler/codec.ts:35-415.

Header

The stream begins with:

  • magic: SVGM
  • version byte: 1
  • string table
  • encoded root node

Header validation happens in src/compiler/codec.ts:57-91.

String minimization strategy

Known tags and attributes are represented as numeric codes rather than literal strings. Unknown tags, unknown attributes, text content, raw paint values, and certain references are interned into a string table. See:

  • tag and attribute code tables: src/bytecode/constants.ts:38-121
  • string table collection: src/compiler/codec.ts:93-138

Numeric encoding

Numbers are encoded using fixed-point scaling and variable-length integers. See:

  • fixed-point helpers: src/bytecode/binary.ts:119-125
  • numeric value encoding: src/compiler/codec.ts:168-177

Path encoding

Path data is parsed into normalized command tokens and encoded as command opcodes plus numeric operands. See:

  • parser path support: src/parser/svg.ts:34-63, src/parser/svg.ts:315-379
  • path command codes: src/bytecode/constants.ts:123-148
  • path bytecode encoding: src/compiler/codec.ts:182-196

Color encoding

Paint values support:

  • none
  • currentColor
  • inherit
  • RGBA color bytes
  • URL references
  • raw fallback values

See:

  • paint parsing: src/parser/svg.ts:227-274
  • paint bytecode encoding: src/compiler/codec.ts:217-246

Example

Using a source SVG such as test/fixtures/basic.svg:1-13:

node dist/cli/bin.js stats test/fixtures/basic.svg

This project currently demonstrates bytecode compression plus faithful SVG reconstruction for the tested static subset. Tests covering this behavior live in test/svgcmp.test.ts:20-83.

Validation and errors

The project includes explicit validation for malformed input and invalid bytecode, including:

  • rejecting missing/non-SVG roots
  • rejecting unsupported constructs like <script>
  • rejecting invalid path/transform/number encodings
  • rejecting invalid bytecode headers and malformed byte streams

Relevant code:

  • parser validation: src/parser/svg.ts:65-140
  • decode validation: src/compiler/codec.ts:57-91, src/compiler/codec.ts:258-415
  • tests: test/svgcmp.test.ts:77-83

Tests

Current test coverage includes:

  • normalized SVG parsing
  • path tokenization
  • transform tokenization
  • compile/decode roundtrip behavior
  • execution back to SVG markup
  • bytecode inspection reporting
  • scope validation
  • invalid SVG rejection
  • invalid bytecode rejection

See test/svgcmp.test.ts:20-83.

Repository layout

src/
  ast/
  bytecode/
  cli/
  compiler/
  parser/
  serializer/
  vm/
test/
  fixtures/
plans/

License

MIT, as declared in package.json:32.

About

SVG bytecode compiler and renderer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors