/svgr

Transform SVG into React components 🦁

Primary LanguageJavaScript

svgr

Tranform SVG into React components 🦁

Build Status Code Coverage version MIT License

PRs Welcome Chat

Watch on GitHub Star on GitHub Tweet

npm install svgr

Example

Take an icon.svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="1px" viewBox="0 0 48 1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
    <title>Rectangle 5</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="19-Separator" transform="translate(-129.000000, -156.000000)" fill="#063855">
            <g id="Controls/Settings" transform="translate(80.000000, 0.000000)">
                <g id="Content" transform="translate(0.000000, 64.000000)">
                    <g id="Group" transform="translate(24.000000, 56.000000)">
                        <g id="Group-2">
                            <rect id="Rectangle-5" x="25" y="36" width="48" height="1"></rect>
                        </g>
                    </g>
                </g>
            </g>
        </g>
    </g>
</svg>

Run SVGR

svgr --no-semi --icon --replace-attr-value "#063855=currentColor" icon.svg

Output

import React from "react"

const SvgComponent = props => (
  <svg width="1em" height="1em" viewBox="0 0 48 1" {...props}>
    <path d="M0 0h48v1H0z" fill="currentColor" fillRule="evenodd" />
  </svg>
)

export default SvgComponent

Motivation

React supports SVG out of the box, it's simpler, easier and much more powerful to have components instead of SVG files. Wrapped in a React component, your SVG is inlined in the page and you can style it using CSS.

There is a lot of similar projects but I wanted something more solid and configurable. SVGR is based on h2x, a powerful and configurable HTML transpiler. It uses AST (like Babel) that gives a lot of power.

Command line usage

  Usage: svgr [options] <file>


  Options:

    -V, --version                    output the version number
    -d, --out-dir <dirname>          output files into a directory
    --no-svgo                        disable SVGO
    --no-prettier                    disable Prettier
    --template <file>                specify a custom template to use
    --no-expand-props                disable props expanding
    --icon                           use "1em" as width and height
    --replace-attr-value [old=new]   replace an attribute value
    -p, --precision <value>          set the number of digits in the fractional part (svgo)
    --no-title                       remove title tag (svgo)
    --tab-width                      specify the number of spaces by indentation-level (prettier)
    --use-tabs                       indent lines with tabs instead of spaces (prettier)
    --no-semi                        remove semi-colons (prettier)
    --single-quote                   use single-quotes instead of double-quotes (prettier)
    --trailing-comma <none|es5|all>  print trailing commas wherever possible when multi-line (prettier)
    --no-bracket-spacing             print spaces between brackets in object literals (prettier)
    --jsx-bracket-same-line	         put the > of a multi-line JSX element at the end of the last line instead of being alone on the next line (prettier)
    -h, --help                       output usage information

  Examples:
    svgr --replace-attr-value "#fff=currentColor" icon.svg

Recipes

Transform a whole directory

A whole directory can be processed, all SVG files (matching .svg or .SVG) are transformed into React components.

$ svgr -d icons icons
icons/web/clock-icon.svg -> icons/web/ClockIcon.js
icons/web/wifi-icon.svg -> icons/web/WifiIcon.js
icons/spinner/cog-icon.svg -> icons/spinner/CogIcon.js
icons/spinner/spinner-icon.svg -> icons/spinner/SpinnerIcon.js

Use stdin

$ svgr < icons/web/wifi-icon.svg

Use stdin / stdout

$ svgr < icons/web/wifi-icon.svg > icons/web/WifiIcon.js

Transform icons

To create icons, two options are important:

  • --icon: title is removed and SVG inherits text size
  • --replace-attr-value "#000000=currentColor": "#000000" is replaced by "currentColor" and SVG inherits text color
$ svgr --icon --replace-attr-value "#000000=currentColor" my-icon.svg

Use a specific template

You can use a specific template, for an example of template, see the default one.

$ svgr --template path/to/template.js my-icon.svg

Node API usage

SVGR can also be used programmatically:

import svgr from 'svgr'

const svgCode = `
<?xml version="1.0" encoding="UTF-8"?>
<svg width="88px" height="88px" viewBox="0 0 88 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
    <title>Dismiss</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="Blocks" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="square">
        <g id="Dismiss" stroke="#063855" stroke-width="2">
            <path d="M51,37 L37,51" id="Shape"></path>
            <path d="M51,51 L37,37" id="Shape"></path>
        </g>
    </g>
</svg>
`

svgr(svgCode, { prettier: false }).then(jsCode => {
  console.log(jsCode)
})

Webpack usage

SVGR has a Webpack loader, you can use it using following webpack.config.js:

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: ['svgr/webpack', 'babel-loader']
      }
    ]
  }
}

It is also possible to specify options:

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'svgr/webpack',
            options: {
              svgo: false
            }
          },
          'babel-loader',
        ]
      }
    ]
  }
}

Options

SVGR ships with a handful of customizable options, usable in both the CLI and API.

SVGO

Use SVGO to optimize SVG code before transforming it into a component.

Default CLI Override API Override
true --no-svgo svgo: <bool>

Prettier

Use Prettier to format JavaScript code output.

Default CLI Override API Override
true --no-prettier prettier: <bool>

Template

Specify a template file (CLI) or a template function (API) to use. For an example of template, see the default one.

Default CLI Override API Override
wrapIntoComponent --template template: <func>

Expand props

All properties given to component will be forwarded on SVG tag.

Default CLI Override API Override
true --no-expand-props expandProps: <bool>

Icon

Remove title and replace SVG "width" and "height" value by "1em" (SVG size inherits from text size).

Default CLI Override API Override
false --icon icon: <bool>

Replace attribute value

Replace an attribute value by an other. The main usage of this option is to change an icon color to "currentColor" in order to inherit from text color.

Default CLI Override API Override
[] --replace-attr-value <old=new> replaceAttrValues: <string[]>

Precision

Set number of digits in the fractional part. See SVGO.

Default CLI Override API Override
3 --precision <int> precision: <int>

Title

Remove the title from SVG. See SVGO removeTitle plugin.

Default CLI Override API Override
true --no-title title: <bool>

Tab Width

Specify the number of spaces per indentation-level. See Prettier.

Default CLI Override API Override
2 --tab-width <int> tabWidth: <int>

Tabs

Indent lines with tabs instead of spaces. See Prettier.

Default CLI Override API Override
false --use-tabs useTabs: <bool>

Semicolons

Print semicolons at the ends of statements. See Prettier.

Default CLI Override API Override
true --no-semi semi: <bool>

Quotes

Use single quotes instead of double quotes. See Prettier.

Default CLI Override API Override
false --single-quote singleQuote: <bool>

Trailing Commas

Print trailing commas wherever possible when multi-line. See Prettier.

Default CLI Override API Override
"none" --trailing-comma <none|es5|all> trailingComma: "<none|es5|all>"

Bracket Spacing

Print spaces between brackets in object literals. See Prettier.

Default CLI Override API Override
true --no-bracket-spacing bracketSpacing: <bool>

JSX Brackets

Put the > of a multi-line JSX element at the end of the last line instead of being alone on the next line (does not apply to self closing elements). See Prettier.

Default CLI Override API Override
false --jsx-bracket-same-line jsxBracketSameLine: <bool>

Other projects

A lot of projects tried to solve this problem, unfortunately, none of them fulfills my use cases.

Using raw node:

Using command line:

Or using a Webpack loader:

Or using a browserify loader:

Or using gulp / grunt plugin:

Or at runtime:

Or using grunt:

License

MIT