UNPKG

goji

Version:

An HTML templating engine inspired by Thymeleaf

340 lines (295 loc) 17.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Home</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Home</h1> <h3> </h3> <section> <article><h1>Goji</h1><p><em>Goji</em> is a template engine for <a href="https://nodejs.org/">Node.js</a> that conforms to the <a href="https://hapijs.com/">Hapi</a> view engine <a href="http://hapijs.com/api/8.0.0#serverviewsoptions">requirements</a>.</p> <p><em>Goji</em> was inspired by <a href="https://www.thymeleaf.org/">Thymeleaf</a>. The name was picked from Wikipedia's <a href="https://en.wikipedia.org/wiki/Category:Herbs">list of herbs</a> based on whimsy and availability.</p> <p><em>Goji's</em> templates are (mostly) valid HTML. <em>Goji</em> templates rely on custom attributes that are replaced during the compilation and rendering process.</p> <p>For the API documentation see -- <a href="http://jsumners.github.io/goji/Goji.html">http://jsumners.github.io/goji/Goji.html</a></p> <p>For a short example project see -- <a href="https://github.com/jsumners/goji-hapi-example">https://github.com/jsumners/goji-hapi-example</a></p> <h1>Install</h1><pre class="prettyprint source lang-bash"><code>$ npm install --save goji</code></pre><h1>Example</h1><h2>Template</h2><pre class="prettyprint source lang-html"><code>&lt;!DOCTYPE html> &lt;html> &lt;head>&lt;/head> &lt;body> &lt;div g-text=&quot;foo.bar&quot;>This should be replaced with the value of foo.bar&lt;/div> &lt;div g-text=&quot;foobar()&quot;>This should be replaced with the result of foobar()&lt;/div> &lt;div g-text=&quot;answer === 41 ? foo.bar : 'nope'&quot;>&lt;/div> &lt;div g-text=&quot;(answer === 42) ? foo.bar : 'nope'&quot;>&lt;/div> &lt;/body> &lt;/html></code></pre><h2>Processing</h2><pre class="prettyprint source lang-javascript"><code>var Goji = require('goji'); var goji = new Goji(); var template = goji.loadTemplateNamed('template'); var renderer = goji.compile(template); var context = { foo: { bar: 'foo.bar' }, foobar: function foobar() { return 'foobar() invoked'; }, answer: 42 }; console.log(renderer(context));</code></pre><h1>Compiler Options</h1><p><em>Goji's</em> compiler will load templates based on name when parsing <code>g-include</code> or <code>g-replace</code> attributes, and when using the <code>loadTemplateNamed(name)</code> method.</p> <p>By default, the compiler will look for templates with a file extension of &quot;.html&quot; in an &quot;html&quot; directory that is in the same directory as your project's <code>node_modules</code> directory. Said templates will be cached for five minutes. If you need to change this behavior, you can use the <a href="http://jsumners.github.io/goji/Compiler.html#Options">Compiler Options</a> object:</p> <ul> <li><code>cache</code>: Set to <code>true</code> (default) to enable caching of compiled templates. Set to <code>false</code> to compile templates every load.</li> <li><code>cacheTTL</code>: Time, in seconds, to keep templates in the cache. Default value is 300 (5 minutes).</li> <li><code>templatesDir</code>: The location where templates are stored. This should be the full path (use <code>path.resolve</code>). If it is not present, then it will be set to an &quot;html&quot; directory that is in the same directory as a <code>node_modules</code> directory.</li> <li><code>partialsDir</code>: The location where partial templates are stored. Partials are snippets of html that will be included via the <code>g-partial</code> attribute. The default value for this is <code>(templatesDir + '/partials')</code>.</li> <li><code>templatesExt</code>: The file extension used on template files. This defaults to &quot;.html&quot;. Note that it should include the leading dot.</li> </ul> <pre class="prettyprint source lang-javascript"><code>{ cache: true, cacheTTL: 300, templatesDir: '/path/to/your/templates/directory', partialsDir: '/path/to/your/templates/partials/directory', templatesExt: '.html' }</code></pre><p>The compiler options can be passed to the <em>Goji</em> constructor, or to the <code>compile</code> method.</p> <h1>Template Language</h1><p>As mentioned in the introduction, <em>Goji</em> uses custom attributes on standard HTML elements. Thus <em>Goji's</em> templating &quot;language&quot; is really just vanilla HTML.</p> <p>However, the values of those attributes are not standard. <em>Gogi's</em> attribute values are a mixture of a JavaScript expression language and simple identifiers.</p> <h2>Expression Language</h2><p><em>Goji's</em> expression language is a subset of vanilla JavaScript. It will evaluate simple calculations, ternary operations, object lookups, and invoke methods.</p> <p>Any time an expression is evaluated it is done so within a <em>context</em>. The context is a regular JavaScript object literal. For example, the following literal is a completely valid context that can be used as normal within the expression:</p> <pre class="prettyprint source lang-javascript"><code>{ foo: { bar: [1, 2, 3] }, foobar: function foobar() { return 'result of foobar()'; }, bar: 'bar', baz: 42 }</code></pre><p>The expression language used is <a href="https://github.com/jleibund/exprjs/">exprjs</a>. To see a complete rundown of the available expressions, view their <a href="https://github.com/jleibund/exprjs/blob/master/test/test-expr.js">test-expr.js</a>.</p> <h2>Supported Attributes</h2><h3>g-attr</h3><p><code>g-attr</code> allows you to modify any generic attribute. <code>g-attr</code> attribute values are an expression in the form:</p> <ul> <li><code>value</code>: where <code>value</code> is the name of an attribute to modify/add. For example: <code>g-attr=&quot;href&quot;</code>. This is a shortcut for a single string expression</li> <li><code>'value'</code>: same as above, but as an actual string expression</li> <li><code>['value', 'value', ...]</code>: an array of attribute names to modify/add. For example: <code>g-attr=&quot;['href', 'data-foo']&quot;</code></li> </ul> <p>Each named attribute in the <code>g-attr</code> expression will take its value from an attribute, who's value is an expression, named in the format <code>g-attr-attributeName</code>. For example: <code>g-attr=&quot;data-foo&quot;</code> will get the value for attribute <code>data-foo</code> from the expression in the value of the <code>g-attr-data-foo</code> attribute.</p> <p>Thus, the following template:</p> <pre class="prettyprint source lang-html"><code>&lt;a g-attr=&quot;['href', 'id']&quot; g-attr-href=&quot;foo.url&quot; g-attr-id=&quot;foo.id&quot;>foo&lt;/a></code></pre><p>With the context:</p> <pre class="prettyprint source lang-javascript"><code>{ foo: { url: 'http://example.com/foo', id: 'foobar' } }</code></pre><p>Will render to:</p> <pre class="prettyprint source lang-html"><code>&lt;a href=&quot;http://example.com/foo&quot; id=&quot;foobar&quot;>foo&lt;/a></code></pre><p><strong>Note:</strong> if you modify the <code>class</code> attribute with this method then it will overwrite any class names in a pre-existing class attribute. To append or prepend classes, use <code>g-class</code> and <code>g-classprepend</code>.</p> <h3>g-class</h3><p><code>g-class</code> appends the result of an expression to the element's class attribute. For example, given the following HTML:</p> <pre class="prettyprint source lang-html"><code>&lt;div g-class=&quot;foo.class&quot; class=&quot;bar&quot;>placeholder&lt;/div></code></pre><p>The rendered template would be:</p> <pre class="prettyprint source lang-html"><code>&lt;div class=&quot;bar foo&quot;>placeholder&lt;/div></code></pre><p>Where the expression <code>foo.class</code> evaluates to &quot;foo&quot;.</p> <p>If the element does not already have a class attribute, the the attribute will be added.</p> <h3>g-classprepend</h3><p><code>g-classprepend</code> works like <code>g-class</code> except it prepends the class attribute with the result of the <code>g-classprepend</code> expression.</p> <h3>g-text</h3><p><code>g-text</code> substitutes the result of an expression in place of the element's content. For example, given the following HTML:</p> <pre class="prettyprint source lang-html"><code>&lt;p>Hello &lt;span g-text=&quot;'world'&quot;>??&lt;/span>!&lt;/p></code></pre><p>The rendered template would be:</p> <pre class="prettyprint source lang-html"><code>&lt;p>Hello &lt;span>world&lt;/span>!&lt;/p></code></pre><h3>g-each</h3><p><code>g-each</code> is used to iterate over an array. It uses a simple expression to select the array and name the iteration variable. The expression is in the form <code>[iteration variable name] in [array name]</code>. For example:</p> <pre class="prettyprint source lang-html"><code>&lt;ul> &lt;li g-each=&quot;item in items&quot; g-text=&quot;item&quot;>placeholder&lt;/li> &lt;/ul></code></pre><p>If the context is:</p> <pre class="prettyprint source lang-javascript"><code>{items: ['list item 1', 'list item 2', 'list item 3']}</code></pre><p>Then the rendered content would be:</p> <pre class="prettyprint source lang-html"><code>&lt;ul> &lt;li>list item 1&lt;/li> &lt;li>list item 2&lt;/li> &lt;li>list item 3&lt;/li> &lt;/ul></code></pre><p>However, if the template is:</p> <pre class="prettyprint source lang-html"><code>&lt;table> &lt;tr g-each=&quot;row in rows&quot;> &lt;td g-text=&quot;row.cell1&quot;>cell1&lt;/td> &lt;td g-text=&quot;row.cell2&quot;>cell2&lt;/td> &lt;/tr> &lt;/table></code></pre><p>And the context is:</p> <pre class="prettyprint source lang-javascript"><code>{ rows: [ {cell1: 'r1c1', cell2: 'r1c2'}, {cell1: 'r2c1', cell2: 'r2c2'} ] }</code></pre><p>Then the rendered content would be:</p> <pre class="prettyprint source lang-html"><code>&lt;table> &lt;tr> &lt;td>r1c1&lt;/td> &lt;td>r1c2&lt;/td> &lt;/tr> &lt;tr> &lt;td>r2c1&lt;/td> &lt;td>r2c2&lt;/td> &lt;/tr> &lt;/table></code></pre><p>There are a few things to notice in these examples:</p> <ol> <li>If the template element has both <code>g-each</code> and <code>g-text</code> attributes, then the template element will be used as the template for the iterations.</li> <li>If the template element only has a <code>g-each</code> attribute, then the <em>parent element's content</em> will be used as the template for the iterations.</li> <li>In either case 1 or 2, the content of the <em>parent element</em> will be replaced with the rendered content.</li> </ol> <p><code>g-each</code> includes the following extra context on each iteration:</p> <pre class="prettyprint source lang-javascript"><code>{ iter: { i: `number`, odd: `boolean`, even: `boolean` } }</code></pre><p>Thus, on the third iteration, the extra context would be:</p> <pre class="prettyprint source lang-javascript"><code>{ iter: { i: 2, odd: false, even: true } }</code></pre><p>Combined with <code>g-class</code>, you can render the following template:</p> <pre class="prettyprint source lang-html"><code>&lt;ul> &lt;li g-each=&quot;item in items&quot; g-text=&quot;item&quot; g-class=&quot;(iter.odd) ? 'odd' : 'even'&quot;>placeholder&lt;/li> &lt;/ul></code></pre><p>Into:</p> <pre class="prettyprint source lang-html"><code>&lt;ul> &lt;li class=&quot;even&quot;>list item 1&lt;/li> &lt;li class=&quot;odd&quot;>list item 2&lt;/li> &lt;li class=&quot;even&quot;>list item 3&lt;/li> &lt;/ul></code></pre><p>Given the same context as the first example in this section.</p> <h3>g-if</h3><p><code>g-if</code> is <em>Goji's</em> conditional attribute. If the expression supplied in a <code>g-if</code> attribute value evaluates to <code>true</code> then the whole block will be parsed and rendered. If the expression evaluates to <code>false</code>, then the whole block will be removed without futher processing.</p> <p>For example:</p> <pre class="prettyprint source lang-html"><code>&lt;div g-if=&quot;1 === 1&quot;> &lt;p g-text=&quot;'This will be rendered'&quot;>placeholder&lt;/p> &lt;p g-if=&quot;1 === 1&quot; g-text=&quot;'As will this'&quot;>placeholder&lt;/p> &lt;p g-if=&quot;1 === 2&quot;>This will not&lt;/p> &lt;/div></code></pre><p>Will render to the following:</p> <pre class="prettyprint source lang-html"><code>&lt;div> &lt;p>This will be rendered&lt;/p> &lt;p>As will this&lt;/p> &lt;/div></code></pre><h3>g-include</h3><p><code>g-include</code> inserts the content of a fragment in place of the element's content. The value of <code>g-include</code> is a simple identifier in the form <code>[templateName]::[fragmentId]</code>. For example, given the following HTML:</p> <pre class="prettyprint source lang-html"><code>&lt;div class=&quot;container&quot;> &lt;div g-include=&quot;fooTemplate::#bar&quot;>This will be replaced&lt;/div> &lt;/div></code></pre><p><em>Goji</em> will look for a template file named &quot;fooTemplate&quot;, parse it, and then retrieve the content from an element with an <code>id</code> attribute value of &quot;bar&quot;. So, if fooTemplate's content is:</p> <pre class="prettyprint source lang-html"><code>&lt;p id=&quot;bar&quot;>bar's content&lt;/p></code></pre><p>Then the rendered template will be:</p> <pre class="prettyprint source lang-html"><code>&lt;div class=&quot;container&quot;> &lt;div>bar's content&lt;/div> &lt;/div></code></pre><h3>g-replace</h3><p><code>g-replace</code> works much like <code>g-include</code>, the difference is that <code>g-replace</code> replaces the element on which it is an attribute. Thus, given the same example as in <code>g-include</code> the rendered template would be:</p> <pre class="prettyprint source lang-html"><code>&lt;div class=&quot;container&quot;> &lt;p id=&quot;bar&quot;>bar's content&lt;/p> &lt;/div></code></pre><h3>g-partial</h3><p><code>g-partial</code> is similar to <code>g-include</code> and <code>g-replace</code>. The difference is that <code>g-partial</code> is 1) processed during the render phase and 2) the attribute value is an expression. The result of the expression is expected to be the name of another template file. Said template is then loaded, rendered, and injected as the body of the element upon which the <code>g-partial</code> attribute is present.</p> <p>Thus, given the following document:</p> <pre class="prettyprint source lang-html"><code>&lt;html> &lt;head>&lt;/head> &lt;body> &lt;main g-partial=&quot;partial.name&quot;> placeholder &lt;/main> &lt;/body> &lt;/html></code></pre><p>With a partial template named &quot;indexBody.html&quot; in the templates directory who's content is merely:</p> <pre class="prettyprint source lang-html"><code>&lt;p>Hello world!&lt;/p></code></pre><p>And a context of:</p> <pre class="prettyprint source lang-javascript"><code>{ partial: { name: 'indexBody' } }</code></pre><p>Then the rendered document would be:</p> <pre class="prettyprint source lang-html"><code>&lt;html> &lt;head>&lt;/head> &lt;body> &lt;main> &lt;p>Hello world!&lt;/p> &lt;/main> &lt;/body> &lt;/html></code></pre><p><strong>Note:</strong> as of <em>Goji</em> version <strong>0.8.0</strong> the default path for partials is in a sub-directory of the main templates directory. The default name for this sub-directory is <code>partials</code>.</p> <h1>License</h1><p><a href="http://jsumners.mit-license.org/">http://jsumners.mit-license.org</a></p> <p>THE MIT LICENSE (MIT) Copyright © 2014 James Sumners james.sumners@gmail.com</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p></article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Compiler.html">Compiler</a></li><li><a href="Goji.html">Goji</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.1</a> on Tue Jun 09 2015 14:05:51 GMT-0400 (EDT) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>