A Twitch.tv viewer reward and games system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1022 lines
20 KiB

  1. <a name="a6"/>
  2. ## Syntax
  3. <a name="a6-2"/>
  4. ### Tags
  5. A tag is simply a leading word:
  6. ```jade
  7. html
  8. ```
  9. for example is converted to `<html></html>`
  10. tags can also have ids:
  11. ```jade
  12. div#container
  13. ```
  14. which would render `<div id="container"></div>`
  15. how about some classes?
  16. ```jade
  17. div.user-details
  18. ```
  19. renders `<div class="user-details"></div>`
  20. multiple classes? _and_ an id? sure:
  21. ```jade
  22. div#foo.bar.baz
  23. ```
  24. renders `<div id="foo" class="bar baz"></div>`
  25. div div div sure is annoying, how about:
  26. ```jade
  27. #foo
  28. .bar
  29. ```
  30. which is syntactic sugar for what we have already been doing, and outputs:
  31. ```html
  32. <div id="foo"></div><div class="bar"></div>
  33. ```
  34. <a name="a6-3"/>
  35. ### Tag Text
  36. Simply place some content after the tag:
  37. ```jade
  38. p wahoo!
  39. ```
  40. renders `<p>wahoo!</p>`.
  41. well cool, but how about large bodies of text:
  42. ```jade
  43. p
  44. | foo bar baz
  45. | rawr rawr
  46. | super cool
  47. | go jade go
  48. ```
  49. renders `<p>foo bar baz rawr.....</p>`
  50. interpolation? yup! both types of text can utilize interpolation,
  51. if we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following:
  52. ```jade
  53. #user #{name} &lt;#{email}&gt;
  54. ```
  55. outputs `<div id="user">tj &lt;tj@vision-media.ca&gt;</div>`
  56. Actually want `#{}` for some reason? escape it!
  57. ```jade
  58. p \#{something}
  59. ```
  60. now we have `<p>#{something}</p>`
  61. We can also utilize the unescaped variant `!{html}`, so the following
  62. will result in a literal script tag:
  63. ```jade
  64. - var html = "<script></script>"
  65. | !{html}
  66. ```
  67. Nested tags that also contain text can optionally use a text block:
  68. ```jade
  69. label
  70. | Username:
  71. input(name='user[name]')
  72. ```
  73. or immediate tag text:
  74. ```jade
  75. label Username:
  76. input(name='user[name]')
  77. ```
  78. As an alternative, we may use a trailing `.` to indicate a text block, for example:
  79. ```jade
  80. p.
  81. foo asdf
  82. asdf
  83. asdfasdfaf
  84. asdf
  85. asd.
  86. ```
  87. outputs:
  88. ```html
  89. <p>foo asdf
  90. asdf
  91. asdfasdfaf
  92. asdf
  93. asd.
  94. </p>
  95. ```
  96. 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:
  97. ```jade
  98. p .
  99. ```
  100. outputs:
  101. ```html
  102. <p>.</p>
  103. ```
  104. It should be noted that text blocks should be doubled escaped. For example if you desire the following output.
  105. ```html
  106. <p>foo\bar</p>
  107. ```
  108. use:
  109. ```jade
  110. p.
  111. foo\\bar
  112. ```
  113. <a name="a6-4"/>
  114. ### Comments
  115. Single line comments currently look the same as JavaScript comments,
  116. aka `//` and must be placed on their own line:
  117. ```jade
  118. // just some paragraphs
  119. p foo
  120. p bar
  121. ```
  122. would output
  123. ```html
  124. <!-- just some paragraphs -->
  125. <p>foo</p>
  126. <p>bar</p>
  127. ```
  128. Jade also supports unbuffered comments, by simply adding a hyphen:
  129. ```jade
  130. //- will not output within markup
  131. p foo
  132. p bar
  133. ```
  134. outputting
  135. ```html
  136. <p>foo</p>
  137. <p>bar</p>
  138. ```
  139. <a name="a6-5"/>
  140. ### Block Comments
  141. A block comment is legal as well:
  142. ```jade
  143. body
  144. //
  145. #content
  146. h1 Example
  147. ```
  148. outputting
  149. ```html
  150. <body>
  151. <!--
  152. <div id="content">
  153. <h1>Example</h1>
  154. </div>
  155. -->
  156. </body>
  157. ```
  158. Jade supports conditional-comments as well, for example:
  159. ```jade
  160. head
  161. //if lt IE 8
  162. script(src='/ie-sucks.js')
  163. ```
  164. outputs:
  165. ```html
  166. <head>
  167. <!--[if lt IE 8]>
  168. <script src="/ie-sucks.js"></script>
  169. <![endif]-->
  170. </head>
  171. ```
  172. <a name="a6-6"/>
  173. ### Nesting
  174. Jade supports nesting to define the tags in a natural way:
  175. ```jade
  176. ul
  177. li.first
  178. a(href='#') foo
  179. li
  180. a(href='#') bar
  181. li.last
  182. a(href='#') baz
  183. ```
  184. <a name="a6-7"/>
  185. ### Block Expansion
  186. Block expansion allows you to create terse single-line nested tags,
  187. the following example is equivalent to the nesting example above.
  188. ```jade
  189. ul
  190. li.first: a(href='#') foo
  191. li: a(href='#') bar
  192. li.last: a(href='#') baz
  193. ```
  194. <a name="a6-8"/>
  195. ### Case
  196. The case statement takes the following form:
  197. ```jade
  198. html
  199. body
  200. friends = 10
  201. case friends
  202. when 0
  203. p you have no friends
  204. when 1
  205. p you have a friend
  206. default
  207. p you have #{friends} friends
  208. ```
  209. Block expansion may also be used:
  210. ```jade
  211. friends = 5
  212. html
  213. body
  214. case friends
  215. when 0: p you have no friends
  216. when 1: p you have a friend
  217. default: p you have #{friends} friends
  218. ```
  219. <a name="a6-9"/>
  220. ### Attributes
  221. Jade currently supports `(` and `)` as attribute delimiters.
  222. ```jade
  223. a(href='/login', title='View login page') Login
  224. ```
  225. When a value is `undefined` or `null` the attribute is _not_ added,
  226. so this is fine, it will not compile `something="null"`.
  227. ```jade
  228. div(something=null)
  229. ```
  230. Boolean attributes are also supported:
  231. ```jade
  232. input(type="checkbox", checked)
  233. ```
  234. Boolean attributes with code will only output the attribute when `true`:
  235. ```jade
  236. input(type="checkbox", checked=someValue)
  237. ```
  238. Multiple lines work too:
  239. ```jade
  240. input(type='checkbox',
  241. name='agreement',
  242. checked)
  243. ```
  244. Multiple lines without the comma work fine:
  245. ```jade
  246. input(type='checkbox'
  247. name='agreement'
  248. checked)
  249. ```
  250. Funky whitespace? fine:
  251. ```jade
  252. input(
  253. type='checkbox'
  254. name='agreement'
  255. checked)
  256. ```
  257. Colons work:
  258. ```jade
  259. rss(xmlns:atom="atom")
  260. ```
  261. Suppose we have the `user` local `{ id: 12, name: 'tobi' }`
  262. and we wish to create an anchor tag with `href` pointing to "/user/12"
  263. we could use regular javascript concatenation:
  264. ```jade
  265. a(href='/user/' + user.id)= user.name
  266. ```
  267. or we could use jade's interpolation, which I added because everyone
  268. using Ruby or CoffeeScript seems to think this is legal js..:
  269. ```jade
  270. a(href='/user/#{user.id}')= user.name
  271. ```
  272. The `class` attribute is special-cased when an array is given,
  273. allowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly:
  274. ```jade
  275. body(class=bodyClasses)
  276. ```
  277. <a name="a6-10"/>
  278. ### HTML
  279. Inline html is fine, we can use the pipe syntax to
  280. write arbitrary text, in this case some html:
  281. ```jade
  282. html
  283. body
  284. | <h1>Title</h1>
  285. | <p>foo bar baz</p>
  286. ```
  287. Or we can use the trailing `.` to indicate to Jade that we
  288. only want text in this block, allowing us to omit the pipes:
  289. ```jade
  290. html
  291. body.
  292. <h1>Title</h1>
  293. <p>foo bar baz</p>
  294. ```
  295. Both of these examples yield the same result:
  296. ```html
  297. <html><body><h1>Title</h1>
  298. <p>foo bar baz</p>
  299. </body></html>
  300. ```
  301. The same rule applies for anywhere you can have text
  302. in jade, raw html is fine:
  303. ```jade
  304. html
  305. body
  306. h1 User <em>#{name}</em>
  307. ```
  308. <a name="a6-11"/>
  309. ### Doctypes
  310. To add a doctype simply use `!!!`, or `doctype` followed by an optional value:
  311. ```jade
  312. !!!
  313. ```
  314. or
  315. ```jade
  316. doctype
  317. ```
  318. Will output the _html 5_ doctype, however:
  319. ```jade
  320. !!! transitional
  321. ```
  322. Will output the _transitional_ doctype.
  323. Doctypes are case-insensitive, so the following are equivalent:
  324. ```jade
  325. doctype Basic
  326. doctype basic
  327. ```
  328. it's also possible to simply pass a doctype literal:
  329. ```jade
  330. doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
  331. ```
  332. yielding:
  333. ```html
  334. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">
  335. ```
  336. Below are the doctypes defined by default, which can easily be extended:
  337. ```js
  338. var doctypes = exports.doctypes = {
  339. '5': '<!DOCTYPE html>',
  340. 'default': '<!DOCTYPE html>',
  341. 'xml': '<?xml version="1.0" encoding="utf-8" ?>',
  342. 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  343. 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
  344. 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
  345. '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
  346. 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
  347. 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
  348. };
  349. ```
  350. To alter the default simply change:
  351. ```js
  352. jade.doctypes.default = 'whatever you want';
  353. ```
  354. <a name="a7"/>
  355. ## Filters
  356. Filters are prefixed with `:`, for example `:markdown` and
  357. pass the following block of text to an arbitrary function for processing. View the _features_
  358. at the top of this document for available filters.
  359. ```jade
  360. body
  361. :markdown
  362. Woah! jade _and_ markdown, very **cool**
  363. we can even link to [stuff](http://google.com)
  364. ```
  365. Renders:
  366. ```html
  367. <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>
  368. ```
  369. <a name="a8"/>
  370. ## Code
  371. Jade currently supports three classifications of executable code. The first
  372. is prefixed by `-`, and is not buffered:
  373. ```jade
  374. - var foo = 'bar';
  375. ```
  376. This can be used for conditionals, or iteration:
  377. ```jade
  378. - for (var key in obj)
  379. p= obj[key]
  380. ```
  381. Due to Jade's buffering techniques the following is valid as well:
  382. ```jade
  383. - if (foo)
  384. ul
  385. li yay
  386. li foo
  387. li worked
  388. - else
  389. p oh no! didnt work
  390. ```
  391. Hell, even verbose iteration:
  392. ```jade
  393. - if (items.length)
  394. ul
  395. - items.forEach(function(item){
  396. li= item
  397. - })
  398. ```
  399. Anything you want!
  400. Next up we have _escaped_ buffered code, which is used to
  401. buffer a return value, which is prefixed by `=`:
  402. ```jade
  403. - var foo = 'bar'
  404. = foo
  405. h1= foo
  406. ```
  407. Which outputs `bar<h1>bar</h1>`. Code buffered by `=` is escaped
  408. by default for security, however to output unescaped return values
  409. you may use `!=`:
  410. ```jade
  411. p!= aVarContainingMoreHTML
  412. ```
  413. Jade also has designer-friendly variants, making the literal JavaScript
  414. more expressive and declarative. For example the following assignments
  415. are equivalent, and the expression is still regular javascript:
  416. ```jade
  417. - var foo = 'foo ' + 'bar'
  418. foo = 'foo ' + 'bar'
  419. ```
  420. Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript:
  421. ```jade
  422. if foo == 'bar'
  423. ul
  424. li yay
  425. li foo
  426. li worked
  427. else
  428. p oh no! didnt work
  429. ```
  430. <a name="a9"/>
  431. ## Iteration
  432. Along with vanilla JavaScript Jade also supports a subset of
  433. constructs that allow you to create more designer-friendly templates,
  434. one of these constructs is `each`, taking the form:
  435. ```jade
  436. each VAL[, KEY] in OBJ
  437. ```
  438. An example iterating over an array:
  439. ```jade
  440. - var items = ["one", "two", "three"]
  441. each item in items
  442. li= item
  443. ```
  444. outputs:
  445. ```html
  446. <li>one</li>
  447. <li>two</li>
  448. <li>three</li>
  449. ```
  450. iterating an array with index:
  451. ```jade
  452. items = ["one", "two", "three"]
  453. each item, i in items
  454. li #{item}: #{i}
  455. ```
  456. outputs:
  457. ```html
  458. <li>one: 0</li>
  459. <li>two: 1</li>
  460. <li>three: 2</li>
  461. ```
  462. iterating an object's keys and values:
  463. ```jade
  464. obj = { foo: 'bar' }
  465. each val, key in obj
  466. li #{key}: #{val}
  467. ```
  468. would output `<li>foo: bar</li>`
  469. Internally Jade converts these statements to regular
  470. JavaScript loops such as `users.forEach(function(user){`,
  471. so lexical scope and nesting applies as it would with regular
  472. JavaScript:
  473. ```jade
  474. each user in users
  475. each role in user.roles
  476. li= role
  477. ```
  478. You may also use `for` if you prefer:
  479. ```jade
  480. for user in users
  481. for role in user.roles
  482. li= role
  483. ```
  484. <a name="a10"/>
  485. ## Conditionals
  486. Jade conditionals are equivalent to those using the code (`-`) prefix,
  487. however allow you to ditch parenthesis to become more designer friendly,
  488. however keep in mind the expression given is _regular_ JavaScript:
  489. ```jade
  490. for user in users
  491. if user.role == 'admin'
  492. p #{user.name} is an admin
  493. else
  494. p= user.name
  495. ```
  496. is equivalent to the following using vanilla JavaScript literals:
  497. ```jade
  498. for user in users
  499. - if (user.role == 'admin')
  500. p #{user.name} is an admin
  501. - else
  502. p= user.name
  503. ```
  504. Jade also provides `unless` which is equivalent to `if (!(expr))`:
  505. ```jade
  506. for user in users
  507. unless user.isAnonymous
  508. p
  509. | Click to view
  510. a(href='/users/' + user.id)= user.name
  511. ```
  512. <a name="a11"/>
  513. ## Template inheritance
  514. Jade supports template inheritance via the `block` and `extends` keywords. A block is simply a "block" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: `app.set('view options', { layout: false });`.
  515. Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`.
  516. ```jade
  517. html
  518. head
  519. title My Site - #{title}
  520. block scripts
  521. script(src='/jquery.js')
  522. body
  523. block content
  524. block foot
  525. #footer
  526. p some footer content
  527. ```
  528. Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output "some footer content".
  529. ```jade
  530. extends layout
  531. block scripts
  532. script(src='/jquery.js')
  533. script(src='/pets.js')
  534. block content
  535. h1= title
  536. each pet in pets
  537. include pet
  538. ```
  539. It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together.
  540. ```jade
  541. extends regular-layout
  542. block content
  543. .sidebar
  544. block sidebar
  545. p nothing
  546. .primary
  547. block primary
  548. p nothing
  549. ```
  550. <a name="a12"/>
  551. ## Block append / prepend
  552. Jade allows you to _replace_ (default), _prepend_, or _append_ blocks. Suppose for example you have default scripts in a "head" block that you wish to utilize on _every_ page, you might do this:
  553. ```jade
  554. html
  555. head
  556. block head
  557. script(src='/vendor/jquery.js')
  558. script(src='/vendor/caustic.js')
  559. body
  560. block content
  561. ```
  562. Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block:
  563. ```jade
  564. extends layout
  565. block append head
  566. script(src='/vendor/three.js')
  567. script(src='/game.js')
  568. ```
  569. When using `block append` or `block prepend` the `block` is optional:
  570. ```jade
  571. extends layout
  572. append head
  573. script(src='/vendor/three.js')
  574. script(src='/game.js')
  575. ```
  576. <a name="a13"/>
  577. ## Includes
  578. Includes allow you to statically include chunks of Jade,
  579. or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure:
  580. ./layout.jade
  581. ./includes/
  582. ./head.jade
  583. ./foot.jade
  584. and the following _layout.jade_:
  585. ```jade
  586. html
  587. include includes/head
  588. body
  589. h1 My Site
  590. p Welcome to my super amazing site.
  591. include includes/foot
  592. ```
  593. both includes _includes/head_ and _includes/foot_ are
  594. read relative to the `filename` option given to _layout.jade_,
  595. which should be an absolute path to this file, however Express
  596. does this for you. Include then parses these files, and injects
  597. the AST produced to render what you would expect:
  598. ```html
  599. <html>
  600. <head>
  601. <title>My Site</title>
  602. <script src="/javascripts/jquery.js">
  603. </script><script src="/javascripts/app.js"></script>
  604. </head>
  605. <body>
  606. <h1>My Site</h1>
  607. <p>Welcome to my super lame site.</p>
  608. <div id="footer">
  609. <p>Copyright>(c) foobar</p>
  610. </div>
  611. </body>
  612. </html>
  613. ```
  614. As mentioned `include` can be used to include other content
  615. such as html or css. By providing an explicit filter name
  616. with `include:`, Jade will read that file in, apply the
  617. [filter](#a7), and insert that content into the output.
  618. ```jade
  619. html
  620. head
  621. //- css and js have simple filters that wrap them in
  622. <style> and <script> tags, respectively
  623. include stylesheet.css
  624. include script.js
  625. body
  626. //- use the "markdown" filter to convert Markdown to HTML
  627. include:markdown introduction.markdown
  628. //- html files have no filter and are included verbatim
  629. include content.html
  630. ```
  631. Include directives may also accept a block, in which case the
  632. the given block will be appended to the _last_ block defined
  633. in the file. For example if `head.jade` contains:
  634. ```jade
  635. head
  636. script(src='/jquery.js')
  637. ```
  638. We may append values by providing a block to `include head`
  639. as shown below, adding the two scripts.
  640. ```jade
  641. html
  642. include head
  643. script(src='/foo.js')
  644. script(src='/bar.js')
  645. body
  646. h1 test
  647. ```
  648. You may also `yield` within an included template, allowing you to explicitly mark where the block given to `include` will be placed. Suppose for example you wish to prepend scripts rather than append, you might do the following:
  649. ```jade
  650. head
  651. yield
  652. script(src='/jquery.js')
  653. script(src='/jquery.ui.js')
  654. ```
  655. Since included Jade is parsed and literally merges the AST, lexically scoped variables function as if the included Jade was written right in the same file. This means `include` may be used as sort of partial, for example suppose we have `user.jade` which utilizes a `user` variable.
  656. ```jade
  657. h1= user.name
  658. p= user.occupation
  659. ```
  660. We could then simply `include user` while iterating users, and since the `user` variable is already defined within the loop the included template will have access to it.
  661. ```jade
  662. users = [{ name: 'Tobi', occupation: 'Ferret' }]
  663. each user in users
  664. .user
  665. include user
  666. ```
  667. yielding:
  668. ```html
  669. <div class="user">
  670. <h1>Tobi</h1>
  671. <p>Ferret</p>
  672. </div>
  673. ```
  674. If we wanted to expose a different variable name as `user` since `user.jade` references that name, we could simply define a new variable as shown here with `user = person`:
  675. ```jade
  676. each person in users
  677. .user
  678. user = person
  679. include user
  680. ```
  681. <a name="a14"/>
  682. ## Mixins
  683. Mixins are converted to regular JavaScript functions in
  684. the compiled template that Jade constructs. Mixins may
  685. take arguments, though not required:
  686. ```jade
  687. mixin list
  688. ul
  689. li foo
  690. li bar
  691. li baz
  692. ```
  693. Utilizing a mixin without args looks similar, just without a block:
  694. ```jade
  695. h2 Groceries
  696. mixin list
  697. ```
  698. Mixins may take one or more arguments as well, the arguments
  699. are regular javascripts expressions, so for example the following:
  700. ```jade
  701. mixin pets(pets)
  702. ul.pets
  703. - each pet in pets
  704. li= pet
  705. mixin profile(user)
  706. .user
  707. h2= user.name
  708. mixin pets(user.pets)
  709. ```
  710. Would yield something similar to the following html:
  711. ```html
  712. <div class="user">
  713. <h2>tj</h2>
  714. <ul class="pets">
  715. <li>tobi</li>
  716. <li>loki</li>
  717. <li>jane</li>
  718. <li>manny</li>
  719. </ul>
  720. </div>
  721. ```
  722. <a name="a15"/>
  723. ## Generated Output
  724. Suppose we have the following Jade:
  725. ```jade
  726. - var title = 'yay'
  727. h1.title #{title}
  728. p Just an example
  729. ```
  730. When the `compileDebug` option is not explicitly `false`, Jade
  731. will compile the function instrumented with `__.lineno = n;`, which
  732. in the event of an exception is passed to `rethrow()` which constructs
  733. a useful message relative to the initial Jade input.
  734. ```js
  735. function anonymous(locals) {
  736. var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" };
  737. var rethrow = jade.rethrow;
  738. try {
  739. var attrs = jade.attrs, escape = jade.escape;
  740. var buf = [];
  741. with (locals || {}) {
  742. var interp;
  743. __.lineno = 1;
  744. var title = 'yay'
  745. __.lineno = 2;
  746. buf.push('<h1');
  747. buf.push(attrs({ "class": ('title') }));
  748. buf.push('>');
  749. buf.push('' + escape((interp = title) == null ? '' : interp) + '');
  750. buf.push('</h1>');
  751. __.lineno = 3;
  752. buf.push('<p>');
  753. buf.push('Just an example');
  754. buf.push('</p>');
  755. }
  756. return buf.join("");
  757. } catch (err) {
  758. rethrow(err, __.input, __.filename, __.lineno);
  759. }
  760. }
  761. ```
  762. When the `compileDebug` option _is_ explicitly `false`, this instrumentation
  763. 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
  764. to toString() compiled templates and avoid running the entire Jade library on
  765. the client, increasing performance, and decreasing the amount of JavaScript
  766. required.
  767. ```js
  768. function anonymous(locals) {
  769. var attrs = jade.attrs, escape = jade.escape;
  770. var buf = [];
  771. with (locals || {}) {
  772. var interp;
  773. var title = 'yay'
  774. buf.push('<h1');
  775. buf.push(attrs({ "class": ('title') }));
  776. buf.push('>');
  777. buf.push('' + escape((interp = title) == null ? '' : interp) + '');
  778. buf.push('</h1>');
  779. buf.push('<p>');
  780. buf.push('Just an example');
  781. buf.push('</p>');
  782. }
  783. return buf.join("");
  784. }
  785. ```