Skip to content

Resolve percent <svg> dimensions against --size and improve error#126

Open
rursache wants to merge 1 commit intoswhitty:mainfrom
rursache:feat/svg-percent-dims
Open

Resolve percent <svg> dimensions against --size and improve error#126
rursache wants to merge 1 commit intoswhitty:mainfrom
rursache:feat/svg-percent-dims

Conversation

@rursache
Copy link
Copy Markdown
Contributor

Summary

Issue #42 covers SVG canvas units. PR #45 added support for absolute units on the root <svg> width/height. Two cases still failed at parse time with a generic missingAttribute error:

  1. Percent values, eg width=\"100%\", when no viewBox is present
  2. Missing width/height entirely when no viewBox is present

Per the SVG spec these need a viewport to resolve against. SwiftDraw had no way for callers to supply one, so this PR adds an opt-in viewport and threads --size through the CLI so the existing flag becomes the user-visible answer.

What changes

  • XMLParser gains an XMLParser.Viewport struct and a defaultViewport property
  • DOM.SVG.parse(fileURL:options:defaultViewport:) and parse(data:options:defaultViewport:) accept the viewport
  • The CLI passes config.size as the viewport when loading SVGs for png/jpeg/pdf output, so --size 800x600 responsive.svg resolves percent dimensions and missing dimensions against the requested canvas
  • Falls back to viewBox dimensions when width/height are missing but a viewBox is declared (already common browser behavior)
  • New XMLParser.Error.unresolvableDimension(reason:) replaces missingAttribute for these cases. The reason string explains exactly what is missing and how to fix it, eg:

    <svg> width=\"100%\" cannot be resolved without a viewBox or an explicit viewport (--size on the command line)

  • Public SVG initializers and existing API surface are unchanged. Callers that do not opt in to a viewport now get the clearer error in place of the previous one
  • README documents the new resolution behavior under the command line tool section

Examples

Before:

$ swiftdraw responsive.svg --format png --size 800x600
# fails: missingAttribute(\"width\")

After:

$ swiftdraw responsive.svg --format png --size 800x600
# resolves width=\"100%\" against 800x600 and renders

SVGs that omit dimensions but provide a viewBox now also work without --size:

<svg viewBox=\"0 0 150 75\">...</svg>

Test plan

  • New unit tests in DOM/Tests/Parser.SVGTests.swift covering: percent + viewport, percent without viewport (throws), missing dims + viewport, missing dims + viewBox, missing all (throws unresolvableDimension), mixed percent/explicit
  • Existing parseSVGMissingHeightInvalidNode / parseSVGMissingWidthInvalidNode still throw (unchanged behavior when no viewport is provided)
  • Full suite: 207 tests pass (swift test)
  • swift build clean

Relates to #42

The root <svg> width/height attributes were rejected with a generic
missingAttribute error whenever they used percent values
(width="100%") or were omitted entirely without a viewBox. Per the
SVG spec these need a viewport to resolve against, but SwiftDraw had
no way for callers to provide one.

This adds an opt-in viewport that XMLParser can resolve against:

- XMLParser.Viewport: a width/height pair callers can set via the
  new XMLParser.defaultViewport property or threaded through
  DOM.SVG.parse(fileURL:options:defaultViewport:) /
  parse(data:options:defaultViewport:).
- The CLI now passes --size as the default viewport when loading
  SVGs for png/jpeg/pdf output, so percent dimensions and missing
  dimensions resolve against the requested canvas.
- A new XMLParser.Error.unresolvableDimension(reason:) replaces the
  generic missingAttribute for these cases. The reason string
  explains exactly what is missing (percent + no viewport, missing
  attribute + no viewBox/viewport) and how to provide it.

Public SVG initializers and existing API surface are unchanged.
Callers that do not opt in to a viewport now get the clearer error
message in place of the previous one.

Relates to swhitty#42
@rursache rursache force-pushed the feat/svg-percent-dims branch from 29b59bf to 1e8f3a6 Compare April 22, 2026 18:41
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

❌ Patch coverage is 84.21053% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.76%. Comparing base (8f03233) to head (1e8f3a6).

Files with missing lines Patch % Lines
SwiftDraw/Sources/SVG.swift 0.00% 12 Missing ⚠️
DOM/Sources/Parser.XML.SVG.swift 92.30% 3 Missing ⚠️
DOM/Tests/Parser.SVGTests.swift 96.15% 2 Missing ⚠️
...Draw/Sources/CommandLine/CommandLine+Process.swift 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #126      +/-   ##
==========================================
- Coverage   89.80%   89.76%   -0.05%     
==========================================
  Files         159      159              
  Lines       15868    15961      +93     
==========================================
+ Hits        14251    14327      +76     
- Misses       1617     1634      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant