/wiki/JsPlate.wiki

http://jsdoc-toolkit.googlecode.com/ · Unknown · 237 lines · 165 code · 72 blank · 0 comment · 0 complexity · b59bc5f9bcd75dfe5ede5f1c5d17844c MD5 · raw file

  1. #summary Creating JavaScript templates used by JsDoc Toolkit
  2. = !JsPlate Introduction =
  3. !JsPlate is a !JavaScript-based templating system. This system is used by !JsDoc Toolkit to format the documentation information it parses out of your source files into published output, such as HTML web pages or XML documents.
  4. = Overview =
  5. As !JsDoc Toolkit uses them, a "template" is a directory containing the following files:
  6. * publish.js
  7. * <!JsPlate template file/s>
  8. * <any other file/s>
  9. === publish.js ===
  10. The publish.js file is required. It defines and controls the process of publishing a collection of input and output files. Using !JsDoc Toolkit you may have many input files, and these may be combined or split in various ways into a complete package of output files.
  11. === !JsPlate Files ===
  12. A template file defines how to format some data into a particular kind of output file. It contains formatting instructions written in the !JsPlate microlanguage, a very simple template language that will be demonstrated below.
  13. === Other Files ===
  14. Other files you might include could be static resources like images, stylesheets, or whatever else you want to be part of your final published output.
  15. The expectation is that all output files will be saved to or copied over to a single output directory. By convention, the default name of this directory is "js_docs_out" but you can provide any name you prefer using the {{{-d=some/other/dir/}}} command line option.
  16. = publish.js In Detail =
  17. To create a !JsPlate template you first create a folder. The name of that folder is the name of the template. For example, if you wanted to create a template called "mytmp" you would start with an empty folder named "mytmp". Within your new template folder you must now create a file named `publish.js`. A very minimal publish.js file might look like this:
  18. {{{
  19. function publish(fileGroup, context) {
  20. }
  21. }}}
  22. As you can see, there is one function defined in the `publish.js` file: In the `publish` function you can add any code you like to handle the main publishing work. !JsDoc Toolkit will pass in a fileGroup object along with the commandline options you provided when you invoked the application.
  23. A fileGroup has a property called `files` that contains information about every file the parser scanned. You can iterate over that to get information about each file.
  24. {{{
  25. function publish(fileGroup, context) {
  26. var file_template = new JsPlate(context.t+"file.tmpl");
  27. for (var i = 0; i < fileGroup.files.length; i++) {
  28. var output = template.process(fileGroup.files[i]);
  29. }
  30. }
  31. }}}
  32. = !JsPlate In Detail =
  33. The !JsPlate micro-language really is "micro" -- it has exactly four syntax constructs. The first two are tags:
  34. * `<for>...</for>` - loops over objects in an array or named in an object.
  35. * `<if>...</if>` - conditionally renders some content based on a test.
  36. Additionally there are two field specifiers.
  37. * `{+foo+}` - inserts the value in the foo variable into the template output.
  38. * `{!doSomething();!}` - evaluates the !JavaScript code.
  39. The content of a `{+ ... +}` doesn't have to be static, for example you can insert the current date into the output like so: `{+ new Date() +}`. Similarly, notice that `{+ foo +}` is really just a nicer way of saying: `{! output += foo; !}` -- you can manipulate `output` directly from within `{! ... !}` if you want. Comments can be added using the `{# this is ignored #}` syntax.
  40. == for Loops ==
  41. The `for` mark-up tag lets you loop over all the items stored in an array or stored in an object as properties. For example, assume that `data.things` is an array. To render a list of the things in your output, you could do the following:
  42. {{{
  43. <ul>
  44. <for each="thing" in="data.things">
  45. <li>{+thing+}</li>
  46. </for>
  47. </ul>
  48. }}}
  49. This would work exactly the same if you were accessing all the _values_ stored in an object: if `data.things` were set to {Sue: "red", Bob: "blue"} the above code would print the values like so:
  50. {{{
  51. <ul>
  52. <li>red</li>
  53. <li>blue</li>
  54. </ul>
  55. }}}
  56. If you were only interested in outputting the keys, not the values, you could use the built-in `keys` function like so:
  57. {{{
  58. <ul>
  59. <for each="thing" in="keys(data.things)">
  60. <li>{+thing+}</li>
  61. </for>
  62. </ul>
  63. }}}
  64. Which would yield:
  65. {{{
  66. <ul>
  67. <li>Sue</li>
  68. <li>Bob</li>
  69. </ul>
  70. }}}
  71. And, since the `in` attribute can take any !JavaScript as it's value you can get sorted keys like so.
  72. {{{
  73. <ul>
  74. <for each="thing" in="keys(data.things).sort()">
  75. <li>{+thing+}</li>
  76. </for>
  77. </ul>
  78. }}}
  79. Which would yield:
  80. {{{
  81. <ul>
  82. <li>Bob</li>
  83. <li>Sue</li>
  84. </ul>
  85. }}}
  86. If you wanted both the keys and values you can use the special key varaible that exists within each `for` loop. If the value is assigned to "foo" the key would be available as "$foo_key" like so:
  87. {{{
  88. <ul>
  89. <for each="thing" in="data.things">
  90. <li>{+$thing_key+": "+thing+}</li>
  91. </for>
  92. </ul>
  93. }}}
  94. Resulting in:
  95. {{{
  96. <ul>
  97. <li>Bob: blue</li>
  98. <li>Sue: red</li>
  99. </ul>
  100. }}}
  101. Using another special variable you can get the numeric index of a `for` loop. If the value is assigned to "foo" the numeric key would be available as "$foo_i" like so:
  102. {{{
  103. <ul>
  104. <for each="thing" in="data.things">
  105. <li>{+$thing_i+": "+thing+}</li>
  106. </for>
  107. </ul>
  108. }}}
  109. Resulting in:
  110. {{{
  111. <ul>
  112. <li>0: blue</li>
  113. <li>1: red</li>
  114. </ul>
  115. }}}
  116. Finally, within a `for` loop there is a way to detect if you are on the last iteration. If the value is assigned to "foo" the boolean that indicates the last loop will be available as "$foo_last" like so:
  117. {{{
  118. <ul>
  119. <for each="thing" in="data.things">
  120. <li>{+thing+}</li>
  121. <if test="!$thing_last">...</if>
  122. </for>
  123. </ul>
  124. }}}
  125. Resulting in:
  126. {{{
  127. <ul>
  128. <li>blue</li>
  129. ...
  130. <li>red</li>
  131. </ul>
  132. }}}
  133. == if Blocks ==
  134. The `if` mark-up allows you conditionally output some text or field based on a test.
  135. {{{
  136. <if test="thing=='Bob'">
  137. <em>The Best</em>
  138. </if>
  139. }}}
  140. Would only add "The Best" to the output when the `thing` was "Bob." You can of course nest `for` and `if` as much as you need, perhaps only looping in certain conditions, or only doing certain things for certain loop iterations.
  141. {{{
  142. <if test="thing=='Bob'">
  143. <em>The Best</em>
  144. <else />
  145. <em>meh!</em>
  146. </if>
  147. }}}
  148. = Creating Output Files =
  149. == Saving Generated Output To Files ==
  150. From within your `publish.js` file you can save the your template output to files using the `IO.saveFile` function.
  151. {{{
  152. function publish(fileGroup, context) {
  153. var file_template = new JsPlate(context.t+"file.tmpl");
  154. for (var i = 0; i < fileGroup.files.length; i++) {
  155. var output = template.process(fileGroup.files[i]);
  156. IO.saveFile(context.d, "docs"+i+".htm", output);
  157. }
  158. }
  159. }}}
  160. The `IO.saveFile` function takes an output directory as it's first argument, and this will automatically be set on the `context` based on what output directory you specified on the command line when you executed !JsDoc Toolkit.
  161. == Copying Static Files To The Output Directory==
  162. From within your `publish.js` file you can copy files from the template directory into the output directory using the `IO.copyFile` function. For example if you had a static css file that you wanted copied into the output directory, you could do this:
  163. {{{
  164. IO.copyFile(context.t+"mystyle.css", context.d);
  165. }}}