Created
September 12, 2012 14:19
-
-
Save getify/3706912 to your computer and use it in GitHub Desktop.
how "grips" templating handles it, in response to https://gist.github.com/3696453
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{$: '#settings' } | |
<h1>Settings</h1> | |
{$* $.settings | name = _.key | options['low','high'] = _.value ? "checked" } | |
<h2>{$= name $}</h2> | |
{$* options } | |
<input type="radio" name="{$= name $}" value="{$= _.key $}" {$= _.value $}> {$= _.key $} | |
{$} | |
{$} | |
{$} | |
<!-- | |
Here's how "grips" templating engine would handle it. | |
Some notes: | |
1. Some of the "grips" template tag syntax shown in this example: | |
- `{$: "#id" }` defines a top-level template section by id. | |
- `{$* ref }` defines a loop block to iterate over `ref`. | |
- `{$= ref $}` includes the value of `ref`. | |
- for define tags and loop tags, you can optionally have a | delimited | |
list of assignment statements. (see `name` and `setting` assignments above) | |
- any reference of a variable that is not scoped (prefixed) with `$.` or | |
`_.` will automatically be treated as a "local variable" within that | |
block. you can create local variables as much as necessary. (see `name` | |
and `setting` variables above) | |
- assignments can optionally use a ?: ternary operator. A special syntax | |
applies to the else clause: an empty string ("") expression is assumed if the | |
else clause (`: ref`) is omitted. | |
- a special syntax for assignment statements is when the LH of the assignment | |
includes a set literal (like `checked['low','high'] = ...`), and the RH of | |
the assignment is a ?: ternary expression. The example above | |
(`checked['low','high'] = setting ? 'checked'`) roughly equates to: | |
`checked['low'] = (setting === 'low') ? 'checked' : ''` and | |
`checked['high'] = (setting === 'high') ? 'checked' : ''`. It basically is | |
a pre-computation hash for the comparisons, where the comparison results can | |
then be used in the template as an include. Since the conditional comparison | |
has already happened before you include, it emulates the concept of a | |
conditional include. | |
2. in expressions, `$` is how you reference the data structure in the current | |
context. | |
3. in expressions, `_` is how you reference the current iterator in a loop. | |
- `_.value` is the actual value of the current iteration (whatever data | |
type it may be). | |
- `_.key` is either the numeric index for an array iteration, or the string | |
property name for an object-property iteration. | |
- `_.index` is the numeric index of the iteration (regardless of whether | |
iterating over an array or object). | |
- `_.even` is true for even (0,2,4,...) iterations. | |
- `_.odd` is true for odd (1,3,5,...) iterations (iterations are 0-based). | |
4. Loops can iterate over arrays, objects, set literals (`['low','high']` as shown | |
above), or range literals (which would look like `[3..7]`). | |
--> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function __3_html__(G) { | |
function __sort_fn__(a, b) { | |
return a - b; | |
} | |
var partial = G.definePartial, | |
clone = G.cloneObj, | |
extend = G.extend, | |
esc = G.strEscapes, | |
error = G.error, | |
unerr = new Error("Unknown error"), | |
RLH = G.RangeLiteralHash, | |
cID = "3.html"; | |
partial(function __settings__($, $$) { | |
$ = $ || {}; | |
$$ = clone($$) || {}; | |
var i, ret = "", | |
ret2, _; | |
ret += "\n <h1>Settings</h1>\n "; | |
ret2 = (function __loop__() { | |
function __iter__($, $$, value, key, index) { | |
var i, ret = "", | |
ret2, _; | |
if (value == null) return ret; | |
$$ = clone($$); | |
_ = { | |
value: value, | |
key: key, | |
index: index, | |
even: (index % 2) === 0, | |
odd: (index % 2) === 1, | |
first: (index === 0), | |
last: (index === len - 1) | |
}; | |
try { | |
$$.name = _.key; | |
} catch (err1) { | |
return error(cID, { | |
"type": 11, | |
"pos": { | |
"line": 3, | |
"col": 21 | |
}, | |
"val": "name = _.key" | |
}, "Assignment failed in loop iteration: " + JSON.stringify(_, ["key", "index"]), err1); | |
} | |
try { | |
$$.options = {}; | |
var _set = ['low', 'high']; | |
for (i = 0; i < 2; i++) { | |
$$.options[_set[i]] = (_.value === _set[i]) ? "checked" : ""; | |
} | |
} catch (err2) { | |
return error(cID, { | |
"type": 11, | |
"pos": { | |
"line": 3, | |
"col": 36 | |
}, | |
"val": "options['low','high'] = _.value ? \"checked\" : \"\"" | |
}, "Assignment failed in loop iteration: " + JSON.stringify(_, ["key", "index"]), err2); | |
} | |
ret += "\n <h2>"; | |
try { | |
ret += $$.name; | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 4, | |
"col": 16 | |
}, | |
"val": "name" | |
}, "Insert reference failed", err); | |
} | |
ret += "</h2>\n "; | |
ret2 = (function __loop__() { | |
function __iter__($, $$, value, key, index) { | |
var i, ret = "", | |
ret2, _; | |
if (value == null) return ret; | |
$$ = clone($$); | |
_ = { | |
value: value, | |
key: key, | |
index: index, | |
even: (index % 2) === 0, | |
odd: (index % 2) === 1, | |
first: (index === 0), | |
last: (index === len - 1) | |
}; | |
ret += "\n <input type=\"radio\" name=\""; | |
try { | |
ret += $$.name; | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 6, | |
"col": 42 | |
}, | |
"val": "name" | |
}, "Insert reference failed", err); | |
} | |
ret += "\" value=\""; | |
try { | |
ret += _.key; | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 6, | |
"col": 62 | |
}, | |
"val": "_.key" | |
}, "Insert reference failed", err); | |
} | |
ret += "\" "; | |
try { | |
ret += _.value; | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 6, | |
"col": 76 | |
}, | |
"val": "_.value" | |
}, "Insert reference failed", err); | |
} | |
ret += "> "; | |
try { | |
ret += _.key; | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 6, | |
"col": 92 | |
}, | |
"val": "_.key" | |
}, "Insert reference failed", err); | |
} | |
ret += "\n "; | |
return ret; | |
} | |
var i, j = 0, | |
len, ret = "", | |
it, tmp; | |
try { | |
it = $$.options; | |
if (it == null) { | |
return ""; | |
} | |
if (Object.prototype.toString.call(it) === "[object Array]") { | |
len = it.length; | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[i], "" + i, i); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} else if (typeof it === "object") { | |
tmp = Object.keys(it); | |
len = tmp.length; | |
if (it instanceof RLH) { | |
tmp.sort(__sort_fn__); | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[tmp[i]], tmp[i], i); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} else { | |
for (i in it) { | |
if (it.hasOwnProperty(i)) { | |
ret2 = __iter__($, $$, it[i], i, j++); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} | |
} | |
} else { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 5, | |
"col": 12 | |
}, | |
"val": "options" | |
}, "Invalid loop-iterator reference") || unerr; | |
} | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 5, | |
"col": 12 | |
}, | |
"val": "options" | |
}, "Failed loop iteration", err); | |
} | |
return ret; | |
})(); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
ret += "\n "; | |
return ret; | |
} | |
var i, j = 0, | |
len, ret = "", | |
it, tmp; | |
try { | |
it = $.settings; | |
if (it == null) { | |
return ""; | |
} | |
if (Object.prototype.toString.call(it) === "[object Array]") { | |
len = it.length; | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[i], "" + i, i); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} else if (typeof it === "object") { | |
tmp = Object.keys(it); | |
len = tmp.length; | |
if (it instanceof RLH) { | |
tmp.sort(__sort_fn__); | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[tmp[i]], tmp[i], i); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} else { | |
for (i in it) { | |
if (it.hasOwnProperty(i)) { | |
ret2 = __iter__($, $$, it[i], i, j++); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
} | |
} | |
} | |
} else { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 3, | |
"col": 8 | |
}, | |
"val": "$.settings" | |
}, "Invalid loop-iterator reference") || unerr; | |
} | |
} catch (err) { | |
return error(cID, { | |
"type": 9, | |
"pos": { | |
"line": 3, | |
"col": 8 | |
}, | |
"val": "$.settings" | |
}, "Failed loop iteration", err); | |
} | |
return ret; | |
})(); | |
if (ret2 instanceof G.TemplateError) { | |
return ret2; | |
} else { | |
ret += ret2; | |
} | |
ret += "\n"; | |
return ret; | |
}, "3.html#settings", { | |
"type": 2, | |
"pos": { | |
"line": 1, | |
"col": 0 | |
}, | |
"val": "{$: '#settings' }" | |
}); | |
})(this.grips || grips); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Here's the same template code from above generation, but without the | |
// debugging guards. | |
(function (G) { | |
function __sort_fn__(a, b) { | |
return a - b; | |
} | |
var partial = G.definePartial, | |
clone = G.cloneObj, | |
extend = G.extend, | |
esc = G.strEscapes, | |
unerr = new Error("Unknown error"), | |
RLH = G.RangeLiteralHash, | |
cID = "3.html"; | |
partial(function ($, $$) { | |
$ = $ || {}; | |
$$ = clone($$) || {}; | |
var i, ret = "", | |
ret2, _; | |
ret += "\n <h1>Settings</h1>\n "; | |
ret2 = (function () { | |
function __iter__($, $$, value, key, index) { | |
var i, ret = "", | |
ret2, _; | |
if (value == null) return ret; | |
$$ = clone($$); | |
_ = { | |
value: value, | |
key: key, | |
index: index, | |
even: (index % 2) === 0, | |
odd: (index % 2) === 1, | |
first: (index === 0), | |
last: (index === len - 1) | |
}; | |
$$.name = _.key; | |
$$.options = {}; | |
var _set = ['low', 'high']; | |
for (i = 0; i < 2; i++) { | |
$$.options[_set[i]] = (_.value === _set[i]) ? "checked" : ""; | |
} | |
ret += "\n <h2>"; | |
ret += $$.name; | |
ret += "</h2>\n "; | |
ret2 = (function () { | |
function __iter__($, $$, value, key, index) { | |
var i, ret = "", | |
ret2, _; | |
if (value == null) return ret; | |
$$ = clone($$); | |
_ = { | |
value: value, | |
key: key, | |
index: index, | |
even: (index % 2) === 0, | |
odd: (index % 2) === 1, | |
first: (index === 0), | |
last: (index === len - 1) | |
}; | |
ret += "\n <input type=\"radio\" name=\""; | |
ret += $$.name; | |
ret += "\" value=\""; | |
ret += _.key; | |
ret += "\" "; | |
ret += _.value; | |
ret += "> "; | |
ret += _.key; | |
ret += "\n "; | |
return ret; | |
} | |
var i, j = 0, | |
len, ret = "", | |
it, tmp; | |
it = $$.options; | |
if (it == null) { | |
return ""; | |
} | |
if (Object.prototype.toString.call(it) === "[object Array]") { | |
len = it.length; | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[i], "" + i, i); | |
ret += ret2; | |
} | |
} else if (typeof it === "object") { | |
tmp = Object.keys(it); | |
len = tmp.length; | |
if (it instanceof RLH) { | |
tmp.sort(__sort_fn__); | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[tmp[i]], tmp[i], i); | |
ret += ret2; | |
} | |
} else { | |
for (i in it) { | |
if (it.hasOwnProperty(i)) { | |
ret2 = __iter__($, $$, it[i], i, j++); | |
ret += ret2; | |
} | |
} | |
} | |
} else { | |
return unerr; | |
} | |
return ret; | |
})(); | |
ret += ret2; | |
ret += "\n "; | |
return ret; | |
} | |
var i, j = 0, | |
len, ret = "", | |
it, tmp; | |
it = $.settings; | |
if (it == null) { | |
return ""; | |
} | |
if (Object.prototype.toString.call(it) === "[object Array]") { | |
len = it.length; | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[i], "" + i, i); | |
ret += ret2; | |
} | |
} else if (typeof it === "object") { | |
tmp = Object.keys(it); | |
len = tmp.length; | |
if (it instanceof RLH) { | |
tmp.sort(__sort_fn__); | |
for (i = 0; i < len; i++) { | |
ret2 = __iter__($, $$, it[tmp[i]], tmp[i], i); | |
ret += ret2; | |
} | |
} else { | |
for (i in it) { | |
if (it.hasOwnProperty(i)) { | |
ret2 = __iter__($, $$, it[i], i, j++); | |
ret += ret2; | |
} | |
} | |
} | |
} else { | |
return unerr; | |
} | |
return ret; | |
})(); | |
ret += ret2; | |
ret += "\n"; | |
return ret; | |
}, "3.html#settings"); | |
})(this.grips || grips); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment