1 | # Jade - template engine
|
2 |
|
3 | Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com)
|
4 | and implemented with JavaScript for [node](http://nodejs.org).
|
5 |
|
6 | ## Features
|
7 |
|
8 | - client-side support
|
9 | - great readability
|
10 | - flexible indentation
|
11 | - block-expansion
|
12 | - mixins
|
13 | - static includes
|
14 | - attribute interpolation
|
15 | - code is escaped by default for security
|
16 | - contextual error reporting at compile & run time
|
17 | - executable for compiling jade templates via the command line
|
18 | - html 5 mode (using the _!!! 5_ doctype)
|
19 | - optional memory caching
|
20 | - combine dynamic and static tag classes
|
21 | - parse tree manipulation via _filters_
|
22 | - supports [Express JS](http://expressjs.com) out of the box
|
23 | - transparent iteration over objects, arrays, and even non-enumerables via `- each`
|
24 | - block comments
|
25 | - no tag prefix
|
26 | - AST filters
|
27 | - filters
|
28 | - :sass must have [sass.js](http://github.com/visionmedia/sass.js) installed
|
29 | - :less must have [less.js](http://github.com/cloudhead/less.js) installed
|
30 | - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js) installed or [node-discount](http://github.com/visionmedia/node-discount)
|
31 | - :cdata
|
32 | - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed
|
33 | - [Vim Syntax](https://github.com/digitaltoad/vim-jade)
|
34 | - [TextMate Bundle](http://github.com/miksago/jade-tmbundle)
|
35 | - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)
|
36 | - [html2jade](https://github.com/donpark/html2jade) converter
|
37 |
|
38 | ## Implementations
|
39 |
|
40 | - [php](http://github.com/everzet/jade.php)
|
41 | - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)
|
42 | - [ruby](http://github.com/stonean/slim)
|
43 |
|
44 | ## Installation
|
45 |
|
46 | via npm:
|
47 |
|
48 | npm install jade
|
49 |
|
50 | ## Browser Support
|
51 |
|
52 | To compile jade to a single file compatible for client-side use simply execute:
|
53 |
|
54 | $ make jade.js
|
55 |
|
56 | 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.
|
57 |
|
58 | $ make jade.min.js
|
59 |
|
60 | By default Jade inlines its utility functions within the template functions generated, such as `escape()` and `attrs()`. Jade also 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 }`, and `{ inline: false }`. The following template
|
61 |
|
62 | p Hello #{name}
|
63 |
|
64 | Can then be as small as the following generated function:
|
65 |
|
66 | ```js
|
67 | function anonymous(locals) {
|
68 | var attrs = jade.attrs, escape = jade.escape;
|
69 | var buf = [];
|
70 | with (locals || {}) {
|
71 | var interp;
|
72 | buf.push('<p>');
|
73 | buf.push('Hello ' + escape((interp = name) == null ? '' : interp) + '');
|
74 | buf.push('</p>');
|
75 | }
|
76 | return buf.join("");
|
77 | }
|
78 | ```
|
79 |
|
80 | 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.
|
81 |
|
82 | ## Public API
|
83 |
|
84 | ```javascript
|
85 | var jade = require('jade');
|
86 |
|
87 | // Render a string
|
88 | jade.render('string of jade', { options: 'here' });
|
89 |
|
90 | // Render a file
|
91 | jade.renderFile('path/to/some.jade', { options: 'here' }, function(err, html){
|
92 | // options are optional,
|
93 | // the callback can be the second arg
|
94 | });
|
95 |
|
96 | // Compile a function
|
97 | var fn = jade.compile('string of jade', options);
|
98 | fn.call(scope, locals);
|
99 | ```
|
100 |
|
101 | ### Options
|
102 |
|
103 | - `scope` Evaluation scope (`this`)
|
104 | - `self` Use a `self` namespace to hold the locals. _false by default_
|
105 | - `locals` Local variable object
|
106 | - `filename` Used in exceptions, and required when using includes
|
107 | - `debug` Outputs tokens and function body generated
|
108 | - `compiler` Compiler to replace jade's default
|
109 | - `compileDebug` When `false` no debug instrumentation is compiled
|
110 | - `inline` When `false` the helpers are not inlined (ideal for client-side use)
|
111 |
|
112 | ## Syntax
|
113 |
|
114 | ### Line Endings
|
115 |
|
116 | **CRLF** and **CR** are converted to **LF** before parsing.
|
117 |
|
118 | ### Tags
|
119 |
|
120 | A tag is simply a leading word:
|
121 |
|
122 | html
|
123 |
|
124 | for example is converted to `<html></html>`
|
125 |
|
126 | tags can also have ids:
|
127 |
|
128 | div#container
|
129 |
|
130 | which would render `<div id="container"></div>`
|
131 |
|
132 | how about some classes?
|
133 |
|
134 | div.user-details
|
135 |
|
136 | renders `<div class="user-details"></div>`
|
137 |
|
138 | multiple classes? _and_ an id? sure:
|
139 |
|
140 | div#foo.bar.baz
|
141 |
|
142 | renders `<div id="foo" class="bar baz"></div>`
|
143 |
|
144 | div div div sure is annoying, how about:
|
145 |
|
146 | #foo
|
147 | .bar
|
148 |
|
149 | which is syntactic sugar for what we have already been doing, and outputs:
|
150 |
|
151 | `<div id="foo"></div><div class="bar"></div>`
|
152 |
|
153 | ### Tag Text
|
154 |
|
155 | Simply place some content after the tag:
|
156 |
|
157 | p wahoo!
|
158 |
|
159 | renders `<p>wahoo!</p>`.
|
160 |
|
161 | well cool, but how about large bodies of text:
|
162 |
|
163 | p
|
164 | | foo bar baz
|
165 | | rawr rawr
|
166 | | super cool
|
167 | | go jade go
|
168 |
|
169 | renders `<p>foo bar baz rawr.....</p>`
|
170 |
|
171 | interpolation? yup! both types of text can utilize interpolation,
|
172 | if we passed `{ locals: { name: 'tj', email: 'tj@vision-media.ca' }}` to `render()`
|
173 | we can do the following:
|
174 |
|
175 | #user #{name} <#{email}>
|
176 |
|
177 | outputs `<div id="user">tj <tj@vision-media.ca></div>`
|
178 |
|
179 | Actually want `#{}` for some reason? escape it!
|
180 |
|
181 | p \#{something}
|
182 |
|
183 | now we have `<p>#{something}</p>`
|
184 |
|
185 | We can also utilize the unescaped variant `!{html}`, so the following
|
186 | will result in a literal script tag:
|
187 |
|
188 | - var html = "<script></script>"
|
189 | | !{html}
|
190 |
|
191 | Nested tags that also contain text can optionally use a text block:
|
192 |
|
193 | label
|
194 | | Username:
|
195 | input(name='user[name]')
|
196 |
|
197 | or immediate tag text:
|
198 |
|
199 | label Username:
|
200 | input(name='user[name]')
|
201 |
|
202 | Tags that accept _only_ text such as `script`, `style`, and `textarea` do not
|
203 | need the leading `|` character, for example:
|
204 |
|
205 | html
|
206 | head
|
207 | title Example
|
208 | script
|
209 | if (foo) {
|
210 | bar();
|
211 | } else {
|
212 | baz();
|
213 | }
|
214 |
|
215 | Once again as an alternative, we may use a leading '.' to indicate a text block, for example:
|
216 |
|
217 | p.
|
218 | foo asdf
|
219 | asdf
|
220 | asdfasdfaf
|
221 | asdf
|
222 | asd.
|
223 |
|
224 | outputs:
|
225 |
|
226 | <p>foo asdf
|
227 | asdf
|
228 | asdfasdfaf
|
229 | asdf
|
230 | asd
|
231 | .
|
232 | </p>
|
233 |
|
234 | This however differs from a leading '.' followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal:
|
235 |
|
236 | p .
|
237 |
|
238 | outputs:
|
239 |
|
240 | <p>.</p>
|
241 |
|
242 |
|
243 | It should be noted that text blocks should be doubled escaped. For example if you desire the following output.
|
244 |
|
245 | </p>foo\bar</p>
|
246 |
|
247 | use:
|
248 |
|
249 | p.
|
250 | foo\\bar
|
251 |
|
252 | ### Comments
|
253 |
|
254 | Single line comments currently look the same as JavaScript comments,
|
255 | aka "//" and must be placed on their own line:
|
256 |
|
257 | // just some paragraphs
|
258 | p foo
|
259 | p bar
|
260 |
|
261 | would output
|
262 |
|
263 | <!-- just some paragraphs -->
|
264 | <p>foo</p>
|
265 | <p>bar</p>
|
266 |
|
267 | Jade also supports unbuffered comments, by simply adding a hyphen:
|
268 |
|
269 | //- will not output within markup
|
270 | p foo
|
271 | p bar
|
272 |
|
273 | outputting
|
274 |
|
275 | <p>foo</p>
|
276 | <p>bar</p>
|
277 |
|
278 | ### Block Comments
|
279 |
|
280 | A block comment is legal as well:
|
281 |
|
282 | body
|
283 | //
|
284 | #content
|
285 | h1 Example
|
286 |
|
287 | outputting
|
288 |
|
289 | <body>
|
290 | <!--
|
291 | <div id="content">
|
292 | <h1>Example</h1>
|
293 | </div>
|
294 | -->
|
295 | </body>
|
296 |
|
297 | Jade supports conditional-comments as well, for example:
|
298 |
|
299 | body
|
300 | //if IE
|
301 | a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox
|
302 |
|
303 | outputs:
|
304 |
|
305 | <body>
|
306 | <!--[if IE]>
|
307 | <a href="http://www.mozilla.com/en-US/firefox/">Get Firefox</a>
|
308 | <![endif]-->
|
309 | </body>
|
310 |
|
311 |
|
312 | ### Nesting
|
313 |
|
314 | Jade supports nesting to define the tags in a natural way:
|
315 |
|
316 | ul
|
317 | li.first
|
318 | a(href='#') foo
|
319 | li
|
320 | a(href='#') bar
|
321 | li.last
|
322 | a(href='#') baz
|
323 |
|
324 | ### Block Expansion
|
325 |
|
326 | Block expansion allows you to create terse single-line nested tags,
|
327 | the following example is equivalent to the nesting example above.
|
328 |
|
329 | ul
|
330 | li.first: a(href='#') foo
|
331 | li: a(href='#') bar
|
332 | li.last: a(href='#') baz
|
333 |
|
334 |
|
335 | ### Attributes
|
336 |
|
337 | Jade currently supports '(' and ')' as attribute delimiters.
|
338 |
|
339 | a(href='/login', title='View login page') Login
|
340 |
|
341 | When a value is `undefined` or `null` the attribute is _not_ added,
|
342 | so this is fine, it will not compile 'something="null"'.
|
343 |
|
344 | div(something=null)
|
345 |
|
346 | Boolean attributes are also supported:
|
347 |
|
348 | input(type="checkbox", checked)
|
349 |
|
350 | Boolean attributes with code will only output the attribute when `true`:
|
351 |
|
352 | input(type="checkbox", checked=someValue)
|
353 |
|
354 | Multiple lines work too:
|
355 |
|
356 | input(type='checkbox',
|
357 | name='agreement',
|
358 | checked)
|
359 |
|
360 | Multiple lines without the comma work fine:
|
361 |
|
362 | input(type='checkbox'
|
363 | name='agreement'
|
364 | checked)
|
365 |
|
366 | Funky whitespace? fine:
|
367 |
|
368 |
|
369 | input(
|
370 | type='checkbox'
|
371 | name='agreement'
|
372 | checked)
|
373 |
|
374 | Colons work:
|
375 |
|
376 | rss(xmlns:atom="atom")
|
377 |
|
378 | Suppose we have the `user` local `{ id: 12, name: 'tobi' }`
|
379 | and we wish to create an anchor tag with `href` pointing to "/user/12"
|
380 | we could use regular javascript concatenation:
|
381 |
|
382 | a(href='/user/' + user.id)= user.name
|
383 |
|
384 | or we could use jade's interpolation, which I added because everyone
|
385 | using Ruby or CoffeeScript seems to think this is legal js..:
|
386 |
|
387 | a(href='/user/#{user.id}')= user.name
|
388 |
|
389 | The `class` attribute is special-cased when an array is given,
|
390 | allowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly:
|
391 |
|
392 | body(class=bodyClasses)
|
393 |
|
394 | ### Doctypes
|
395 |
|
396 | To add a doctype simply use `!!!`, or `doctype` followed by an optional value:
|
397 |
|
398 | !!!
|
399 |
|
400 | Will output the _transitional_ doctype, however:
|
401 |
|
402 | !!! 5
|
403 |
|
404 | or
|
405 |
|
406 | !!! html
|
407 |
|
408 | or
|
409 |
|
410 | doctype html
|
411 |
|
412 | doctypes are case-insensitive, so the following are equivalent:
|
413 |
|
414 | doctype Basic
|
415 | doctype basic
|
416 |
|
417 | Will output the _html 5_ doctype. Below are the doctypes
|
418 | defined by default, which can easily be extended:
|
419 |
|
420 | ```javascript
|
421 | var doctypes = exports.doctypes = {
|
422 | '5': '<!DOCTYPE html>',
|
423 | 'xml': '<?xml version="1.0" encoding="utf-8" ?>',
|
424 | 'default': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
425 | 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
426 | 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
|
427 | 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
|
428 | '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
|
429 | 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
|
430 | 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
|
431 | };
|
432 | ```
|
433 |
|
434 | To alter the default simply change:
|
435 |
|
436 | ```javascript
|
437 | jade.doctypes.default = 'whatever you want';
|
438 | ```
|
439 |
|
440 | ## Filters
|
441 |
|
442 | Filters are prefixed with `:`, for example `:markdown` and
|
443 | pass the following block of text to an arbitrary function for processing. View the _features_
|
444 | at the top of this document for available filters.
|
445 |
|
446 | body
|
447 | :markdown
|
448 | Woah! jade _and_ markdown, very **cool**
|
449 | we can even link to [stuff](http://google.com)
|
450 |
|
451 | Renders:
|
452 |
|
453 | <body><p>Woah! jade <em>and</em> markdown, very <strong>cool</strong> we can even link to <a href="http://google.com">stuff</a></p></body>
|
454 |
|
455 | Filters may also manipulate the parse tree. For example perhaps I want to
|
456 | 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.
|
457 |
|
458 | body
|
459 | conditionals:
|
460 | if role == 'admin'
|
461 | p You are amazing
|
462 | else
|
463 | p Not so amazing
|
464 |
|
465 | Not that we no longer prefix with "-" for these code blocks. Examples of
|
466 | 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.
|
467 |
|
468 | ## Code
|
469 |
|
470 | Jade currently supports three classifications of executable code. The first
|
471 | is prefixed by `-`, and is not buffered:
|
472 |
|
473 | - var foo = 'bar';
|
474 |
|
475 | This can be used for conditionals, or iteration:
|
476 |
|
477 | - for (var key in obj)
|
478 | p= obj[key]
|
479 |
|
480 | Due to Jade's buffering techniques the following is valid as well:
|
481 |
|
482 | - if (foo)
|
483 | ul
|
484 | li yay
|
485 | li foo
|
486 | li worked
|
487 | - else
|
488 | p oh no! didnt work
|
489 |
|
490 | Hell, even verbose iteration:
|
491 |
|
492 | - if (items.length)
|
493 | ul
|
494 | - items.forEach(function(item){
|
495 | li= item
|
496 | - })
|
497 |
|
498 | Anything you want!
|
499 |
|
500 | Next up we have _escaped_ buffered code, which is used to
|
501 | buffer a return value, which is prefixed by `=`:
|
502 |
|
503 | - var foo = 'bar'
|
504 | = foo
|
505 | h1= foo
|
506 |
|
507 | Which outputs `bar<h1>bar</h1>`. Code buffered by `=` is escaped
|
508 | by default for security, however to output unescaped return values
|
509 | you may use `!=`:
|
510 |
|
511 | p!= aVarContainingMoreHTML
|
512 |
|
513 | The one exception made in terms of allowing "vanilla" JavaScript, is
|
514 | the `- each` token. This takes the form of:
|
515 |
|
516 | - each VAL[, KEY] in OBJ
|
517 |
|
518 | An example iterating over an array:
|
519 |
|
520 | - var items = ["one", "two", "three"]
|
521 | - each item in items
|
522 | li= item
|
523 |
|
524 | outputs:
|
525 |
|
526 | <li>one</li>
|
527 | <li>two</li>
|
528 | <li>three</li>
|
529 |
|
530 | iterating an array with index:
|
531 |
|
532 | - var items = ["one", "two", "three"]
|
533 | - each item, i in items
|
534 | li #{item}: #{i}
|
535 |
|
536 | outputs:
|
537 |
|
538 | <li>one: 0</li>
|
539 | <li>two: 1</li>
|
540 | <li>three: 2</li>
|
541 |
|
542 | iterating an object's keys and values:
|
543 |
|
544 | - var obj = { foo: 'bar' }
|
545 | - each val, key in obj
|
546 | li #{key}: #{val}
|
547 |
|
548 | would output `<li>foo: bar</li>`
|
549 |
|
550 | You can also nest these!
|
551 |
|
552 | - each user in users
|
553 | - each role in user.roles
|
554 | li= role
|
555 |
|
556 | When a property is undefined, Jade will output an empty string. For example:
|
557 |
|
558 | textarea= user.signature
|
559 |
|
560 | when undefined would normally output "undefined" in your html, however recent
|
561 | versions of Jade will simply render:
|
562 |
|
563 | <textarea></textarea>
|
564 |
|
565 | ## Includes
|
566 |
|
567 | Includes allow you to statically include chunks of Jade
|
568 | which lives in a separate file. The classical example is
|
569 | including a header and footer. Suppose we have the following
|
570 | directory structure:
|
571 |
|
572 | ./layout.jade
|
573 | ./includes/
|
574 | ./head.jade
|
575 | ./tail.jade
|
576 |
|
577 | and the following _layout.jade_:
|
578 |
|
579 | html
|
580 | include includes/head
|
581 | body
|
582 | h1 My Site
|
583 | p Welcome to my super amazing site.
|
584 | include includes/foot
|
585 |
|
586 | both includes _includes/head_ and _includes/foot_ are
|
587 | read relative to the `filename` option given to _layout.jade_,
|
588 | which should be an absolute path to this file, however Express
|
589 | and the `renderFile()` method do this for you. Include then parses
|
590 | these files, and injects the AST produced to render what you would expect:
|
591 |
|
592 | ```html
|
593 | <html>
|
594 | <head>
|
595 | <title>My Site</title>
|
596 | <script src="/javascripts/jquery.js">
|
597 | </script><script src="/javascripts/app.js"></script>
|
598 | </head>
|
599 | <body>
|
600 | <h1>My Site</h1>
|
601 | <p>Welcome to my super lame site.</p>
|
602 | <div id="footer">
|
603 | <p>Copyright>(c) foobar</p>
|
604 | </div>
|
605 | </body>
|
606 | </html>
|
607 | ```
|
608 |
|
609 | ## Mixins
|
610 |
|
611 | Mixins are converted to regular JavaScript functions in
|
612 | the compiled template that Jade constructs. Mixins may
|
613 | take arguments, though not required:
|
614 |
|
615 | mixin list
|
616 | ul
|
617 | li foo
|
618 | li bar
|
619 | li baz
|
620 |
|
621 | Utilizing a mixin without args looks similar, just without a block:
|
622 |
|
623 | h2 Groceries
|
624 | mixin list
|
625 |
|
626 | Mixins may take one or more arguments as well, the arguments
|
627 | are regular javascripts expressions, so for example the following:
|
628 |
|
629 | mixin pets(pets)
|
630 | ul.pets
|
631 | - each pet in pets
|
632 | li= pet
|
633 |
|
634 | mixin profile(user)
|
635 | .user
|
636 | h2= user.name
|
637 | mixin pets(user.pets)
|
638 |
|
639 | Would yield something similar to the following html:
|
640 |
|
641 | ```html
|
642 | <div class="user">
|
643 | <h2>tj</h2>
|
644 | <ul class="pets">
|
645 | <li>tobi</li>
|
646 | <li>loki</li>
|
647 | <li>jane</li>
|
648 | <li>manny</li>
|
649 | </ul>
|
650 | </div>
|
651 | ```
|
652 |
|
653 | ## Generated Output
|
654 |
|
655 | Suppose we have the following Jade:
|
656 |
|
657 | ```
|
658 | - var title = 'yay'
|
659 | h1.title #{title}
|
660 | p Just an example
|
661 | ```
|
662 |
|
663 | When the `compileDebug` option is not explicitly `false`, Jade
|
664 | will compile the function instrumented with `__.lineno = n;`, which
|
665 | in the event of an exception is passed to `rethrow()` which constructs
|
666 | a useful message relative to the initial Jade input.
|
667 |
|
668 | ```js
|
669 | function anonymous(locals) {
|
670 | var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" };
|
671 | var rethrow = jade.rethrow;
|
672 | try {
|
673 | var attrs = jade.attrs, escape = jade.escape;
|
674 | var buf = [];
|
675 | with (locals || {}) {
|
676 | var interp;
|
677 | __.lineno = 1;
|
678 | var title = 'yay'
|
679 | __.lineno = 2;
|
680 | buf.push('<h1');
|
681 | buf.push(attrs({ "class": ('title') }));
|
682 | buf.push('>');
|
683 | buf.push('' + escape((interp = title) == null ? '' : interp) + '');
|
684 | buf.push('</h1>');
|
685 | __.lineno = 3;
|
686 | buf.push('<p>');
|
687 | buf.push('Just an example');
|
688 | buf.push('</p>');
|
689 | }
|
690 | return buf.join("");
|
691 | } catch (err) {
|
692 | rethrow(err, __.input, __.filename, __.lineno);
|
693 | }
|
694 | }
|
695 | ```
|
696 |
|
697 | When the `compileDebug` option _is_ explicitly `false`, this instrumentation
|
698 | 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
|
699 | to toString() compiled templates and avoid running the entire Jade library on
|
700 | the client, increasing performance, and decreasing the amount of JavaScript
|
701 | required.
|
702 |
|
703 | ```js
|
704 | function anonymous(locals) {
|
705 | var attrs = jade.attrs, escape = jade.escape;
|
706 | var buf = [];
|
707 | with (locals || {}) {
|
708 | var interp;
|
709 | var title = 'yay'
|
710 | buf.push('<h1');
|
711 | buf.push(attrs({ "class": ('title') }));
|
712 | buf.push('>');
|
713 | buf.push('' + escape((interp = title) == null ? '' : interp) + '');
|
714 | buf.push('</h1>');
|
715 | buf.push('<p>');
|
716 | buf.push('Just an example');
|
717 | buf.push('</p>');
|
718 | }
|
719 | return buf.join("");
|
720 | }
|
721 | ```
|
722 |
|
723 | ## bin/jade
|
724 |
|
725 | Output html to _stdout_:
|
726 |
|
727 | jade < my.jade > my.html
|
728 |
|
729 | Generate _examples/*.html_:
|
730 |
|
731 | jade examples/*.jade
|
732 |
|
733 | Pass options:
|
734 |
|
735 | jade examples/layout.jade --options '{ locals: { title: "foo" }}'
|
736 |
|
737 | Usage info:
|
738 |
|
739 | Usage: jade [options]
|
740 | [path ...]
|
741 | < in.jade > out.jade
|
742 | Options:
|
743 | -o, --options <str> JavaScript options object passed
|
744 | -h, --help Output help information
|
745 | -w, --watch Watch file(s) or folder(s) for changes and re-compile
|
746 | -v, --version Output jade version
|
747 | --out <dir> Output the compiled html to <dir>
|
748 |
|
749 | ## License
|
750 |
|
751 | (The MIT License)
|
752 |
|
753 | Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>
|
754 |
|
755 | Permission is hereby granted, free of charge, to any person obtaining
|
756 | a copy of this software and associated documentation files (the
|
757 | 'Software'), to deal in the Software without restriction, including
|
758 | without limitation the rights to use, copy, modify, merge, publish,
|
759 | distribute, sublicense, and/or sell copies of the Software, and to
|
760 | permit persons to whom the Software is furnished to do so, subject to
|
761 | the following conditions:
|
762 |
|
763 | The above copyright notice and this permission notice shall be
|
764 | included in all copies or substantial portions of the Software.
|
765 |
|
766 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
767 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
768 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
769 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
770 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
771 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
772 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|