Search code examples
reactjssvgrollup

Rollup: SVG characters unintentionally escaped


I have a react project built using rollup and I'm having some issues with SVG. In this project I'm including another external react library and in this library I have some SVGs defined like this:

import * as React from 'react'

function SvgCloseIcon(props) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="#fff" xmlns="http://www.w3.org/2000/svg" {...props}>
      <path fillRule="evenodd" clipRule="evenodd" d="M6.7072 5.29289C6.31668 4.90237 5.68351 4.90237 5.29299 5.29289C4.90246 5.68342 4.90246 6.31658 5.29299 6.70711L10.5859 12L5.29289 17.293C4.90237 17.6835 4.90237 18.3167 5.29289 18.7072C5.68342 19.0977 6.31658 19.0977 6.70711 18.7072L12.0001 13.4142L17.293 18.7071C17.6835 19.0976 18.3167 19.0976 18.7072 18.7071C19.0977 18.3166 19.0977 17.6834 18.7072 17.2929L13.4143 12L18.7071 6.7072C19.0976 6.31668 19.0976 5.68351 18.7071 5.29299C18.3166 4.90246 17.6834 4.90246 17.2929 5.29299L12.0001 10.5858L6.7072 5.29289Z" fill="current" />
    </svg>
  )
}

export default SvgCloseIcon

which after compilation with rollup and @rollup/plugin-image are transformed like this:

data:image/svg+xml,%3csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.707 5.293a1 1 0 0 0-1.414 1.414L10.586 12l-5.293 5.293a1 1 0 1 0 1.414 1.414L12 13.414l5.293 5.293a1 1 0 0 0 1.414-1.414L13.414 12l5.293-5.293a1 1 0 0 0-1.414-1.414L12 10.586 6.707 5.293Z' fill='current'/%3e%3c/svg%3e.

as you can see the characters < and > are escaped and when I try to run my code it fails at runtime with the following exception:

Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('data:image/svg+xml,%3csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.707 5.293a1 1 0 0 0-1.414 1.414L10.586 12l-5.293 5.293a1 1 0 1 0 1.414 1.414L12 13.414l5.293 5.293a1 1 0 0 0 1.414-1.414L13.414 12l5.293-5.293a1 1 0 0 0-1.414-1.414L12 10.586 6.707 5.293Z' fill='current'/%3e%3c/svg%3e') is not a valid name.

for completeness this is my rollup.config.js:

import terser from '@rollup/plugin-terser'
import typescript from '@rollup/plugin-typescript'
import nodePolyfills from 'rollup-plugin-polyfill-node'
import json from '@rollup/plugin-json'
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import image from '@rollup/plugin-image'
import alias from '@rollup/plugin-alias'
import postcss from 'rollup-plugin-postcss'

export default {
  input: 'src/index.tsx',
  output: [
    {
      file: 'dist/bundle.es.js',
      format: 'es',
      exports: 'named',
      sourcemap: true,
    },
    {
      file: 'dist/bundle.js',
      format: 'cjs',
    },
    {
      file: 'dist/bundle.min.js',
      format: 'iife',
      name: 'version',
      plugins: [terser()],
    },
  ],
  plugins: [
    replace({
      preventAssignment: true,
      values: {
        'process.env.NODE_ENV': JSON.stringify('production'),
      },
    }),
    alias({
      entries: [
        { find: '@', replacement: 'src/' },
      ],
    }),
    json(),
    nodePolyfills(),
    postcss({
      modules: true,
      use: [
        [
          'sass', {
            includePaths: [
              './node_modules',
            ],
          },
        ],
      ],
    }),
    resolve(
      {
        jsnext: true,
        preferBuiltins: true,
        browser: true,
      },
    ),
    typescript(),
    commonjs(),
    image(),
  ],
}

How can I handle my problem in this case, considering that I don't have the ability to change the SVG definition of the external library I'm trying to use?


Solution

  • I didn't find a real solution but a kind of workaround that can help other users. The problem was that the @rollup/plugin-image plugin was compiling all the images and SVGs including my node_modules but the library that exposes the SVGs I needed had alread compiled the SVGs nicely. So I resolved telling to plugin-image to just compile a folder inside my project where I put my images (.png) in this way.

    import image from '@rollup/plugin-image'
    
    export default {
      input: 'src/index.tsx',
      ...,
      image({
        include: [
          'src/icons/*',
        ],
      })
    }
    

    then using @svgr/rollup I can use the SVGs of the library without any problem.

    import image from '@rollup/plugin-image'
    import svgr from '@svgr/rollup'
    
    export default {
      input: 'src/index.tsx',
      ...,
      image({
        include: [
          'src/icons/*',
        ],
      })
      svgr(),
    }