Really clean transforms from Jade to React in your Javascript

Usage no npm install needed!

<script type="module">
  import reactJadeTransformer from '';


React Jade Transformer

Yeah, another one... This library is a no frills transformer from Jade Markup to React components, because I wanted one that works the way I want it to. It uses the Jade Parser, Esprima, and escodegen under the hood, so parsing and results should be very true to their initial implementation.


This is an early implementation. Not all features of Jade are transformed into something sensible in React yet.

Currently Supported:

  • Elements
  • Mixins as Components
  • Buffered Output
  • Each/For
  • If/Else/Unless/Else If
  • Switch
  • Classes

Transformation Reference

All Jade Transformations would be written inside rj tagged with backticks, for example rjspan.spanClass. This reference is written with the assumption that you know Jade and React syntax.

Basic Structure

All standard DOM elements will transform to a React.DOM call.

React.DOM.span({ className: 'spanClass ' });

Attributes render as properties.

    'id': 'someId',
    'data-foo': 'bar',
    className: 'component '

Jade Classes will get mixed with a class property, so you can use shorthand classes in conjunction with classSet or equivalent.

React.DOM.div({ className: 'component ' + React.addons.classSet(classesObj) });

Object Literals can be passed in for properties such as style.

.component(style={width: 234})
    'style': { width: 234 },
    className: 'component '

Jade does NOT support objects being passed to standard DOM elements (only mixins), so this will not work as you expect:

    'propsObj': true,
    className: 'component '

Nesting Children and Strings works as you would expect:

  h1.component__title This is the title
React.DOM.div({ className: 'component ' },
  React.DOM.h1({ className: 'component__title ' }, 'This is the title')


Variables can be output using the standard Jade syntax for buffered output.

  h1.component__title= this.props.title
React.DOM.div({ className: 'component ' },
  React.DOM.h1({ className: 'component__title ' }, this.props.title)

This would also work for breaking up components as variables, ie:

var title = rj`h1.component__title= this.props.title`

  = title
var title = React.DOM.h1({ className: 'component__title ' }, this.props.title);

React.DOM.div({ className: 'component ' }, title);

If Conditionals

If/Unless Conditionals are rendered as ternary statements.

  if this.props.title
    h1.component__title= this.props.title
    h2 No title Provided
React.DOM.div({ className: 'component ' },
    ? React.DOM.h1({ className: 'component__title ' }, this.props.title)
    : React.DOM.h2({}, 'No title Provided')

Be aware that you can ONLY return a single element from an If or Else Conditional:

  if this.props.title
    h1.component__title= this.props.title
    h2 This won't render
      h1 These will both render
      h2 So Will This
React.DOM.div({ className: 'component ' },
    ? React.DOM.h1({ className: 'component__title ' }, this.props.title)
    : React.DOM.div({},
        React.DOM.h1({}, 'These will both render'),
        React.DOM.h2({}, 'So Will This')

Case Conditionals

Cases create self calling functions that run a switch statement, so you can do longer cases within your components. The function is bound to this so you can still access component methods.

case someVar.length
  when 0
    h1 Nothing Here
  when 1
    h1 One Thing Here
    h1 Lots of things here
    h2 This will never be reached.
(function () {
    switch (someVar.length) {
    case 0:
        return React.DOM.h1({}, 'Nothing Here');
    case 1:
        return React.DOM.h1({}, 'One Thing Here');
        return React.DOM.h1({}, 'Lots of things here');


each is supported as a standard map function. while is not supported. The this variable is bound to the map function.

  each thing, ix in things
    li.item(key=ix)= thing
React.DOM.ul({ className: 'items ' }, (thing, ix) {
        'key': ix,
        className: 'item '
    }, thing);
  }, this)

Calling Components

Just like JSX, you can call React Component Classes without a factory, by making use of Jade's mixin syntax.

React.createElement(Component, { 'onClick': this.onClick });

Unlike DOM elements, you can provide a single argument as the properties, allowing you to pass along props without writing out every single property.

+Component(_.assign(this.props, {
  "foo": "bar"
React.createElement(Component, _.assign(this.props, { 'foo': 'bar' }));

Components take children same as elements.

  p Some Children
  p Some More Children
React.createElement(Component, { 'onClick': this.onClick },
  React.DOM.p({}, 'Some Children'),
  React.DOM.p({}, 'Some More Children')


One of the limitations of Jade is that you can't provide single arguments to DOM elements, for example:


...does not work, as the parser does not recognise it. The transformer supports &attributes to allow you to pass an extra property object to a DOM element or a component mixin:

  div&attributes({className: "blue")
  p Some More Children
React.createElement(Component, Object.assign({ 'onClick': this.onClick }, this.props),
  React.DOM.div({className: "blue"}),
  React.DOM.p({}, 'Some More Children')

This transformation makes use of the Object.assign functionality, so the assumption is there that you'll shim Object.assign until Harmony is supported. This feels like a safe shim to work with, unlikely to drift in functionality from the specification.

Unescaped HTML

Unescaped variables will be transformed into the standard property used for React's unescaped HTML.

  section.article__content!= this.renderedHTML

 -- or --

    != this.renderedHTML
  className: "article"
}, React.DOM.section({
  dangerouslySetInnerHTML: {__html: this.renderedHTML}

Extra children can not be provided when using unescaped HTML.

On the Roadmap

This is a pretty early implementation so I'm not sure when I'll consider it 'done'. Currently in use on some projects, I'm implementing things as I hit the use case, so file an issue if you feel like something can clearly be added to the transform. Things I can see coming:

  • ability to use variable assignment (this might be more complex than I want to support though, as we start building more closures and what not to make it work)


Install with npm

npm install --save-dev react-jade-transformer

In Code

Write standard Javascript, (even ES6 transpiled Javascript), and use a special tag (rj`) to denote Jade:

var SimpleComponent = React.createClass({
  exampleProps: {
    title: "The Title",
    subtitle: "The Subtitle"
  render: function() {
    return rj`
        h3.component__title= this.props.title
        p= this.props.children

The Transformer will process any code in between the rj`` backticks.


var reactJade = require("react-jade-transformer");

var bundler = browserify({
  entries: ["./code.js"]

If you wish to use the transformer in conjunction with another transpiler, for example ES6, Coffeescript or Typescript, you can break up the transform into two steps.

var reactJade = require("react-jade-transformer");
var babelify = require("babelify"); // es6 transformer

var bundler = browserify({
  entries: ["./code.js"]
}).transform(reactJade.browserify({prepare: true}))
  .transform(reactJade.browserify({transform: true}));

The prepare step converts any rj`` step into a function call:

// newlines broken for readability
    h3.component__title= this.props.title\n
    p= this.props.children\n
", this)

The transform step converts any call to "___reactJadeTransform" into a React Component. With this approach, the function call should survive through any intermediate steps by conventional transpilers, as it is just a standard Javascript function call with a string argument and this attached. The latter argument is used so the transformer can keep up with arrow function assignment of the this variable.

That said though, the transformation is now isolated to JUST the reactJadeTransforms themselves, so often you can do all React Jade Transformations before any other parsers, so long as the next step is the chain supports standard Javascript syntax.


var reactJade = require("react-jade-transformer");

gulp.task("node", function() {
  return gulp.src("./test/*.js")

The Gulp Transformer supports the same options as Browserify:

var reactJade = require("react-jade-transformer");
var coffee = require("gulp-coffee");

gulp.task("node", function() {
  return gulp.src("./test/*.js")
             .pipe(reactJade.gulp({prepare: true}))
             .pipe(reactJade.gulp({transform: true}))

Babel Plugin

Transformation must be done before the babel transform, so for example, using Babel directly you would do the following:

var babel = require("babel");
var reactJade = require("react-jade-transformer");

babel.transform("code", {
  plugins: [
    {transformer: reactJade.babel, position: "before"},

In this way, React Jade will play nice with any other transformations you have.


Copyright (c) 2015 Offsider, used under The MIT License (MIT)

License provided in