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:
const ReactComponent = pug` .wrapper if props.shouldShowGreeting p.greeting Hello World! button(onClick=props.notify) Click Me`
And it will be transpiled into:
const ReactComponent = <div ="wrapper"> propsshouldShowGreeting ? <p ="greeting">Hello World!</p> : null <button =>Click Me</button> </div>
Usage
Syntax
Full information of the syntax you can find in official documentation: pugjs.org.
Basic example
const Component = 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 = 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 = 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 = pug` ul(className=) `;
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