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 to styleName
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 add transform-react-pug
before transform-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")
- 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