# jade **Repository Path**: mirrors_rubenv/jade ## Basic Information - **Project Name**: jade - **Description**: Jade - robust, elegant, feature rich template engine for nodejs - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-18 - **Last Updated**: 2026-01-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Jade - template engine Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com) and implemented with JavaScript for [node](http://nodejs.org). ## Features - client-side support - great readability - flexible indentation - block-expansion - mixins - static includes - attribute interpolation - code is escaped by default for security - contextual error reporting at compile & run time - executable for compiling jade templates via the command line - html 5 mode (using the _!!! 5_ doctype) - optional memory caching - combine dynamic and static tag classes - parse tree manipulation via _filters_ - template inheritance - supports [Express JS](http://expressjs.com) out of the box - transparent iteration over objects, arrays, and even non-enumerables via `each` - block comments - no tag prefix - AST filters - filters - :sass must have [sass.js](http://github.com/visionmedia/sass.js) installed - :less must have [less.js](http://github.com/cloudhead/less.js) installed - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js) installed or [node-discount](http://github.com/visionmedia/node-discount) - :cdata - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed - [Vim Syntax](https://github.com/digitaltoad/vim-jade) - [TextMate Bundle](http://github.com/miksago/jade-tmbundle) - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs) - [html2jade](https://github.com/donpark/html2jade) converter ## Implementations - [php](http://github.com/everzet/jade.php) - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html) - [ruby](http://github.com/stonean/slim) ## Installation via npm: npm install jade ## Browser Support To compile jade to a single file compatible for client-side use simply execute: $ make jade.js Alternatively, if uglifyjs is installed via npm (`npm install uglify-js`) you may execute the following which will create both files. However each release builds these for you. $ make jade.min.js By default Jade instruments templates with line number statements such as `__.lineno = 3` for debugging purposes. When used in a browser it's useful to minimize this boiler plate, you can do so by passing the option `{ compileDebug: false }`. The following template p Hello #{name} Can then be as small as the following generated function: ```js function anonymous(locals, attrs, escape, rethrow) { var buf = []; with (locals || {}) { var interp; buf.push('\n
Hello ' + escape((interp = name) == null ? '' : interp) + '\n
'); } return buf.join(""); } ``` Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions via `jade.attrs`, `jade.escape` etc. ```js function anonymous(locals, attrs, escape, rethrow) { var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; var buf = []; with (locals || {}) { var interp; buf.push('\nHello ' + escape((interp = name) == null ? '' : interp) + '\n
'); } return buf.join(""); } ``` ## Public API ```javascript var jade = require('jade'); // Compile a function var fn = jade.compile('string of jade', options); fn(locals); ``` ### Options - `self` Use a `self` namespace to hold the locals. _false by default_ - `locals` Local variable object - `filename` Used in exceptions, and required when using includes - `debug` Outputs tokens and function body generated - `compiler` Compiler to replace jade's default - `compileDebug` When `false` no debug instrumentation is compiled ## Syntax ### Line Endings **CRLF** and **CR** are converted to **LF** before parsing. ### Tags A tag is simply a leading word: html for example is converted to `` tags can also have ids: div#container which would render `` how about some classes? div.user-details renders `` multiple classes? _and_ an id? sure: div#foo.bar.baz renders `` div div div sure is annoying, how about: #foo .bar which is syntactic sugar for what we have already been doing, and outputs: `` ### Tag Text Simply place some content after the tag: p wahoo! renders `wahoo!
`. well cool, but how about large bodies of text: p | foo bar baz | rawr rawr | super cool | go jade go renders `foo bar baz rawr.....
` interpolation? yup! both types of text can utilize interpolation, if we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following: #user #{name} <#{email}> outputs `#{something}
` We can also utilize the unescaped variant `!{html}`, so the following will result in a literal script tag: - var html = "" | !{html} Nested tags that also contain text can optionally use a text block: label | Username: input(name='user[name]') or immediate tag text: label Username: input(name='user[name]') Tags that accept _only_ text such as `script`, `style`, and `textarea` do not need the leading `|` character, for example: html head title Example script if (foo) { bar(); } else { baz(); } Once again as an alternative, we may use a trailing '.' to indicate a text block, for example: p. foo asdf asdf asdfasdfaf asdf asd. outputs:foo asdf asdf asdfasdfaf asdf asd .
This however differs from a trailing '.' followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal: p . outputs:.
It should be noted that text blocks should be doubled escaped. For example if you desire the following output. foo\bar use: p. foo\\bar ### Comments Single line comments currently look the same as JavaScript comments, aka "//" and must be placed on their own line: // just some paragraphs p foo p bar would outputfoo
bar
Jade also supports unbuffered comments, by simply adding a hyphen: //- will not output within markup p foo p bar outputtingfoo
bar
### Block Comments A block comment is legal as well: body // #content h1 Example outputting Jade supports conditional-comments as well, for example: body //if IE a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox outputs: ### Nesting Jade supports nesting to define the tags in a natural way: ul li.first a(href='#') foo li a(href='#') bar li.last a(href='#') baz ### Block Expansion Block expansion allows you to create terse single-line nested tags, the following example is equivalent to the nesting example above. ul li.first: a(href='#') foo li: a(href='#') bar li.last: a(href='#') baz ### Attributes Jade currently supports '(' and ')' as attribute delimiters. a(href='/login', title='View login page') Login When a value is `undefined` or `null` the attribute is _not_ added, so this is fine, it will not compile 'something="null"'. div(something=null) Boolean attributes are also supported: input(type="checkbox", checked) Boolean attributes with code will only output the attribute when `true`: input(type="checkbox", checked=someValue) Multiple lines work too: input(type='checkbox', name='agreement', checked) Multiple lines without the comma work fine: input(type='checkbox' name='agreement' checked) Funky whitespace? fine: input( type='checkbox' name='agreement' checked) Colons work: rss(xmlns:atom="atom") Suppose we have the `user` local `{ id: 12, name: 'tobi' }` and we wish to create an anchor tag with `href` pointing to "/user/12" we could use regular javascript concatenation: a(href='/user/' + user.id)= user.name or we could use jade's interpolation, which I added because everyone using Ruby or CoffeeScript seems to think this is legal js..: a(href='/user/#{user.id}')= user.name The `class` attribute is special-cased when an array is given, allowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly: body(class=bodyClasses) ### HTML Inline html is fine, we can use the pipe syntax to write arbitrary text, in this case some html: ``` html body |foo bar baz
``` Or we can use the trailing `.` to indicate to Jade that we only want text in this block, allowing us to omit the pipes: ``` html body.foo bar baz
``` Both of these examples yield the same result: ```foo bar baz
``` The same rule applies for anywhere you can have text in jade, raw html is fine: ``` html body h1 User #{name} ``` ### Doctypes To add a doctype simply use `!!!`, or `doctype` followed by an optional value: !!! Will output the _transitional_ doctype, however: !!! 5 or !!! html or doctype html doctypes are case-insensitive, so the following are equivalent: doctype Basic doctype basic Will output the _html 5_ doctype. Below are the doctypes defined by default, which can easily be extended: ```javascript var doctypes = exports.doctypes = { '5': '', 'xml': '', 'default': '', 'transitional': '', 'strict': '', 'frameset': '', '1.1': '', 'basic': '', 'mobile': '' }; ``` To alter the default simply change: ```javascript jade.doctypes.default = 'whatever you want'; ``` ## Filters Filters are prefixed with `:`, for example `:markdown` and pass the following block of text to an arbitrary function for processing. View the _features_ at the top of this document for available filters. body :markdown Woah! jade _and_ markdown, very **cool** we can even link to [stuff](http://google.com) Renders:Woah! jade and markdown, very cool we can even link to stuff
Filters may also manipulate the parse tree. For example perhaps I want to bake conditionals right into jade, we could do so with a filter named _conditionals_. Typically filters work on text blocks, however by passing a regular block our filter can do anything it wants with the tags nested within it. body conditionals: if role == 'admin' p You are amazing else p Not so amazing Not that we no longer prefix with "-" for these code blocks. Examples of how to manipulate the parse tree can be found at _./examples/conditionals.js_ and _./examples/model.js_, basically we subclass and re-implement visitor methods as needed. There are several interesting use-cases for this functionality above what was shown above such as transparently aggregating / compressing assets to reduce the number of HTTP requests, transparent record error reporting, and more. ## Code Jade currently supports three classifications of executable code. The first is prefixed by `-`, and is not buffered: - var foo = 'bar'; This can be used for conditionals, or iteration: - for (var key in obj) p= obj[key] Due to Jade's buffering techniques the following is valid as well: - if (foo) ul li yay li foo li worked - else p oh no! didnt work Hell, even verbose iteration: - if (items.length) ul - items.forEach(function(item){ li= item - }) Anything you want! Next up we have _escaped_ buffered code, which is used to buffer a return value, which is prefixed by `=`: - var foo = 'bar' = foo h1= foo Which outputs `barWelcome to my super lame site.
``` ## Mixins Mixins are converted to regular JavaScript functions in the compiled template that Jade constructs. Mixins may take arguments, though not required: mixin list ul li foo li bar li baz Utilizing a mixin without args looks similar, just without a block: h2 Groceries mixin list Mixins may take one or more arguments as well, the arguments are regular javascripts expressions, so for example the following: mixin pets(pets) ul.pets - each pet in pets li= pet mixin profile(user) .user h2= user.name mixin pets(user.pets) Would yield something similar to the following html: ```html'); buf.push('Just an example'); buf.push('
'); } return buf.join(""); } catch (err) { rethrow(err, __.input, __.filename, __.lineno); } } ``` When the `compileDebug` option _is_ explicitly `false`, this instrumentation is stripped, which is very helpful for light-weight client-side templates. Combining Jade's options with the `./runtime.js` file in this repo allows you to toString() compiled templates and avoid running the entire Jade library on the client, increasing performance, and decreasing the amount of JavaScript required. ```js function anonymous(locals) { var attrs = jade.attrs, escape = jade.escape; var buf = []; with (locals || {}) { var interp; var title = 'yay' buf.push(''); buf.push('Just an example'); buf.push('
'); } return buf.join(""); } ``` ## Example Makefile Below is an example Makefile used to compile _pages/*.jade_ into _pages/*.html_ files by simply executing `make`. ```make JADE = $(shell find pages/*.jade) HTML = $(JADE:.jade=.html) all: $(HTML) %.html: %.jade jade < $< --path $<> > $@ clean: rm -f $(HTML) .PHONY: clean ``` this can be combined with the `watch(1)` command to produce a watcher-like behaviour: $ watch make ## jade(1) ``` Usage: jade [options] [dir|file ...] Options: -h, --help output usage information -v, --version output the version number -o, --obj