A JavaScript library and CLI for compiling SVG into compact bytecode and executing that bytecode back into SVG markup.
- 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
The current v1 scope is frozen in code at src/ast/feature-scope.ts:1-45.
svggdefssymbolusepathrectcircleellipselinepolylinepolygonclipPathmasklinearGradientradialGradientstoptexttspan
- geometry
- paint
- opacity
- path data
- points data
- transforms
- gradient references
viewBox- ids and href-style references
- raw-string fallback for unsupported static attributes
The main pipeline is:
- Parse SVG into a normalized document tree.
- Convert known elements and attributes to numeric codes.
- Encode numbers using fixed-point + variable-length integer encoding.
- Encode path
dvalues as binary path commands and numeric operands. - Encode paint values as typed binary values where possible.
- Store remaining uncommon strings in a compact string table.
- Decode bytecode back into the normalized SVG tree.
- 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
npm installnpm run buildnpm run testnpm run checkProject scripts are defined in package.json:20-23.
The CLI binary is exposed as svgcmp via package.json:14-16.
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 scopeCompile SVG into bytecode:
node dist/cli/bin.js compile input.svg output.binRender bytecode back into SVG:
node dist/cli/bin.js render output.bin restored.svgInspect bytecode structure:
node dist/cli/bin.js inspect output.binMeasure compression and structure:
node dist/cli/bin.js stats input.svgPrint supported scope:
node dist/cli/bin.js scopeCLI command handling is implemented in src/cli/bin.ts:9-129.
Public exports are re-exported from src/index.ts:1-6.
Defined in src/vm/api.ts:20-80.
import {
compileSvg,
compileSvgDetailed,
decodeBytecode,
executeBytecode,
inspectBytecode,
roundtripSvg
} from 'svgcmp';Compiles SVG text into bytecode.
const bytecode = compileSvg(svgText);Compiles SVG and returns the normalized document plus inspection metadata.
const result = compileSvgDetailed(svgText);
console.log(result.bytecode);
console.log(result.inspection);Decodes bytecode back into the normalized SVG document model.
const document = decodeBytecode(bytecode);Executes bytecode into final SVG markup.
const svg = executeBytecode(bytecode, { xmlDeclaration: true });Returns structural metadata such as byte length, string table size, node counts, and path count.
const inspection = inspectBytecode(bytecode);Compiles SVG and immediately serializes the reconstructed document back into SVG.
const { bytecode, svg, inspection } = roundtripSvg(svgText, { xmlDeclaration: true });The current bytecode format is defined in src/bytecode/constants.ts:1-148 and encoded/decoded in src/compiler/codec.ts:35-415.
The stream begins with:
- magic:
SVGM - version byte:
1 - string table
- encoded root node
Header validation happens in src/compiler/codec.ts:57-91.
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
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 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
Paint values support:
nonecurrentColorinherit- 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
Using a source SVG such as test/fixtures/basic.svg:1-13:
node dist/cli/bin.js stats test/fixtures/basic.svgThis 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.
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
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.
src/
ast/
bytecode/
cli/
compiler/
parser/
serializer/
vm/
test/
fixtures/
plans/
MIT, as declared in package.json:32.