|
| 1 | +Themes are templates |
| 2 | +--------------------- |
| 3 | + |
| 4 | +The theme infrastructure is really a templating library. It consists |
| 5 | +of an extended version of EJS (like ERB but for JavaScript). |
| 6 | + |
| 7 | +Many templating libraries (Smarty, Django templates) adds a special |
| 8 | +template script language that provides things like inheritance and |
| 9 | +blocks, but also general programming constructs like loops and |
| 10 | +conditionals. |
| 11 | + |
| 12 | +The EJS templating language uses JavaScript as templating scripting |
| 13 | +language, giving you the full power JavaScript in your templates. In |
| 14 | +addition, it provides a standard library for interacting with the |
| 15 | +template content. |
| 16 | + |
| 17 | +EJS tags |
| 18 | +--------- |
| 19 | + |
| 20 | +An EJS template consist of verbatim HTML (or other text) and |
| 21 | +server-side JavaScripts mixed in one file. There are three syntaxes |
| 22 | +available to mix in JavaScript in the verbatim HTML: |
| 23 | + |
| 24 | + <h1>some HTML</h1> |
| 25 | + <% myVar = someJavaScript(); xyzzy = goesHere(); %> |
| 26 | + <p>some more HTML</p> |
| 27 | + <% if (myVar != '') { %> |
| 28 | + myVar is not empty |
| 29 | + <% } %> |
| 30 | + |
| 31 | +This will execute the javascript statements beteen <% and %>, but |
| 32 | +throw away any result values. To insert a value in the generated HTML, |
| 33 | +you use the <%= syntax: |
| 34 | + |
| 35 | + <p>Result from previous code plus 47: <%= xyzzy + 47 %></p> |
| 36 | + |
| 37 | +This will convert the value in the expression to string and then |
| 38 | +include it. If the value already is a string, you can gain a little |
| 39 | +more expressive freedom by using the <%: syntax instead: |
| 40 | + |
| 41 | + <p>Result from previous code: <%: myVar %></p> |
| 42 | + |
| 43 | +The advantage of the latter one is that it does not require the code |
| 44 | +between <%: and %> to be a full JavaScript expression, but can be a |
| 45 | +fragment of one. To understand how this is usefull, we have to examine |
| 46 | +another property of EJS: What happens to verbatim HTML. |
| 47 | + |
| 48 | + |
| 49 | +Verbatim text in EJS and the evaluation model |
| 50 | +---------------------------------------------- |
| 51 | + |
| 52 | +During evaluation of an EJS template, verbatim HTML is appended to a |
| 53 | +variable called ejs_data, one part at a time. Consider the following code: |
| 54 | + |
| 55 | + Some text |
| 56 | + <% temp = ejs_data; ejs_data = ''; %> |
| 57 | + some text to be encoded |
| 58 | + <% data = base64encode(ejs_data); ejs_data = temp; %> |
| 59 | + Base64 dump: <%= data %> |
| 60 | + |
| 61 | +This will encode the string "some text to be encoded" with the |
| 62 | +base64encode function and insert the result at the end of the output. |
| 63 | +The original, unencoded string is not inserted in the output. |
| 64 | + |
| 65 | +Since ejs_data is just a normal variable that can be hidden by a local |
| 66 | +variable in a function, this allows for creating functions that |
| 67 | +returns mostly text using the normal EJS templating syntax: |
| 68 | + |
| 69 | + <% function header(n) { var ejs_data = ''; %> |
| 70 | + Hello world <%= n %> times! |
| 71 | + <% return ejs_data; } %> |
| 72 | + |
| 73 | +This is equivalent to |
| 74 | + |
| 75 | + <% |
| 76 | + function (n) { |
| 77 | + return "Hello world " + n + " times!"; |
| 78 | + } |
| 79 | + %> |
| 80 | + |
| 81 | +Of course this only starts to be usefull when the function should |
| 82 | +return a larger body of verbatim text. |
| 83 | + |
| 84 | +So, back to the usefullness of the <%: syntax: |
| 85 | + |
| 86 | + Base64 dump: |
| 87 | + <%: base64encode(function () { var ejs_data = ''; %> |
| 88 | + some text to be encoded |
| 89 | + <% return ejs_data; }); %> |
| 90 | + |
| 91 | +Here, the base64encode function call only ends inside the last <% %> |
| 92 | +block. This type of expression is extensively used for the template |
| 93 | +inheritance and block functions. |
| 94 | + |
| 95 | +Standard functions |
| 96 | +------------------- |
| 97 | + |
| 98 | +In addition to the ability to mix verbatim text and code, templates |
| 99 | +needs some additional functionality not found in a scripting language, |
| 100 | +or at least not in the same form. This include textual inheritance and |
| 101 | +blocks. |
| 102 | + |
| 103 | +In EJS this is provided by a standrad function library. |
| 104 | + |
| 105 | +template.inherit('page.ejs'); |
| 106 | + Declares that the template inherits from another template, page.ejs. |
| 107 | + This should only be called once in a template, and at the top. |
| 108 | + |
| 109 | +<%: template.use('blockName'); %> |
| 110 | +<%: template.use('blockName', function() { var ejs_data=''; %>Default content<% return ejs_data; }); %> |
| 111 | + Declares a block that can be overridden by an inheriting template. |
| 112 | + If the first form of the call is used the block is empty unless |
| 113 | + overridden. |
| 114 | + |
| 115 | +<% template.define('blockName', function() { var ejs_data=''; %>New block content<% return ejs_data; }); %> |
| 116 | + Overrides the content of a block of an inherited template. |
| 117 | + |
| 118 | +Note: All templates should define (or inherit from a template that |
| 119 | +defines) a top-level block named "body". The content of this block, |
| 120 | +will be the final output of the template. |
0 commit comments