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
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)} />