Comparing version 0.1.0 to 0.2.0
@@ -12,2 +12,5 @@ 'use strict'; | ||
shell: { | ||
cleanDoc: { | ||
command: 'rm -rf doc/*' | ||
}, | ||
doc: { | ||
@@ -28,3 +31,3 @@ command: './node_modules/.bin/jsdoc -c jsdoc.conf .' | ||
grunt.registerTask('doc', ['shell:doc']); | ||
grunt.registerTask('doc', ['shell:cleanDoc', 'shell:doc']); | ||
grunt.registerTask('publishdoc', ['githubPages:target']); |
@@ -14,4 +14,10 @@ 'use strict'; | ||
while (!fs.existsSync(_path + '/node_modules') || _path.substr(-4) === 'goji') { | ||
_path = path.resolve(_path + '/..'); | ||
if (_path.indexOf('node_modules/goji') !== -1) { | ||
while (!fs.existsSync(_path + '/node_modules') || _path.substr(-4) === 'goji') { | ||
_path = path.resolve(_path + '/..'); | ||
} | ||
} else { | ||
while (!fs.existsSync(_path + '/node_modules')) { | ||
_path = path.resolve(_path + '/..'); | ||
} | ||
} | ||
@@ -61,2 +67,93 @@ | ||
/** | ||
* <p>Parses for elements that have a <code>g-each</code> attribute and renders | ||
* them. If the element also has a <code>g-text</code> attribute, then the | ||
* element is used as the template. Otherwise, the content of the parent | ||
* element is used as the template. In either case, the final result will be | ||
* that the parent element's content is replaced with the rendered template.</p> | ||
* | ||
* <p>Additionally, an extra context will be present during the parsing of the | ||
* template. This extra context is an object named <code>iter</code>. It has a | ||
* property <code>i</code> that indicates the iteration number. It also has | ||
* two boolean properties: <code>odd</code> and <code>even</code>. These two | ||
* properties can be used as shortcuts to determine whether the iteration | ||
* number is odd or even.</p> | ||
* | ||
* @param {object} $ A cheerio object that respresents the template | ||
* @param {object} context The context for the template actions | ||
* @param {object} gContext A context of extra information provided by Goji | ||
* @returns {object} The modified cheerio object | ||
* @since 0.2.0 | ||
* @private | ||
*/ | ||
Compiler.prototype._each = function _each($, context, gContext) { | ||
var self = this; | ||
var iter = { | ||
i: 0, | ||
get odd() { | ||
return (this.i % 2) !== 0; | ||
}, | ||
get even() { | ||
return (this.i % 2) === 0; | ||
} | ||
}; | ||
return $('[g-each]').each(function gEach(i, elem) { | ||
// This thing is a mess | ||
iter.i = 0; | ||
var $elem = $(elem); | ||
var parts = $elem.attr('g-each').split(' in ').map(function(val) { | ||
return val.trim(); | ||
}); | ||
// Retrieve the desired array from the context | ||
var expr = exprjs.parse(parts[1]); | ||
var list = exprjs.run(expr, context, gContext); | ||
// Evaluate the subsitution expression if it is directly on the element | ||
var gText = $elem.attr('g-text'); | ||
if (gText) { | ||
var expr2 = exprjs.parse($elem.attr('g-text')); | ||
$elem.removeAttr('g-text'); | ||
} | ||
$elem.removeAttr('g-each'); // remove it so we don't run it again | ||
var varName = parts[0]; | ||
var _context = {}; | ||
_context[varName] = ''; | ||
// Prepare our target DOM nodes | ||
var $parent = $elem.parent(); | ||
var $node = $elem.clone(); | ||
$parent.html(''); | ||
var iterRender = function(){}; | ||
if (gText) { | ||
iterRender = function iterRender1(item) { | ||
_context[varName] = item; | ||
var result = exprjs.run(expr2, _context, iter); | ||
$node.html(result); | ||
$parent.append($node.clone()); | ||
iter.i += 1; | ||
}; | ||
} else { | ||
var innerTemplate = $node.html(); | ||
iterRender = function iterRender2(item) { | ||
_context[varName] = item; | ||
var result = self._render(innerTemplate, _context, iter); | ||
$node.html(result); | ||
$parent.append($node.clone()); | ||
iter.i += 1; | ||
}; | ||
} | ||
// Finally loop through and render | ||
list.forEach(iterRender); | ||
return $elem; | ||
}); | ||
}; | ||
/** | ||
* This method is used to parse a given <code>template</code> for included | ||
@@ -155,11 +252,13 @@ * blocks from other templates. An include does not replace the element on | ||
* | ||
* @param template A template as compiled by {@link Compiler#_parse} | ||
* @param context The object to use as the context for actions | ||
* @param {string} template A template as compiled by {@link Compiler#_parse} | ||
* @param {object} context The object to use as the context for actions | ||
* @param {object} gContext A context of extra information provided by Goji | ||
* @returns {string} The rendered template | ||
* @private | ||
*/ | ||
Compiler.prototype._render = function _render(template, context) { | ||
Compiler.prototype._render = function _render(template, context, gContext) { | ||
var $ = cheerio.load(template); | ||
this._text($, context); | ||
this._each($, context, gContext); // Should be parsed first | ||
this._text($, context, gContext); | ||
@@ -175,6 +274,7 @@ return $.html(); | ||
* @param {object} context The context for the the template actions | ||
* @param {object} gContext A context of extra information provided by Goji | ||
* @returns {object} The modified cheerio object | ||
* @private | ||
*/ | ||
Compiler.prototype._text = function _text($, context) { | ||
Compiler.prototype._text = function _text($, context, gContext) { | ||
return $('[g-text]').each(function(i, elem) { | ||
@@ -184,3 +284,3 @@ var $elem = $(elem); | ||
var parsed = exprjs.parse(expression); | ||
var result = exprjs.run(parsed, context); | ||
var result = exprjs.run(parsed, context, gContext); | ||
@@ -187,0 +287,0 @@ $elem.text(result); |
{ | ||
"name": "goji", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "An HTML templating engine inspired by Thymeleaf", | ||
@@ -5,0 +5,0 @@ "main": "goji.js", |
@@ -95,3 +95,3 @@ # Goji | ||
foobar: function foobar() { | ||
return 'result of foobar()`; | ||
return 'result of foobar()'; | ||
}, | ||
@@ -124,5 +124,79 @@ bar: 'bar', | ||
### g-each | ||
`g-each` 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 `[iteration variable name] in [array name]`. For example: | ||
```html | ||
<ul> | ||
<li g-each="item in items" g-text="item">placeholder</li> | ||
</ul> | ||
``` | ||
If the context is: | ||
```javascript | ||
{items: ['list item 1', 'list item 2', 'list item 3']} | ||
``` | ||
Then the rendered content would be: | ||
```html | ||
<ul> | ||
<li>list item 1</li> | ||
<li>list item 2</li> | ||
<li>list item 3</li> | ||
</ul> | ||
``` | ||
However, if the template is: | ||
```html | ||
<table> | ||
<tr g-each="row in rows"> | ||
<td g-text="row.cell1">cell1</td> | ||
<td g-text="row.cell2">cell2</td> | ||
</tr> | ||
</table> | ||
``` | ||
And the context is: | ||
```javascript | ||
{ | ||
rows: [ | ||
{cell1: 'r1c1', cell2: 'r1c2'}, | ||
{cell1: 'r2c1', cell2: 'r2c2'} | ||
] | ||
} | ||
``` | ||
Then the rendered content would be: | ||
```html | ||
<table> | ||
<tr> | ||
<td>r1c1</td> | ||
<td>r1c2</td> | ||
</tr> | ||
<tr> | ||
<td>r2c1</td> | ||
<td>r2c2</td> | ||
</tr> | ||
</table> | ||
``` | ||
There are a few things to notice in these examples: | ||
1. If the template element has both `g-each` and `g-text` attributes, | ||
then the template element will be used as the template for the | ||
iterations. | ||
2. If the template element only has a `g-each` attribute, then the *parent | ||
element's content* will be used as the template for the iterations. | ||
3. In either case 1 or 2, the content of the *parent element* will be | ||
replaced with the rendered content. | ||
### g-include | ||
`g-include` inserts the content of a fragment in place of the element's | ||
content. The value of `g-include` is a simple identifier that in the form | ||
content. The value of `g-include` is a simple identifier in the form | ||
`[templateName]::[fragmentId]`. For example, given the following HTML: | ||
@@ -129,0 +203,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1119050
912
245