Pug
Pug is a templating engine for HTML that allows you to write a simpler more condense webpage, as well as integrating Javascript to dynamically generate pages.
Getting Started
Local
Install it using NPM: npm i -g pug-cli
. You can compile a Pug file directly, or by watching the file and it's dependencies for changes.
# compile the single file
pug filename.pug -o ./outputfolder
# watch the file and its dependencies for changes and compile on change
pug -w filename.pug -o ./outputfolder
NPM
Install using npm i pug
. To use it in a project, you can do it two ways: compiling the Pug source ahead of time and passing in new dynamic data on render, or compiling and rendering in one step. The latter is much less efficient, as it is re-compiled every time it is run.
index.pug
body
h1= headerText
app.js
const pug = require('pug');
// Compiling ahead of time
const renderIndex = pug.compileFile('index.pug');
const pageHTML = renderIndex({ headerText: "Hello" });
const differentHTML = renderIndex({ headerText: "World" });
// Compiling and rendering all at once (less efficient)
const pageHTML = pug.renderFile('index.pug', { headerText: "Hello" });
const differentHTML = pug.renderFile('index.pug', { headerText: "World" });
Iteration/Testing
You can do quick testing of code at https://pughtml.com/.
Syntax
Writing HTML in Pug is very similar to Emmet shorthand/selectors in CSS.
element#id.class(attr="value" foo="bar") innerText
doctype html
html(lang="en")
body
header#header.header.header__wrapper
.header__logo
span
img.header__logo-img(src="..." alt="Logo")
| Some <b>text</b>!
h1 Company Name
//- outputs
//- <!DOCTYPE html>
//- <html lang="en">
//- <body>
//- <header id="header" class="header header__wrapper">
//- <div class="header__logo">
//- <span><img src="..." alt="Logo" /> Some <b>text</b>!</span>
//- </div>
//- <h1>Company Name</h1>
//- </header>
//- </body>
//- </html>
Comments
// This comment will appear in the HTML
//- This is a silent comment
//-
Nesting inside a comment creates
a comment block
Javascript
Any line that starts with a hyphen or anything that follows an equals sign in an attribute list can be valid Javascript.
- var num = 6;
- var name = "John Smith";
h1(data-name= name.replace(/\s/, '.').toLowerCase())= `This guy is probably ${num} feet tall!`
p
span thing!
= name
//- outputs
//- <h1 data-name="john.smith">This guy is probably 6 feet tall!</h1>
//- <p><span>thing!</span>John Smith</p>
Inline Elements
h1: span.header Yeah!
p.
#[strong A strong phrase] in the middle of some #[em other] pug tags.
//- Outputs
//- <h1><span class="header">Yeah!</span></h1>
//- <p><strong>A strong phrase</strong> in the middle of some <em>other</em> pug tags</p>
Multiline
p.
This text can be broken
up on multiple lines
p
img(src="stuff")
| This works, too.
//- outputs
//- <p>This text can be broken
//- up on multiple lines</p>
//- <p><img src="stuff" />This works, too.</p>
script.
console.log('or here');
// Works for script tags, as well.
Self-Closing Tags
hr
//- outputs <hr/>
foo/
//- outputs <foo/>
Imports / Include
Pug allows import of HTML directly as well as Pug files.
include filename.pug
include another.html
Variables
Variables in Pug are defined as they are in Javascript and should be preceded by a hyphen. Multiline variable definitions are done by starting a line with a hyphen, leaving no whitespace, and continuing indented on the next line. As long as the indentation remains, you will be in "Javascript land".
- var location = 'russia';
-
var obj = {
thing: "one",
otherThing: "two",
}
p= location
span(class= obj.thing) OK
//- outputs
//- <p>russia</p>
//- <span class="one">OK</span>
Conditionals
- var location = 'russia';
- var cold = true;
if location === 'los-angeles'
p Party!
else if location === 'mexico'
p MORE Party!
else if cold
p cold party
else
p no party
span= cold ? "Brr!" : "*panting*"
//- outputs
//- <p>cold party</p>
//- <span>Brr!</span>
Iteration
Arrays
- var items = ['candy', 'cake', 'ice cream'];
each item in items
p.item(id= item.replace(' ', '-'))= item.toUpperCase()
//- outputs
//- <p id="candy" class="item">CANDY</p>
//- <p id="cake" class="item">CAKE</p>
//- <p id="ice-cream" class="item">ICE CREAM</p>
Objects
-
var people = {
'John': 'Johnson',
'Ashley': 'Ashtown',
};
each last, first in people
p= first + ' ' + last
//- outputs
//- <p>John Johnson</p>
//- <p>Ashley Ashtown</p>
Mixins
Mixins allow one piece of code to be reused over and over with different variables, returning a modified version of the template within the declaration.
The mixin needs to be declared and defined. It's usually easiest to do this in a separate file and include them in. Lets call this _mixins.pug
:
//- Here the mixins are declared
mixin makeStrong(text)
strong= text
mixin makeList(list)
ul.generated-list
each item in list
li= item
Then the file that will use them needs to include that file:
include _mixins.pug
- const faveFoods = ['pizza', 'pie', 'spaghetti'];
h1 This is my list!
.contents
p
+makeStrong('I love these foods!')
+makeList(faveFoods)
Compiling this will return this HTML:
<h1>This is my list!</h1>
<div class="contents">
<p><strong>I love these foods!</strong></p>
<ul class="generated-list">
<li>pizza</li>
<li>pie</li>
<li>spaghetti</li>
</ul>
</div>
Template Inheritance
Template inheritance is run by extends
and block
commands. Once a template is created, you can extend
that template and replace each block
as desired. Note that blocks can have defaults, as seen below with block news
.
layout.pug
body
h1 Here is my website
block about
block news
p No news today.
block foot
div Default content
home.pug
extends layout.pug
block about
p About me.
block news
for story in articles
article
p= story.contents
block foot
//- Make defaults disappear by using no content in the block
//- outputs
//- <body>
//- <h1>Here is my website</h1>
//- <p>About me.</p>
//- <article><p>A story's content</p></article>
//- </body>
Unescaped HTML/Javascript
To insert unescaped HTML/Javascript that is located within a string, preface the string with an exclamation and enclose it with curly braces.
- var num = 6;
- var name = "John Smith";
- const john = `This guy is <i>probably</i> ${num} feet tall!`;
h1(data-name= name.replace(/\s/, '.').toLowerCase()) !{john}
p !{'this <b>is it</b>'}
script.
alert('!{name}');
//- outputs
//- <h1 data-name="john.smith">This guy is <i>probably</i> 6 feet tall!</h1>
//- <p>this <b>is it</b></p>
//- <script>alert('John Smith');</script>
Sublime Text Syntax
Packages in Sublime Text are interdependent on each other and many of the default packages are inferior to third-party (e.g. Babel over Javascript). When Pug's Javascript syntax is not cooperating or popping to allow Pug's syntax to take over again, you can Disable Package > Javascript
and install Babel
and this will cause Pug to correctly highlight conditionals and the succeeding code.
If this does not work, you can switch over to Pug (Python)
and that will do ok.
References
- https://www.sitepoint.com/a-beginners-guide-to-pug/
- https://pughtml.com/
- https://devhints.io/pug
- https://pugjs.org/language/conditionals.html
- https://pugjs.org/language/includes.html
- https://cssdeck.com/labs/learning-the-jade-templating-engine-syntax
- https://stackoverflow.com/questions/27107451/how-to-insert-raw-html-in-pug-file-not-include-external-html-file
- https://pugjs.org/language/mixins.html
- https://github.com/davidrios/pug-tmbundle/issues/22
Last modified: 202408230508