peternewnham / react-html-parser

Converts HTML strings directly into React components and provide a simple way to modify and replace the content.
https://peternewnham.github.io/react-html-parser
MIT License
781 stars 103 forks source link

SVG viewBox not working well #56

Open hrahimi270 opened 5 years ago

hrahimi270 commented 5 years ago

Hi there. I'm working with SVG and I need to parse my SVG to HTML for React. Now, I realized that viewBox property has an issue. Parsed SVG must have a viewBox but react-html-parser make it viewbox with small b. It makes a mistake to render SVG especially in responsive.

Please fix this. Reagards.

DavidLozzi commented 5 years ago

Ditto. Please fix, related to https://github.com/wrakky/react-html-parser/issues/45

DavidLozzi commented 5 years ago

I got a valid workaround working...

  renameProp = (oldProp, newProp, { [oldProp]: old, ...others }) => ({
    ...others,
    [newProp]: old
  });

  render() {
      ...
      const htmlOutput = ReactHtmlParser(htmlData, { transform: this.transform });
      const props = this.renameProp('viewbox', 'viewBox', htmlOutput[1].props);
      const newOutput = [];
      newOutput.push(null); //unsure if they're all null, but in my example I was seeing null in the first position
      newOutput.push({
        ...htmlOutput[1],
        props
      });

      return (
        <div className="slide-medium">
          {newOutput}
        </div>
      );

This is still an early POC, but thought I'd pass it along

DavidLozzi commented 5 years ago

Unfortunately, this works for viewBox but not a slew of other properties that are incorrect throughout the svg file.... still looking for a solution

cj-clifton commented 5 years ago

Also having trouble with this but with react routers Link component, it is converted to link and so doesn't work.

cj-clifton commented 5 years ago

Try this https://stackoverflow.com/a/43558609/6755649 and make sure you pass the Components that you want rendered correctly (without being converted to lowercase html tags) to JsxParser in the components prop

DavidLozzi commented 5 years ago

I ended up skipping this library altogether, there were too many issues with the SVG, and just setting the content like: dangerouslySetInnerHTML={{ __html: '<svg>...</svg>' }}

george2seven commented 5 years ago

I've used svg-to-jsx library to convert first to jsx and then run it by this one. All of the properties are read correctly except "preserveaspectratio" which is reverted back to lowercase.

Yangjiaxi commented 5 years ago

I came into the same problem when rendering KaTeX math formula, I wrote this to fix.

transform = (node, index) => {
  if (node.type === 'tag' && node.name === 'svg') {
    const child = node.children[0];
    const { width, height, viewbox, preserveaspectratio } = node.attribs;
    return (
      <svg
        key={index}
        width={width}
        height={height}
        viewBox={viewbox}
        preserveAspectRatio={preserveaspectratio}
      >
        {convertNodeToElement(child, index, this.transform)}
      </svg>
    );
  }
}

and

...
const renderedPost = HtmlParser(post, { transform: this.transform })
...
Natedeploys commented 5 years ago

I tried @Yangjiaxi 's fix but i still had some issues, tried this https://www.npmjs.com/package/html-react-parser and it was fixed.

RenatMG commented 4 years ago

parse(svgList[key].toString(), { replace: attribs => { if(attribs.name === 'symbol'){ attribs.attribs.viewBox = attribs.attribs.viewbox delete attribs.attribs.viewbox } } })

jouni commented 4 years ago

The related source code is here: https://github.com/wrakky/react-html-parser/blob/master/src/utils/htmlAttributesToReact.js#L41

Not sure what the correct fix would be. But adding viewbox: 'viewBox' to the map in ReactAttributes.js works.

jouni commented 4 years ago

Note, that other svg features stop working as well, for example:

jerome-diver commented 4 years ago

i think that this lib is using htmlparse2 library and there is an option from htmlparser2 to not render lower case attributes of nodes. So i don't know if this can be used as an option inside this library, but it should...

cr7cr8 commented 3 years ago
{ReactHtmlParser(svgHtmlString, { transform: transformFn })}
function transformFn(node, index) {
  if (node.name === "svg") {

    const { viewbox, ...rest } = node.attribs;

    return (
      <svg   {...rest} viewBox={viewbox}>
        {node.children.map((child, index) => {
          return convertNodeToElement(child, index, transformFn)
        })}
      </svg>
    )
  }
}