interweave
interweave copied to clipboard
SVG tags are not rendering
https://codesandbox.io/s/target-first-child-css-styled-components-forked-7p64n0?file=/src/index.js
I am getting SVG string from the backend I want to render it in my React app...But I am not able to achieve it.. see the code link at the top
@rahujoshi Interweave was only designed for HTML as it parses it with the DOM, SVG wont work.
I'm not sure why you would run SVGs through interweave anyways.
@rahujoshi I have this issue too. SVG attributes use camel case like viewBox but Interweave converts all attributes to lowercase. I have inline SVGs as part of a HTML string hence needing to use Interweave. My only solution was to use dangerouslySetInnerHTML instead.
@milesj inline SVGs are valid in HTML (e.g. https://www.w3schools.com/html/html5_svg.asp) so the DOM should be able to parse it fine. If you have SVGs as part of a HTML string you would expect them to be rendered I would have thought. With allowElements and allowAttributes set to true, it's just the camelCase attributes being lowercased that stop it from rendering properly.
It depends on whether createHTMLDocument supports parsing SVG correctly or not, which is what Interweave uses under the hood.
I can't recall off the top of my head.
Thanks for your response. I've just had a play around in code sandbox. You need to use createElementNS to create an element in the SVG namespace, using createElement didn't work. So doc.createElementNS("http://www.w3.org/2000/svg", "svg") works.
I understand that this probably makes this too much of a hassle for you as you'd have to identify all of the SVG elements and process them differently.
To solve my issue I've written the following transform function. I know it's not particularly safe, but I trust the source HTML, so it works for me.
const transform = (node: HTMLElement, children: Node[]): React.ReactNode => {
const namespaces = [
'http://www.w3.org/1998/Math/MathML',
'http://www.w3.org/2000/svg'
]
if(node.namespaceURI && namespaces.includes(node.namespaceURI)){
const attributes:{[att:string]: string|null} = {}
node.getAttributeNames().forEach(attName => {
attributes[attName] = node.getAttribute(attName)
})
return React.createElement(node.tagName, attributes, children)
}
return undefined
}
Awesome transformer. This may be a quick win to support it in core in the future.
@rahujoshi Interweave was only designed for HTML as it parses it with the DOM, SVG wont work.
I'm not sure why you would run SVGs through interweave anyways.
I'm using Interweave to parse an HTML doc received in an AJAX response to an API call. Some of the HTML docs contain SVG elements. I don't think it's unreasonable to assume that could be the case. IW is an awesome utility and would love to see support for SVG elements added. FTM I'm using @dantabel's excellent suggestion.