Jade

an introduction

slides.forbesl.co.uk

Templating Language

  • Produces HTML
  • Supports dynamic code
  • Supports reusability (DRY)

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Jade</title>
  </head>
  <body>
    <h1>Jade - node template engine</h1>
    <article>
      <p>Jade is a terse and simple
         templating language with a
         strong focus on performance
         and powerful features.</p>
    </article>
  </body>
</html>

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Jade
  <body>
    <h1>Jade - node template engine
    <article>
      <p>Jade is a terse and simple
         templating language with a
         strong focus on performance
         and powerful features.

JADE

doctype html
html(lang="en")
  head
    title Jade
  body
    h1 Jade - node template engine
    article
      p.
        Jade is a terse and simple
        templating language with a
        strong focus on performance
        and powerful features.

Produces HTML

Doctype

doctype html
<!DOCTYPE html>

Deprecated syntax:

!!! 5

Tag, attributes & content

h1(id="heading-a" class="title") Heading A
<h1 id="heading-a" class="title">Heading A</h1>

ID and Class shorthand

h1#heading-a.title Heading A
<h1 id="heading-a" class="title">Heading A</h1>

Text

h1 Inside A Tag
| On it's own line
p.
  Multi-line inside
  a tag.
<h1>Inside A Tag</h1>
On it's own line
<p>Multi-line insde
   a tag</p>

Comments

// A comement that appears in the output
//- A comment that does not appear in the output
<!-- A comment that appears in the output -->

Deprecated syntax

//if IE 8

Inline HTML

<!--[if IE 8]>
  <html lang="en" class="lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
  <html lang="en">
<!--<![endif]-->

Supports dynamic code

Buffering Output

= jsVariable
!= jsVariable
var html = jade.render(template, {jsVariable: '<foo>'});
&lt;foo&gt;
<foo>

Buffering Output

function template(locals) {
  var buf = [], jade_interp;
  var locals_ = locals || {}, jsVariable = locals_.jsVariable;
  buf.push(jade.escape(null == (jade_interp = jsVariable) ?
                       "" : jade_interp)
        + (null == (jade_interp = jsVariable) ? "" : jade_interp));
  return buf.join("");
}

Dynamic Attributes

a(href="mailto:" + email)= email
var html = jade.render(template, {email:'[email protected]'});
<a href="mailto:[email protected]">[email protected]</a>

Interpolatioin

p.
  We would like to welcome #{name} to this talk
  with the following snippet of html: !{html}
var html = jade.render(template, {
  name: 'Forbes',
  html: '<strong>welcome</strong>'
});
<p>We would like to welcome Forbes to this talk
   with the following snippet of html: <strong>welcome</strong></p>

Loops and Conditionals

ul
  each value in list
    li= value
if awesome
  p You are awesome
else
  p You could use improvement
var html = jade.render(template, {list: [1, 2], awesome: true});
<ul>
  <li>1</li>
  <li>2</li>
</ul>
<p>You are awesome</p>

Custom JavaScript

(a last resort)

ul
  - list.forEach(function (value) {
    li= value
  - });
var html = jade.render(template, {list: [1, 2]});
<ul>
  <li>1</li>
  <li>2</li>
</ul>

Supports reusability (DRY)

Includes

The simplest way to re-use code

//- root.jade
article
  include ./child.jade
//- child.jade
h2 An Article
p Blah Blah Blah
var html = jade.renderFile('root.jade');
<article>
  <h2>An Article</h2>
  <p>Blah Blah Blah</p>
</article>

Mixins

Re-use blocks with an adjustment

mixin article(name, body)
  article
    h2= name
    p= body
+article('A1', 'The first article')
+article('A2', 'The second article')
<article>
  <h2>A1</h2>
  <p>The first article</p>
</article>
<article>
  <h2>A2</h2>
  <p>The second article</p>
</article>

Mixins with bodies

mixin article(name)
  article
    h2= name
    block
+article('A1')
  p The first article
+article('A2')
  p The second article
<article>
  <h2>A1</h2>
  <p>The first article</p>
</article>
<article>
  <h2>A2</h2>
  <p>The second article</p>
</article>

Inheritance

//- base.jade
doctype html
html
  head
    block title
      title Default Title
  body
    block content
//- article.jade
extends ./base.jade

block title
  title My Article Title

block content
  p An epic article

Inheritance

<!DOCTYPE html>
<html>
  <head>
    <title>My Article Title</title>
  </head>
  <body>
    <p>An epic article</p>
  </body>
</html>

Inheritance - Multi Level

//- authenticated.jade
extends ./base.jade

block title
  title Authenticated
//- anonymous.jade
extends ./base.jade

block title
  title Anonymous

Filters

:markdown
  # Heading 1
  
  Paragraph of text
<h1>Heading 1</h1>
<p>Paragraph of text</p>

Jade API

Compile / Compile Client

var jade = require('jade');

var fn = jade.compile('h1= name');
var html = fn({name: 'Forbes Lindesay'});
// => <h1>Forbes Lindesay</h1>
var src = jade.compileClient('h1= name');
// => a function called `template`
script(src="node_modules/jade/runtime.js")
script(src="template.js")
script.
  var html = template({name: 'Forbes Lindesay'});

Render

var html = jade.render('h1= name', {name: 'Forbes Lindesay'});
// => <h1>Forbes Lindesay</h1>

Render File

//- input.jade
h1= name
var html = jade.renderFile('input.jade', {name: 'Forbes Lindesay'});
// => <h1>Forbes Lindesay</h1>

Final Thoughts

Express.js

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.render('home.jade', {title: 'Home Page'});
});
app.listen(3000);

Jade Compiler

The jade compiler is well designed, and consists of three stages

  • Lexer - takes jade in and generates a stream of tokens
  • Parser - takes a stream of tokens and generates an abstract syntax tree
  • Compiler - takes an abstract syntax tree and generates JavaScript

Tooling

Jade's tooling is now very high up on my list of priorities

  • jade-lang.com - documentation and in-browser editor
  • brackets plugin - robust syntax highlighter and code-mirror mode
  • sublime text plugin - passable syntax highlighter
  • command line build tool
  • node.js API

Forbes Lindesay

slides.forbesl.co.uk

Social Networks

Twitter: @ForbesLindesay

GitHub: @ForbesLindesay

Blog: www.forbeslindesay.co.uk

Open Source

Jade

Browserify Middleware

readable-email.org

brcdn.org

tempjs.org