Files
2026-05-27 23:29:53 +01:00

3.8 KiB

Tasks: enterprise-compress-svg

Change ID: enterprise-compress-svg Package: @suaveplan/compress-svg Target path: universal/compression/compress-svg Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types


1. Scaffold

  • Create directory universal/compression/compress-svg/ with src/, tests/, src/__benchmarks__/, and all feature subdirectories per the layout in proposal.md.
  • Write package.json at version 0.1.0 with "type": "module", "sideEffects": false, full exports map, deps: @suaveplan/error workspace:^, @suaveplan/types workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability.
  • Write tsconfig.json extending @suaveplan/typescript-config/library.json.
  • Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config.
  • Add lint, typecheck, test, test:coverage, build, docs:check scripts.

2. Types + errors

  • Write src/types/common.ts — SvgNode, SvgPlugin, CompressOptions, CompressResult interfaces.
  • Write src/types/common.md.
  • Write src/error-codes.ts — SvgCompressErrorCode, SVG_COMPRESS_ERROR_METADATA, registerSvgCompressErrorCodes().
  • Write Zod schemas: CompressOptionsSchema, CompressResultSchema.

3. Parser

  • Implement parseSvg(svg: string): SvgNode — push-based SAX-like parser; no DOMParser dependency; handles element, text, comment, cdata, doctype nodes; throws SvgCompressError(SVG_COMPRESS_PARSE_FAILED) on malformed input.
  • Implement serializeSvg(node: SvgNode): string — compact serialiser.
  • Write svg-parser.test.ts (≤500 lines): round-trip for various SVG structures, malformed input throws.
  • Write svg-parser.md.

4. Plugins (one task each — each ≤300 lines)

  • removeComments — remove type: 'comment' nodes. Tests + md.
  • removeMetadata — remove <metadata> elements. Tests + md.
  • removeDoctype — remove type: 'doctype' nodes. Tests + md.
  • collapseGroups — merge single-child <g> elements, hoisting attrs. Tests + md.
  • cleanupAttrs — remove redundant/default attributes (e.g. fill="black" when it's the SVG default). Tests + md.
  • convertPathData — reduce decimal precision in d attribute to floatPrecision places. Tests + md.
  • convertTransforms — collapse and simplify transform attribute matrices. Tests + md.
  • mangleIds — replace id values with short sequential identifiers. Tests + md.

5. Presets

  • Write src/presets/index.ts — PRESET_DEFAULT, PRESET_SAFE, PRESET_AGGRESSIVE.

6. Main compressSvg function

  • Implement compressSvg(svg, options): CompressResult — parse → apply plugin pipeline → multipass loop until stable → serialize → return result with ratio.
  • Wire OTel: span svg.compress, counter svg_compress_total, histogram svg_compress_duration_ms + svg_compress_ratio.
  • Write compress-svg.test.ts (≤500 lines): each preset, multipass, custom plugin, parse error.
  • Write compress-svg.md.

7. Benchmarks

  • Write src/__benchmarks__/compress-svg.bench.ts — 10 kB SVG, 100 kB SVG, 1 MB SVG.

8. Tests

  • Write tests/integration.test.ts — PRESET_DEFAULT on real SVG files (inline fixtures).
  • Write tests/property.test.ts (fast-check) — idempotency, parse↔serialize round-trip, ratio ≤ 1.

9. Docs + verify + publish

  • All co-located .md files (≥200 words each).
  • Write README.md at package root.
  • bunx turbo lint typecheck test --filter=@suaveplan/compress-svg — green.
  • bunx turbo test:coverage --filter=@suaveplan/compress-svg — 100%.
  • bun scripts/publish.ts --package @suaveplan/compress-svg.
  • Archive to openspec/archive/2026-04-24-enterprise-compress-svg/.