Templates by Pug

Pug is a terse and simple templating language for HTML.

Pug

Pug is an elegant templating language, it has roots from Emmet and Haml and is meant for quick, clean HTML coding. Pug is not the most performant out there but for static websites, as is our purpose here it is good enough.

Personally, Pug allows me to write HTML very quickly especially combined with the powers of mixins, a good structure and includes.

Here is a sample hello world page in Pug:

  doctype html
  html
    head
      title title name
    body
      header
        h1#title Hello World
      .container
        p(style="margin-top: 50px;") Lorem ipsum

In pug, comments start with a // or //- for unbuffered code. And javascript starts with a -, you can execute javascript in these blocks.

// this is a comment
//- will not output within markup

- var hello = "world"; console.log(hello);

Tags and Content

The first word in a line is your HTML tag. Anything that starts with a period is a class. Anything that starts with a hash symbol # is an id.

Pug knows when tags are self-closing, like in the next example with img. If no tag is specified, it just uses divs.

Tags, ID and Classes
span.button.orange#alertBtn.primary
<span id="alertBtn" class="button orange primary"></span>

To add text, type it after the element seperated by a space. You can also use pipes | to add a newline for larger blocks of text or whenever you want to seperate two elements with a space or text content.

To add an element on the same line without intending, add a semi-colon : before the new element.

Content
p I'm a paragraph
<p>I'm a paragraph</p>
p
  | I'm another paragraph with a 
  a(href="#") link
  |  inside.
<p>I'm another paragraph with a <a href="#">link</a> inside.</p>
.box
  .box
    .box: .box
<div class="box">
  <div class="box">
    <div class="box">
      <div class="box"></div>
    </div>
  </div>
</div>

Interpolation

You can interpolate content, escaped, unescaped.

Escaped Interpolation
- var myself = "Jack";
- var brother = "John";
- var sister = "Jane";
h1= myself
p Siblings: #{brother} and #{sister}
<h1>Jack</h1>
<p>Siblings: John and Jane</p>

myself follows the basic pattern for evaluating a template local, but the code in between #{ and } is evaluated, escaped, and the result buffered into the output of the template being rendered.

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

Escaped Interpolation
- var tags = ["this", "is", "sparta"];
p #{tags.join("... ").toUpperCase()}!!!
<p>THIS... IS... SPARTA!!!</p>

You can embed HTML through interpolation as well, but you have to make sure it is safe. In the context of static content, this usually will be.

Unescaped Interpolation
- var sum = "<b>"+(4+2)+"</b>"
.sum 4 + 2 = !{sum}
<div class="sum">4 + 2 = <b>6</b></div>

Attributes

Elements can have attributes, these are added in parentheses and seperated by commas.

If you don't put the value of the attribute in a string, then it tries to evaluate a javascript expression.

Attributes
a(href="/") Home
a.button(href="#Away", class="btn") Onwards
<a href="/">Home</a>
<a href="#Away" class="button btn">Onwards</a>

The class attribute can be a string or an object mapping the value to a boolean.

Expressions
- var err = {type: "warning", msg: "You died"}
- var err2 = {type: "error", msg: "Something went wrong"}
.notice(class=err.type == "error" ? 'big red' : 'default') #{err.msg}
.notice(class=err2.type == "error" ? 'big red' : 'default') #{err2.msg)
<div class="notice default">You died</div>
<div class="notice big red">Something went wrong</div>
- var $ = {}; $.page = '/docs'

a.item(class={active: $.page === "/docs"}) Docs
a.item(class={active: $.page === "/about"}) About
<a class="item active">Docs</a>
<a class="item">About</a>

Control

As expected in a rendering engine there are control structures that you can use.

The if / else if / else control
if "pigs" == "fly"
  p Magical world
else if "pigs" == "cats"
  p Impossible!
else
  p Just real life
<p>Just real life</p>
The for loop
- var animals = ["cats", "dogs", "lions", "bears"]
.animals
  for animal in animals
    span.animal #{animal}
  each animal, i in animals
    b(id="a"+i) #{animal}
<div class="animals">
  <span class="animal">Cats</span>
  <span class="animal">dogs</span>
  <span class="animal">lions</span>
  <span class="animal">bears</span>
  <b id="a0">cats</b>
  <b id="a1">dogs</b>
  <b id="a2">lions</b>
  <b id="a3">bears</b>
</div>

Mixins

In the pinnacle of DRY. You can use Mixins which are resuable blocks that you can call repeatedly again and again. They can accept arguments of any type like functions.

Mixins
mixin menuItem(url, content, title)
  a.item(href=url, title=title) #{content}

.menu
  +menuItem("/home", "Home", "Back to home")
  +menuItem("/about", "About Markade", "Learn more about markade")
<div class="menu">
  <a class="item" title="Back to home">Home</a>
  <a class="item" title="Learn more about markade">About Markade</a>
</div>

Templates

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

You can also append content instead of overwriting it. Do this with block append or append for short or prepend for the opposite.

Block, Extends and Append
// _layout.pug
h1 This is the layout
block content

// docs.pug
extends _layout
block content
  p These are the docs

// welcome.pug
extends docs
block append content
  p This is more content
<h1>This is the layout</h1>
<p>These are the docs</p>
<p>This is more content</p>

It is possible to include other pug files. Even a file with only mixins or blocks that won't immediately render.

This is useful to use for a footer, header, sidebar setup for example.

Include
// _menu.pug
a(href="#1") Link
a(href="#2") Link

// docs.pug
p A paragraph
include _menu
<p>A paragraph</p>
<a href="#1">Link</a>
<a href="#2">Link</a>

Resources