npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@mapbox/svg-react-transformer

v2.1.0

Published

Transform SVG into JSX or React component modules

Downloads

190

Readme

@mapbox/svg-react-transformer

Transform SVGs into JSX or React component modules.

This module takes one string (the SVG) and converts it to another string (the JSX or React component module). That low-level focus means it can be used by a variety of higher-level modules that target specific contexts. Examples:

Installation

npm install @mapbox/svg-react-transformer

API

toComponentModule

svgReactTransformer.toComponentModule(svg, [options])

Returns a Promise that resolves with the React component module string. Runs an SVG string through toJsx to get a JSX string, then inserts the JSX into a templated React component module.

svg (toComponentModule)

Type: string. Required.

The input SVG.

options (toComponentModule)

options.svgoPlugins (toComponentModule)

Type: Array<Object>.

See the same option for toInlineSvg.

options.name (toComponentModule)

Type: string. Default: 'SvgComponent'.

A name for the React component class. The value will be converted to PascalCase (e.g. fancy-pants -> FancyPants) and then passed as the id option to toJsx.

options.propTypes (toComponentModule)

Type: string.

A stringified object defining propTypes for the generated React component. It should be the string of the code that you'd put in here: MyComponent.propTypes = ${this.place}, e.g. '{ title: PropTypes.string.isRequired }'.

This value will be passed to your selected template. If this value is defined, the built-in templates will include const PropTypes = require('prop-types');.

To programmatically convert a real object to a string that works here, I suggest using stringify-object.

options.defaultProps (toComponentModule)

Type: string.

A stringified object defining defaultProps for the generated React component. It should be the string of the code that you'd put in here: MyComponent.defaultProps = ${this.place}, e.g. '{ title: 'Untitled' }'.

This value will be passed to your selected template.

To programmatically convert a real object to a string that works here, I suggest using stringify-object.

options.template (toComponentModule)

Type: Function | 'default' | 'fancy'. Default: 'default'.

If the value is a string, it can be one of the component module template values described below: default, fancy.

If the value is a function, it must be a custom template function.

options.precompile (toComponentModule)

Type: boolean. Default: false.

If true, the template will be passed through Babel (with the ES2015 and React presets), so you don't have to compile it yourself.

Component module templates

default template

The default template creates a module exporting a React.PureComponent that renders the SVG element and its children as React elements.

This template is simple and unopinionated.

Here's an example generated by the default template.

"use strict";
const React = require("react");

class SvgComponent extends React.PureComponent {
  render() {
    return (
      <svg {...this.props} viewBox="0 0 18 18">
        <path d="M7 4l1.6 4H5.5S4.1 6 3 6h-.8L3 8l1 3h4.6L7 15h2l3.2-4H14c1 0 2-.7 2-1.5S15 8 14 8h-1.8L9 4H7z" />
      </svg>
    );
  }
}

SvgComponent.defaultProps = {
  role: "img",
  focusable: "false"
};

module.exports = SvgComponent;

fancy template

This is an opinionated template with a few nice features:

  • Applies some accessibility patterns. Adds aria-hidden and focusable="false" to the <svg> element, and exposes an alt prop for alternative text (hidden from sight, legible for screen readers).
  • Uses the SVG's viewbox attribute to determine an aspect ratio, and applies a wrapper <div> and CSS so that the element can have a fluid width while preserving its aspect ratio (across browsers IE11+).
  • Adds extra SVGO plugins removeTitle, removeStyleElement, and removeAttrs to remove width and height from the <svg> element. The alt prop provides better accessibility than titles for almost all use cases; <style> elements within SVGs can be dangerous for inlined SVG; and width and height will be determined by the SVG's containing context.
  • Exposes containerClassName, containerStyle, svgClassName, and svgStyle props for customizing the whole thing.

Here is an example generated by the fancy template:

"use strict";
const React = require("react");
class Fakery extends React.PureComponent {
  render() {
    const containerStyle = this.props.containerStyle || {};
    if (!containerStyle.position || containerStyle.position === "static") {
      containerStyle.position = "relative";
    }
    containerStyle.paddingBottom = "100%";
    const svgStyle = this.props.svgStyle || {};
    svgStyle.position = "absolute";
    svgStyle.overflow = "hidden";
    svgStyle.top = 0;
    svgStyle.left = 0;
    svgStyle.width = "100%";
    const text = !this.props.alt
      ? null
      : <div style={{ position: "absolute", left: -9999 }}>
          {this.props.alt}
        </div>;
    return (
      <div style={containerStyle} className={this.props.containerClassName}>
        <svg
          aria-hidden={true}
          focusable="false"
          style={svgStyle}
          className={this.props.svgClassName}
          viewBox="0 0 18 18"
        >
          <g
            style={{
              marginTop: "0"
            }}
          >
            <path d="M3.4 9.2c.1-1.1.4-2.3 1.5-3.2.9-.7 1.8-.8 2.9-.5 1.4.5 1 .5 2.4 0 1.5-.6 3 0 3.7.8.1.2.2.3 0 .4-1.8 1.3-1.6 3.9.3 5 .2.1.3.2.2.4-.4 1-1 1.9-1.7 2.7-.5.5-1.1.7-1.8.4-.1 0-.3-.1-.4-.1-.9-.1-1.7-.1-2.5.2-.3.1-.5.2-.8.3-.4.1-.8-.1-1.1-.4-.7-.5-1.1-1.2-1.5-1.9-.7-1.1-1.2-2.7-1.2-4.1" />
            <path d="M11.6 2.5c0 1.2-1 2.4-2 2.7-.6.1-.8 0-.7-.6.2-1.2 1.2-2.2 2.5-2.5.2 0 .2 0 .2.2v.2" />
          </g>
        </svg>
        {text}
      </div>
    );
  }
}
module.exports = Fakery;

Custom template functions

Custom template functions receive one argument, a data object, and must return a string. The data object argument includes the following properties:

  • name: The value of the name option above (converted to PascalCase).
  • propTypes: The value of the propTypes option, above.
  • defaultProps: The value of the defaultProps option above.
  • jsxSvg: The JSX string generated from your source SVG.
  • inlineSvg: Your source SVG processed by SVGO for use inline with HTML. (In a template you could use this with dangerouslySetInnerHTML.)

What about other modules that do similar things?

There are many npm packages for converting SVGs to React components: Webpack loaders, Browserify transforms, CLIs, Gulp plugins, Brunch plugins, etc. They are all addressing the same problem but formatting their output differently. However, their APIs seems to be too specialized for them to share logic, so they end up reimplementing a lot of the same stuff in different ways.

There are only a few steps to accomplish what we all want:

  1. Optimize the SVG with SVGO.
  2. Transform the SVG to JSX (or a React element object).
  3. Plug the JSX into a React component module.

Then you need an API that allows the user to configure these steps; that is, to specify SVGO plugins and control the React component output.

So that's the goal of this package: provide an API to accomplish those steps (without unnecessarily reimplementing functionality that (should) belong to other packages). Ideally, then, this package could be used by Webpack loaders, Browserify transforms, CLIs, Gulp plugins, Brunch plugins, etc., and save them from reimplementing the same functionality over and over again.

toJsx

svgReactTransformer.toJsx(svg, [options])

Returns a Promise that resolves with the JSX string. Runs an SVG through toInlineSvg, then converts the SVG to JSX.

svg (toJsx)

Type: string. Required.

The input SVG.

options (toJsx)

Any of the options for toInlineSvg. These are passed directly to that function.

toInlineSvg

svgReactTransformer.toInlineSvg(svg, [options])

Returns a Promise that resolves with your SVG processed by SVGO so that it works inline within HTML and is otherwise optimized. You could use the result with dangerouslySetInnerHTML, for example. It's also used internally by toComponentModule.

svg (toInlineSvg)

Type: string. Required.

The input SVG.

options (toInlineSvg)

options.svgoPlugins (toInlineSvg)

Type: Array<Object>.

Configuration for SVGO plugins.

The following are automatically set (but can be overridden) because they are important for SVGs that will be inserted inline into an HTML document:

[
  { removeDoctype: true },
  { removeComments: true },
  { removeXMLNS: true },
  {
    // svgId is determined by the `id` option, below.
    cleanupIDs: { prefix: svgId + '-' }
  }
]
options.id (toInlineSvg)

Type: string. Default: a cuid-generated string.

Used by SVGO's cleanupIDs plugin to scope id attributes. Any characters other than /[a-zA-Z0-9]/ will be stripped.