Skip to content

Fix SVG dimension bug - apply configured width/height to SVG output#25

Open
man8 wants to merge 9 commits intomainfrom
devin/1753183463-fix-svg-dimensions
Open

Fix SVG dimension bug - apply configured width/height to SVG output#25
man8 wants to merge 9 commits intomainfrom
devin/1753183463-fix-svg-dimensions

Conversation

@man8
Copy link
Owner

@man8 man8 commented Jul 22, 2025

Fix SVG viewBox preservation for proper content scaling

Summary

This PR fixes a critical bug where SVGs were only getting container dimension changes (width/height attributes) but not actual content scaling. The issue occurred because SVGO optimization was removing viewBox attributes before they could be preserved, causing content to remain at original coordinates while only container dimensions changed.

Root cause: SVGO's preset-default configuration includes removeViewBox: true, which stripped viewBox attributes during optimization, preventing proper content scaling.

Solution:

  1. Configure SVGO to preserve viewBox attributes by disabling removeViewBox in preset overrides
  2. Enhance applySvgAttributes method to preserve original viewBox when applying new dimensions
  3. Add comprehensive test coverage for viewBox preservation scenarios

Review & Testing Checklist for Human

  • Test end-to-end with real SVG files - Verify that SVG content actually scales proportionally when dimensions change, not just container margins
  • Check file size impact - Compare output file sizes before/after to ensure SVGO config change doesn't significantly bloat files
  • Test backwards compatibility - Verify existing SVG processing workflows still work correctly with the viewBox preservation changes
  • Test edge cases - Try SVGs without original viewBox, malformed SVGs, and complex SVG structures to ensure robust handling

Recommended test plan: Use the test SVG in /tmp/svg-test/ and generate variants with different dimensions to visually confirm content scales rather than just adding margins.


Diagram

%%{ init : { "theme" : "default" }}%%
graph TB
    CLI["cli/index.js"]
    IP["src/processors/<br/>image-processor.ts"]:::major-edit
    Tests["src/__tests__/<br/>svg-dimensions.test.ts"]:::minor-edit
    SVGO["SVGO Optimization"]
    Output["SVG Output Files"]
    
    CLI --> IP
    IP --> SVGO
    SVGO --> Output
    Tests --> IP
    
    IP -- "processSvgOutput:<br/>Configure SVGO to preserve viewBox" --> SVGO
    IP -- "applySvgAttributes:<br/>Preserve original viewBox" --> Output
    
    subgraph Legend
        L1[Major Edit]:::major-edit
        L2[Minor Edit]:::minor-edit  
        L3[Context/No Edit]:::context
    end

classDef major-edit fill:#90EE90
classDef minor-edit fill:#ADD8E6
classDef context fill:#FFFFFF
Loading

Notes

  • Performance trade-off: Disabling removeViewBox in SVGO may result in slightly larger file sizes, but this is necessary for proper scaling functionality
  • DOM parsing dependency: The fix relies on jsdom for SVG manipulation - any jsdom parsing failures will fall back to original content
  • All CI checks passing: 13/13 checks across multiple platforms (Ubuntu, macOS, Windows) and Node.js versions (18, 20, 22)

Session requested by: Louis Mandelstam (@man8)
Devin session: https://app.devin.ai/sessions/af8a710843d14c529ba7cbb4f4981b57

- Modified parseSvgConfig to include variant width/height in SVG configuration
- Updated applySvgAttributes to apply dimensions to SVG root element
- Added comprehensive test suite for SVG dimension handling
- Fixes issue where SVG assets ignored explicit dimension configuration

The fix ensures SVG assets respect the same dimension configuration as PNG assets by:
- Including variant width/height in the SVG configuration object
- Applying these dimensions as standard SVG width/height attributes
- Preserving existing functionality like preserveAspectRatio and viewBox
- Following existing code patterns for SVG attribute manipulation
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

cursor[bot]

This comment was marked as outdated.

- Fix Bug 1: Replace flawed includes('width=') logic with robust regex patterns that target SVG root element specifically, preventing false matches with stroke-width attributes
- Fix Bug 2: Correct dimension prioritisation in parseSvgConfig() to ensure variant-level width/height takes precedence over variant.svg properties
- Add comprehensive tests for both bugs including stroke-width false positive scenarios and dimension prioritisation validation
- All 8 SVG dimension tests passing, linting clean
man8 added 4 commits July 22, 2025 12:42
…bute handling

- Replace fragile regex-based attribute manipulation with DOM-based approach
- Eliminate false positives from stroke-width matching width= attributes
- Add comprehensive error handling with fallback to original content
- Add test coverage for malformed SVG parsing scenarios
- Maintain existing svgo optimization pipeline integration
- All 82 tests passing with improved robustness
- jsdom is used in production code (applySvgAttributes method)
- prevents build failures in production environments
- maintains @types/jsdom in devDependencies for TypeScript compilation
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: SVG Parsing Overwrites Dimensions Incorrectly

The parseSvgConfig method incorrectly overrides width and height values from variant.svg with undefined when variant.width or variant.height are not explicitly set. This occurs because width: variant.width and height: variant.height are unconditionally assigned after spreading variant.svg, preventing svg-level dimensions from being used as fallbacks. This behavior is inconsistent with how other properties handle fallbacks.

src/processors/image-processor.ts#L560-L563

colorTransforms: variant.colorTransforms || variant.svg?.colorTransforms,
width: variant.width,
height: variant.height
};

Fix in CursorFix in Web


Was this report helpful? Give feedback by reacting with 👍 or 👎

man8 added 3 commits July 22, 2025 13:25
- Preserve original viewBox when applying new dimensions to ensure content scales properly
- Configure SVGO to not remove viewBox attributes during optimization
- Add comprehensive test cases for viewBox preservation and explicit viewBox handling
- Fixes issue where SVGs only changed container size without scaling content

The core issue was that SVGO's preset-default configuration was removing viewBox
attributes before the applySvgAttributes method could preserve them. This caused
SVGs to only change their container dimensions (width/height) without scaling
the actual content, resulting in margin adjustments rather than proper scaling.
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