feat: add svg as a DocumentFormat read into the drawing variant - #614
Merged
Conversation
svg joins the twelve DocumentFormat members as a drawing-variant format:
reading maps the six shape primitives (rect/circle/ellipse/line/polyline/
polygon/path) onto a one-page drawing ContentDocument, writing emits one
shape element per vector. Transforms compose into a single 2x3 affine
classified by frame representability (axis-aligned maps fold into the
frame, a similarity rotation records rotationDeg about the frame's
centre, shears and rotation-composed non-uniform scales narrow to a
path); CSS lengths and the viewBox map resolve into page points at
1 user unit = 1px = 0.75pt exactly.
The adapter family lives in src/svg/: text.ts (byte<->text boundary
rejecting malformed UTF-8), read.ts and write.ts, path.ts (the full
path-data grammar -- M/L/H/V/C/S/Z plus Q/T/A and the relative forms;
S/Q/T convert exactly, A is the one bounded approximation at <=90deg
per kappa cubic after the exact endpoint-to-centre parameterisation),
transform.ts (transform-list parse/compose and classification), units.ts
(CSS length units and the root fallback chain), paint.ts (fill/stroke
presentation attributes and dash styles), and diagnostics.ts (the
SVG_DIAGNOSTIC_CODES scope-limit vocabulary: text, images, use,
gradients, CSS, and opacity are named diagnostics on onSvgDiagnostic,
never silent drops).
The composition engine now routes 111 (source, target) pairs: svg
bridges to its drawing sibling odg (svgToOdg/odgToSvg -- same-variant,
PDF-bypassing, lossless for the six primitives) and reaches PDF through
the drawing layout engine odg already feeds (svgToPdf/pdfToSvg, where
recovered text boxes sit outside the vector-only writer scope and are
reported per shape). Writing svg takes exactly one page:
SvgMultiPageNotSpecifiedError names the page count until { page }
selects one. svgPdfCodec and odgSvgCodec expose the same pairs as
z.codec() forms.
SvgBytesSchema validates well-formed UTF-8 plus a real <svg tag; svg
reads its root <title> as metadata.title and setDocumentMetadata
rejects svg in both directions, since <title> is svg's whole metadata
surface. svg->csv and svg->markdown honestly produce empty output (no
text in the read's scope, no vector vocabulary in the target) -- pinned
in the round-trip matrix, which now selects a page when a multi-page
intermediate meets the one-drawing target.
Code Coverage OverviewLanguages: TypeScript TypeScript / unitThe overall coverage in commit 3efdc70 in the Show a code coverage summary of the most impacted files.
|
Contributor
|
🎉 This PR is included in version 2.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #82
svg joins the twelve
DocumentFormatmembers as a drawing-variant format, mapping the six shape primitives (rect/circle/ellipse/line/polyline/polygon/path) onto a one-page drawingContentDocument— the same mapping odf.js performs for ODF'sdraw:primitives, per the issue's framing.Read/write adapter family (
src/svg/)text.ts— byte↔text boundary, rejecting malformed UTF-8 (same contract as csv/markdown).read.ts— the six primitives onto vectors; transform lists composed as one 2×3 affine; CSS lengths and the viewBox map resolved into page points (1 user unit = 1px = 0.75pt exactly). Root size falls back to the CSS 300×150px default undersvg/default-size-assumed; aspect mismatch reportssvg/preserve-aspect-ratio-stretched.write.ts— one SVG shape element per vector; the writer emits a 1pt-per-unit root so read-back is the identity map and round trips are exact.path.ts— the full path-data grammar:M/L/H/V/C/Zoverlap with the schema segments exactly;S/Q/Tconvert exactly (a quadratic elevates to an exact cubic;Treflects the previous quadratic's own control);Ais the one bounded approximation — exact F.6.5 endpoint-to-centre parameterisation with the F.6.5.6 radii correction, then kappa cubics at ≤90° per segment.transform.ts— transform-list parse/compose plus frame-representability classification: an axis-aligned map (any scale, mirrors included) folds into the frame, a similarity rotation recordsrotationDegabout the frame's centre, a shear or rotation-composed non-uniform scale narrows topath. The affine itself is exact in every case.units.ts,paint.ts— CSS length units/root fallback chain; fill/stroke presentation attributes and dash styles.diagnostics.ts—SVG_DIAGNOSTIC_CODES, the scope-limit vocabulary. Text, images,usereferences, gradients, CSS style blocks, and opacity are named diagnostics ononSvgDiagnostic, never silent drops — the same contract as markdown's construct-mapping vocabulary. A plain vector SVG reads silently.Composition wiring (parallels the csv commit 75180a1)
svgToOdg/odgToSvgbridge svg to its drawing sibling — same-variant direct copy, PDF-bypassing, lossless for the six primitives.svgToPdf/pdfToSvgrun through the existing drawing layout engine with zero new layout code;pdfToSvgreusespdfToOdg's near-1:1 vector recovery, and recovered text boxes sit outside the vector-only writer scope, reported per shape.svgPdfCodec/odgSvgCodecasz.codec()pairs; registry codec writes page 0 by default.SvgBytesSchema(well-formed UTF-8 + a real<svgtag); metadata reads root<title>asmetadata.title,setDocumentMetadatarejects svg in both directions (<title>is svg's whole metadata surface).SvgMultiPageNotSpecifiedErrornames the page count until{ page }selects one (drawing pages are anonymous, where csv's sheets are named).svg→csvandsvg→markdownhonestly produce empty output — no text in the read's scope, no vector vocabulary in the target — pinned in the round-trip matrix, which now re-runs with{ page: 0 }the way the csv sweep re-runs with{ sheet }.Full quality bar green: lint, typecheck, build, 2238 unit tests (76 new across the five svg suites), 3 worker tests, 66 smoke tests.
Generated by Claude Code