From f764aee4b919c28974dba7b91edac9a04172ba25 Mon Sep 17 00:00:00 2001 From: Jacob Thornton Date: Mon, 23 Jan 2012 14:14:16 -0800 Subject: add templates for doc generation --- docs/build/node_modules/hogan.js/test/index.js | 848 +++++++++++++++++++++++++ 1 file changed, 848 insertions(+) create mode 100644 docs/build/node_modules/hogan.js/test/index.js (limited to 'docs/build/node_modules/hogan.js/test/index.js') diff --git a/docs/build/node_modules/hogan.js/test/index.js b/docs/build/node_modules/hogan.js/test/index.js new file mode 100644 index 000000000..9b235ebe7 --- /dev/null +++ b/docs/build/node_modules/hogan.js/test/index.js @@ -0,0 +1,848 @@ +/* + * Copyright 2011 Twitter, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var Hogan = Hogan || require('../lib/hogan') + , doc = this["document"] + +function testScanTextNoTags() { + var text = "

hi

"; + var tokens = Hogan.scan(text); + is(tokens.length, 1, "One token"); + is(tokens[0]+'', text, "text is equal to first token"); +} + +function testScanOneTag() { + var text = "{{hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 1, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); +} + +function testScanMultipleTags() { + var text = "asdf{{hmm}}asdf2{{hmm2}}asdf3"; + var tokens = Hogan.scan(text); + is(tokens.length, 5, "3 text tokens, 2 tag tokens."); + is(tokens[0]+'', "asdf", "first token is text"); + is(tokens[1].n, "hmm", "second token is tag"); + is(tokens[1].tag, "_v", "second token is a variable"); + is(tokens[2]+'', "asdf2", "third token is text"); + is(tokens[3].n, "hmm2", "fourth token is tag"); + is(tokens[3].tag, "_v", "fourth token is a variable"); + is(tokens[4]+'', "asdf3", "Fifth token is text"); +} + +function testScanSectionOpen() { + var text = "{{#hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 1, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); + is(tokens[0].tag, "#", "First token is a section."); +} + +function testScanSectionClose() { + var text = "{{/hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 1, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); + is(tokens[0].tag, "/", "First token is a section."); +} + +function testScanSection() { + var text = "{{#hmm}}{{/hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 2, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); + is(tokens[0].tag, "#", "First token is a section."); + is(tokens[1].n, "hmm", "Second token content is variable name."); + is(tokens[1].tag, "/", "Second token is a section."); +} + +function testScanSectionInContent() { + var text = "abc{{#hmm}}def{{/hmm}}ghi"; + var tokens = Hogan.scan(text); + is(tokens.length, 5, "3 text tokens, 2 tag tokens."); + is(tokens[0]+'', "abc", "first token is text"); + is(tokens[1].n, "hmm", "second token is tag"); + is(tokens[1].tag, "#", "second token is a variable"); + is(tokens[2]+'', "def", "third token is text"); + is(tokens[3].n, "hmm", "fourth token is tag"); + is(tokens[3].tag, "/", "fourth token is a variable"); + is(tokens[4]+'', "ghi", "Fifth token is text"); +} + +function testScanNegativeSection() { + var text = "{{^hmm}}{{/hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 2, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); + is(tokens[0].tag, "^", "First token is a negative section."); + is(tokens[1].n, "hmm", "First token content is variable name."); + is(tokens[1].tag, "/", "Second token is a section."); +} + +function testScanPartial() { + var text = "{{>hmm}}"; + var tokens = Hogan.scan(text); + is(tokens.length, 1, "One token"); + is(tokens[0].n, "hmm", "First token content is variable name."); + is(tokens[0].tag, ">", "First token is a partial."); +} + + +function testScanBackwardPartial() { + var text = "{{
\' \" &"}); + is(s, "< > <div> ' " &", "input correctly escaped."); + + var ec ={ "'": "'", '"': """, "<": "<", ">": ">", "&": "&"} + for (var char in ec) { + var s = t.render({foo: char + " just me"}); + is(s, ec[char] + " just me", "input correctly escaped."); + } + +} + +function testMustacheInjection() { + var text = "{{foo}}"; + var t = Hogan.compile(text); + s = t.render({foo:"{{{<42}}}"}) + is(s, "{{{<42}}}", "Can't inject mustache"); +} + +function testTripleStache() { + var text = "{{{foo}}}"; + var t = Hogan.compile(text); + var s = t.render({foo: "< >
\' \" &"}); + is(s, "< >
\' \" &", "input correctly not-escaped."); +} + +function testAmpNoEscaping() { + var text = "{{&foo}}"; + var t = Hogan.compile(text); + var s = t.render({foo: "< >
\' \" &"}); + is(s, "< >
\' \" &", "input correctly not-escaped."); +} + +function testPartial() { + var partialText = "this is text from the partial--the magic number {{foo}} is from a variable"; + var p = Hogan.compile(partialText); + + var text = "This template contains a partial ({{>testPartial}})." + var t = Hogan.compile(text); + + var s = t.render({foo: 42}, {testPartial: p}); + is(s, "This template contains a partial (this is text from the partial--the magic number 42 is from a variable).", "partials work"); +} + +function testNestedPartials() { + var partialText = "this is text from the partial--the magic number {{foo}} is from a variable"; + var p = Hogan.compile(partialText); + + var partialText2 = "This template contains a partial ({{>testPartial}})." + var p2 = Hogan.compile(partialText2); + + var text = "This template contains a partial that contains a partial [{{>testPartial2}}]." + var t = Hogan.compile(text); + + var s = t.render({foo: 42}, {testPartial: p, testPartial2: p2}); + is(s, "This template contains a partial that contains a partial [This template contains a partial (this is text from the partial--the magic number 42 is from a variable).].", "nested partials work"); +} + +function testNegativeSection() { + var text = "This template {{^foo}}BOO {{/foo}}contains an inverted section." + var t = Hogan.compile(text); + var s = t.render(); + is(s, "This template BOO contains an inverted section.", "inverted sections with no context work"); + + s = t.render({foo:[]}); + is(s, "This template BOO contains an inverted section.", "inverted sections with empty list context work"); + + s = t.render({ foo:false }); + is(s, "This template BOO contains an inverted section.", "inverted sections with false context work"); + + s = t.render({foo:''}); + is(s, "This template contains an inverted section.", "inverted sections with empty string context work"); + + s = t.render({foo:true}); + is(s, "This template contains an inverted section.", "inverted sections with true context work"); + + s = t.render({foo: function() { return false; }}); + is(s, "This template BOO contains an inverted section.", "inverted sections with false returning method in context work"); +} + +function testSectionElision() { + var text = "This template {{#foo}}BOO {{/foo}}contains a section." + var t = Hogan.compile(text); + var s = t.render(); + is(s, "This template contains a section.", "sections with no context work"); + + s = t.render({foo:[]}); + is(s, "This template contains a section.", "sections with empty list context work"); + + s = t.render({foo:false}); + is(s, "This template contains a section.", "sections with false context work"); +} + +function testSectionObjectContext() { + var text = "This template {{#foo}}{{bar}} {{/foo}}contains a section." + var t = Hogan.compile(text); + var s = t.render({foo:{bar:42}}); + is(s, "This template 42 contains a section.", "sections with object context work"); +} + +function testSectionArrayContext() { + var text = "This template {{#foo}}{{bar}} {{/foo}}contains a section." + var t = Hogan.compile(text); + var s = t.render({foo:[{bar:42}, {bar:43}, {bar:44}]}); + is(s, "This template 42 43 44 contains a section.", "sections with object ctx and array values work"); +} + +function testFalsyVariableNoRender() { + var text = "I ({{cannot}}) be seen!"; + var t = Hogan.compile(text); + var s = t.render(); + is(s, "I () be seen!", "missing value doesn't render."); +} + +function testSectionExtensions() { + var text = "Test {{_//|__foo}}bar{{/foo}}"; + var options = {sectionTags:[{o:'_//|__foo', c:'foo'}]}; + var tree = Hogan.parse(Hogan.scan(text), options); + is(tree[1].tag, "#", "_//|__foo node transformed to section"); + is(tree[1].n, "_//|__foo", "_//|__foo node transformed to section"); + + var t = Hogan.compile(text, options ); + var s = t.render({'_//|__foo':true}); + is(s, "Test bar", "Custom sections work"); +} + +function testMisnestedSectionExtensions() { + var text = "Test {{__foo}}bar{{/bar}}"; + var options = {sectionTags:[{o:'__foo', c:'foo'}, {o:'__bar', c:'bar'}]}; + var msg = ''; + try { + var tree = Hogan.parse(Hogan.scan(text), options); + } catch (e) { + msg = e.message; + } + is(msg, "Nesting error: __foo vs. bar", "Error is generated"); +} + +function testNestedSection() { + var text = "{{#foo}}{{#bar}}{{baz}}{{/bar}}{{/foo}}"; + var t = Hogan.compile(text); + var s = t.render({foo: 42, bar: 42, baz:42}); + is(s, "42", "can reach up context stack"); +} + +function testDottedNames() { + var text = '"{{person.name}}" == "{{#person}}{{name}}{{/person}}"'; + var t = Hogan.compile(text); + var s = t.render({person:{name:'Joe'}}); + is(s, '"Joe" == "Joe"', "dotted names work"); +} + +function testImplicitIterator() { + var text = '{{#stuff}} {{.}} {{/stuff}}'; + var t = Hogan.compile(text); + var s = t.render({stuff:[42,43,44]}); + is(s, " 42 43 44 ", "implicit iterators work"); +} + +function testPartialsAndDelimiters() { + var text = '{{>include}}*\n{{= | | =}}\n*|>include|'; + var partialText = ' .{{value}}. '; + var partial = Hogan.compile(partialText); + var t = Hogan.compile(text); + var s = t.render({value:"yes"}, {'include':partial}); + is(s, " .yes. *\n* .yes. ", "partials work around delimiters"); +} + +function testStringPartials() { + var text = "foo{{>mypartial}}baz"; + var partialText = " bar "; + var t = Hogan.compile(text); + var s = t.render({}, {'mypartial': partialText}); + is(s, "foo bar baz", "string partial works."); +} + +function testMissingPartials() { + var text = "foo{{>mypartial}} bar"; + var t = Hogan.compile(text); + var s = t.render({}); + is(s, "foo bar", "missing partial works."); +} + +function testIndentedStandaloneComment() { + var text = 'Begin.\n {{! Indented Comment Block! }}\nEnd.'; + var t = Hogan.compile(text); + var s = t.render(); + is(s, 'Begin.\nEnd.', "Standalone comment blocks are removed."); +} + +function testNewLineBetweenDelimiterChanges() { + var data = { section: true, data: 'I got interpolated.' }; + var text = '\n{{#section}}\n {{data}}\n |data|\n{{/section}}x\n\n{{= | | =}}\n|#section|\n {{data}}\n |data|\n|/section|'; + var t = Hogan.compile(text); + var s = t.render(data); + is(s, '\n I got interpolated.\n |data|\nx\n\n {{data}}\n I got interpolated.\n', 'render correct') +} + +function testMustacheJSApostrophe() { + var text = '{{apos}}{{control}}'; + var t = Hogan.compile(text); + var s = t.render({'apos':"'", 'control':"X"}); + is(s, ''X', 'Apostrophe is escaped.'); +} + +function testMustacheJSArrayOfImplicitPartials() { + var text = 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}\n'; + var partialText = '{{.}}\n'; + var t = Hogan.compile(text); + var s = t.render({numbers:[1,2,3,4]}, {partial: partialText}); + is(s, 'Here is some stuff!\n1\n2\n3\n4\n', 'Partials with implicit iterators work.'); +} + +function testMustacheJSArrayOfPartials() { + var text = 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}\n'; + var partialText = '{{i}}\n'; + var t = Hogan.compile(text); + var s = t.render({numbers:[{i:1},{i:2},{i:3},{i:4}]}, {partial: partialText}); + is(s, 'Here is some stuff!\n1\n2\n3\n4\n', 'Partials with arrays work.'); +} + +function testMustacheJSArrayOfStrings() { + var text = '{{#strings}}{{.}} {{/strings}}'; + var t = Hogan.compile(text); + var s = t.render({strings:['foo', 'bar', 'baz']}); + is(s, 'foo bar baz ', 'array of strings works with implicit iterators.'); +} + +function testMustacheJSUndefinedString() { + var text = 'foo{{bar}}baz'; + var t = Hogan.compile(text); + var s = t.render({bar:undefined}); + is(s, 'foobaz', 'undefined value does not render.'); +} + +function testMustacheJSTripleStacheAltDelimiter() { + var text = '{{=<% %>=}}<% foo %> {{foo}} <%{bar}%> {{{bar}}}'; + var t = Hogan.compile(text); + var s = t.render({foo:'yeah', bar:'hmm'}); + is(s, 'yeah {{foo}} hmm {{{bar}}}', 'triple stache inside alternate delimiter works.'); +} + +/* shootout benchmark tests */ + +function testShootOutString() { + var text = "Hello World!"; + var expected = "Hello World!" + var t = Hogan.compile(text) + var s = t.render({}) + is(s, expected, "Shootout String compiled correctly"); +} + +function testShootOutReplace() { + var text = "Hello {{name}}! You have {{count}} new messages."; + var expected = "Hello Mick! You have 30 new messages."; + var t = Hogan.compile(text) + var s = t.render({ name: "Mick", count: 30 }) + is(s, expected, "Shootout Replace compiled correctly"); +} + +function testShootOutArray() { + var text = "{{#names}}{{name}}{{/names}}"; + var expected = "MoeLarryCurlyShemp"; + var t = Hogan.compile(text); + var s = t.render({ names: [{name: "Moe"}, {name: "Larry"}, {name: "Curly"}, {name: "Shemp"}] }) + is(s, expected, "Shootout Array compiled correctly"); +} + +function testShootOutObject() { + var text = "{{#person}}{{name}}{{age}}{{/person}}"; + var expected = "Larry45"; + var t = Hogan.compile(text) + var s = t.render({ person: { name: "Larry", age: 45 } }) + is(s, expected, "Shootout Object compiled correctly"); +} + +function testShootOutPartial() { + var text = "{{#peeps}}{{>replace}}{{/peeps}}"; + var t = Hogan.compile(text); + var partial = Hogan.compile(" Hello {{name}}! You have {{count}} new messages."); + var s = t.render({ peeps: [{name: "Moe", count: 15}, {name: "Larry", count: 5}, {name: "Curly", count: 2}] }, { replace: partial }); + var expected = " Hello Moe! You have 15 new messages. Hello Larry! You have 5 new messages. Hello Curly! You have 2 new messages."; + is(s, expected, "Shootout Partial compiled correctly"); +} + +function testShootOutRecurse() { + var text = "{{name}}{{#kids}}{{>recursion}}{{/kids}}"; + var t = Hogan.compile(text); + var partial = Hogan.compile("{{name}}{{#kids}}{{>recursion}}{{/kids}}"); + var s = t.render({ + name: '1', + kids: [ + { + name: '1.1', + kids: [ + { name: '1.1.1', kids: [] } + ] + } + ] + }, { recursion: partial }); + var expected = "11.11.1.1"; + is(s, expected, "Shootout Recurse compiled correctly"); +} + +function testShootOutFilter() { + var text = "{{#filter}}foo {{bar}}{{/filter}}"; + var t = Hogan.compile(text); + var s = t.render({ + filter: function() { + return function(text, render) { + return render(text).toUpperCase(); + } + }, + bar: "bar" + }); + var expected = "FOO BAR" + is(s, expected, "Shootout Filter compiled correctly"); +} + +function testShootOutComplex() { + var text = + "

{{header}}

" + + "{{#hasItems}}" + + "
    " + + "{{#items}}" + + "{{#current}}" + + "
  • {{name}}
  • " + + "{{/current}}" + + "{{^current}}" + + "
  • {{name}}
  • " + + "{{/current}}" + + "{{/items}}" + + "
" + + "{{/hasItems}}" + + "{{^hasItems}}" + + "

The list is empty.

" + + "{{/hasItems}}"; + + var expected = "

Colors

"; + var t = Hogan.compile(text) + var s = t.render({ + header: function() { + return "Colors"; + }, + items: [ + {name: "red", current: true, url: "#Red"}, + {name: "green", current: false, url: "#Green"}, + {name: "blue", current: false, url: "#Blue"} + ], + hasItems: function() { + return this.items.length !== 0; + }, + empty: function() { + return this.items.length === 0; + } + }) + + is(s, expected, "Shootout Complex compiled correctly"); +} + +function testRenderOutput() { + if (doc) return + var fs = require('fs'); + var inPath = 'test/templates'; + var outPath = 'test/html'; + + fs.readdirSync(inPath).forEach(function (file) { + var i = fs.readFileSync([inPath, file].join('/'), 'utf-8'); + var t = Hogan.compile(i); + var r = t.render({}); + var o = fs.readFileSync([outPath, file].join('/').replace(/mustache$/, 'html')).toString(); + is(r === o, true, file + ' should correctly render html') + }) +} + +function testDefaultRenderImpl() { + var ht = new Hogan.Template(); + is(ht.render() === '', true, 'default renderImpl returns an array.'); +} + + +function appendText(el, text) { + var textNode = document.createTextNode(text); + el.appendChild(textNode); + el.appendChild(document.createElement('br')); +} + +if (!this["output"]) { + var output = function (s) { + return doc ? appendText(doc.getElementById('console'), s) : console.log(s); + }; +} +var passed = 0; +var failed = 0; + +function is(got, expected, msg) { + if (got === expected) { + output("OK: " + msg); + ++passed; + } else { + output("FAIL: " + msg); + output("Expected |" + expected + "|"); + output(" Got |" + got + "|"); + ++failed; + } +} + +function complete() { + output("\nTests Complete"); + output("--------------"); + output("Passed: " + passed); + output("Failed: " + failed); + output("\n"); +} + +function runTests() { + output("Tests Starting"); + output("--------------"); + testScanTextNoTags(); + testScanOneTag(); + testScanMultipleTags(); + testScanSectionOpen(); + testScanSectionClose(); + testScanSection(); + testScanSectionInContent(); + testScanNegativeSection(); + testScanPartial(); + testScanBackwardPartial(); + testScanAmpersandNoEscapeTag(); + testScanTripleStache(); + testScanSectionWithTripleStacheInside(); + testScanSetDelimiter(); + testScanResetDelimiter(); + testSetDelimiterWithWhitespace(); + testSingleCharDelimiter(); + testParseBasic(); + testParseVariables(); + testParseSection(); + testParseIndexes(); + testParseNegativeSection(); + testParseNestedSections(); + testMissingClosingTag(); + testBadNesting(); + testBasicOutput(); + //testBasicOutputAsString(); + testOneVariable(); + //testOneVariableAsString(); + testMultipleVariables(); + testNumberValues(); + testObjectRender(); + testObjectToStringRender(); + testArrayRender(); + testEscaping(); + testMustacheInjection(); + testTripleStache(); + testAmpNoEscaping(); + testPartial(); + testNestedPartials(); + testNegativeSection(); + testSectionElision(); + testSectionObjectContext(); + testSectionArrayContext(); + testRenderWithWhitespace(); + testRenderWithWhitespaceAroundTripleStache(); + testRenderWithWhitespaceAroundAmpersand(); + testFalsyVariableNoRender(); + testRenderOutput(); + testDefaultRenderImpl(); + testSectionExtensions(); + testMisnestedSectionExtensions(); + testNestedSection(); + testShootOutString(); + testShootOutReplace(); + testShootOutArray(); + testShootOutObject(); + testShootOutPartial(); + testShootOutRecurse(); + testShootOutFilter(); + testShootOutComplex(); + testDottedNames(); + testImplicitIterator(); + testPartialsAndDelimiters(); + testStringPartials(); + testMissingPartials(); + testIndentedStandaloneComment(); + testNewLineBetweenDelimiterChanges(); + testMustacheJSApostrophe(); + testMustacheJSArrayOfImplicitPartials(); + testMustacheJSArrayOfPartials(); + testMustacheJSArrayOfStrings(); + testMustacheJSUndefinedString(); + testMustacheJSTripleStacheAltDelimiter(); + complete(); +} + +if (doc) { + window.onload = runTests; +} else { + runTests(); +} \ No newline at end of file -- cgit v1.2.3