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.

510 lines
11 KiB

  1. # Jade
  2. The jade template engine for node.js
  3. ## Synopsis
  4. jade [-h|--help] [-v|--version] [-o|--obj STR]
  5. [-O|--out DIR] [-p|--path PATH] [-P|--pretty]
  6. [-c|--client] [-D|--no-debug]
  7. ## Examples
  8. translate jade the templates dir
  9. $ jade templates
  10. create {foo,bar}.html
  11. $ jade {foo,bar}.jade
  12. jade over stdio
  13. $ jade < my.jade > my.html
  14. jade over s
  15. $ echo "h1 Jade!" | jade
  16. foo, bar dirs rendering to /tmp
  17. $ jade foo bar --out /tmp
  18. compile client-side templates without debugging
  19. instrumentation, making the output javascript
  20. very light-weight. This requires runtime.js
  21. in your projects.
  22. $ jade --client --no-debug < my.jade
  23. ## Tags
  24. Tags are simply nested via whitespace, closing
  25. tags defined for you. These indents are called "blocks".
  26. ul
  27. li
  28. a Foo
  29. li
  30. a Bar
  31. You may have several tags in one "block":
  32. ul
  33. li
  34. a Foo
  35. a Bar
  36. a Baz
  37. ## Self-closing Tags
  38. Some tags are flagged as self-closing by default, such
  39. as `meta`, `link`, and so on. To explicitly self-close
  40. a tag simply append the `/` character:
  41. foo/
  42. foo(bar='baz')/
  43. Would yield:
  44. <foo/>
  45. <foo bar="baz"/>
  46. ## Attributes
  47. Tag attributes look similar to HTML, however
  48. the values are regular JavaScript, here are
  49. some examples:
  50. a(href='google.com') Google
  51. a(class='button', href='google.com') Google
  52. As mentioned the attribute values are just JavaScript,
  53. this means ternary operations and other JavaScript expressions
  54. work just fine:
  55. body(class=user.authenticated ? 'authenticated' : 'anonymous')
  56. a(href=user.website || 'http://google.com')
  57. Multiple lines work too:
  58. input(type='checkbox',
  59. name='agreement',
  60. checked)
  61. Multiple lines without the comma work fine:
  62. input(type='checkbox'
  63. name='agreement'
  64. checked)
  65. Funky whitespace? fine:
  66. input(
  67. type='checkbox'
  68. name='agreement'
  69. checked)
  70. ## Boolean attributes
  71. Boolean attributes are mirrored by Jade, and accept
  72. bools, aka _true_ or _false_. When no value is specified
  73. _true_ is assumed. For example:
  74. input(type="checkbox", checked)
  75. // => "<input type="checkbox" checked="checked" />"
  76. For example if the checkbox was for an agreement, perhaps `user.agreed`
  77. was _true_ the following would also output 'checked="checked"':
  78. input(type="checkbox", checked=user.agreed)
  79. ## Class attributes
  80. The _class_ attribute accepts an array of classes,
  81. this can be handy when generated from a javascript
  82. function etc:
  83. classes = ['foo', 'bar', 'baz']
  84. a(class=classes)
  85. // => "<a class="foo bar baz"></a>"
  86. ## Class literal
  87. Classes may be defined using a ".CLASSNAME" syntax:
  88. .button
  89. // => "<div class="button"></div>"
  90. Or chained:
  91. .large.button
  92. // => "<div class="large button"></div>"
  93. The previous defaulted to divs, however you
  94. may also specify the tag type:
  95. h1.title My Title
  96. // => "<h1 class="title">My Title</h1>"
  97. ## Id literal
  98. Much like the class literal there's an id literal:
  99. #user-1
  100. // => "<div id="user-1"></div>"
  101. Again we may specify the tag as well:
  102. ul#menu
  103. li: a(href='/home') Home
  104. li: a(href='/store') Store
  105. li: a(href='/contact') Contact
  106. Finally all of these may be used in any combination,
  107. the following are all valid tags:
  108. a.button#contact(style: 'color: red') Contact
  109. a.button(style: 'color: red')#contact Contact
  110. a(style: 'color: red').button#contact Contact
  111. ## Block expansion
  112. Jade supports the concept of "block expansion", in which
  113. using a trailing ":" after a tag will inject a block:
  114. ul
  115. li: a Foo
  116. li: a Bar
  117. li: a Baz
  118. ## Text
  119. Arbitrary text may follow tags:
  120. p Welcome to my site
  121. yields:
  122. <p>Welcome to my site</p>
  123. ## Pipe text
  124. Another form of text is "pipe" text. Pipes act
  125. as the text margin for large bodies of text.
  126. p
  127. | This is a large
  128. | body of text for
  129. | this tag.
  130. |
  131. | Nothing too
  132. | exciting.
  133. yields:
  134. <p>This is a large
  135. body of text for
  136. this tag.
  137. Nothing too
  138. exciting.
  139. </p>
  140. Using pipes we can also specify regular Jade tags
  141. within the text:
  142. p
  143. | Click to visit
  144. a(href='http://google.com') Google
  145. | if you want.
  146. ## Text only tags
  147. As an alternative to pipe text you may add
  148. a trailing "." to indicate that the block
  149. contains nothing but plain-text, no tags:
  150. p.
  151. This is a large
  152. body of text for
  153. this tag.
  154. Nothing too
  155. exciting.
  156. Some tags are text-only by default, for example
  157. _script_, _textarea_, and _style_ tags do not
  158. contain nested HTML so Jade implies the trailing ".":
  159. script
  160. if (foo) {
  161. bar();
  162. }
  163. style
  164. body {
  165. padding: 50px;
  166. font: 14px Helvetica;
  167. }
  168. ## Template script tags
  169. Sometimes it's useful to define HTML in script
  170. tags using Jade, typically for client-side templates.
  171. To do this simply give the _script_ tag an arbitrary
  172. _type_ attribute such as _text/x-template_:
  173. script(type='text/template')
  174. h1 Look!
  175. p Jade still works in here!
  176. ## Interpolation
  177. Both plain-text and piped-text support interpolation,
  178. which comes in two forms, escapes and non-escaped. The
  179. following will output the _user.name_ in the paragraph
  180. but HTML within it will be escaped to prevent XSS attacks:
  181. p Welcome #{user.name}
  182. The following syntax is identical however it will _not_ escape
  183. HTML, and should only be used with strings that you trust:
  184. p Welcome !{user.name}
  185. ## Inline HTML
  186. Sometimes constructing small inline snippets of HTML
  187. in Jade can be annoying, luckily we can add plain
  188. HTML as well:
  189. p Welcome <em>#{user.name}</em>
  190. ## Code
  191. To buffer output with Jade simply use _=_ at the beginning
  192. of a line or after a tag. This method escapes any HTML
  193. present in the string.
  194. p= user.description
  195. To buffer output unescaped use the _!=_ variant, but again
  196. be careful of XSS.
  197. p!= user.description
  198. The final way to mess with JavaScript code in Jade is the unbuffered
  199. _-_, which can be used for conditionals, defining variables etc:
  200. - var user = { description: 'foo bar baz' }
  201. #user
  202. - if (user.description) {
  203. h2 Description
  204. p.description= user.description
  205. - }
  206. When compiled blocks are wrapped in anonymous functions, so the
  207. following is also valid, without braces:
  208. - var user = { description: 'foo bar baz' }
  209. #user
  210. - if (user.description)
  211. h2 Description
  212. p.description= user.description
  213. If you really want you could even use `.forEach()` and others:
  214. - users.forEach(function(user){
  215. .user
  216. h2= user.name
  217. p User #{user.name} is #{user.age} years old
  218. - })
  219. Taking this further Jade provides some syntax for conditionals,
  220. iteration, switch statements etc. Let's look at those next!
  221. ## Assignment
  222. Jade's first-class assignment is simple, simply use the _=_
  223. operator and Jade will _var_ it for you. The following are equivalent:
  224. - var user = { name: 'tobi' }
  225. user = { name: 'tobi' }
  226. ## Conditionals
  227. Jade's first-class conditional syntax allows for optional
  228. parenthesis, and you may now omit the leading _-_ otherwise
  229. it's identical, still just regular javascript:
  230. user = { description: 'foo bar baz' }
  231. #user
  232. if user.description
  233. h2 Description
  234. p.description= user.description
  235. Jade provides the negated version, _unless_ as well, the following
  236. are equivalent:
  237. - if (!(user.isAnonymous))
  238. p You're logged in as #{user.name}
  239. unless user.isAnonymous
  240. p You're logged in as #{user.name}
  241. ## Iteration
  242. JavaScript's _for_ loops don't look very declarative, so Jade
  243. also provides its own _for_ loop construct, aliased as _each_:
  244. for user in users
  245. .user
  246. h2= user.name
  247. p user #{user.name} is #{user.age} year old
  248. As mentioned _each_ is identical:
  249. each user in users
  250. .user
  251. h2= user.name
  252. If necessary the index is available as well:
  253. for user, i in users
  254. .user(class='user-#{i}')
  255. h2= user.name
  256. Remember, it's just JavaScript:
  257. ul#letters
  258. for letter in ['a', 'b', 'c']
  259. li= letter
  260. ## Mixins
  261. Mixins provide a way to define jade "functions" which "mix in"
  262. their contents when called. This is useful for abstracting
  263. out large fragments of Jade.
  264. The simplest possible mixin which accepts no arguments might
  265. look like this:
  266. mixin hello
  267. p Hello
  268. You use a mixin by placing `+` before the name:
  269. +hello
  270. For something a little more dynamic, mixins can take
  271. arguments, the mixin itself is converted to a javascript
  272. function internally:
  273. mixin hello(user)
  274. p Hello #{user}
  275. +hello('Tobi')
  276. Yields:
  277. <p>Hello Tobi</p>
  278. Mixins may optionally take blocks, when a block is passed
  279. its contents becomes the implicit `block` argument. For
  280. example here is a mixin passed a block, and also invoked
  281. without passing a block:
  282. mixin article(title)
  283. .article
  284. .article-wrapper
  285. h1= title
  286. if block
  287. block
  288. else
  289. p No content provided
  290. +article('Hello world')
  291. +article('Hello world')
  292. p This is my
  293. p Amazing article
  294. yields:
  295. <div class="article">
  296. <div class="article-wrapper">
  297. <h1>Hello world</h1>
  298. <p>No content provided</p>
  299. </div>
  300. </div>
  301. <div class="article">
  302. <div class="article-wrapper">
  303. <h1>Hello world</h1>
  304. <p>This is my</p>
  305. <p>Amazing article</p>
  306. </div>
  307. </div>
  308. Mixins can even take attributes, just like a tag. When
  309. attributes are passed they become the implicit `attributes`
  310. argument. Individual attributes can be accessed just like
  311. normal object properties:
  312. mixin centered
  313. .centered(class=attributes.class)
  314. block
  315. +centered.bold Hello world
  316. +centered.red
  317. p This is my
  318. p Amazing article
  319. yields:
  320. <div class="centered bold">Hello world</div>
  321. <div class="centered red">
  322. <p>This is my</p>
  323. <p>Amazing article</p>
  324. </div>
  325. If you use `attributes` directly, *all* passed attributes
  326. get used:
  327. mixin link
  328. a.menu(attributes)
  329. block
  330. +link.highlight(href='#top') Top
  331. +link#sec1.plain(href='#section1') Section 1
  332. +link#sec2.plain(href='#section2') Section 2
  333. yields:
  334. <a href="#top" class="highlight menu">Top</a>
  335. <a id="sec1" href="#section1" class="plain menu">Section 1</a>
  336. <a id="sec2" href="#section2" class="plain menu">Section 2</a>
  337. If you pass arguments, they must directly follow the mixin:
  338. mixin list(arr)
  339. if block
  340. .title
  341. block
  342. ul(attributes)
  343. each item in arr
  344. li= item
  345. +list(['foo', 'bar', 'baz'])(id='myList', class='bold')
  346. yields:
  347. <ul id="myList" class="bold">
  348. <li>foo</li>
  349. <li>bar</li>
  350. <li>baz</li>
  351. </ul>