Boost your HTML game preprocessing it with Pug.
Overview
Pug is a template engine for Node.js. It acts as a middleman, you write much simpler Pug code, and it compiles it into HTML code that browsers can understand.
Pug can be helpful as we can feed it with reference data, resulting in different HTML. We can make use of conditionals, loops, includes or mixins. Also, Pug supports JavaScript natively, giving us the chance of using JavaScript expressions to format our HTML.
Usage
Basic code
Basically, in Pug you define your tags/elements writing down its name, and indenting its content. Spaces and indentations are, thus, extremely important to get right. This is how you would create a basic HTML5 structure:
Notice how
head
and
body
elements are indented and therefore included inside the
html
tag.
Language reference
Conditionals
In Pug we can make use of the following operators to check for conditions:
if
else-if
else
unless
Parameter | Description |
---|---|
if
(statement) |
Evaluates
statement
to see if it returns true or false. The code nested underneath
if
will run only if
statement
returns true.
|
else if
(statement) |
Chained to an existing
if
or
else if
statement; it only runs if the previous statement evaluated to false. The code nested underneath the
else if
statement will run only if
statement
evaluates to true.
|
else |
The code nested underneath the
else
statement will run only if all previous statements returned false.
|
unless
(statement) |
The negation of
if (statement)
; the code nested underneath
unless
will run only if
statement returns false. It is the same as
if (!statement)
|
- var test = true
unless (test)
h1 Test was false
else if (test == 'string')
h1 Test was a string
else
h1 Test was true
<h1>Test was true</h1>
Loops
Iterate a number of times over data to create your markup.
Parameter | Description |
---|---|
each |
Evaluates over
arrays
and
objects .
|
while |
Evaluates against a condition. |
for |
Evaluates a given number of times. |
// each loop
ul
each val in [1, 2, 3, 4, 5]
li= val
// while loop
- var n = 0;
ul
while n < 4
li= n++
// for loop
- var n = 4;
for (let i = 0; i < n; ++i)
li= i
<!-- each loop-->
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<!-- while loop-->
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<!-- for loop-->
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
Includes
We can include a Pug file inside another. This can be really useful for our Atomic Design approach, mostly with Templates and Pages.
doctype html
html
include includes/head.pug
body
h1 My Site
p Welcome to my super site.
// The contents of includes/head.pug would be:
//
head
title My Site
script(src='/js/main.min.js')
<!DOCTYPE html>
<html>
<head>
<title>My Site</title>
<script src="/js/main.min.js"></script>
</head>
<body>
<h1>My Site</h1>
<p>Welcome to my super site.</p>
</body>
</html>
Mixins
Also useful for Atomic Design, but most focused towards Atoms, Molecules and Organisms, we have the mixins: reusable blocks of Pug code.
// We define our mixin, that accepts the "name" attribute.
mixin pet(name)
li.pet= name
//Then, we make use of it in our code
ul
+pet('cat')
+pet('dog')
+pet('pig')
<ul>
<li class="pet">cat</li>
<li class="pet">dog</li>
<li class="pet">pig</li>
</ul>
Template inheritance
We can use Pug's templating capabilities through the use of
block
and
extends
keywords.
First, we create a base layout file, in which the bits susceptible to be changed or filled are called
block
and its contents indented inside. Bear in mind that this can be empty. If filled, it is just with "defaul" content that will be substituted afterwards when the layout gets extended.
html
head
title Site's title
block scripts
// This is the default content
script(src='/default.js')
body
block content
// This is empty by default
footer
| Site's footer
// Here we declare that we are extending the previous file
extends ../v1/04-templates/layout.pug
block scripts
script(src='/shiny-new-js-that-will-replace-the-layout-one.js')
script(src='/as-many-stuff-as-you-want.js')
// Here we input the data for each differente page based on the template
block content
h1 Hello world!
p Sollicitudin Venenatis Tristique Fermentum Fusce
<!-- The previous Pug code would compile into this HTML -->
<html>
<head>
<title>Site's title</title>
<script src="/shiny-new-js-that-will-replace-the-layout-one.js"></script>
<script src="/as-many-stuff-as-you-want.js"></script>
</head>
<body>
<h1>Hello world!</h1>
<p>Sollicitudin Venenatis Tristique Fermentum Fusce</p>
</body>
</html>
In certain situations, we might want to keep the default contents of the layout, but add more content, we can do so with the
append
and
prepend
functions
// Here we declare that we are extending the previous file
extends ../v1/04-templates/layout.pug
block append scripts
script(src='/appended.js')
<!-- The previous Pug code would compile into this HTML -->
<html>
<head>
<title>Site's title</title>
<script src="/default.js"></script>
<script src="/appended.js"></script>
</head>
<body>
</body>
</html>