DEV Community

Cover image for The Pug Template Engine
Naya Willis
Naya Willis

Posted on

The Pug Template Engine

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>
Enter fullscreen mode Exit fullscreen mode

To install

npm i pug 
Enter fullscreen mode Exit fullscreen mode

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')
Enter fullscreen mode Exit fullscreen mode

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') 
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

The above compiles to

<form action="/path" method="POST">
     ...
</form>
Enter fullscreen mode Exit fullscreen mode

To add a class or id

h1.heading#main_heading Some text
Enter fullscreen mode Exit fullscreen mode

The above compiles to

<h1 class="heading" id="main_heading">
     ...
</h1>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Writing a comment in pug

Uncommented
p Let's comment this out

Commented
//- p Let's comment this out
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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.

Pug Documentation

Top comments (0)