Installation

via npm:

npm install jade

Usage

options

All API methods take the following set of options:

{
filename:
string
Used in exceptions, and required for relative includes and extends
doctype:
string
If the doctype is not specified as part of the template, you can specify it here. It is sometimes useful to get self-closing tags and remove mirroring of boolean attributes.
pretty:
boolean | string
Adds whitespace to the resulting html to make it easier for a human to read using ' ' as indentation. If a string is specified, that will be used as indentation instead (e.g. '\t').
self:
boolean
Use a self namespace to hold the locals (false by default)
debug:
boolean
If set to true, the tokens and function body is logged to stdout
compileDebug:
boolean
Set this to false to disable debugging instrumentation (recommended in production). Set it to true to include the function source in the compiled template for better error messages (sometimes useful in development).
cache:
boolean
If set to true, compiled functions are cached. filename must be set as the cache key.
compiler:
class
Override the default compiler
parser:
class
Override the default parser
globals:
Array.<string>
Add a list of global names to make accessible in templates
}

jade.compile(source, options)

Compile some jade source to a function which can be rendered multiple times with different locals.

source
string
The source jade to compile
options
options
An options object (see above)
returns
function
A function to generate the html from an object containing locals
var jade = require('jade');

// Compile a function
var fn = jade.compile('string of jade', options);

// Render the function
var html = fn(locals);
// => '<string>of jade</string>'

jade.compileFile(path, options)

Compile some jade source from a file to a function which can be rendered multiple times with different locals.

source
path
The path to a jade file
options
options
An options object (see above)
returns
function
A function to generate the html from an object containing locals
var jade = require('jade');

// Compile a function
var fn = jade.compileFile('path to jade file', options);

// Render the function
var html = fn(locals);
// => '<string>of jade</string>'

jade.compileClient(source, options)

Compile some jade source to a string of JavaScript that can be used client side along with the jade runtime.

source
string
The source jade to compile
options
options
An options object (see above)
returns
string
A string of JavaScript representing a function
var jade = require('jade');

// Compile a function
var fn = jade.compileClient('string of jade', options);

// Render the function
var html = fn(locals);
// => 'function template(locals) { return "<string>of jade</string>"; }'

jade.render(source, options)

source
string
The source jade to render
options
options
An options object (see above), also used as the locals object
returns
string
The resulting html string
var jade = require('jade');

var html = jade.render('string of jade', options);
// => '<string>of jade</string>'

jade.renderFile(filename, options)

filename
string
The path to the jade file to render
options
options
An options object (see above), also used as the locals object
returns
string
The resulting html string
var jade = require('jade');

var html = jade.renderFile('path/to/file.jade', options);
// ...

Attributes

Tag attributes look similar to html, however their values are just regular JavaScript.

a(href='google.com') Google
a(class='button', href='google.com') Google
 
<a href="google.com">Google</a><a href="google.com" class="button">Google</a>
 

All the normal JavaScript expressions work fine too:

- var authenticated = true
body(class=authenticated ? 'authed' : 'anon')
 
<body class="authed"></body>
 

If you have many attributes, you can also spread them across many lines:

input(
  type='checkbox'
  name='agreement'
  checked
)
 
<input type="checkbox" name="agreement" checked="checked"/>
 

Unescaped Attributes

By default, all attributes are escaped (replacing special characters with escape sequences) to prevent attacks such as cross site scripting. If you need to use special characters you can use != instead of =.

div(escaped="<code>")
div(unescaped!="<code>")
 
<div escaped="&lt;code&gt;"></div>
<div unescaped="<code>"></div>
 
Danger

Unescaped buffered code can be dangerous. You must be sure to sanatize any user inputs to avoid Cross Site Scripting

Boolean Attributes

Boolean attributes are mirrored by Jade, and accept bools, aka true or false. When no value is specified true is assumed.

input(type='checkbox', checked)
input(type='checkbox', checked=true)
input(type='checkbox', checked=false)
input(type='checkbox', checked=true.toString())
 
<input type="checkbox" checked="checked"/>
<input type="checkbox" checked="checked"/>
<input type="checkbox"/>
<input type="checkbox" checked="true"/>
 

If the doctype is html jade knows not to mirror the attribute and uses the terse style (understood by all browsers).

doctype html
input(type='checkbox', checked)
input(type='checkbox', checked=true)
input(type='checkbox', checked=false)
input(type='checkbox', checked=true && 'checked')
 
<input type="checkbox" checked="checked">
<!DOCTYPE html>
<input type="checkbox" checked>
<input type="checkbox" checked>
<input type="checkbox">
<input type="checkbox" checked="checked">
 

Style Attributes

The style attribute can be a string (like any normal attribute) but it can also be an object, which is handy when parts of the style are generated by JavaScript.

a(style={color: 'red', background: 'green'})
 
<a style="color:red;background:green"></a>
 

Class Attributes

The class attribute can be a string (like any normal attribute) but it can also be an array of class names, which is handy when generated from JavaScript.

- var classes = ['foo', 'bar', 'baz']
a(class=classes)
//- the class attribute may also be repeated to merge arrays
a.bing(class=classes class=['bing'])
 
<a class="foo bar baz"></a><a class="bing foo bar baz bing"></a>
 

It can also be an object mapping class names to true or false values, which is useful for applying conditional classes

- var currentUrl = '/about'
a(class={active: currentUrl === '/'} href='/') Home
a(class={active: currentUrl === '/about'} href='/about') About
 
<a href="/">Home</a><a href="/about" class="active">About</a>
 

Class Literal

Classes may be defined using a .classname syntax:

a.button
 
<a class="button"></a>
 

Since div's are such a common choice of tag, it is the default if you omit the tag name:

.content
 
<div class="content"></div>
 

ID Literal

IDs may be defined using a #idname syntax:

a#main-link
 
<a id="main-link"></a>
 

Since div's are such a common choice of tag, it is the default if you omit the tag name:

#content
 
<div id="content"></div>
 

&attributes

Pronounced "and attributes", the &attributes syntax can be used to explode an object into attributes of an element.

div#foo(data-bar="foo")&attributes({'data-foo': 'bar'})
 
<div id="foo" data-bar="foo" data-foo="bar"></div>
 

The object does not have to be an object literal. It can also just be a variable that has an object as its value (see also Mixin Attributes)

- var attributes = {'data-foo': 'bar'};
div#foo(data-bar="foo")&attributes(attributes)
 
<div id="foo" data-bar="foo" data-foo="bar"></div>
 
Danger

Attributes applied using &attributes are not automatically escaped. You must be sure to sanatize any user inputs to avoid Cross Site Scripting. This is done for you if you are passing in attributes from a mixin call.

Case

The case statement is a shorthand for JavaScript's switch statement and takes the following form:

- var friends = 10
case friends
  when 0
    p you have no friends
  when 1
    p you have a friend
  default
    p you have #{friends} friends
<p>you have 10 friends</p>

Case Fall Through

You can use fall through just like in a select statement in JavaScript

- var friends = 0
case friends
  when 0
  when 1
    p you have very few friends
  default
    p you have #{friends} friends
<p>you have very few friends</p>

Block Expansion

Block expansion may also be used:

- var friends = 1
case friends
  when 0: p you have no friends
  when 1: p you have a friend
  default: p you have #{friends} friends
<p>you have a friend</p>

Code & Interpolation

Jade makes it possible to write inline JavaScript code in your templates. There are three types of code.

Unbuffered Code

Unbuffered code starts with - does not add any output directly, e.g.

- for (var x = 0; x < 3; x++)
  li item
<li>item</li>
<li>item</li>
<li>item</li>

Buffered Code

Buffered code starts with = and outputs the result of evaluating the JavaScript expression in the template. For security, it is first HTML escaped:

p
  = 'This code is <escaped>!'
<p>This code is &lt;escaped&gt;!</p>

It can also be written inline with attributes, and supports the full range of JavaScript expressions:

p= 'This code is' + ' <escaped>!'
<p>This code is &lt;escaped&gt;!</p>

Unescaped Buffered Code

Unescaped buffered code starts with != and outputs the result of evaluating the JavaScript expression in the template. This does not do any escaping, so is not safe for user input:

p
  != 'This code is <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>

It can also be written inline with attributes, and supports the full range of JavaScript expressions:

p!= 'This code is <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>
Danger

Unescaped buffered code can be dangerous. You must be sure to sanatize any user inputs to avoid Cross Site Scripting

Interpolation

Both plain-text and piped-text support interpolation. The following will output the user.name in the paragraph:

- var user = {name: 'Forbes Lindesay'}
p Welcome #{user.name}
<p>Welcome Forbes Lindesay</p>

It is generally recommended that you use = for buffering code unless it is a small amount of code in a large block.

Unescaped Interpolation

You can also use unescaped interpolation to output HTML:

- var user = {name: '<strong>Forbes Lindesay</strong>'}
p Welcome #{user.name}
p Welcome !{user.name}
<p>Welcome &lt;strong&gt;Forbes Lindesay&lt;/strong&gt;</p>
<p>Welcome <strong>Forbes Lindesay</strong></p>
Danger

Unescaped buffered code can be dangerous. You must be sure to sanatize any user inputs to avoid Cross Site Scripting

Comments

Single line comments look the same as JavaScript comments and must be placed on their own line:

// just some paragraphs
p foo
p bar
<!-- just some paragraphs -->
<p>foo</p>
<p>bar</p>

Jade also supports unbuffered comments, by simply adding a hyphen

//- will not output within markup
p foo
p bar
<p>foo</p>
<p>bar</p>

Block Comments

A block comment is legal as well:

body
  //
    As much text as you want
    can go here.
<body>
  <!--
  As much text as you want
  can go here.
  -->
</body>

Conditional Comments

Jade does not have any special syntax for conditional comments. If your line begins with < then it is treated as plain text. So just use normal HTML syle conditional comments:

<!--[if IE 8]>
<html lang="en" class="lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en">
<!--<![endif]-->
<!--[if IE 8]>
<html lang="en" class="lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en">
<!--<![endif]-->

Conditionals

Jade's first-class conditional syntax allows for optional parenthesis, and you may now omit the leading - otherwise it's identical, still just regular javascript:

- var user = { description: 'foo bar baz' }
- var authorised = false
#user
  if user.description
    h2 Description
    p.description= user.description
  else if authorised
    h2 Description
    p.description.
      User has no description,
      why not add one...
  else
    h1 Description
    p.description User has no description
 
  <p class="description">foo bar baz</p>
<div id="user">
  <h2>Description</h2>
  <p class="description">foo bar baz</p>
</div>
 

Jade also provides a negated version unless (the following are therefore equivalent):

unless user.isAnonymous
  p You're logged in as #{user.name}
if !user.isAnonymous
  p You're logged in as #{user.name}

Doctype

doctype html
 
<!DOCTYPE html>
 

Doctype Shortcuts

There are shortcuts for commonly used doctypes:

doctype html
<!DOCTYPE html>
doctype xml
<?xml version="1.0" encoding="utf-8" ?>
doctype transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
doctype strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
doctype frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
doctype 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
doctype basic
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
doctype mobile
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">

Custom Doctypes

You can also use your own literal custom doctype:

doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">
 

Doctype Option

The doctype affects compilation in some other cases, for example self closing tags and boolean attributes). For this reason, you might sometimes want to specify it manually. You can do this via the doctype option. e.g.

var jade = require('./');

// Compile a function
var fn = jade.compile('img(src="foo.png")', {doctype: 'xml'});

// Render the function
var html = fn({});
// => '<img src="foo.png"></img>'

// Compile a function
var fn = jade.compile('img(src="foo.png")', {doctype: 'html'});

// Render the function
var html = fn({});
// => '<img src="foo.png">'

Extends - Template Inheritance

The extends keyword allows a template to extend a layout or parent template. It can then override certain pre-defined blocks of content.

//- layout.jade
doctype html
html
  head
    block title
      title Default title
  body
    block content
//- index.jade
extends ./layout.jade

block title
  title Article Title

block content
  h1 My Article
<!doctype html>
<html>
  <head>
    <title>Article Title</title>
  </head>
  <body>
    <h1>My Article</h1>
  </body>
</html>
Note
You can have multiple levels of inheritance, allowing you to create powerful hierarchies of templates.

Filters

Filters let you use other languages within a jade template. They take a block of plain text as an input.

:markdown
  # Markdown

  I often like including markdown documents.
script
  :coffee
    console.log 'This is coffee script'
<h1>Markdown</h1>
<p>I often like including markdown documents.</p>
<script>console.log('This is coffee script')</script>
Warning

Filters are compile time. This makes them fast but means they cannot support dynamic content.

Built in filters are not available in the browser as they would not all work. Providing you compile your templates server side, they will still work fine though.

Includes

Includes allow you to insert the contents of one jade file into another.

//- index.jade
doctype html
html
  include ./includes/head.jade
  body
    h1 My Site
    p Welcome to my super lame site.
    include ./includes/foot.jade
//- includes/head.jade
head
  title My Site
  script(src='/javascripts/jquery.js')
  script(src='/javascripts/app.js')
//- includes/foot.jade
#footer
  p Copyright (c) foobar
<!doctype html>
<html>
  <head>
    <title>My Site</title>
    <script src='/javascripts/jquery.js'></script>
    <script src='/javascripts/app.js'></script>
  </head>
  <body>
    <h1>My Site</h1>
    <p>Welcome to my super lame site.</p>
    <div id="footer">
      <p>Copyright (c) foobar</p>
    </div>
  </body>
</html>

Including Plain Text

Including files that are not jade just includes the raw text.

//- index.jade
doctype html
html
  head
    style
      include style.css
  body
    h1 My Site
    p Welcome to my super lame site.
    script
      include script.js
/* style.css */
h1 { color: red; }
// script.js
console.log('You are awesome');
<!doctype html>
<html>
  <head>
    <style>
      /* style.css */
      h1 { color: red; }
    </style>
  </head>
  <body>
    <h1>My Site</h1>
    <p>Welcome to my super lame site.</p>
    <script>
      // script.js
      console.log('You are awesome');
    </script>
  </body>
</html>

Including Filtered Text

You can combine filters with includes to filter things as you include them.

//- index.jade
doctype html
html
  head
    title An Article
  body
    include:markdown article.md
# article.md

This is an article written in markdown.
<!doctype html>
<html>
  <head>
    <title>An Article</title>
  </head>
  <body>
    <h1>article.md</h1>
    <p>This is an article written in markdown.</p>
  </body>
</html>

Template inheritance

Jade supports template inheritance via the block and extends keywords. A block is simply a "block" of Jade that may be replaced within a child template, this process is recursive.

Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`.

layout.jade

html
  head
    title My Site - #{title}
    block scripts
      script(src='/jquery.js')
  body
    block content
    block foot
      #footer
        p some footer content

Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output "some footer content".

page-a.jade

extends ./layout.jade

block scripts
  script(src='/jquery.js')
  script(src='/pets.js')

block content
  h1= title
  each pet in pets
    include pet

It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together.

sub-layout.jade

extends ./layout.jade

block content
  .sidebar
    block sidebar
      p nothing
  .primary
    block primary
      p nothing

page-b.jade

extends ./sub-layout.jade

block content
  .sidebar
    block sidebar
      p nothing
  .primary
    block primary
      p nothing

Block append / prepend

Jade allows you to replace (default), prepend, or append blocks. Suppose for example you have default scripts in a "head" block that you wish to utilize on every page, you might do this:

html
  head
    block head
      script(src='/vendor/jquery.js')
      script(src='/vendor/caustic.js')
  body
    block content

Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block:

extends layout

block append head
  script(src='/vendor/three.js')
  script(src='/game.js')

When using `block append` or `block prepend` the `block` is optional:

extends layout

append head
  script(src='/vendor/three.js')
  script(src='/game.js')

Iteration

Jade supports two primary methods of iteration, each and while.

each

Jade's first-class iteration syntax makes it easier to iterate over arrays and objects within a template:

ul
  each val in [1, 2, 3, 4, 5]
    li= val
 
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
 

You can also get the index as you iterate:

ul
  each val, index in ['zero', 'one', 'two']
    li= index + ': ' + val
 
<ul>
  <li>0: zero</li>
  <li>1: one</li>
  <li>2: two</li>
</ul>
 

Jade also lets you iterate over the keys in an object:

ul
  each val, index in {1:'one',2:'two',3:'three'}
    li= index + ': ' + val
 
<ul>
  <li>1: one</li>
  <li>2: two</li>
  <li>3: three</li>
</ul>
 

The object or array to iterate over is just plain JavaScript so it can be a variable or the result of a function call or almost anything else. e.g.

- var values = [];
ul
  each val in values.length ? values : ['There are no values']
    li= val
 
<ul>
  <li>There are no values</li>
</ul>
 

You can also use for as an alias of each.

while

You can also use while to create a loop:

- var n = 0
ul
  while n < 4
    li= n++
 
<ul>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
 

Mixins

Mixins allow you to create reusable blocks of jade.

//- Declaration
mixin list
  ul
    li foo
    li bar
    li baz
//- Use
+list
+list
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>

They are compiled to functions and can take arguments:

mixin pet(name)
  li.pet= name
ul
  +pet('cat')
  +pet('dog')
  +pet('pig')
<ul>
  <li class="pet">cat</li>
  <li class="pet">dog</li>
  <li class="pet">pig</li>
</ul>

Mixin Blocks

Mixins can also take a block of jade to act as the content:

mixin article(title)
  .article
    .article-wrapper
      h1= title
      if block
        block
      else
        p No content provided

+article('Hello world')

+article('Hello world')
  p This is my
  p Amazing article
<div class="article">
  <div class="article-wrapper">
    <h1>Hello world</h1>
    <p>No content provided</p>
  </div>
</div>

<div class="article">
  <div class="article-wrapper">
    <h1>Hello world</h1>
    <p>This is my</p>
    <p>Amazing article</p>
  </div>
</div>

Mixin Attributes

Mixins also get an implicit attributes argument taken from the attributes passed to the mixin:

mixin link(href, name)
  //- attributes == {class: "btn"}
  a(class!=attributes.class, href=href)= name

+link('/foo', 'foo')(class="btn")
<a href="/foo" class="btn" >foo</a>
Note
The values in attributes are already escaped so you should use != to avoid escaping them a second time (see also unescaped attributes).

You can also use with &attributes (see also &attributes)

mixin link(href, name)
  a(href=href)&attributes(attributes)= name

+link('/foo', 'foo')(class="btn")
<a href="/foo" class="btn" >foo</a>

Rest Arguments

You can write mixins that take an unknown number of arguments using the "rest arguments" syntax. e.g.

mixin list(id, ...items)
  ul(id=id)
    each item in items
      li= item

+list('my-list', 1, 2, 3, 4)
<ul id="my-list">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

Plain Text

Jade provides three common ways of getting plain text. They are useful in different situations

Piped Text

The simplest way of adding plain text to templates is to prefix the line with a | character (pronounced "pipe").

| Plain text can include <strong>html</strong>
p
  | It must always be on its own line
Plain text can include <strong>html</strong>
<p>It must always be on its own line</p>

Inline in a Tag

Since it's a common use case, you can put text in a tag just by adding it inline after a space.

p Plain text can include <strong>html</strong>
<p>Plain text can include <strong>html</strong></p>

Block in a Tag

Often you might want large blocks of text within a tag. A good example is with inline scripts or styles. To do this, just add a . after the tag (with no preceding space):

script.
  if (usingJade)
    console.log('you are awesome')
  else
    console.log('use jade')
<script>
  if (usingJade)
    console.log('you are awesome')
  else
    console.log('use jade')
</script>

Tags

By default, text at the start of a line (or after only white space) represents an html tag. Indented tags are nested, creating the tree like structure of html.

ul
  li Item A
  li Item B
  li Item C
<ul>
  <li>Item A</li>
  <li>Item B</li>
  <li>Item C</li>
</ul>

Jade also knows which elements are self closing:

img
<img/>

Block Expansion

To save space, jade provides an inline syntax for nested tags.

a: img
<a><img/></a>

Self Closing Tags

Tags such as img, meta, link and so on are automatically self-closing (unless you use the xml doctype). You can also explicitly self close a tag by simply appending the / character. Only do this if you know what you're doing

foo/
foo(bar='baz')/
<foo/>
<foo bar="baz"/>