babel-plugin-transform-react-pug
Use Pug templates to write react components.
babel-plugin-transform-react-pug
is a plugin for babel which transpiles pug syntax within template literals to jsx.
Write your components this way:
export const ReactComponent = props => pug`
.wrapper
if props.shouldShowGreeting
p.greeting Hello World!
button(onClick=props.notify) Click Me
`
And it will be transpiled into:
export const ReactComponent = props => (
<div className="wrapper">
{props.shouldShowGreeting ? (
<p className="greeting">Hello World!</p>
) : null}
<button onClick={props.notify}>Click Me</button>
</div>
)
Usage
Syntax
Full information of the syntax you can find in official documentation: pugjs.org.
Basic example
const Component = props => pug` //- const Component = props => (
div //- <div>
if props.amount > MAX_AMOUNT //- {props.amount > MAX_AMOUNT ? (
OtherComponent(fluid crucial) //- <OtherComponent fluid={true} crucial={true} />
else //- ) : (
p You can set bigger amount ;) //- <p>You can set bigger amount ;)</p>
//- )}
each item, index in props.items //- {props.items.map((item, index) => (
div(key=item.id) //- <div key={item.id}>
h3 Header #{index + 1} //- <h3>Header {index + 1}</h3>
= item.body //- {item.body}
//- </div>
//- )}
//- </div>
//- )
`;
How to pass functions and other primitives
const Component = props => pug` //- const Component = props => (
div //- <div>
button( //- <button
type="button" //- type="button"
onClick=props.onClick //- onClick={props.onClick}
) Click Me //- >Click Me</button>
//-
OtherComponent( //- <OtherComponent
...props.objectWithPropsForChild //- {...props.objectWithPropsForChild}
fluid //- fluid={true}
data-array=[1, 2, 3] //- data-array={[1, 2, 3]}
) //- />
//- </div>
//- )
`;
Define local variables and use javascript in attributes
const Component = props => pug` //- const Component = props => (
Fragment //- <Fragment>
button( //- <button
...one //- {...one}
...two //- {...two}
onClick=() => alert('Hello') //- onClick={() => alert('Hello')}
text='number ' + 10 //- text={'number ' + 10}
condition=foo === bar ? foo : bar //- condition={foo === bar ? foo : bar}
) //- ></button>
//-
- const variable = format(props.no) //-
p Variable is #{variable} //- <p>Variable is {format(props.no)}</p>
//- </Fragment>
//- )
`;
Interpolation
If you'd prefer to use interpolation, you can. This is possible by using ${}
within your template.
const Component = props => pug`
ul(className=${props.modifier})
${props.items.map((item, index) => pug`li(key=${index}) ${item}`)}
`;
Eslint integration
Install eslint-plugin-react-pug if you use eslint-plugin-react.
CSS Modules
Whether you use babel plugin to turn on CSS Modules specifically for JSX (e.g. babel-plugin-react-css-modules) or use webpack loader for that to transform styles into key-value object, it's possible to use it with pug.
-
With babel-plugin-react-css-modules you need to set
classAttribute
option tostyleName
value and that's it.{ "plugins": [ ["transform-react-pug", { "classAttribute": "styleName" }] ] }
import './styles.css' // .hello{color:red} const withCorrectStyles = pug` div.hello I am a red text `
-
With webpack loader or other approaches which transform styles into object
import classes from './styles.css' // .hello{color:green} const withCorrectStyles = pug` div(className=classes.hello) I am a green text `
The developer experience can be improved here by setting
classAttribute
option tostyleName
value and adding babel-plugin-transform-jsx-css-modules{ "plugins": [ ["transform-react-pug", { "classAttribute": "styleName" }], "transform-jsx-css-modules" ] }
import './styles.css' // .hello{color:green} const withCorrectStyles = pug` div.hello I am a green text `
Install
-
Install via yarn or npm
yarn add --dev babel-plugin-transform-react-pug
npm install --save-dev babel-plugin-transform-react-pug
-
Add to babel configuration before transpiling jsx (usually in
.babelrc
){ "plugins": [ "transform-react-pug", "transform-react-jsx" ] }
-
Now all your templates written with pug are understood by react and browsers.
Configuration
Name | Type | Default | Description |
---|---|---|---|
classAttribute |
String |
className |
Attribute name which considered by PUG as "class" |
classAttribute
Default:
pug`p.one`
=>
<p className="one" />
With "styleName" as value:
pug`p.one`
=>
<p styleName="one" />
create-react-app
Integrating with create-react-app is tricky because it does not allow you to modify babel configuration. There are two documented possibilities:
-
That is easy, you will get
.babelrc
file in your root directory, just addtransform-react-pug
beforetransform-react-jsx
there. -
Go through official instruction to rewire your application. Then modify your
config-overrides.js
:+ const {injectBabelPlugin} = require('react-app-rewired'); module.exports = function override(config, env) { - //do stuff with the webpack config... + config = injectBabelPlugin('transform-react-pug', config); return config; }
React Native
Just add this plugin to the list in .babelrc
file.
{
- "presets": ["react-native"]
+ "presets": ["react-native"],
+ "plugins": ["transform-react-pug"]
}
We don't need transform-react-jsx
here because it's coming with react-native
preset.
How it works
Coming soon...
Limitations
-
We can't use dots in component names because pugjs treats everything after dot as a className. For example,
React.Fragment
becomes<React className="Fragment" />
, not<React.Fragment />
A nice workaround is made by babel-plugin-transform-jsx-classname-components. Just add it to
.babelrc
:{ "plugins": [ ["transform-jsx-classname-components", { "objects": ["React"] }] ] }
-
We don't support html language in pug templates. This is different than what Pug promises.
However, you can still use tag interpolation:
p Good #[strong Morning]
FAQ
Can I import template from other files?
The short answer is no and we are not going to implement that in near future. Take a look at initial request with small explanation (#15).
How to get syntax highlighting in IDE (or text editors)?
WebStorm
-
Open settings
-
"Editor" -> "Language Injections"
-
Click on Add new "Generic Js" injection
- Name:
Pug In Template Literals (JavaScript)
- ID:
Vue (Vue.js template)
(current version of pug plugin is created in HTML scope, so we use workaround here) - Prefix:
<template lang="pug">
- Suffix:
</template>
- Places Patterns:
+ taggedString("pug")
- Name:
-
Click "OK" and "Apply"
Atom
-
Install language-babel and language-pug-jade
I suggest language-pug-jade because it works better for me. But there are more approaches for building pugjs grammar: language-pug and atom-pug, and you can try them too.
-
Open settings of language-babel in atom
-
Find the field under "JavaScript Tagged Template Literal Grammar Extensions"
-
Enter:
pug:source.pug
More details: gandm/language-babel#javascript-tagged-template-literal-grammar-extensions
-
Restart the atom
Visual Studio Code
-
Open settings of extensions
-
Search "vscode-react-pug" by the search field
-
Click "Install" and "Reload"
-
If you use any grammar other than default one (e.g. Babel JavaScript which is quite popular), you might need to add supporting of Atom's Grammar (Microsoft/vscode-js-atom-grammar).
Check out the history beyond that: kaminaly/vscode-react-pug#4.
License
MIT