Install Pug

1
yarn add pug

Overview

pug.compile() will compile the Pug source code into a JavaScript function that takes a data object(called locals) as an argument. Call that resultant function with your data, then it will return a string of HTML rendered with your data.

The compiled function can be re-used, and called with different sets of data.

1
2
// - template.pug
p #{name}'s Pug source code!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const pug = require('pug')
// Compile the source code
const compiledFunction = pug.compile('template.pug')
// Render a set of data
console.log(compiledFunction({
name: 'Timothy'
}))
// "<p>Timothy's Pug source code!</p>"

// Render another set of data
console.log(compiledFunction({
name: 'Forbes'
}))

// "<p>Forbes' Pug source code!</p>"

Pug also provides the pug.render() family of functions that combine compileing and rendering into one step. However, the template function will be re-compiled every time render is called, which might impact performance. Alternatively, you can use the cache option with render, which will automatically store the compiled function into an internal cache.

1
2
3
4
5
6
const pug = require('pug')

// Compile template.pug and render a set of data
console.log(pug.renderFile('template.pug', {
name: 'Timothy'
}))

Use with Express

Pug fully integrates with Express, as a supported view engine.

Production Defaults

In Express, the environmental variables NODE_ENV is designed to inform the web application of the execution environment: whether it is in development or in production. Express and Pug automatically modify the defaults of a few options in production environment, to provide a better out-of-the-box experience for users.

Specifically, when process.env.NODE_ENV is set to 'production', and Pug is used with Express, the compileDebug option is false by default, while the cache option is true.

API Reference

All API mehtods accept the following set of options:

  • filename: string

    The name of the file being compiled. Used in exceptions, and required for relative include and extend. Default to Pug

  • basedir: string

    The root directory of all absolute inclusion

  • 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.

  • filters: object

    Hash table of custom filters. Default to undefined

  • self: boolean

    Use a self namespaces to hold the locals. It will speed up the compilation, but instead of writing variable you will have to write self.variable to access to property of the locals object. Default to false

  • debug: boolean

    If set to true, the tokens and function body are logged to stdout

  • compileDebug: boolean

    If set to true, the function source will be included in the compiled template for better error messages. It is enabled by default, unless used with express in production mode.

  • globals: Array

    Add a list of global names to make accessible in templates

  • cache: boolean

    If set to true, compiled functions are cached. filename must be set as the cache key. Only applies to render functions. Default to false

  • inlineRuntimeFunctions: boolean

    Inline runtime functions instead of require-ing them from a shared version. For compileClient functions, the default is true(so that one does not have include the runtime). For all other compilation or rendering types, the default is false

  • name: string

    The name of the template function. Only applies to compileClient function. Default to template.

Methods

  • pug.compile(source[, options])

    Compile a Pug template to a function, which can be rendered multiple times with different locals.

    • source: string

      the source pug template to compile

    • options: An option object

    • returns: function

      A function to generate the HTML from an object containing locals

    1
    2
    3
    4
    var pug = require('pug')
    var compiledTemplate = pug.compile('string of pug', options)

    var html = compiledFunction(locals)
  • pug.compileFile(path[, options])

    Compile a Pug template from a file to a function, which can be rendered multiple times with different locals.

    • path: string

      The path to a Pug file

    • options: An option object

    • returns: function

      A function to generate HTML from an object containing locals

    1
    2
    3
    var pug = require('pug')
    var compiledTemplate = pug.compileFile('path to pug file', options)
    var html = compiledTemplate(locals)
  • pug.compileClient(source[, options])

    Compile a Pug template to a string of JavaScript, which can be used client side along with Pug runtime.

    • source: string

      The Pug template to compile

    • options: an option object

    • returns: string

      A string of JavaScript representing a function

    1
    2
    3
    var pug = require('pug')
    var compiledTemplate = pug.compileClient('string of pug', options)
    var html = compiledTemplate(locals)
  • pug.render(source[, options[, callback]])

    • source: string

      The source pug template to render

    • options: an options object

    • callback: function

      Node.js-style callback receiving the rendered results. The callback is called synchronously.

    • returns: string

      The resulting HTML String

  • pug.renderFile(path[, options[, callback]])

    • path: string

      the path to the pug file to render

    • option: an options object

    • callback: function

      Node.js-style callback receiving the rendered results. This callback is called synchronously.

    • returns: function

      The resulting HTML stirng

Attributes

Tag attributes look similar to HTML(with optional commas), but their values are just regular JavaScript.

1
a(href='google.com') Google => <a href="google.com">Google</a>

Normal JavaScript expression works fine:

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

Multiline Attributes

1
2
3
4
5
6
input(
type='checkbox'
name='agreement'
checked
)
=> <input type="checkbox" name="agreement" checked />

If your JavaScript runtime supports ES6 template strings, you can use that syntax for attributes.

1
2
3
4
5
6
7
8
9
10
11
12
input(data-json=`
{
"very-long": "piece of",
"data": true
}
`)
=> <input data-json="
{
&quot;very-long&quot;: &quot;piece of &quot;,
&quot;data&quot;: true
}
"/>

Quoted Attributes

If your attribute name contains odd character that might interfere with JavaScript syntax, either quote it using "" or '', or use commas to separate different attributes.

1
2
3
div(class='div-class', (click)='play()')
div(class='div-class' '(click)'='play()')
=> <div class="div-class" (click)="play()"></div>

Attribute Interpolation

  • Simply write the attribute in JavaScript:

    1
    2
    3
    4
    5
    6
    7
    var url = 'pub-test.html'
    a(href='/' + url) Link => <a href='/pub-test.html'>Link</a>

    var btnType = 'info'
    var btnSize = 'lg'
    button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)
    => <button type="button" class="btn btn-info btn-lg"><button>

Boolean Attributes

1
2
3
4
input(type='checkbox' checked) => <input type="checkbox" checked="checked" />
input(type='checkbox' checked=true) => <input type="checkbox" checked="checked" />
input(type='checkbox' checked=false) => <input type="checkbox" />
input(type='checkbox' checked=true.toString()) => <input type="checkbox" checked="true" />

Style Attributes

The style attribute can be a string, like any normal attribute, but it can be an object, which is handy when styles are generated by JavaScript:

1
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 is also can be an array of class names, which is handy when generated from JavaScript.

1
2
3
4
var classes = ['foo', 'bar', 'baz']
a(class=classes) => <a class="foo bar baz"></a>

a.bang(class=classes class=[bing]) => <a class="bang foo bar baz bing"></a>

It can also be an object which maps class names to true or false values. This is useful for applying conditional classes:

1
2
var currentURL = '/about'
a(class={active: currentURL === '/about' href='/about'}) => <a class="active"></a>

Class Literal

Classes may be defined using a .classname syntax:

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

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

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

ID Literal

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

&attributes

Pronounced as and attributes, the &attributes syntax can be used to expode an object into attributes of an element:

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

Case

The case statement is a shorthand for JavaScript’s switch, it takes the following form:

1
2
3
4
5
6
7
8
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

Case Fall Through

You can use fall through, just as you would in a JavaScript switch statement

1
2
3
4
5
6
7
8
var friends = 0

case friends
when 0
when 1
p you have very few friends
default
p you have #{friends} friends

The difference, however, is a fall through in JavaScript happens whenever a break statement is not explicitly included.

Code

Pug allows you to write inline JavaScript code in your templates. There are three types of code: Unbuffered, Buffered, and Unescaped Buffered.

Unbuffered Code

Unbuffered code starts with -. It does not directly add anything to the output

1
2
3
4
5
6
7
8
- for (var x = 0; x < 3; x++)
li item

=>

<li>item</li>
<li>item</li>
<li>item</li>

Pug also supports block unbuffered code:

1
2
3
4
5
6
7
8
9
10
11
12
13
-
var list = ['Uno', 'Dos', 'Tres', 'Cuatro', 'Cinco', 'Seis']
each item in list
li= item

=>

<li>Uno</li>
<li>Dos</li>
<li>Tres</li>
<li>Cuatro</li>
<li>Cinco</li>
<li>Seis</li>

Buffered Code

Buffered code start with =. It evaluates the JavaScript expression and outputs the result. For security, buffered code is first HTML excaped.

1
2
3
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 expression:

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

Unescaped Buffered Code

Unescaped buffered code starts with !=. It evaluates the JavaScript expression and outputs the result. Unescaped buffered code does not perform any escaping, so is unsafe for user input.

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

Comments

Buffered comments look the same as single-line JavaScript comments. They act sort of like markup tags, producing HTML comments in the rendered page.

Like tags, buffered comments must appear on their own line:

1
2
3
4
5
6
7
8
9
// just some paragraphs
p foo
p bar

=>

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

Pug also supports unbuffered comments, Simply ass a hyphen(-) to the start of the comment.

These are only for commenting on the Pug code itself, and do not appear in the rendered HTML.

1
2
3
4
5
6
//- will not output within markup
p foo

=>

<p>foo</p>

Block Comments

1
2
3
4
5
body
//- Comments for your templates writers.
Use as much text as you want
// Comments for your HTML readers
Use as much text as you want

Conditionals

Pug’s first-class conditional syntax allows for optional parenthese.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- var user = { description: 'foo bar baz '}
- var authorized = false
#user
if user.description
h2.green Description
p.description= user.description
else if authorized
h2.blue Description
p.description.
User has no description
why not add one...
else
h2.red Description
p.description User has no description

Pug also provides the conditional unless which works like a negated if. The following are equivalent:

1
2
3
4
5
6
7
unless user.isAnonymous
p You're logged in as #{user.name}

=

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

Filters

Include

Include allow you to insert the contents of one Pug file into another.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// index.pug
doctype html
html
include includes/head.pug
body
h1 My Site
p Welcome to my super lame site
include includes/foot.pug

// includes/head.pug
head
title My Site
script(src='/javascripts/jquery.js')
script(src='/javascripts/app.js')

// includes/foot.pug
footer#footer
p Copyright (c) foobar

If the path is absolute(e.g. include /root.pug), it is resolved by prepending options.basedir.

If no file extension is given, .pug is automatically appended to the file name.

Including Plain Text

Including non-Pug files simply includes their raw text.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// index.pug
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('Yor are awesome')

Template Inheritance

Pug supports template inheritance. Template instance works via block and extends keyword.

In a template, a block is simply a ‘block’ of Pug that a child template may replace. This process is recursive.

Pug blocks can provide default content, if appropriate. Providing default content is purely optional, though. The example below defines block scripts, block content and block foot

1
2
3
4
5
6
7
8
9
10
11
// layout.pug
html
head
title My Site - #{title}
block scripts
script(src='/jquery.js')
body
block content
block foot
#footer
p some footer content

To extend this layout, create a new file and use the extends directive with a path to the parent template(if no file extension is given, .pug is automatically appended to the file name). Then define one or more blocks to override the parent block content.

1
2
3
4
5
6
7
8
9
10
11
12
// page-a.pug
extends layout.pug

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

block content
h1= title
- var pets = ['cat', 'dog']
each petName in pets
include pet.pug
1
2
// pet.pug
p= petName

Block append/prepend

Pug allows you to replace, prepend and append blocks

Suppose you have default scripts in a head block that you wish to use on every page you might do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// layout.pug
html
head
block head
script(src="/vendor/jquery.js")
script(src="/vendor/caustic.js")
body
block content

// page.pug
extends layout

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

Interpolation

String Interpolation, Escaped

Consider the placement of the following tempalte’s locals: title, author and theGreat

1
2
3
4
5
6
7
- var title = 'On Dogs'
- var author = 'enlore'
- var theGreat = '<span>escaped!</span>'

h1= title
p Written by #{author}
p This will be safe: #{theGreat}

This can be valid JavaScript expression, so you can do whatever feels good.

1
2
- var msg = 'not my inside voice'
p This is ${msg.toUpperCase()}

String Interpolation, Unescaped

You don’t have to play it safe, you can buffer unescaped values into your templates too

1
2
3
- var riskyBusiness = '<em>Some of the girts</em>'
.quote
p joel: !{riskyBusiness}

Keep in mind that buffering unescaped content into your templates can be mighty risky if that content comes fresh from your users.

Tag Interpolation

Interpolation works not only on JavaScript values, but on Pug as well, just use the tag interpolation syntax like so:

1
2
p.
Interpolate #[strong strongly word] there

Whitespace Control

The tag interpolation syntax is especially useful for inline tags, where whitespace before and after the tag is significant.

By default, however, Pug removes all spaces before and after tags.

Iteration

Pug supports two primary methods of iteration: each and while

each

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ul
each val, index in [1, 2, 3, 4]
li= index + ': ' + val

ul
each val, index in {1: 'one', 2: 'two'}
li= index + ': ' + val

- var values = []
ul
each val in values.length ? values : ['There is no value']
li= val

ul
each val in values
li= val
else
li There is no value

While

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

Mixins

Mixins allow you to create reusable blocks of Pug

1
2
3
4
5
6
7
8
9
10
// Declaration
mixin list
ul
li foo
li bar
li baz

// Use
+list
+list
1
2
3
4
5
6
7
8
9
10
11
12
mixin pet(name)
li.pet= name

ul
+pet('cat')
+pet('dog')

=>
<ul>
<li class="pet">cat</li>
<li class="pet">dog</li>
</ul>

Mixin Attributes

Mixins also get an implicit attributes argument, which is taken from the attributes passed to the mixin

1
2
3
4
5
6
mixin link(href, name)
a(class!=attributes.class href=href)= name

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

Note: The values in attributes by default are already escaped, you should use != to avoid escaping them a secondtime.

Rest Arguments

You can write mixins that takes an unknown number of arguments using the rest arguments syntax

1
2
3
4
5
6
mixin list(id, ...items)
ul(id=id)
each item in items
li= item

+list('my-list', 1,2,3,4)

Plain Text

Pug provides four ways of getting plain text

Inline in a Tag

The easiest way to add plain text is inline. The first term on the line is the tag itsel. Everything after the tag and one space will be the text content of that tag.

1
p This is plain old <em>text</em> content.

Literal HTML

Whole lines are also treated as plain text when they begin with a left angle bracket (<), which may occasionally be useful for writing literal HTML tags in places that could otherwise be inconvenient.

1
2
3
4
5
<html>
body
p Indenting the body tag there will make no difference
p HTML itself isn not whitespace-sensitive
</html>

Piped Text

Another way to add plain text to templates is to prefix a line with a pipe character (|). This method is useful for mixing plain text with inline tag.

1
2
3
4
5
p
| The pipe always goes at the beginning of its own line,
| not counting indentation.
=>
<p>The pipe always goes at the beginning of its own line, not counting indentation.</p>

Block in a Tag

Often you might want large blocks of text wihtin a tag. To do this, just add a . right after the tag name, or after the closing parenthesis, if the tag has attributes.

1
2
3
4
5
script.
if (usingPug)
console.log('You are awesome')
else
console.log('use pug')

Tags

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

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

1
a: img => <a><img /></a>

self-closing tag

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