Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / Node.js

Feeling Jaded with Jade? Don't Be!

4.96/5 (13 votes)
30 Mar 2016CPOL11 min read 68.9K  
Look into the Jade Templating engine and the required syntax

Introduction

There are times when you want to go and experiment with new frameworks, tools, languages or "a.n.other thing" and it all goes well until you try to get your head around the syntax. You look at the documentation or the reference section of the website/wiki/pdf and yes the basics are covered, but sometimes there is still not enough to answer your eager questions of "How Do I...?".

Hopefully things will soon become clear(er)!

What is Jade

As you may guess from the Introduction, Jade is a view engine or more specifically a templating engine. The authors describe it as "a terse and simple templating language with a strong focus on performance and powerful features". Node.js is a JavaScript event driven server technology and by using the Express module you can use an out of the box web application framework. The templates and web pages served to the callers are generated by the templating engine, which by default is configured to be Jade. There are many others available all with slightly different focus or goals which you can choose as you see fit, however this is outwith the scope of this article.

Putting it another way, Jade provides a method of writing cleaner markup which when called by the web application is converted to HTML compliant syntax for presenting to the browser.

To get a flavour of what is to come lets take a look at this very simple example:

HTML Markup Jade Equivalent
HTML
<!DOCTYPE html>
<html>
<head>
<title>Jade Demo</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body><h1>Welcome CodeProject</h1>
<p>Welcome to this Jade Article</p>
</body>
</html>
doctype html
html
  head
    title Jade Demo
    link(rel='stylesheet', href='http://www.codeproject.com/stylesheet/style.css')
  body
    h1 Welcome CodeProject
    p Welcome to this Jade Article

As you can see, it is clean, structured, no closing tags, no <> brackets.

Are you ready?

Document Structure

With the Jade templating system each Jade document has the .jade file extension. The content of the file is a whitespace indented structure, with each tag (generally, see Shortforming later) represented on a new line. Nested tags such as list items within an ordered list would be indented deeper than the parent tag. This can clearly be seen on the example above with the HTML, HEAD, TITLE relationship.

You cannot mix and match whitespace, so either use tabs or spaces, it gets upset if you don't. See the note later on this.

Layouts and Block Content and Stylesheets

If you are a ASP developer, then you will be familiar with the concept of master pages. This concept can also be used within Jade. You might have a website that has common functionality that you wish to have on every page. Rather than including this content on every page you write, you simply refer to an existing layout template. This is achieved using the extends keyword. In addition to this, the page may be broken up into sections, these sections can be referred to as blocks. The template engine will match up the relevant block to content and populate accordingly. The 'content' is an arbitrary identifier given to the block.

For example, my index page might be wrapped by the generic site master layout in which case on the index page I could do;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers

The layout.jade would contain all the generic HTML markup;

doctype html
html
  head
    title Hello CodeProject
    link(rel='stylesheet', href='http://www.codeproject.com/stylesheets/style.css')
  body
    block content

You can also see in the above example how we can refer to CSS stylesheets using the link tag. This would generate the following markup if you were to look at the browser page source;

HTML
<!DOCTYPE html>
<html>
<head>
<title>Hello CodeProject</title>
<link rel="stylesheet" href="http://www.codeproject.com/stylesheets/style.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Welcome to CodeProject Readers</p>
</body>
</html>

NOTE: When working in Visual Studio, it is very easy to get caught out by using different whitespace methods, e.g. Tabs or Spaces, VS will throw an exception if you mix and match. I recommend that you turn on "View Whitespace" from the "Edit|Advanced" menu (hotkey CTRL+E,S).

Also, if you have used tabs, it is easy to convert this to spaces by using the "Untabify Selected lines" from the same menu.

You could also permanently set the text editor to use spaces instead of tabs.

Jade also supports include, which simply tells the Jade engine to include another Jade file in the output, e.g.

include somefolder/somefile

would require the somefile.jade file in the somefolder to be added to the content.

You will also notice that in the examples above, reference to the layout file and the included files does not need to have the .jade extension, this is automatic.

Handling Javascript, Referencing Libraries

Many web pages nowadays cannot exist without reference to JavaScript libraries or have JavaScript functions embedded within them. Fortunately, Jade can handle these scenarios without any problem.

If we take the page above and wanted to reference jQuery and then use the jQuery document ready handler to display an alert, this is no problem. To the layout.jade we can add the reference to the jQuery library, I'll point it to the public CDN on the jQuery domain.

doctype html
html
  head
    title Hello CodeProject
    link(rel='stylesheet', href='http://www.codeproject.com/stylesheets/style.css')
    script(type='text/javascript', src='http://code.jquery.com/jquery-1.11.0.min.js')
  body
    block content

And on the index page add in the JavaScript jQuery ready handler and function to trigger the alert;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });

NOTE: If you are paying close attention you will notice that at the end of the script(...) reference you will see a period '.', this has special meaning to the Jade parser that everything that follows (up to the next tag) is treated as part of the content for that element.

This period '.' can also be used with other tags, for example the paragraph p;

p. 
  This is some text in the paragraph and
  it is continuing across more than one
  line, but will appear as a continuous 
  paragraph in the output.

So far we have looked at the basic structure of Jade documents, used the Extend and Block keywords and also seen how we can reference CSS or JavaScript files and include other Jade files or JavaScript in the page.

Tags and Classes

Following on from where we were with the demo, let us now add some class information into the mix. On the index page, let us define a new style via the 'bigred' class and apply it to a new paragraph on the page;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });
  p.bigred Another paragraph with some styling applied.

  style.
    .bigred 
    { 
    font-size: 1.5em;
    color: red; 
    }

You can see the class is applied by simply appending the class name to the paragraph using the '.', p.bigred It is also possible to apply multiple different classes to the one tag by simply chaining the names of the classes. For example, lets define an italic class style and apply it to the same paragraph, using p.bigred.italic;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });



  p.bigred.italic Another paragraph with some styling applied.

  style.
    .bigred 
    { 
    font-size: 1.5em;
    color: red; 
    }
    .italic
    {
     font-style: italic;
    }

If we take everything done so far, you can see how this all looks in the generated HTML output;

HTML
<!DOCTYPE html>
<html>
<head>
<title>Hello CodeProject</title>
<link rel="stylesheet" href="http://www.codeproject.com/stylesheets/style.css">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js">
</script>
</head>
<body>
<h1>Hello World!</h1>
<p>Welcome to CodeProject Readers</p>
<script type="text/javascript">$(document).ready(function() {
                    alert("Hello CodeProject!");
                    });
                    </script>
<p>This is some text in the paragraph and
it is continuing across more than one
line, but will appear as a continuous 
paragraph in the output.
</p>
<p class="bigred italic">Another paragraph with some styling applied.</p>
<style>.bigred 
{ 
font-size: 1.5em;
color: red; 
}
.italic
{
 font-style: italic;
}</style>
</body>
</html>

Naming elements

You may of course want to give elements names. You may wish to reference them in code or just be able to see what is what. It is easy to name an element via its id attribute by simply using the # symbol. for example;

Jade HTML
p#IntroText This is the intro text paragraph
HTML
<p id="IntroText">This is the intro text paragraph</p>

This can of course be mixed with adding the class names. So now we have;

Jade HTML
HTML
p.underline#AnotherPara This is another named paragraph with a class applied.
HTML
<p id="AnotherPara" class="underline">This is another named paragraph with a class applied.</p>

The DIV

The DIV element is probably one of the most commonly used tags now in web development. The Jade developers have also taken this into consideration. Simply starting with an identifier and optional class name will automatically render a div.

Jade HTML
#MyDiv
#AnotherDiv.underline
HTML
<div id="MyDiv"></div>
<div id="AnotherDiv" class="underline"></div>
 

Other Common Tags

We have already looked at paragraph tag p in the examples above, let us take a look at some of the other common tags.

Ordered List (OL), Unordered List (UL), ListItem (LI)

In the same way as many of the other tags it is simply a case of starting on a new line and nesting to the appropriate indent. Let us create both of these types of list within their own div blocks and wrap them both up in another parent div;

Jade HTML
#ListExamples
  #ULExample
    ul
      li This is a list item
      li This is another list item

  #OLExample
    ol
      li This is a list item
      li This is another list item
HTML
<div id="ListExamples">
<div id="ULExample">
<ul>
<li>This is a list item</li>
<li>This is another list item</li>
</ul>
</div>
<div id="OLExample">
<ol>
<li>This is a list item</li>
<li>This is another list item</li>
</ol>
</div>
</div>

You can of course use the previous examples for naming and class handling against the elements as you see fit.

Image (IMG)

You can probably work out from what you have seen so far how the image tag can work. You specify the tag as normal, any class elements or name and then specify the image source as an attribute;

img.#SomeImage(src='http://www.codeproject.com/images/demoimage.png')

Multiple Attribute Handling and Input Elements

Starting with multiple attributes, it is a simple as specifying these as a list of comma separated key/value pairs enclosed within parenthesis against the tag. For example if you wanted to specify alt and title attributes against the image tag you would write;

img#SomeImageID(src='http://www.codeproject.com/images/demoimage.png', alt="This is an image ALT", title="This is the image Title")

You can also add a list of classes as an attribute or chain these to the end;

img#SomeImageID(src='http://www.codeproject.com/images/demoimage.png',alt="This is an image ALT",title="This is the image Title", class="AClass BClass CClass").DClass.EClass

With input elements you may have to specify which items are selected or checked. This can be achieved using simple attributes again. In the example below we will create a group of 3 radio buttons, each with their own element name, but part of the same group (meaning only 1 can be selected at a time), the second will be default selected;

input#Element1(type="radio", name="RadioGroup", checked=false)
input#Element2(type="radio", name="RadioGroup", checked=true)
input#Element3(type="radio", name="RadioGroup")

You will notice that both the first and last checked state have both been set to false using different approaches. Likewise, I could have just written checked for the selected one.  

NOTE: The comma is in fact optional and provided the key=value attributes are whitespace separated, Jade still renders everything correctly. 

Shortforming Nested Tags

Jade developers have also thought of this. You might have for example an image that appears within a link. Instead of having the image on a new line you can short form this like a: img

Jade HTML
a#ImageLink(href="offsomewhere.htm"): img(src="someimage.png")
HTML
<a id="ImageLink" href="offsomewhere.htm"><img src="someimage.png"/></a>

Comments, Text and Raw HTML

Comments in HTML can be specified in a couple of ways, either single line or a block. The single line is expressed using a simple // and the block use the same // ,but start the comment on a new indented line. There is also a third method that will only comment in the Jade markup, but not include it in the rendered HTML //-, these can be seen below;

// Single Line comment.

//
  This is a multiple line
  comment that covers several
  lines.

//- This comment will not appear in the html output.

There is also a time when you just want the text or HTML to be displayed 'as is' i.e. not formatted. To achieve this, we use the pipe character |, it must also be on its own line or the pipe symbol will be considered as text;

| This text will show <em>as is</em> with the italics tags being rendered as text in the output.

p | This text will output with a pipe symbol showing

p
  | This paragraph will not have a pipe symbol showing

What Else Can Jade Achieve

Rendering HTML is clearly handled very well, but templating engines need to do a whole lot more to become really useful.

Mixology with Mixins

Steady on, we are not making cocktails here, but we are talking about creating fragments of reusable markup that can be applied as required. The fragment is first defined using the mixin keyword followed by a name and then the fragments are called using the +MixinName() format.

Jade HTML
mixin ContactList
  ul
    li Bob
    li Dave
    li Frank

p Here is the contact list
+ContactList()

p Here is another contact list
+ContactList()
HTML
<p>Here is the contact list</p>
<ul>
  <li>Bob</li>
  <li>Dave</li>
  <li>Frank</li>
</ul>
<p>Here is another contact list</p>
<ul>
  <li>Bob</li>
  <li>Dave</li>
  <li>Frank</li>
</ul>

Script Execution in the template

Code can be executed in the template by starting the block with an -, this is called Unbuffered code. For example to repeat a table row 3 times you might do;

Jade HTML
//Generate a table with 3 identical rows
table
  - for(x=0;x<3;x++)
    <tr><td>This is a row</td></tr>
HTML
<!--Generate a table with 3 identical rows-->
<table>
<tr><td>This is a row</td></tr>
<tr><td>This is a row</td></tr>
<tr><td>This is a row</td></tr>
</table>

There are two other type of code, Buffered Escaped and Buffered Unescaped output. The escaped output will encode any HTML in the output stream and you guessed it, the unencoded won't. These two methods are identified by using the = and != markup respectively.

Jade HTML
  // Escaped output
- var Escaped = true
    if Escaped
      p= 'This html tag will become <div>escaped</div>!'
    else
      p= 'This wont be visible'
HTML
// Escaped output
<p>This html tag will become &lt;div&gt;escaped&lt;/div&gt;!</p>

For the unescaped version, simply replace the p= for p!=

Conditionals

You have already seen an example of this, we just did one in the example above! Jade also supports an unless operation which carries out negation of the condition check;

Jade HTML
- var bob = 'woman'
    unless bob == 'man'
      p Bob is a not man!
HTML
<p>Bob is a not man!</p>

Iteration

Iteration can be accomplished by using the structure below;

Jade HTML
-var i = [1,2,3,4,5,6]
each value in i
  li= 'This is item ' + value
HTML
<li>This is item 1</li>
<li>This is item 2</li>
<li>This is item 3</li>
<li>This is item 4</li>
<li>This is item 5</li>
<li>This is item 6</li>

Switch / Case

Jade uses the case...when...default structure to shorthand the JavaScript switch.

Jade HTML
- var id = 3
case id
  when 1
    p This is 1
  when 2
    p This is 2
  when 3
    p This is 3
  when 4
    p This is 4
  default
    p There is no hope!
HTML
<p>This is 3</p>

Block Expansion

Block expansion is very similar to the shortforming earlier. Block expansion also makes use of the : . If we look at the Switch case above and re-write it using block expansion it would look like this;

- var id = 3
case id
  when 1: p This is 1
  when 2: p This is 2
  when 3: p This is 3
  when 4: p This is 4
  default: p There is no hope!

But what about things like Twitter Bootstrap Integration

Don't panic, this is all handled just fine. All you have to do is rewrite the requirements of the bootstrap markup in the Jade format. There is even a kind developer who has already converted a bunch of the default elements in Bootstrap to Jade. These can be found in Github at;

https://github.com/ALT-F1/bootstrap3-jade-node-express-grunt/tree/master/app/views/bootstrap3-templates 

It doesn't really matter what you are using, If you follow the principles of Jade and strip out the end tags, the <> and place the ids or class, attributes as required you will get there!

The Jade Online Playground

It is definitely worth using the provided playground on the Jade website. You can type/paste snippets of Jade and see how the outputted HTML is presented. This is a great way to see if you are getting what you expect as you learn the syntax.

The playground can be found at: http://jade-lang.com/demo/[^] and it is simply a case of clicking and editing the Jade Input or Locals boxes.

Points of Interest

Use the Playground to test snippets, it gives a better indication of where problems occur in your markup than the current Visual Studio error messages!

I hope you find this useful, there are certainly things mentioned here that I picked up through trial and error while trying to wrangle with the Bootstrap conversion to Jade (before I discovered it had been done before!).

The more you use Jade, the simpler it does become and it does make for cleaner templates.

I just need to take it to a larger scale project to see how things go! 

References

History

  • 30th March 2016 - Online playground now supports case fall through, updated text. (https://github.com/pugjs/pug/issues/1363)
  • 31st May 2014 - Tidy up, added case fall through though fix statement.
  • 3rd February 2014 - Added Block Expansion reference.
  • 31st January 2014 - typo fix, minor revisions, fall through bug reference link added.
  • 29th January 2014 - first release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)