Use Pug templates to write react components.
npm version Build Status Codecov
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> )
Full information of the syntax you can find in official documentation: pugjs.org.
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> //- ) `;
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> //- ) `;
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> //- ) `;
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}`)} `;
Install eslint-plugin-react-pug if you use eslint-plugin-react.
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
classAttributeoption tostyleNamevalue 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
classAttributeoption tostyleNamevalue 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 via yarn or npm
yarn add --dev babel-plugin-transform-react-pugnpm 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.
| Name | Type | Default | Description |
|---|---|---|---|
classAttribute |
String |
className |
Attribute name which considered by PUG as "class" |
Default:
pug`p.one`
=>
<p className="one" />
With "styleName" as value:
pug`p.one`
=>
<p styleName="one" />
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
.babelrcfile in your root directory, just addtransform-react-pugbeforetransform-react-jsxthere. -
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; }
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.
Coming soon...
-
We can't use dots in component names because pugjs treats everything after dot as a className. For example,
React.Fragmentbecomes<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]
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).
-
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"
-
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.pugMore details: gandm/language-babel#javascript-tagged-template-literal-grammar-extensions
-
Restart the atom
-
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.
MIT