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

babel-plugin-jsx-classnames-advanced

v1.0.2

Published

Babel plugin for automatically adding classnames() to [className] attributes.

Downloads

727

Readme

babel-plugin-jsx-classnames-advanced

Build Status Coverage Status NPM version NPM downloads

Plugin for babel@7, automatically adding classnames() to [className] attributes.

Inspired from meowtec's repo babel-plugin-jsx-classnames for babel@6.

// transforming
<Component className={expression} />

// to
import classnames from 'classnames';
<Component className={classnames(expression)} />

Why

Passing expression to classnames which is imported automatically.

Comparison of src:

// string template
<Component className={`${styles.wrap || ''} ${this.props.className || ''}`} />
<Component className={`${active ? 'btn-active' : ''} ${disabled ? 'btn-disabled' : ''}`} />

// using classnames
import classnames from 'classnames';
<Component className={classnames([styles.wrap, this.props.className])} />
<Component className={classnames({ 'btn-active': active, 'btn-disabled': disabled })} />

// using babel-plugin-jsx-classnames-advanced
<Component className={[styles.wrap, this.props.className]} />
<Component className={{ 'btn-active': active, 'btn-disabled': disabled }} />

Usage

Install

npm i babel-plugin-jsx-classnames-advanced --save-dev

Babel config

Work with @babel/preset-react, or position after @babel/plugin-syntax-jsx.

{
  "presets": [
    ...
    // "@babel/preset-react"
  ],
  "plugins": [
    ...
    // "@babel/plugin-syntax-jsx",
    "babel-plugin-jsx-classnames-advanced"
  ]
}

Cases:

// src

// ignores
<Component otherAttributeNames={[]} />
<Component className="wrap" />
<Component className={"wrap"} />
<Component className={styles.wrap} />

// expressions
<Component className={[styles.wrap, this.props.className]} />
<Component className={{ [styles.wrap]: true }} />
<Component className={'a' + 'b'} />

// other attribute names in ant-design
<Component dropdownClassName={[styles.wrap, this.props.className]} />
<Component wrapperClassName={[styles.wrap, this.props.className]} />
<Component wrapClassName={[styles.wrap, this.props.className]} />
// transformed

import _babel_plugin_jsx_classnames_advanced from 'classnames';

// ignores
<Component otherAttributeNames={[]} />
<Component className="wrap" />
<Component className={"wrap"} />
<Component className={styles.wrap} />

// expressions
<Component className={_babel_plugin_jsx_classnames_advanced([styles.wrap, this.props.className])} />
<Component className={_babel_plugin_jsx_classnames_advanced({ [styles.wrap]: true })} />
<Component className={_babel_plugin_jsx_classnames_advanced('a' + 'b')} />

// other attribute names in ant-design
<Component dropdownClassName={_babel_plugin_jsx_classnames_advanced([styles.wrap, this.props.className])} />
<Component wrapperClassName={_babel_plugin_jsx_classnames_advanced([styles.wrap, this.props.className])} />
<Component wrapClassName={_babel_plugin_jsx_classnames_advanced([styles.wrap, this.props.className])} />

Options

Babel config with options:

{
  "plugins": [
    ["babel-plugin-jsx-classnames-advanced", { nameHint: 'nameHint' }]
  ]
}

nameHint

string | false(boolean), defaults to '_babel_plugin_jsx_classnames_advanced'

Unique import name of classnames (callee of callExpression) in modules, passed to addDefault.

Note that the import name which generated by babel api in the first transformation, will be referenced in others, for uniq imports and better performance.

Default value works well in most cases. It would cause problems if there are variables same as nameHint in scopes.

Which should be avoided:

// src

<Component className={[]} />

{  // inner scope
  const _babel_plugin_jsx_classnames_advanced = () => {};
  <Component className={[]} />
}
// transformed

// generated by babel api, according to the first transformation
import _babel_plugin_jsx_classnames_advanced from 'classnames';
// first transformation
<Component className={_babel_plugin_jsx_classnames_advanced([])} />

{  // inner scope
  const _babel_plugin_jsx_classnames_advanced = () => {}
  // generated for referencing to imported function in line 1, but it refs to function of inner scope
  <Component className={_babel_plugin_jsx_classnames_advanced([])} />
}

option false, keep default behavior of addDefault:

// src
<Component className={[]} />
<Component className={[]} />

// transformed
import _babel_plugin_jsx_classnames_advanced2 from 'classnames';
import _babel_plugin_jsx_classnames_advanced from 'classnames';

<Component className={_babel_plugin_jsx_classnames_advanced([])} />
<Component className={_babel_plugin_jsx_classnames_advanced2([])} />

attributeNames

Array<string>, defaults to ['className', 'dropdownClassName', 'wrapperClassName', 'wrapClassName', 'overlayClassName']

Defaults to frequent attribute names, integrating with ant-design.

This array will be replaced entirely, passing necessary options like 'className' manually.

ignoreMemberExpression

boolean, defaults to true

Ignore memberExpression, for less transforms, integrating with css module.

// ignored
import styles from './index.css';
<Component className={styles.wrap} />

If you want to transform memberExpression, recommend to:

<Component className={[foo.bar]} />

option false:

// src
import styles from './index.css';
<Component className={styles.wrap} />
<Component className={foo.bar} />

// transformed
import _babel_plugin_jsx_classnames_advanced from 'classnames';
import styles from './index.css';
<Component className={_babel_plugin_jsx_classnames_advanced(styles.wrap)} />
<Component className={_babel_plugin_jsx_classnames_advanced(foo.bar)} />

ignoreIdentifier

boolean, defaults to true

Transforms of identifier will be ignored, for less transforms.

// ignored
<Component className={foo} />

If you want to transform identifier, recommend to:

<Component className={[foo]} />

option false:

// src
<Component className={foo} />

// transformed
<Component className={_babel_plugin_jsx_classnames_advanced(foo)} />