Closed AlbinoGeek closed 1 week ago
or a literal string with \<svg>... in it.
Please can you provide an example string that represents a valid SVG that fails in this manner.
<style data-emotion="css 1umw9bq-MuiSvgIcon-root">.css-1umw9bq-MuiSvgIcon-root{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:1em;height:1em;display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;-webkit-transition:fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;fill:currentColor;font-size:1.5rem;}</style><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1umw9bq-MuiSvgIcon-root" focusable="false" aria-hidden="true" viewBox="0 0 24 24" data-testid="FacebookIcon"><path d="M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2m13 2h-2.5A3.5 3.5 0 0 0 12 8.5V11h-2v3h2v7h3v-7h3v-3h-3V9a1 1 0 0 1 1-1h2V5z"></path></svg>
I have also tried stripping the <style>
tag, although this is counter-productive for my use-case. Also, last I checked, SVGs supported both classes and inline styles. It's entirely fair if sharp
doesn't, but I would expect a slightly more useful error message if that's the case.
Thanks, this sample string is not valid XML so that's why you're seeing an "XML parse error" message. As you suggest you'll need to (re)move the <style>
element as valid SVG must be valid XML, and valid XML must have a single root node.
Mmmm.... I'm having trouble understanding how both Resend.js
and NextJS itself manage to display these SVGs, using the sharp
library no less, while retaining the style. I suppose they have some magic surrounding forcing the styles into the SVG's individual path/rect/etc, if I had to guess?
How would you recommend I approach this issue then, considering that removing the styling destroys the images (in the case of these brand images, they do not render correctly without the styles.) My only other option appears to be an entire headless browser just to render an SVG, which seems painful and redundant.
The following absolute madhouse has gotten me close, but not quite:
Edit, Spaghetti rewrote to be.... readable?
const convertSvgToImage = async (
MuiSvgIcon: typeof Facebook
): Promise<Buffer> => {
const html = ReactDOMServer.renderToString(<MuiSvgIcon />)
const css = RegExp(/MuiSvgIcon-root{(.*)}/).exec(html)?.[1] ?? ''
return await sharp(Buffer.from(html
.replace(/<style data-emotion[^>]*>.*<\/style>/, '')
.replace(/class="[^"]*"/, `style="${css}"`)
)).resize(48, 48).png().toBuffer()
}
Well I suppose if anyone find this later...
The above snippet will get you "close enough", maybe?
The colours are wrong, the images are fuzzy, but hey, it "works"?
Closing as this is apparently just not a feature of sharp
, which, fair.
Possible bug
Is this a possible bug in a feature of sharp, unrelated to installation?
npm install sharp
completes without error.node -e "require('sharp')"
completes without error.Are you using the latest version of sharp?
sharp
as reported bynpm view sharp dist-tags.latest
.What is the output of running
npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp
?Does this problem relate to file caching?
sharp.cache(false)
does not fix this problem.Does this problem relate to images appearing to have been rotated by 90 degrees?
rotate()
orkeepExif()
does not fix this problem.What are the steps to reproduce?
1) Use
ReactDOMServer.renderToString
,ReactDOM.render
,ReactDOMServer.renderToStaticMarkup
, or a literal string with<svg>...
in it. 2) Attempt to convert the SVG to PNG using various sample codes.I've also tried the simpler
Same error.
You may ask, "why not
composite
?" Well, see my previous issue.What is the expected behaviour?
PNG output
Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem
"Without dependencies" is hardly possible in the NPM ecosystem, come on now. However, this can be reproduced in the minimal
create-react-app
as well as thecreate-next-app
(this is a NextJS application.)Code directly from my app:
Please provide sample image(s) that help explain this problem
Any image from MaterialUI Icons, literally any of them (yes, I looped through the entire namespace to test.) What I want working atm however are
<Facebook />
,<Instagram />
etc brand logos.