Skip to content

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

Open
man8 wants to merge 10 commits into
mainfrom
devin/1753183463-fix-svg-dimensions
Open

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

Conversation

@man8
Copy link
Copy Markdown
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

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed SVG dimension handling where configured width and height parameters were incorrectly ignored.
  • Tests

    • Added comprehensive test suite for SVG attribute processing, including edge cases for dimension handling and malformed SVG inputs.
  • Chores

    • Added dependencies to support improved SVG processing capabilities.

Review Change Stack

- 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
Copy Markdown
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
Comment thread src/processors/image-processor.ts Fixed
Comment thread src/processors/image-processor.ts Fixed
Comment thread src/processors/image-processor.ts Fixed
Comment thread src/processors/image-processor.ts Fixed
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
Copy Markdown

@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.
Copy link
Copy Markdown
Owner Author

man8 commented May 10, 2026

@blocks Resolve the merge conflicts

@blocksorg
Copy link
Copy Markdown

blocksorg Bot commented May 10, 2026

Merge conflicts resolved and pushed. The conflicts were in package.json and package-lock.json — the PR branch had added jsdom and @types/jsdom as new dependencies for SVG parsing, while main had upgraded fs-extra (→ 11.3.4), glob (→ 12.0.0), js-yaml (→ 4.1.1), and @types/node (→ 22.17.0). The resolution keeps all of those changes together.

View on dashboard

@devin-ai-integration
Copy link
Copy Markdown
Contributor

❌ Cannot revive Devin session - the session is too old. Please start a new session instead.

Keeps jsdom and @types/jsdom from PR branch alongside upgraded
fs-extra, glob, js-yaml, and @types/node versions from main.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

Walkthrough

This pull request fixes SVG dimension attribute handling by replacing error-prone regex replacements with jsdom-based DOM manipulation. Configuration merging precedence is updated to prioritise variant.svg settings over top-level variant properties. The SVGO optimiser is configured to preserve viewBox attributes. A comprehensive test suite validates dimension application, attribute detection edge cases, config merging, and error fallback behaviour.

Changes

SVG Dimension Handling Fix

Layer / File(s) Summary
Dependencies
package.json
Runtime dependency jsdom (v^26.1.0) and development dependency @types/jsdom (v^21.1.7) added.
SVG Processing Implementation
src/processors/image-processor.ts
jsdom import added; applySvgAttributes refactored to use DOM-level attribute manipulation with fallback to original SVG on parse failure; parseSvgConfig merge order changed to spread variant.svg first then override with top-level variant properties (including width/height); SVGO preset-default configured with removeViewBox: false to preserve viewBox during optimisation.
Test Suite
src/__tests__/svg-dimensions.test.ts
Comprehensive Jest test suite validating width/height application across scenarios (both provided, width-only, height-only, neither), stroke-width attribute detection edge cases (single and multiple occurrences), preserveAspectRatio propagation, config merging precedence, viewBox preservation and explicit override, and malformed SVG fallback behaviour.
Changelog
CHANGELOG.md
Added Unreleased "Fixed" entry for SVG dimension bug; removed reference token from 0.3.0 entry.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately and concisely summarizes the main change: fixing an SVG dimension bug by applying configured width/height to SVG output, which is directly supported by the changeset including SVGO configuration adjustments, jsdom integration, and comprehensive tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1753183463-fix-svg-dimensions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
package.json (1)

66-66: ⚡ Quick win

Consider upgrading @types/jsdom to align with the runtime library version.

The gap between jsdom (26.1.0) and @types/jsdom (21.1.7) is larger than typical, though this is normal since @types packages are maintained separately by DefinitelyTyped and updated asynchronously. Newer versions exist (@types/jsdom 28.0.1 as of March 2026) that are fully compatible with jsdom 26.1.0 and would provide better alignment. No security advisories apply to jsdom 26.1.0.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 66, Update the `@types/jsdom` devDependency to a version
aligned with the runtime jsdom package (replace the existing "@types/jsdom"
entry with a newer compatible release such as "^28.0.1") so type definitions
match "jsdom": "26.1.0"; after modifying the package.json entry for
"@types/jsdom" run your package manager (npm install or yarn install) to refresh
the lockfile and verify TypeScript compiles cleanly and tests pass (targets: the
package.json dependency "@types/jsdom" and the runtime "jsdom" reference).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@package.json`:
- Line 66: Update the `@types/jsdom` devDependency to a version aligned with the
runtime jsdom package (replace the existing "@types/jsdom" entry with a newer
compatible release such as "^28.0.1") so type definitions match "jsdom":
"26.1.0"; after modifying the package.json entry for "@types/jsdom" run your
package manager (npm install or yarn install) to refresh the lockfile and verify
TypeScript compiles cleanly and tests pass (targets: the package.json dependency
"@types/jsdom" and the runtime "jsdom" reference).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 39d9ea42-c245-4fe7-a022-dc2a0d3b6a17

📥 Commits

Reviewing files that changed from the base of the PR and between e839f07 and d086d6e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • CHANGELOG.md
  • package.json
  • src/__tests__/svg-dimensions.test.ts
  • src/processors/image-processor.ts

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.

2 participants