JQuery Templates Conformance Suite

This is a conformance suite for the draft jQuery template language.

Each row in the tables below is a test case.

Legend

The "test" column includes the literal text of a template wrapped in an <xmp> element.

The "data" column includes a data value as JavaScript text also wrapped in an <xmp>.

The "expected" column shows the expected output of the template when compiled and applied to the data. If the output starts with "Error:" then the compilation or application should fail with an exception, and in debug mode should produce the following error message.

The "actual" column is auto-generated and contains the actual result and is colored to indicate success or failure.

The right-most column, if any, includes explatory text about the test-case.

Any "test" cells whose content consists of named templates specified via <script type="text/x-jquery-tmpl" id="template-name"> elements will have all templates extracted and compiled as a bundle and the template with id="main" will be the one applied.

Usage

To test the reference implementation, add ?reference to the URL.

To test the reference implementation, add ?compressed to the URL.

To run just some tests, add ?testFilter=<RegExp> where <RegExp> matches the right-most column, the test description.

To turn off logging to the console, add ?nolog to the URL.

Neither bells nor whistles

The tests below test the built-in operators, and plugins that ship by default.

TestDataExpectedActual
{} Empty Template
Hello, World! {} Hello, World! Plain text
Hello, &lt;World&gt;! {} Hello, <World>! HTML entities preserved
𐀀 {} 𐀀 Supplemental codepoints preserved
�-� {} �-� Orphaned surrogates preserved
foo&#10;${"\n"} bar {} foo bar Newlines preserved.
a
b${'\u2029'}c {} a
b
c Unusual newlines
<span style=color:red>Hello</span>, World! {} Hello, World! HTML tags preserved
It costs $5, 5$. {if} {{/- {{. {} It costs $5, 5$. {if} {{/- {{. Dollars and curlies in text
Cow says m${x}, dog says ${y}k { x: 'foo', y: 'bar' } Cow says mfoo, dog says bark Substitution
Cow says m{{=x}}, dog says {{=y}}k { x: 'foo', y: 'bar' } Cow says mfoo, dog says bark Substitution unabbreviated syntax
Hello, ${world}! {} Error:world is not defined Substitution w/out data
i=${i}, f=${f}, nf=${nf}, nan=${nan}, inf=${inf}, nzero=${nzero} { i: 42, f: 0.5, nf: -0.5, nan: NaN, inf: Infinity, nzero: -0 } i=42, f=0.5, nf=-0.5, nan=NaN, inf=Infinity, nzero=0 Substitution numbers
s=${s}, n=${n}, nul=${nul}, supp=${supp} { s: "Hello, World!", n: "42", supp: "\ud800\udc00", nul: "\u0000" } s=Hello, World!, n=42, nul=�, supp=𐀀 Substitution strings
orphans=${orphans} { orphans: "\ud800-\udc00" } orphans=�-� Substitution non-unicode strings
t=${t}, f=${f} { t: true, f: false } t=true, f=false Substitution booleans
s=${s}, o=${o}, thunk=${thunk}, a=${a} { s: new String("foo"), o: { toString: function () { return "[Obj]" } }, thunk: function () { return "Hello, World!"; }, a: [1, 2, 3] } s=foo, o=[Obj], thunk=Hello, World!, a=1,2,3 Substitution objects
Hello, ${x}! { x: { toString: function () { return "string"; }, valueOf: function (typeHint) { return "value"; } } } Hello, string! toString vs valueOf
i++=${i++}, i++=${i++}, readOnce=${readOnce}, counter=${counter}, counter=${counter} { i: 0, readOnce: (function () { var run = false; return function() { if (run) throw Error(); run = true; return 42; }; })(), counter: (function () { var i = 0; return function () { return ++i; }; })() } i++=0, i++=1, readOnce=42, counter=1, counter=2 Substitution evaluation happens once and in order
<div title="${breaker}">${breaker}</div> { breaker: "-->]]></script></style></textarea>\" ' ) >" }
-->]]></script></style></textarea>" ' ) >
Substitution autoescaped
<b>{{if sayHello}}Hello{{else}}Goodbye{{/if}}</b>, ${world}! { sayHello: true, world: "Cincinatti" } Hello, Cincinatti! If branch taken
<b>{{if sayHello}}Hello{{else}}Goodbye{{/if}}</b>, ${world}! { sayHello: false, world: function () { return "Cleveland"; }} Goodbye, Cleveland! Else branch taken
<b>{{if sayHello}}Hello{{/if}}</b>, ${world}! { sayHello: true, world: "Cincinatti" } Hello, Cincinatti! If branch taken no else
<b>{{if sayHello}}Hello{{/if}}</b>, ${world}! { sayHello: false, world: function () { return "Cleveland"; }} , Cleveland! No else branch
<b>{{if sayHello}}Hello{{else sayGoodbye}}Goodbye{{/if}}</b>, ${world}! { sayHello: false, sayGoodbye: true, world: "Cincinatti" } Goodbye, Cincinatti! Condition in else taken
<b>{{if sayHello}}Hello{{else sayGoodbye}}Goodbye{{/if}}</b>, ${world}! { sayHello: false, sayGoodbye: false, world: "Cincinatti" } , Cincinatti! Condition in else not taken
<b>{{if sayHello}}Hello{{else}}Goodbye{{/if}}</b>, ${world}! { sayHello: 1, world: "Cincinatti" } Hello, Cincinatti! If branch taken based on truthy value
<b>{{if sayHello}}Hello{{else}}Goodbye{{/if}}</b>, ${world}! { sayHello: 0, world: function () { return "Cleveland"; }} Goodbye, Cleveland! Else branch taken based on falsey value
<ul>{{each arr}}<li value=\"${$index - -1}\">${$value}{{/each}}</ul> { arr: ["One", "Two"] }
  • One
  • Two
Loop over array
<ul>{{each arr}}<li value=\"${$index - -1}\">${$value}{{/each}}</ul> { arr: [] }
    Loop over empty
    <ul>{{each(i) arr}}<li value=\"${i - -1}\">${$value}{{/each}}</ul> { arr: ["One", "Two"] }
    • One
    • Two
    Loop with custom key variable name
    <ul>{{each(k, v) arr}}<li value=\"${k - -1}\">${v}{{/each}}</ul> { arr: ["One", "Two"] }
    • One
    • Two
    Loop with custom variable names
    <table>{{each(k,v) obj}}<tr><td>${k}<td>${v}</tr>{{/each}}</table> { obj: { "foo": "bar", "baz": "boo" } }
    foobar
    bazboo
    Loop over associative array.
    <script type="text/x-jquery-tmpl" id="main"> this x=${x}, {{tmpl "that"}} </script> <script type="text/x-jquery-tmpl" id="that"> that x=(${x}) </script> { x: "x" } this x=x, that x=(x) Template Calls
    {{tmpl({ x, y }) "that"}} { x: "x" } Error:Invalid {{tmpl}} content: ({ x, y }) "that" Invalid Template Param
    {{tmpl({ x: y }) "that}} { x: "x" } Error:Invalid {{tmpl}} content: ({ x: y }) "that Invalid Template Selector
    <script type="text/x-jquery-tmpl" id="main"> this x=${x}, {{tmpl({x: "y"}) "that"}} </script> <script type="text/x-jquery-tmpl" id="that"> that x=(${x}) </script> { x: "x" } this x=x, that x=(y) Call with different data
    <script type="text/x-jquery-tmpl" id="main"> this x=${++x}, {{tmpl({ x: ++x }) "that"}} </script> <script type="text/x-jquery-tmpl" id="that"> that x=(${++x}) </script> { x: 0 } this x=1, that x=(3) Template Order of Evaluation
    ${1}${1} {} 11 String concatenation of adjacent subs
    ${1 + 1} {} 2 Arithmetic in substitution
    a[0].b[cStr]=${a[0].b[cStr]} { a: [{ b: { c: 42 } }], cStr: "c" } a[0].b[cStr]=42 Member expressions
    undef=${x.undef} { x: {} } undef= Undefined member
    {{if n < 0}}-{{tmpl({ n: -n }) "main"}}{{else n >= 1}}.{{tmpl({n: n - 1}) "main"}}{{/if}} { n: -3 } -... Recursive template
    {{if typeof notDefinedInDataMap !== "undefined"}}${notDefinedInDataMap}{{else}}none{{/if}} {} none Unreached variable need not be defined
    {{if cond}}foo{{else}} {} Error:Unclosed block directives if in {{if cond}}foo{{else}} Missing {{/if}} error message
    {{if cond}}foo{{else}}bar{{else}}boo{{/if}} {} Error:{{else}} without condition must be last:{{if cond}}foo{{else}}bar{{else}}boo{{/if}} Misplaced {{else}}
    {{if }}foo{{/if}} {} Error:{{if}} missing condition:{{if }}foo{{/if}} Missing {{if}} condition
    All nature is but art {{unknown}} to thee. {} Error:I do not know how to compile {{unknown}} Unknown directive name
    ${i + (j} { i: 1, j: 2 } Error:Invalid template substitution: i + (j Catch obviously broken expressions early.
    {{=String()) } { (String()}} { String: function () { return "String!"; } } Error:Invalid template substitution: String()) } { (String() Unbracketing and rebracketing illegal.
    ${arguments[0]} { arguments: [42] } 42 "arguments" as a data key
    ${arguments[0]} {} Error:arguments is not defined "arguments" not present as a data key
    ${delete arguments, arguments[0]} {} Error:arguments is not defined "arguments" really not present as a data key
    ${$data.arguments = 42}, ${arguments} {} 42, 42 "arguments" really not present as a data key
    ${$item.foo} {}, { foo: 42 } 42 Template options available
    <script type="text/x-jquery-tmpl" id="main"> ${$item.foo},{{tmpl({ "$item": { foo: "data" } }) "t"}},${$item.foo} </script> <script type="text/x-jquery-tmpl" id="t">${$item.foo}</script> {}, { foo: "option" } option,data,option Data masking template options
    <script type="text/x-jquery-tmpl" id="main"> ${$item.foo},{{tmpl(,{ "foo": "option2" }) "t"}},${$item.foo} </script> <script type="text/x-jquery-tmpl" id="t">${$item.foo}</script> {}, { foo: "option" } option,option2,option Passing options

    Plugin Tests

    The table below shows the template language extended with a few plugins.

    {{makeID varName}} assigns an ID using a counter and puts it in the variable named varName.

    The Date format plugin annotates all substitutions to convert any Date instances into a prescribed format without introducing new syntax.

    The import plugin looks for a call to a template named notYetLoaded and if so, adds a template to the parse tree bundle that outputs "Loaded just in time!"

    TestDataExpectedActual
    <ul>{{each(i,v) nums}}<li><input value="${v}" id="{{makeID listItemId}}"><button onclick="alert($('#${listItemId}')[0].value)">say</button>{{/each}}</ul> { nums: ["One", "Two", "Three"] }
    {{makeID}} plugin
    <input value="${v}" id="{{makeid listItemId}}"> { v: "value" } Error:I do not know how to compile {{makeid listItemId}} directive names case-sensitive
    Date: ${date}, a number: ${notadate} { date: new Date(2007, 0, 15, 12, 0, 0), notadate: 2010 } Date: 2007-01-15, a number: 2010 Format date plugin
    Main calls and {{tmpl "notYetLoaded"}} {} Main calls and Loaded just in time! Import plugin

    Tests migrated from the original implementation. The global testData is set to

    { one: "first", two: "second", v: "test", arr: ["AA","BB", "CC"], dict: { "leovinus": "this", "scraliontis": "that", "brobstigon": "other" }, fun: function () { return "RETURNED" }, html: "<a>" }
    lorem ipsum testData lorem ipsum plain text passes through untouched
    ${ one } testData first simple variable output
    ${ a b c }} testData Error:Invalid template substitution: a b c multi word variable tag
    ${ _ } { _: "foo" } Error: _ is not defined _ (underscore) cannot be used by data
    ${ $ } { "$": "foo" } Error: $ overridden $ cannot be used by data
    {{syntax_error }} testData Error:I do not know how to compile {{syntax_error }} sytax error passing
    {{type_error }} testData Error:I do not know how to compile {{type_error }} type error passing
    {{reference_error }} testData Error:I do not know how to compile {{reference_error }} reference error passing
    ${ one } testData first newlines do not kill tags
    ${ one } testData first carriage returns do notkill tags
    ${ "on\re" } testData on e returns in strings don't kill tags
    ${ "on\\e" } testData on\e slashes in strings don't kill tags
    a b c${ 8 }. null a b c8. newlines don't kill parsing
    {{}} testData {{}} default
    {{ }} null {{ }} with whitespace
    {{ }} null {{ }} with tabs whitespace
    {{if 1}}{{if 1}}{{/if}} testData Error:Unclosed block directives if in {{if 1}}{{if 1}}{{/if}} default
    {{if 1}}{{/if}}{{/if}} testData Error:Misplaced {{/if}} in {{if 1}}{{/if}}{{/if}} extra /if
    {{if 1}}{{each arr}}{{/if}}{{/each}} testData Error:Misplaced {{/if}} in {{if 1}}{{each arr}}{{/if}}{{/each}} but terminated
    a {{one } b testData a {{one } b ignore malformed a {{one } b
    ${ one }} {{${ two }} testData first} {{second} ignore malformed first} {{second }
    {{one } testData {{one } ignore malformed {{one }
    ${ function(){} } {} Error:Invalid template substitution: function(){ Disallow function operator
    ${ return a } {a:1} Error:Invalid template substitution: return a Disallow return
    ${ for a } {a:1} Error:Invalid template substitution: for a Disallow for
    ${ do{ a }while(a) } {a:1} Error:Invalid template substitution: do{ a Disallow do/while
    {{= do{ a }while(a) }} {a:1} Error:Invalid template substitution: do{ a }while(a) Disallow do/while 2
    ${ if (a)1 } {a:1} Error:Invalid template substitution: if (a)1 Disallow if
    {{= try{b.s}catch(e){} }} {a:1} Error:Invalid template substitution: try{b.s}catch(e){} Disallow try/catch
    {{= with (a){1} }} {a:1} Error:Invalid template substitution: with (a){1} Disallow with keyword
    ${ throw "foo" } {a:1} Error:Invalid template substitution: throw "foo" Disallow throw keyword
    ${ foo["bar"] } {foo:{bar:'baz'}} baz bracketed accessor foo["bar"]
    ${ foo['bar'] } {foo:{bar:'baz'}} baz bracketed accessor foo['bar']
    ${ 'foo<div>bar</div>baz' } null foo<div>bar</div>baz echoing escapes html
    ${ r } {r:'foo<div>bar</div>baz'} foo<div>bar</div>baz echoing escapes html (lookup)
    ${ '&' } null & echoing escapes ampersands 1
    ${ '&amp;' } null &amp; echoing escapes ampersands 2
    ${ '-<&>-<&>-' } null -<&>-<&>- echoing escapes & < >
    A{{! comments test }}B testData AB comments are removed
    {{! inky }}foo{{! blinky }} testData foo comments are removed (2)
    A{{! comments "}}" test }}B testData AB comments may include string of comments
    A{# C{# E #}D #}B testData AD #}B comments cannot nest other comments
    A{# comments "str"ing" test #}B testData AB comments may include strings with escapes (double)
    A{# comments 'str'ing' test #}B testData AB comments may include strings with escapes (single)
    A{# {{= v }} #}B testData AB comments may include tags
    A{# comments test #}B testData AB comments may span lines
    {{if true}}A{{{# comment #}else}}B{{/if}} {} A{{else}}B comments split tokens 1
    {{if true}}A{{{{! comment }}else}}B{{/if}} {} A{{else}}B comments split tokens 2
    {{= "{# not a comment }"}} {} {# not a comment } no comments in markers
    1{{! {{ INVALID_TAG }} }}2 testData 12 comments may contain invalid content (invalid tag)
    1{{! {{/if}} }}2 testData 12 comments may contain invalid content (stray end tag)
    1{{! {{else}} }}2 testData 12 comments may contain invalid content (stray else)
    1{{! {{if ...}} }}2 testData 12 comments may contain invalid content (invalid javascript)
    {{= one }} testData first variable replacement
    {{= one }}/{{= two }} testData first/second many variables work
    ${ one } testData first alternative variable syntax
    ${ one }/${ two } testData first/second many variables work with alt syntax
    ${ "string" } testData string basic string output (double)
    ${ 'string' } testData string basic string output (single)
    ${ "str\"i\"ng" } testData str"i"ng string quote escapes (double)
    ${ 'str\'i\'ng' } testData str'i'ng string quote escapes (single)
    ${ "\{\{ tag \}\}" } testData {{ tag }} string output with tag
    ${ "\}\}" } testData }} string output with end of tag
    {{= }} { self: "self" } self empty variable tag (with tabs whitespace)
    {{= }} { self: "self" } self empty variable tag
    {{=}} { self: "self" } self empty variable tag (with space)
    ${ is_undefined } testData variable lookup error suppression
    ${ is_undefined.member } testData variable lookup error suppression (with member)
    A${ one } testData Afirst variable and text (1)
    ${ one }B testData firstB variable and text (2)
    A${ one }B testData AfirstB variable and text (3)
    ${ a.b.c } {a:{b:{c:"abc"}}} abc lookups work for submembers
    ${ a.b.c } {a:{b:{c:"abc"}}} abc error suppression works for submembers
    ${ foo() } { foo:function(s){ return 'bar'; }} bar functions can be called with in tags
    ${ foo("bar") } { foo:function(s){ return s; }} bar functions pass strings correctly
    ${ foo(bar) } { foo:function(s){ return s; }, 'bar':'baz'} baz functions pass arguments correctly
    ${ foo } {foo: {toString:function () {return 'S';},toValue:function () {return 'V';}}} S variables use toString, not toValue
    ${ dot,dot,comma,dash } {dot:'.','comma':',','dash':'-'} - comma passes variables correctly
    ${ fun } testData RETURNED variable gets called if it is callable
    ${ obj.fun } {obj: testData} RETURNED last variable in sequence gets called if it is callable
    ${ foo.bar } { foo: function () { return { bar: function () {return 'BAZ'; } } } } member functions in a sequence don't get called
    ${ 0 } null 0 (0)
    ${ false } null false (false)
    ${ null } null null (null)
    ${ undefined } null (undefined)
    ${ "" } null ("")
    ${ '' } null ('')
    ${ zero } {zero: 0} 0 (false)
    ${ zero } {zero: false} false (false)
    ${ zero } {zero: null} null (null)
    ${ zero } {zero: undefined} (undefined)
    ${ zero } {zero: ""} ('')
    ${ one + "foo" } testData firstfoo string concatenation
    ${ 1 + 5 } testData 6 adding
    ${ 9 - 5 } testData 4 subtracting
    ${ 5 % 2 } testData 1 modulo
    ${ -n } {n:10} -10 unary minus
    ${ +n } {n:10} 10 unary plus
    ${ "bar" in foo } {foo:{bar:'baz'}} true in operator
    ${ foo instanceof Date } {foo:new Date()} true instanceof operator
    ${ typeof "str" } {} string typeof operator
    ${ n & 1 } {n:5} 1 bitwise AND
    ${ n | 1 } {n:4} 5 bitwise OR
    ${ n ^ 1 } {n:5} 4 bitwise XOR
    ${ ~n } {n:5} -6 bitwise NOT
    ${ n << 1 } {n:5} 10 left shift
    ${ n >> 1 } {n:5} 2 right shift
    ${ n >>> 1 } {n:5} 2 zero-fill right shift
    ${ 1 == 5 } testData false comparing ==
    ${ 1 != 5 } testData true comparing !=
    ${ 5 === 5 } testData true comparing ===
    ${ 5 !== 5 } testData false comparing !==
    ${ 1 >= 5 } testData false comparing >=
    ${ 1 > 5 } testData false comparing >
    ${ 1 <= 5 } testData true comparing <=
    ${ 1 < 5 } testData true comparing <
    ${ zero || "FALSY" } { zero: 0 } FALSY Logical OR
    ${ zero && "TRUEY" } { zero: 1 } TRUEY Logical AND
    ${ zero ? "zero" : "other" } { zero: 1 } zero Conditional Operator
    ${ !zero } { zero: 1 } false Unary logical NOT
    ${ 'test' } {} test Single-Quoted Strings
    ${ 'test' == testvar } { testvar: "test" } true Single-Quoted Comparison
    ${ a += 1 } {a:1} Error: Disallow incremental assignment
    ${ a -= 1 } {a:1} Error: Disallow decremental assignment
    ${ a *= 1 } {a:1} Error: Disallow multiply assignment
    ${ a /= 1 } {a:1} Error: Disallow division assignment
    ${ a <<= 1 } {a:1} Error: Disallow left shift assignment
    ${ a >>= 1 } {a:1} Error: Disallow right shift assignment
    ${ a >>>= 1 } {a:1} Error: Disallow zero-fill right shift assignment
    ${ a &= 1 } {a:1} Error: Disallow bitwise AND assignment
    ${ a |= 1 } {a:1} Error: Disallow bitwise OR assignment
    ${ a ^= 1 } {a:1} Error: Disallow bitwise XOR assignment
    ${ { a:"a"} } {a:1} Error: Disallow literal object creation
    ${ [1,2,3] } {a:1} Error: Disallow literal array creation
    ${ --a } {a:1} Error: Disallow decrement
    ${ (a = 2) } {a:1} Error: Disallow assignments
    {{each arr}}${ $index }:${ this }/{{/each}} testData 0:AA/1:BB/2:CC/ loop
    {{each arr}}${ $index }:${ $value }/{{/each}} testData 0:AA/1:BB/2:CC/ loop
    {{each(i, item) arr}}${ i }:${ item }/{{/each }} testData 0:AA/1:BB/2:CC/ loop
    {{each arr}}${ $index }:${ $value }/{{/each }} testData 0:AA/1:BB/2:CC/ loop
    {{each dict}}${ $index }:{{if $first }}first{{else}}!first{{/if }}/{{/each }} testData leovinus:first/scraliontis:!first/brobostigon:!first/ first
    {{each dict}}{{if !$first }}, {{/if }}${ $index }:${ $value }}{{/each }} testData leovinus:this, scraliontis:that, brobostigon:other first
    {{each arr}}<a>${ $index }</a>{{/each}} testData 012 html content
    {{each arr}}<a>${ $value }</a>{{/each}} testData AABBCC html content
    {{each arr}}<a>${ $value.data }</a>{{/each}} { arr: [{data: 0}, {data: 1}, {data: 2}] } 012 html content
    {{each arr}} <a>${ $value.data }</a> {{/each}} { arr: [{data: 0}, {data: 1}, {data: 2}] } 0 1 2 html content with newlines
    {{each arr}}${ $i }{{syntax_error}}{{/each}} testData Error:I do not know how to compile {{syntax_error}} errors are passed back correctly (syntax)
    {{each arr}}${ $i }{{reference_error}}{{/each}} testData Error:I do not know how to compile {{reference_error}} errors are passed back correctly (reference)
    {{each arr}}${ $i }{{type_error}}{{/each}} testData Error:I do not know how to compile {{type_error}} errors are passed back correctly (type)
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:true } TRUE if:true
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:false } FALSE if:false
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:null } FALSE if:null
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:undefined } FALSE if:undefined
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:{} } TRUE if:[]
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:[] } TRUE if:{}
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:"" } FALSE if:''
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:"A" } TRUE if:A
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:0 } FALSE if:0
    {{if a}}TRUE{{else}}FALSE{{/if}} { a:1 } TRUE if:1
    {{if a}}TRUE{{else}}FALSE{{/if a}} { a:1 } TRUE /if ignores following text
    {{if true}}{{syntax_error}}{{/if}} testData Error:I do not know how to compile {{syntax_error}} errors are passed back correctly (syntax)
    {{if true}}{{reference_error}}{{/if}} testData Error:I do not know how to compile {{reference_error}} errors are passed back correctly (reference)
    {{if true}}{{type_error}}{{/if}} testData Error:I do not know how to compile {{type_error}} errors are passed back correctly (type)
    <script id="test" type="text/x-jquery-tmpl">${ "test text" }</script> <script id="main" type="text/x-jquery-tmpl">{{tmpl "test"}}</script> null test text simple include
    <script id="test2" type="text/x-jquery-tmpl">{{each arr}}[${ $value }]-{{/each }}</script> <script id="main" type="text/x-jquery-tmpl">{{tmpl "test2"}}</script> testData [AA]-[BB]-[CC]- data access
    <script id="nested" type="text/x-jquery-tmpl">{{tmpl "nested0"}}</script> <script id="nested0" type="text/x-jquery-tmpl">${ foo }</script> <script id="main" type="text/x-jquery-tmpl">{{tmpl "nested"}}</script> {foo: "bar"} bar nested - 1 level
    <script id="nested0" type="text/x-jquery-tmpl">{{tmpl "nested1"}}</script> <script id="nested1" type="text/x-jquery-tmpl">{{tmpl "nested2"}}</script> <script id="nested2" type="text/x-jquery-tmpl">${ foo }</script> <script id="main" type="text/x-jquery-tmpl">{{tmpl "nested0" }}</script> {foo: "bar"} bar nested - 2 levels
    <script id="nested" type="text/x-jquery-tmpl">${ foo.bar.sweet }</script> <script id="main" type="text/x-jquery-tmpl">{{tmpl "nested" }}</script> {foo: {bar: {sweet: 1} } } 1 nested - 2 levels - complex data
    <script id="test" type="text/x-jquery-tmpl">${ $index }</script> <script id="main" type="text/x-jquery-tmpl">{{each arr}}{{tmpl "test" }}{{/each}}</script> testData 012 {{each}} index variable
    <script id="test" type="text/x-jquery-tmpl">${ n }</script> <script id="main" type="text/x-jquery-tmpl">{{each(n, item) arr}}{{tmpl "test"}}{{/each}}</script> testData 012 {{each}} index variable
    <script id="test" type="text/x-jquery-tmpl">${ item }</script> <script id="main" type="text/x-jquery-tmpl">{{each(n, item) arr}}{{tmpl "test" }}{{/each}}</script> testData AABBCC {{each}} item variable
    {{= html}} testData <a> encoded
    {{html html}} testData unencoded

    Last modified: Mon May 30 18:00:21 PDT 2011