svgcmp
v0.1.0
Published
SVG bytecode compiler, VM, CLI, and JavaScript library
Maintainers
Readme
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
svggdefssymbolusepathrectcircleellipselinepolylinepolygonclipPathmasklinearGradientradialGradientstoptexttspan
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:
- 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
Installation
npm installDevelopment
Build
npm run buildTest
npm run testFull verification
npm run checkProject 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 scopeExamples
Compile 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.
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:
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
Example
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.
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.
