# @suaveplan/compress-svg - SVG optimisation and minification: whitespace removal, redundant attribute stripping, path data precision reduction, element collapsing, ID mangling, and SVGO-compatible plugin pipeline ## Summary SVG optimisation and minification for TypeScript. Pure TypeScript — no DOMParser, no external SVG library. Runs in Bun, Node.js, browsers, and edge runtimes. ## Documentation tree - [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_ - [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_ - [svg](./src/parser/svg/svg.md) — _(no submodules)_ - [svg](./src/parser/svg/svg.md) — _(no submodules)_ - [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_ - [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_ - [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_ - [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_ - [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_ - [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_ - [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_ - [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_ - [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_ - [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_ - [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_ - [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_ - [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_ - [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_ - [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_ - [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_ - [types](./src/types/common.md) — _(no submodules)_ - [common](./src/types/common.md) — _(no submodules)_ - [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [compress-svg](./src/core/compress-svg/compress-svg.md) — _(no submodules)_- [svg](./src/parser/svg/svg.md) — _(no submodules)_ - [svg](./src/parser/svg/svg.md) — _(no submodules)_- [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_ - [cleanup-attrs](./src/plugins/cleanup-attrs/cleanup-attrs.md) — _(no submodules)_- [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_ - [collapse-groups](./src/plugins/collapse-groups/collapse-groups.md) — _(no submodules)_- [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_ - [convert-path-data](./src/plugins/convert-path-data/convert-path-data.md) — _(no submodules)_- [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_ - [convert-transforms](./src/plugins/convert-transforms/convert-transforms.md) — _(no submodules)_- [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_ - [mangle-ids](./src/plugins/mangle-ids/mangle-ids.md) — _(no submodules)_- [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_ - [remove-comments](./src/plugins/remove-comments/remove-comments.md) — _(no submodules)_- [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_ - [remove-doctype](./src/plugins/remove-doctype/remove-doctype.md) — _(no submodules)_- [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_ - [remove-metadata](./src/plugins/remove-metadata/remove-metadata.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_ - [common](./src/types/common.md) — _(no submodules)_ ## Features - **`compressSvg`** — parse → plugin pipeline → multipass loop → serialize → CompressResult with size metrics - **`parseSvg` / `serializeSvg`** — standalone push-parser and compact serializer - **8 built-in plugins** — removeComments, removeMetadata, removeDoctype, collapseGroups, cleanupAttrs, convertPathData, convertTransforms, mangleIds - **3 presets** — PRESET_DEFAULT, PRESET_SAFE, PRESET_AGGRESSIVE - **Plugin API** — single `apply(node, options): SvgNode | null` contract; compose any plugins - **OTel instrumentation** — counter + duration + ratio histograms via `@opentelemetry/api` - **Property-based tests** — idempotency, parse↔serialize round-trip, ratio invariants ## Installation ```bash bun add @suaveplan/compress-svg ``` ## Quick Start ```typescript import { compressSvg } from '@suaveplan/compress-svg'; const result = compressSvg(svgString); console.log(result.data); // optimised SVG console.log(result.ratio); // e.g. 0.78 console.log(result.passCount); // multipass iterations used ``` ## Presets ```typescript import { compressSvg, PRESET_DEFAULT, PRESET_SAFE, PRESET_AGGRESSIVE } from '@suaveplan/compress-svg'; // Default: removeComments + metadata + doctype + collapseGroups + cleanupAttrs + convertPathData compressSvg(svg, { plugins: PRESET_DEFAULT }); // Safe: no ID mangling, no transform conversion compressSvg(svg, { plugins: PRESET_SAFE }); // Aggressive: all plugins including mangleIds and convertTransforms compressSvg(svg, { plugins: PRESET_AGGRESSIVE }); ``` ## Custom Plugin ```typescript import type { SvgPlugin } from '@suaveplan/compress-svg'; const removeTitle: SvgPlugin = { name: 'removeTitle', apply(node) { return node.type === 'element' && node.name === 'title' ? null : node; }, }; compressSvg(svg, { plugins: [removeTitle, ...PRESET_DEFAULT] }); ``` ## Options ```typescript compressSvg(svg, { plugins: PRESET_DEFAULT, // override the full pipeline floatPrecision: 2, // decimal places for path coords (default: 3) transformPrecision: 3, // decimal places for transforms (default: 5) multipass: true, // re-run until output is stable (default: true) }); ``` ## Modules | Import path | Contents | |---|---| | `@suaveplan/compress-svg` | All exports | | `@suaveplan/compress-svg/core/compress-svg` | `compressSvg` | | `@suaveplan/compress-svg/parser/svg-parser` | `parseSvg`, `serializeSvg` | | `@suaveplan/compress-svg/plugins/remove-comments` | `removeComments` | | `@suaveplan/compress-svg/plugins/remove-metadata` | `removeMetadata` | | `@suaveplan/compress-svg/plugins/remove-doctype` | `removeDoctype` | | `@suaveplan/compress-svg/plugins/collapse-groups` | `collapseGroups` | | `@suaveplan/compress-svg/plugins/cleanup-attrs` | `cleanupAttrs` | | `@suaveplan/compress-svg/plugins/convert-path-data` | `convertPathData` | | `@suaveplan/compress-svg/plugins/convert-transforms` | `convertTransforms` | | `@suaveplan/compress-svg/plugins/mangle-ids` | `mangleIds`, `createMangleIds` | | `@suaveplan/compress-svg/presets` | `PRESET_DEFAULT`, `PRESET_SAFE`, `PRESET_AGGRESSIVE` |