@sepoina/purgesvg
v0.1.6
Published
Batch SVG normalizer: bakes every transform into geometry and refits the drawing into a fixed [-999,-999 .. 999,999] viewBox.
Maintainers
Readme
purgesvg
Normalises SVGs into one canonical coordinate space: every transform is baked into the geometry,
every drawable becomes a transform-free <path> with absolute coordinates, and the drawing is
refitted into a fixed viewBox="-999 -999 1998 1998".
The output is visually identical to the input — only re-expressed. That is the one hard
invariant. (The single exception is --snellify, which is opt-in, off by default, and says so.)
Useful when SVGs arrive from Figma, Illustrator, Inkscape and hand-editing, and you need them to be the same shape of file before anything downstream can treat them alike.
npm install @sepoina/purgesvgNode ≥ 22. Works as a command line tool, as a library, and — for a page with no build step — as a drop-in ES module.
Command line
The installed command is purgesvg. Without installing anything, run it through the scoped name
— plain npx purgesvg would fetch an unrelated package that has held that name since 2018:
npx @sepoina/purgesvg icons/ -d out/ # a whole folder
npx @sepoina/purgesvg logo.svg --stdout # one file, to stdout
npx @sepoina/purgesvg icons/ -t muiIcon -d out/ # Material UI icons, plus a .jsx eachpurgesvg --help prints the full option list. A few worth knowing:
| | |
| --- | --- |
| -t, --template <name> | a named preset. muiIcon fits the drawing to Material's 8.33% border, strips paint so the theme colours it, and writes an <SvgIcon> component beside the SVG |
| --weight <n> | digits of the target box: 2 → ±99, 3 → ±999 (default), 4 → ±9999 |
| --decimal <n> | decimals in the output (default 0, i.e. integer coordinates) |
| --rescaleFitBorder <p...> | guarantee free space around the drawing, in CSS order |
| --nostyle | drop every paint declaration, keeping fill-rule — it is geometry |
| --snellify <n> | refit curves and drop segments. Lossy, and the number is a fitting tolerance, not a bound on how far the outline may move |
Exit codes: 0 ok, 1 a file failed (or warned under --strict), 2 usage error.
Library
One call, one SVG. It is asynchronous only because --snellify loads its curve fitter on demand;
the callbacks hide that entirely.
import { purgeSvg } from '@sepoina/purgesvg';
purgeSvg({
jsonData: {
source: '<svg xmlns="http://www.w3.org/2000/svg" …>…</svg>',
name: 'alarm', // names the .jsx component
options: { template: 'muiIcon', decimal: 2 },
},
onComplete: ({ svg, jsx, warnings, stats }) => { … },
onError: ({ code, message }) => { … },
});It also returns a promise resolving to the same object, so the callbacks are optional:
const { ok, svg, warnings } = await purgeSvg({ jsonData });The promise never rejects on a bad SVG or a rejected option — those are results, with ok: false
and a one-line message. And warnings are not failures: an SVG that warns is still valid output.
QUERY-FORMAT.md documents every option, with its type and default. It is generated from the same table the CLI help comes from, so the two cannot disagree.
That table is exported too, so a settings UI can be built from it rather than from a hand-copied list that goes stale at the next release:
import { flagsStructure } from '@sepoina/purgesvg';
// [{ key: 'decimal', type: 'number', default: 0, group: 'Geometry', description: '…' }, …]Read description rather than help: help documents the command line flag, which for options
spelled negatively there (--noround, --no-optimize) states the opposite of what the key means.
Also exported: transform(source, options), the synchronous pipeline underneath — reach for it when
you already hold the SVG as a string and want it back as one. If you use a snellify tolerance with
it, await ensurePaper() first; purgeSvg does that for you.
In a page with no build step
dist/browser/purgesvg.js (from npm run build) is self-contained — one <script type="module">,
no npm, nothing from a CDN. Prefer the package above whenever you do have a bundler: the standalone
build inlines its dependencies, so an app that already uses svgo would end up with two copies.
What it will tell you
Nothing is silently mangled. The pipeline reports what it could not express in the canonical space —
<text> that had to keep its matrix, animation that may now disagree with the baked geometry, a
non-square source letterboxed into a square box, a drawing pushing into a reserved border — as
warning codes on warnings, or under --verbose on the command line.
Contributing
CODING.md is the source of truth: the pipeline pass by pass, the semantics table, and the reasoning behind each locked decision. Read it before changing anything.
npm test # the suite; does not build
npm run test:all # build both distributions, then test everythingLicense
MIT © Giancarlo Ghigi
