airbnb / babel-plugin-inline-react-svg

A babel plugin that optimizes and inlines SVGs for your React Components.
MIT License
473 stars 91 forks source link

Specifying SVGO option breaks JSX transform #103

Open PaulSearcy opened 3 years ago

PaulSearcy commented 3 years ago

Per title if I specify the SVGO option

[
  "inline-react-svg",
  {
    "svgo": {
      "plugins": [
        "cleanupIDs"
      ]
    }
  }
]

It breaks on line 78 in src/index.js

      const parsedSvgAst = parse(escapeSvgSource.data, {
        sourceType: 'module',
        plugins: ['jsx'],
      });

Here is the SVG, before transform. Which is transformed successfully having no options set for the plugin, not using SVGO, but strips the viewBox attribute which is needed.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.25 31.25" height="31.25" width="31.25"><path d="M18.093 28.997a.28.28 0 01-.202-.086l-1.179-1.17a1.53 1.53 0 00-1.087-.45c-.411 0-.797.16-1.087.45l-1.177 1.17a.29.29 0 01-.474-.088l-.674-1.517a1.546 1.546 0 00-2.03-.786l-1.52.666a.642.642 0 01-.074.004c-.208 0-.326-.099-.335-.255l-.08-1.66a1.54 1.54 0 00-1.54-1.467l-1.727.074a.297.297 0 01-.25-.12.286.286 0 01-.039-.263l.524-1.575a1.546 1.546 0 00-.971-1.95l-1.573-.53a.287.287 0 01-.187-.197.285.285 0 01.056-.266l1.057-1.28a1.546 1.546 0 00-.2-2.167L2.05 14.471a.287.287 0 01-.106-.252.288.288 0 01.15-.227l1.448-.811a1.546 1.546 0 00.596-2.093l-.805-1.453a.288.288 0 01-.007-.272.288.288 0 01.221-.158l1.644-.233a1.547 1.547 0 001.312-1.738L6.277 5.59a.293.293 0 01.287-.333l1.686.385a1.54 1.54 0 001.85-1.144l.383-1.617a.294.294 0 01.45-.173l1.372.935a1.54 1.54 0 002.139-.4l.94-1.367a.286.286 0 01.241-.127c.058 0 .165.016.24.127l.942 1.367a1.542 1.542 0 002.138.4l1.372-.935a.294.294 0 01.45.173l.383 1.616A1.538 1.538 0 0023 5.642l1.617-.376a.566.566 0 01.04-.002c.126 0 .197.037.248.095.039.046.083.122.068.23l-.225 1.645a1.547 1.547 0 001.31 1.738l1.645.233a.288.288 0 01.22.158.289.289 0 01-.005.273l-.806 1.45a1.548 1.548 0 00.597 2.095l1.448.81a.288.288 0 01.148.228.285.285 0 01-.104.252l-1.275 1.064a1.547 1.547 0 00-.201 2.166l1.06 1.28c.083.102.07.21.054.266a.286.286 0 01-.188.198l-1.57.53a1.546 1.546 0 00-.973 1.949l.524 1.575a.29.29 0 01-.276.384l-1.675-.074c-.891 0-1.566.644-1.605 1.465l-.08 1.66a.292.292 0 01-.292.278l-1.637-.692a1.544 1.544 0 00-2.03.786l-.674 1.517a.292.292 0 01-.27.174" fill="#fff"/><path d="M15.625 1.123a.91.91 0 00-.756.398l-.94 1.367a.917.917 0 01-1.273.238l-1.372-.935a.916.916 0 00-1.409.546l-.383 1.615a.92.92 0 01-1.1.682l-1.617-.377a.917.917 0 00-1.117 1.018l.226 1.644c.068.5-.281.963-.78 1.033l-1.645.234a.918.918 0 00-.673 1.352l.805 1.452a.92.92 0 01-.355 1.246l-1.448.81a.917.917 0 00-.139 1.505l1.275 1.063c.388.324.44.9.119 1.29l-1.058 1.278a.918.918 0 00.414 1.455l1.572.53c.48.162.737.68.577 1.16L4.025 23.3a.917.917 0 00.869 1.207l.041-.001 1.658-.073.042-.001c.487 0 .892.381.915.872l.08 1.66a.917.917 0 001.285.794l1.52-.667a.918.918 0 011.208.468l.673 1.517a.914.914 0 001.485.277l1.177-1.17a.913.913 0 011.294 0l1.177 1.17a.915.915 0 001.486-.277l.673-1.517a.917.917 0 011.207-.468l1.52.667a.917.917 0 001.284-.794l.081-1.66a.916.916 0 01.957-.871l1.658.073h.042a.917.917 0 00.869-1.206l-.524-1.575a.918.918 0 01.577-1.16l1.573-.53a.918.918 0 00.413-1.454l-1.058-1.278a.92.92 0 01.12-1.29l1.274-1.063a.917.917 0 00-.14-1.505l-1.447-.81a.92.92 0 01-.355-1.246l.805-1.452a.918.918 0 00-.673-1.352l-1.644-.234a.918.918 0 01-.78-1.033l.225-1.644a.917.917 0 00-1.117-1.018l-1.616.377a.92.92 0 01-1.101-.681l-.384-1.616a.917.917 0 00-1.408-.546l-1.372.935a.917.917 0 01-1.272-.238l-.941-1.367a.91.91 0 00-.756-.398zm0 1.505l.666.969a2.17 2.17 0 003.007.562l.972-.663.272 1.145a2.16 2.16 0 002.6 1.61l1.147-.267-.16 1.166a2.172 2.172 0 001.843 2.44l1.164.165-.57 1.03a2.172 2.172 0 00.836 2.941l1.027.574-.904.754a2.173 2.173 0 00-.281 3.046l.75.906-1.116.376a2.172 2.172 0 00-1.363 2.739l.373 1.115-1.177-.05-.068-.003h-.027a2.165 2.165 0 00-2.165 2.063l-.056 1.175-1.078-.474a2.168 2.168 0 00-2.851 1.105l-.478 1.075-.834-.83a2.15 2.15 0 00-1.529-.631 2.15 2.15 0 00-1.53.631l-.833.83-.478-1.075a2.167 2.167 0 00-2.85-1.105l-1.079.474-.056-1.175a2.165 2.165 0 00-2.164-2.063h-.069l-.028.002-1.175.052.372-1.116a2.172 2.172 0 00-1.364-2.739l-1.114-.376.75-.906a2.173 2.173 0 00-.283-3.046l-.903-.754 1.027-.574a2.172 2.172 0 00.836-2.942l-.57-1.029 1.164-.165a2.171 2.171 0 001.844-2.44l-.16-1.166 1.146.267a2.16 2.16 0 002.6-1.61l.272-1.145.972.663a2.17 2.17 0 003.007-.563l.666-.968" fill="#959595"/></svg>

For now as a workaround I'm using SVGR with the SVGO option, to keep viewBox attribute, as a loader for svgs in our application's webpack configuration which works fine. While using this babel plugin for the mocha tests that use enzyme and load svgs. (That just test for the existence, not the visuals, of the svg)

I would like to go down to one library and one configuration for transforming svgs uniformly across the codebase, but ran into this issue.

ljharb commented 3 years ago

101 was merged 3 days ago, so the readme now describes the new plugin settings format svgo requires.

PaulSearcy commented 3 years ago

@ljharb correct. I just copied and pasted the example in the readme and that does not work.

I tested it before I removed this below and after. Both versions do not work.

            {
              "name": "removeAttrs", 
              "params": { "attrs": "(data-name)" }
            },

Is the current readme wrong?

The babel config is in package.json if that makes any difference? (In that I made sure how it was setup was following JSON example in the readme.

ljharb commented 3 years ago

That shouldn't make a difference.

The intention is that with svgo 2, the new format should work.

One possibility is that this never worked with our transform; another is that it broke with the v2 release and the svgo v0 to v2 update. Can you try with v1 of this transform and see if it works there?

PaulSearcy commented 3 years ago

I tried it with 1.1.12 and it does work.

Two things I noticed.

  1. If any options were passed, either if valid or invalid, the jsx transform is not invoked
      var parsedSvgAst = (0, _parser.parse)(escapeSvgSource, {
        sourceType: 'module',
        plugins: ['jsx']
      });
  2. svgo@0.7.2 keeps viewBox by default while svgo@2.0.3 doesn't
sveg-pl commented 3 years ago

Hi @PaulSearcy, an update of the svgo package dependency inside babel-plugin-inline-react-svg to ^2.x.x did changed the way removeViewBox is set by default. Yet, you'll need to specify the plugin's name for the parser. So to disable an active plugin please try:

[
  "inline-react-svg",
  {
    "svgo": {
      "plugins": [
        {
          "name": "removeViewBox",
          "active": false
        }
      ]
    }
  }
]
lukasoppermann commented 3 years ago

I think I am running into the same issue but don't understand the fix.

I am trying this:

"plugins": [
    [
      "inline-react-svg",
      {
        "svgo": {
          "plugins": [
            {
              "name": "collapseGroups", 
              "active": false
            }
          ]
        }
      }
    ],

However importing the files in my next app I get:

error SyntaxError: /Users/lukasoppermann/Repos/veare-next/components/Logo.tsx: Unexpected token (1:1)

Removing it to:

"plugins": [
    [
      "inline-react-svg",
    ]

Makes it work. However I need the groups in the svg.

sveg-pl commented 3 years ago

However importing the files in my next app I get:

error SyntaxError: /Users/lukasoppermann/Repos/veare-next/components/Logo.tsx: Unexpected token (1:1)

Hi @lukasoppermann, can you please share babel-plugin-inline-react-svg version from package.json and at least couple of lines of Logo.tsx file as "Unexpected token (1:1)" directs us a bit to that direction.

lukasoppermann commented 3 years ago

Sure @sveg-pl

"babel-plugin-inline-react-svg": "^2.0.1"

The important file is the svg, which is imported into the logo.tsx

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 475 116" xml:space="preserve">
<path d="M99.9,2.6L58,113.2H40.6L0.1,2.6h10.1c4.1,0,7.6,2.5,8.8,5.9l31,89.7h0.5L82.3,8.5c1.2-3.4,4.7-5.9,8.8-5.9H99.9z
     M465.5,61.8h-71.7c0,23.4,13.1,42.3,38.8,42.3c6.3,0,14.4-1.4,21.4-3.4l0.2-0.1c0.8-0.2,1.8-0.4,2.7-0.4c5.1,0,9.2,3.8,9.2,8.5l0,1
    c-10.3,3.9-23.7,6.1-34.7,6.1c-39.6,0-54.3-24.7-54.3-57.9c0-33.8,20.1-57.9,50.4-57.9c33.1,0,47,24.1,47.6,53v0.2
    c0,4.7-4,8.5-9.1,8.5L465.5,61.8z M393.9,50.1h64.3c0-19.3-7.7-38.4-29.7-38.4C406.7,11.7,393.9,31.9,393.9,50.1z M193.6,61.8
    l-0.5,0h-71.7c0,23.4,13.1,42.3,38.8,42.3c6.3,0,14.4-1.4,21.4-3.4l0.2-0.1c0.8-0.2,1.7-0.4,2.7-0.4c5.1,0,9.3,3.8,9.3,8.5l0,1
    c-10.3,3.9-23.7,6.1-34.7,6.1c-39.6,0-54.3-24.7-54.3-57.9c0-33.8,20.1-57.9,50.4-57.9c33.1,0,47,24.1,47.5,53v0.2
    C202.7,57.9,198.7,61.7,193.6,61.8z M121.5,50.1h64.3c0-19.3-7.7-38.4-29.7-38.4C134.3,11.7,121.5,31.9,121.5,50.1z M369.8,14.3
    c-0.4,0-0.8,0-1.2,0c-23.4,0-29.8,24.3-29.8,44.2v54.6h-14.8V27.3c0-12.1,0-16.7-0.9-24.7h5.2l0.4,0c4.8,0,9.2,3.9,9.2,9.2v12.1h0.5
    C343.8,11.5,353.9,0,369.1,0c3.5,0,7.7,0.6,10.3,1.3v4.2l0,0.2c0,4.7-4.1,8.5-9.2,8.5L369.8,14.3z M302.4,113.2h-14.5V95.4h-0.5
    c-6.6,13.2-23.2,20.4-38,20.4c-33.9,0-39.3-21.2-39.3-31.2c0-37.1,42.6-38.8,73.6-38.8h2.5v-5.6c0-18.9-7-28.4-26.9-28.4
    c-7.8,0-15.2,1-22.5,3.4l0,0c-1.1,0.4-2.2,0.6-3.4,0.6c-4.9,0-9-3.6-9.2-8.1h0c9.2-4.1,24.6-7.6,35.1-7.6
    c29.5,0,41.9,12.4,41.9,41.2V90C301.2,98.9,301.2,105.6,302.4,113.2z M286.2,64.2v-6.7h-3.9c-25.5,0-55.9,2.4-55.9,26.7
    c0,14.5,11.1,19.9,24.7,19.9C285.7,104.1,286.2,76.1,286.2,64.2z"/>
</svg>

The logo.tsx is the following:

import SVGWordmark from '@svgs/veare-wordmark.svg'
import Link from 'next/link'
import { css } from '@emotion/css'

const style = css`
  fill: var(--on-background__high-emphasis);
  display: block;
  height: 24px;
  &.is-small {
    height: 16px;
  }
  & svg {
    height: 100%;
  }
`

type LogoProps = {
  homepageLink?: boolean,
  small?: boolean
}

const Logo = ({ homepageLink, small, ...props }: LogoProps) => {
  if (homepageLink) {
    return (
      <Link href='/'>
        <a className={`${style} ${small ? 'is-small' : ''} logo`} href='/' aria-label='Go to homepage' {...props}>
          <SVGWordmark />
        </a>
      </Link>
    )
  }
  return (
    <div className={`${style} ${small ? 'is-small' : ''} logo`}>
      <SVGWordmark />
    </div>
  )
}

export { Logo }

Hope that helps to identify the issue.

sveg-pl commented 3 years ago

@lukasoppermann - I solved your issue removing: <?xml version="1.0" encoding="utf-8"?> from the svg file, so that it only contains vectors inside <svg>...</svg> tags. I've added some empty groups and tested it on your repo - works fine.

lukasoppermann commented 3 years ago

Nice that works. Thank you very much

s-taylor commented 3 years ago

@sveg-pl thanks so much for this, I wasted the best part of a day trying to figure out why this wouldn't work.