What is Pug?
Formerly known as Jade, Pug is a template engine for Node/Express. It allows you to write dynamic HTML which converts to plain HTML. In pug, when defining your html you don't have to use closing tags. You only specify the opening one. Once the file is converted to plain html, it will create the opening and closing tags for you.
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title=title
=>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport", content="width=device-width, initial-scale=1.0">
<title>This Page</title>
</head>
</html>
To install
npm i pug
To use
Make sure that after you install it, that you tell express to set pug as your preferred template engine like so:
app.set('view engine', 'pug')
Optionally, you should tell it where to look for your pug files as well. Most likely you'll have them in a views folder which is the default. If you have them in a different folder, you'll have to explicitly tell express:
app.set('views', 'folder')
Now that that's finished, let's go over some Pug syntax.
Defining Attributes
To define attributes you define the html element, then immediately next to it (no whitespaces) you define the attributes within parenthesis like so:
form(action="/path" method="POST")
The above compiles to
<form action="/path" method="POST">
...
</form>
To add a class or id
h1.heading#main_heading Some text
The above compiles to
<h1 class="heading" id="main_heading">
...
</h1>
Note the text 'Some text'. To actually define text content you put a whitespace after you have finished defining your attributes, classes, id, what have you.
To define dynamic content
Say inside your backend somewhere in a render method, you passed some data to that method in an object.
i.e res.render('/path', { title: "This Page" })
To use the value of 'title', there are 2 ways to make this happen.
title=title
or
title #{ title }
Either or works and compiles to
<title>This Page</title>
Writing a comment in pug
Uncommented
p Let's comment this out
Commented
//- p Let's comment this out
Conditionals
Say you wanted to render some content, ONLY if the user is logged in. That would look a little something like so:
if user.loggedIn
a.logout_button(href='/logout') Logout
else
a.login_button(href='/login') Login
The a tags convert to
<a class="logout_button" href='/logout'>Logout</a>
<a class="login_button" href='/login'>Login</a>
INDENTATION IS IMPORTANT. Make sure you are indenting accordingly. If the if statement above belongs in a header, then that's where you should put it.
Iterations
More often than not you will be making requests to a database to get some data to work with. For example, you make a request to your backend to get all of your favorite cars. Each car has a make, model, image. It just so happens you have 3 currently. If you wanted to display this on a webpage dynamically, you would do this:
div.car_card
if favCars.length > 0
each car in favCars
div.card
div.car_image
img(src=car.image alt="car image")
div.car_make
h1=car.make
div.car_model
h2=car.model
else
p No cars available
The above converts to
<div class="car_card">
<div class="card">
<div class="car_image">
<img src="/nissan.png" alt="car image"/>
</div>
<div class="car_make">
<h1>Nissan</h1>
</div>
<div class="car_model">
<h2>Maxima</h2>
</div>
</div>
</div>
The above defines a cars card template. This template will be used for each car rendered.
< CAR IMAGE >
CAR MAKE
CAR MODEL
repeat 3x (your 3 favorite cars in the database)
Extends and Blocks
Using the extends keyword with a file path defined in addition, allows us to inherit some template code from that file into the current file you are working in.
The easiest example I can provide is this:
//- main-layout.pug
html
head
title=title
link(rel="stylesheet" href="/css/index.css")
block links
Here we define a layout.pug template that has the basic html tree structure. It has a head which has a title which is set dynamically. Then it has a link that points to the css folder containing an index.css file. We specify that link because we want the styles defined in index.css to be used across all files that we 'extend' this template to. We then use the block keyword in addition to any name you want to use next to it. In our case we used links. What happens now is that when we extend this template to another pug file we can create additional links to css files that are only relevant to that specific pug file.
//- cars.pug
extends layouts/main-layout.pug
block links
link(rel="stylesheet" href="/css/cars.css")
Now the cars.pug file has everything that's in the main-layout.pug file PLUS the newly added link to the cars.css file. This keeps our code DRY. We don't have to copy the html tree structure from the main-layout.pug file and then paste it in the cars.pug file.
Partials work similarly, but in pug it's referred to as includes.
There's more that you can do with pug. I covered some of the basics. To learn more read their documentation.
Top comments (0)