feat: support external SVG via Image tag#3281
Conversation
🦋 Changeset detectedLatest commit: 02ab3e9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 8 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
ea49f2a to
ac445c0
Compare
diegomura
left a comment
There was a problem hiding this comment.
@exoego amazing work! I appreciate this a lot.
I left some comments, most nit :) Let me know what you think about them, and feel free to push back on any. I think this is almost ready but I'd like to collect your thoughts on these points first
| "@react-pdf/png-js": "^3.0.0", | ||
| "jay-peg": "^1.1.1" | ||
| "jay-peg": "^1.1.1", | ||
| "linkedom": "^0.18.12" |
There was a problem hiding this comment.
This lib is quite heavy. I generally try not to add more overhead. Is the rationale here that web (where bundle size is more important) won't need it and it's fine for Node?
Do we actually need a DOMParser polyfill here? Won't an xml to json solution be more lightweight + simplify the logic?
There was a problem hiding this comment.
Btw, new math module has a parse svg logic, dependency free: https://github.com/diegomura/react-pdf/blob/master/packages/math/src/parseSvg.ts . We can extract it and reuse it maybe?
There was a problem hiding this comment.
Although that does not have support for style tags and maybe other things a well. Maybe we can reuse your solution here there. I'd like to avoid duplicates
There was a problem hiding this comment.
math's parseSvg seemingly does not support <!CDATA[ section, comment, single-quote attributes or maybe more.
So, added small parser de20194
There was a problem hiding this comment.
Thanks. I'll extract and reuse that parser for math and other modules that require going from svg to react-pdf primitives
| // Use BROWSER constant to ensure this code is dead-code eliminated in browser build | ||
| if (!BROWSER) { | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const linkedom = require('linkedom'); |
There was a problem hiding this comment.
I think it should be fine to just use import syntax. Rollup should be clever enough to strip it from the browser build.
There was a problem hiding this comment.
This was fixed by replacing linkedom with own parser.
| key?: string; | ||
| } | ||
|
|
||
| export type AnyImage = Image | SvgImage; |
There was a problem hiding this comment.
Lets rename
| export type AnyImage = Image | SvgImage; | |
| export type Image = RasterImage | SvgImage; |
There was a problem hiding this comment.
Nit. Maybe just have all this logic inside the svg.ts file and avoid having the svg dir. I'd like to keep the src file structure flat as it's a simple package. Maybe you can create a dom-parser.ts file with the polyfill
| const child = instance.children[i]; | ||
|
|
||
| if (isImage(child)) { | ||
| if (isImage(child) && isRasterImage(child)) { |
There was a problem hiding this comment.
Why can't we inline svgs in text? Just not built?
There was a problem hiding this comment.
Unfortunately, inline SVG images in <Text> are not currently supported.
The resolveSvgImages step runs before resolveTextLayout (right-to-left composition), converting SVG Image nodes into SvgNodes.
By the time getAttributedString processes Text children, SVG images are no longer Image nodes.
Even if caught earlier, PDFKit's inline attachment API requires a raster image buffer (Buffer), while SVG image data is a string of vector drawing instructions.
| * allowing them to be processed by the existing SVG rendering pipeline. | ||
| */ | ||
| function resolveSvgImages(node: SafeNode): SafeNode { | ||
| if (isImage(node) && isSvgImage(node.image)) { |
There was a problem hiding this comment.
NIt. Maybe just have all checks in isSvgImage. there's no case where isSvgImage should be true but isImage false
There was a problem hiding this comment.
Thinking out loud: I wonder if we shuold not include this logic on resolveAssets or resolveSVG step... to me it's kind of in the middle. I don't mind having it as a separate step either if you still prefer it. I just don't wanna end having a pipeline of too many steps (in the future)
There was a problem hiding this comment.
Merged into resolveSVG 02ab3e9
The conversion from SVG Image to SvgNode is naturally part of SVG resolution.
It runs right before SVG processing, so keeping them in one step avoids an extra pipeline stage.
resolveAssets is async and focused on fetching images, fonts, etc.
But SVG image conversion is a synchronous tree transformation.
Also, resolveAssets runs twice in the pipeline, so merging into it would run the conversion twice unnecessarily.
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
@react-pdf/renderer@4.4.1+ depends on @react-pdf/layout@^4.5.1 which allows installation of @react-pdf/layout@4.6.0, which depends on @react-pdf/image@3.1.0, which depends on @react-pdf/svg@^1.1.0. @react-pdf/svg does not exist in npm registry (upstream publish error). Solution: Override @react-pdf/image to 3.0.4 which doesn't depend on svg. Dependency chain before fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.1.0 → @react-pdf/svg ❌ After fix: @react-pdf/renderer@4.4.1 → @react-pdf/layout@4.6.0 → @react-pdf/image@3.0.4 (override) ✅ Upstream PR: diegomura/react-pdf#3281
Closes #1622
Closes #1250
Flow
<SVG>tag.Other changes
During tests, I found some features are not working properly, so fixed those.
E.g.
rxin rect, stop in gradient.Attributions to SVG files
I've borrowed a complex SVG which is CC0 license (MIT license compatible) from this web page https://lukaszadam.com/illustrations
<style>tag in the file are converted to inline style since<SVG>seems not to support<style>yet.Other SVG files are manually crafted.
Screenshot of example :
