\' \" &", "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
diff --git a/docs/build/node_modules/hogan.js/test/mustache.js b/docs/build/node_modules/hogan.js/test/mustache.js
new file mode 100644
index 0000000000..b2d8ebc51a
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/mustache.js
@@ -0,0 +1,90 @@
+/*
+ * 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 doc = this['document'];
+var fs = require('fs');
+
+var passed = 0;
+var failed = 0;
+
+if (!this['output']) {
+ var output = function (string) {
+ return doc ? doc.write(string + '
') : console.log(string);
+ };
+}
+
+var Hogan = require(__dirname + '/../lib/hogan');
+var template = fs.readFileSync(__dirname + '/../lib/template.js').toString();
+var compiler = fs.readFileSync(__dirname + '/../lib/compiler.js').toString();
+var mustache_wrapper = fs.readFileSync(__dirname + '/../wrappers/mustache.js.mustache').toString();
+
+// Create a Mustache.js emulator from the distribution template
+var engines = (new Function(Hogan.compile(mustache_wrapper).render({template: template, compiler: compiler}) +
+ '; return {Hogan: Hogan, Mustache: Mustache};'))();
+
+var Mustache = engines.Mustache;
+var Hogan2 = engines.Hogan;
+
+
+// sanity check
+is(Mustache.hasOwnProperty('to_html'), true, 'Mustache has to_html method.');
+
+// Check for Mustache.js partial resolution behavior.
+var context = {
+ foo: 'bar',
+ mypartial: {
+ baz: 'qux'
+ }
+}
+var text = 'abc {{foo}} def {{>mypartial}} ghi';
+var partialText = '{{baz}}';
+var s = Mustache.to_html(text, context, {'mypartial': partialText});
+is(s, 'abc bar def qux ghi', 'Correct emulation of Mustache.js partial-name-in-context resolution.');
+
+// Now check to see that the Hogan resolution is unaffected.
+var t = Hogan2.compile(text);
+s = t.render(context, {'mypartial': partialText});
+is(s, 'abc bar def ghi', 'Hogan behavior not changed by Mustache.js emulation.');
+
+// Check for sendFun behavior
+var buf = "";
+function send(s) {
+ buf += "-FOO " + s + " FOO-";
+}
+var s = Mustache.to_html(text, context, {'mypartial': partialText}, send);
+is(buf, '-FOO abc bar def qux ghi FOO-', 'Correct emulation of Mustache.js sendFun.');
+
+
+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");
+}
+
+complete();
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec.js b/docs/build/node_modules/hogan.js/test/spec.js
new file mode 100644
index 0000000000..15b4d8e19a
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec.js
@@ -0,0 +1,77 @@
+/*
+ * 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');
+var doc = this["document"];
+var fs = require('fs');
+
+var passed = 0;
+var failed = 0;
+
+if (!this["output"]) {
+ var output = function (string) {
+ return doc ? doc.write(string + '
') : console.log(string);
+ };
+}
+
+function runTest(tests) {
+ tests.forEach(function(test) {
+ var partials = {};
+ for (var i in test.partials) {
+ partials[i] = Hogan.compile(test.partials[i]);
+ }
+ var t = Hogan.compile(test.template);
+
+ if (test.data.lambda) {
+ var func = (new Function ('return ' + test.data.lambda.js)());
+ test.data.lambda = function() { return func; };
+ }
+
+ var s = t.render(test.data, partials);
+ is(s, test.expected, test.name + ': ' + test.desc);
+ });
+}
+
+var testDir = './test/spec/specs';
+var files = fs.readdirSync(testDir)
+ .filter(function(f) { return f.indexOf('.json') > 0; })
+ .map(function(f) { return testDir + '/' + f});
+
+for (var i = 0; i < files.length; i++) {
+ var test = JSON.parse(fs.readFileSync(files[i]).toString());
+ runTest(test.tests);
+}
+
+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");
+}
+
+complete();
diff --git a/docs/build/node_modules/hogan.js/test/spec/Changes b/docs/build/node_modules/hogan.js/test/spec/Changes
new file mode 100644
index 0000000000..bb39b9823e
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/Changes
@@ -0,0 +1,31 @@
+2011-03-20: v1.1.2
+ Added tests for standalone tags at string boundaries.
+ Added tests for rendering lambda returns after delimiter changes.
+
+2011-03-20: v1.0.3
+ Added tests for standalone tags at string boundaries.
+ Added tests for rendering lambda returns after delimiter changes.
+
+2011-03-05: v1.1.1
+ Added tests for indented inline sections.
+ Added tests for Windows-style newlines.
+
+2011-03-05: v1.0.2
+ Added tests for indented inline sections.
+ Added tests for Windows-style newlines.
+
+2011-03-04: v1.1.0
+ Implicit iterators.
+ A single period (`.`) may now be used as a name in Interpolation tags,
+ which represents the top of stack (cast as a String).
+ Dotted names.
+ Names containing one or more periods should be resolved as chained
+ properties; naïvely, this is like nesting section tags, but with some
+ built-in scoping protections.
+
+2011-03-02: v1.0.1
+ Clarifying a point in the README about version compliance.
+ Adding high-level documentation to each spec file.
+
+2011-02-28: v1.0.0
+ Initial Release
diff --git a/docs/build/node_modules/hogan.js/test/spec/README.md b/docs/build/node_modules/hogan.js/test/spec/README.md
new file mode 100644
index 0000000000..b01b1bbdb7
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/README.md
@@ -0,0 +1,65 @@
+The repository at https://github.com/mustache/spec is the formal standard for
+Mustache. It defines both normal usage and edge-case behavior for libraries
+parsing the Mustache templating language (or a superset thereof).
+
+The specification is developed as a series of YAML files, under the `specs`
+directory.
+
+Versioning
+----------
+This specification is being [semantically versioned](http://semver.org).
+Roughly described, major version changes will always represent backwards
+incompatible changes, minor version changes will always represent new language
+features and will be backwards compatible, and patch ('tiny') version changes
+will always be bug fixes. For the purposes of semantic versioning, the public
+API is the contents of the `specs` directory and the algorithm for testing
+against it.
+
+Mustache implementations SHOULD report the most recent version of the spec
+(major and minor version numbers). If an implementation has support for any
+optional modules, they SHOULD indicate so with a remark attached to the
+version number (e.g. "vX.Y, including lambdas" or "v.X.Y+λ"). It is
+RECOMMENDED that implementations not supporting at least v1.0.0 of this spec
+refer to themselves as "Mustache-like", or "Mustache-inspired".
+
+Alternate Formats
+-----------------
+
+Since YAML is a reasonably complex format that not every language has good
+tools for working with, we also provide JSON versions of the specs on a
+best-effort basis.
+
+These should be identical to the YAML specifications, but if you find the need
+to regenerate them, they can be trivially rebuilt by invoking `rake build`.
+
+It is also worth noting that some specifications (notably, the lambda module)
+rely on YAML "tags" to denote special types of data (e.g. source code). Since
+JSON offers no way to denote this, a special key ("`__tag__`") is injected
+with the name of the tag as its value. See `TESTING.md` for more information
+about handling tagged data.
+
+Optional Modules
+----------------
+
+Specification files beginning with a tilde (`~`) describe optional modules.
+At present, the only module being described as optional is regarding support
+for lambdas. As a guideline, a module may be a candidate for optionality
+when:
+
+ * It does not affect the core syntax of the language.
+ * It does not significantly affect the output of rendered templates.
+ * It concerns implementation language features or data types that are not
+ common to or core in every targeted language.
+ * The lack of support by an implementation does not diminish the usage of
+ Mustache in the target language.
+
+As an example, the lambda module is primarily concerned with the handling of a
+particular data type (code). This is a type of data that may be difficult to
+support in some languages, and users of those languages will not see the lack
+as an 'inconsistency' between implementations.
+
+Support for specific pragmas or syntax extensions, however, are best managed
+outside this core specification, as adjunct specifications.
+
+Implementors are strongly encouraged to support any and all modules they are
+reasonably capable of supporting.
diff --git a/docs/build/node_modules/hogan.js/test/spec/Rakefile b/docs/build/node_modules/hogan.js/test/spec/Rakefile
new file mode 100644
index 0000000000..5254ce65ad
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/Rakefile
@@ -0,0 +1,27 @@
+require 'json'
+require 'yaml'
+
+# Our custom YAML tags must retain their magic.
+%w[ code ].each do |tag|
+ YAML::add_builtin_type(tag) { |_,val| val.merge(:__tag__ => tag) }
+end
+
+desc 'Build all alternate versions of the specs.'
+multitask :build => [ 'build:json' ]
+
+namespace :build do
+ note = 'Do not edit this file; changes belong in the appropriate YAML file.'
+
+ desc 'Build JSON versions of the specs.'
+ task :json do
+ rm(Dir['specs/*.json'], :verbose => false)
+ Dir.glob('specs/*.yml').each do |filename|
+ json_file = filename.gsub('.yml', '.json')
+
+ File.open(json_file, 'w') do |file|
+ doc = YAML.load_file(filename)
+ file << doc.merge(:__ATTN__ => note).to_json()
+ end
+ end
+ end
+end
diff --git a/docs/build/node_modules/hogan.js/test/spec/TESTING.md b/docs/build/node_modules/hogan.js/test/spec/TESTING.md
new file mode 100644
index 0000000000..d2ca374953
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/TESTING.md
@@ -0,0 +1,46 @@
+Testing your Mustache implementation against this specification should be
+relatively simple. If you have a readily available testing framework on your
+platform, your task may be even simpler.
+
+In general, the process for each `.yml` file is as follows:
+
+1. Use a YAML parser to load the file.
+
+2. For each test in the 'tests' array:
+
+ 1. Ensure that each element of the 'partials' hash (if it exists) is
+ stored in a place where the interpreter will look for it.
+
+ 2. If your implementation will not support lambdas, feel free to skip over
+ the optional '~lambdas.yml' file.
+
+ 2.1. If your implementation will support lambdas, ensure that each member of
+ 'data' tagged with '!code' is properly processed into a language-
+ specific lambda reference.
+
+ * e.g. Given this YAML data hash:
+
+ `{ x: !code { ruby: 'proc { "x" }', perl: 'sub { "x" }' } }`
+
+ a Ruby-based Mustache implementation would process it such that it
+ was equivalent to this Ruby hash:
+
+ `{ 'x' => proc { "x" } }`
+
+ * If your implementation language does not currently have lambda
+ examples in the spec, feel free to implement them and send a pull
+ request.
+
+ * The JSON version of the spec represents these tagged values as a hash
+ with a '`__tag__`' key of 'code'.
+
+ 3. Render the template (stored in the 'template' key) with the given 'data'
+ hash.
+
+ 4. Compare the results of your rendering against the 'expected' value; any
+ differences should be reported, along with any useful debugging
+ information.
+
+ * Of note, the 'desc' key contains a rough one-line description of the
+ behavior being tested -- this is most useful in conjunction with the
+ file name and test 'name'.
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/comments.json b/docs/build/node_modules/hogan.js/test/spec/specs/comments.json
new file mode 100644
index 0000000000..30cb927e62
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/comments.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Comment tags represent content that should never appear in the resulting\noutput.\n\nThe tag's content may contain any substring (including newlines) EXCEPT the\nclosing delimiter.\n\nComment tags SHOULD be treated as standalone when appropriate.\n","tests":[{"name":"Inline","data":{},"expected":"1234567890","template":"12345{{! Comment Block! }}67890","desc":"Comment blocks should be removed from the template."},{"name":"Multiline","data":{},"expected":"1234567890\n","template":"12345{{!\n This is a\n multi-line comment...\n}}67890\n","desc":"Multiline comments should be permitted."},{"name":"Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{! Comment Block! }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{! Indented Comment Block! }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n|","template":"|\r\n{{! Standalone Comment }}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{},"expected":"!","template":" {{! I'm Still Standalone }}\n!","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{},"expected":"!\n","template":"!\n {{! I'm Still Standalone }}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Multiline Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{!\nSomething's going on here...\n}}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Multiline Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{!\n Something's going on here...\n }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Inline","data":{},"expected":" 12 \n","template":" 12 {{! 34 }}\n","desc":"Inline comments should not strip whitespace"},{"name":"Surrounding Whitespace","data":{},"expected":"12345 67890","template":"12345 {{! Comment Block! }} 67890","desc":"Comment removal should preserve surrounding whitespace."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/comments.yml b/docs/build/node_modules/hogan.js/test/spec/specs/comments.yml
new file mode 100644
index 0000000000..7b14c7f327
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/comments.yml
@@ -0,0 +1,103 @@
+overview: |
+ Comment tags represent content that should never appear in the resulting
+ output.
+
+ The tag's content may contain any substring (including newlines) EXCEPT the
+ closing delimiter.
+
+ Comment tags SHOULD be treated as standalone when appropriate.
+tests:
+ - name: Inline
+ desc: Comment blocks should be removed from the template.
+ data: { }
+ template: '12345{{! Comment Block! }}67890'
+ expected: '1234567890'
+
+ - name: Multiline
+ desc: Multiline comments should be permitted.
+ data: { }
+ template: |
+ 12345{{!
+ This is a
+ multi-line comment...
+ }}67890
+ expected: |
+ 1234567890
+
+ - name: Standalone
+ desc: All standalone comment lines should be removed.
+ data: { }
+ template: |
+ Begin.
+ {{! Comment Block! }}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Indented Standalone
+ desc: All standalone comment lines should be removed.
+ data: { }
+ template: |
+ Begin.
+ {{! Indented Comment Block! }}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Standalone Line Endings
+ desc: '"\r\n" should be considered a newline for standalone tags.'
+ data: { }
+ template: "|\r\n{{! Standalone Comment }}\r\n|"
+ expected: "|\r\n|"
+
+ - name: Standalone Without Previous Line
+ desc: Standalone tags should not require a newline to precede them.
+ data: { }
+ template: " {{! I'm Still Standalone }}\n!"
+ expected: "!"
+
+ - name: Standalone Without Newline
+ desc: Standalone tags should not require a newline to follow them.
+ data: { }
+ template: "!\n {{! I'm Still Standalone }}"
+ expected: "!\n"
+
+ - name: Multiline Standalone
+ desc: All standalone comment lines should be removed.
+ data: { }
+ template: |
+ Begin.
+ {{!
+ Something's going on here...
+ }}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Indented Multiline Standalone
+ desc: All standalone comment lines should be removed.
+ data: { }
+ template: |
+ Begin.
+ {{!
+ Something's going on here...
+ }}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Indented Inline
+ desc: Inline comments should not strip whitespace
+ data: { }
+ template: " 12 {{! 34 }}\n"
+ expected: " 12 \n"
+
+ - name: Surrounding Whitespace
+ desc: Comment removal should preserve surrounding whitespace.
+ data: { }
+ template: '12345 {{! Comment Block! }} 67890'
+ expected: '12345 67890'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.json b/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.json
new file mode 100644
index 0000000000..fcf95888db
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Set Delimiter tags are used to change the tag delimiters for all content\nfollowing the tag in the current compilation unit.\n\nThe tag's content MUST be any two non-whitespace sequences (separated by\nwhitespace) EXCEPT an equals sign ('=') followed by the current closing\ndelimiter.\n\nSet Delimiter tags SHOULD be treated as standalone when appropriate.\n","tests":[{"name":"Pair Behavior","data":{"text":"Hey!"},"expected":"(Hey!)","template":"{{=<% %>=}}(<%text%>)","desc":"The equals sign (used on both sides) should permit delimiter changes."},{"name":"Special Characters","data":{"text":"It worked!"},"expected":"(It worked!)","template":"({{=[ ]=}}[text])","desc":"Characters with special meaning regexen should be valid delimiters."},{"name":"Sections","data":{"section":true,"data":"I got interpolated."},"expected":"[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n","template":"[\n{{#section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|#section|\n {{data}}\n |data|\n|/section|\n]\n","desc":"Delimiters set outside sections should persist."},{"name":"Inverted Sections","data":{"section":false,"data":"I got interpolated."},"expected":"[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n","template":"[\n{{^section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|^section|\n {{data}}\n |data|\n|/section|\n]\n","desc":"Delimiters set outside inverted sections should persist."},{"name":"Partial Inheritence","data":{"value":"yes"},"expected":"[ .yes. ]\n[ .yes. ]\n","template":"[ {{>include}} ]\n{{= | | =}}\n[ |>include| ]\n","desc":"Delimiters set in a parent template should not affect a partial.","partials":{"include":".{{value}}."}},{"name":"Post-Partial Behavior","data":{"value":"yes"},"expected":"[ .yes. .yes. ]\n[ .yes. .|value|. ]\n","template":"[ {{>include}} ]\n[ .{{value}}. .|value|. ]\n","desc":"Delimiters set in a partial should not affect the parent template.","partials":{"include":".{{value}}. {{= | | =}} .|value|."}},{"name":"Surrounding Whitespace","data":{},"expected":"| |","template":"| {{=@ @=}} |","desc":"Surrounding whitespace should be left untouched."},{"name":"Outlying Whitespace (Inline)","data":{},"expected":" | \n","template":" | {{=@ @=}}\n","desc":"Whitespace should be left untouched."},{"name":"Standalone Tag","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{=@ @=}}\nEnd.\n","desc":"Standalone lines should be removed from the template."},{"name":"Indented Standalone Tag","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{=@ @=}}\nEnd.\n","desc":"Indented standalone lines should be removed from the template."},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n|","template":"|\r\n{{= @ @ =}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{},"expected":"=","template":" {{=@ @=}}\n=","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{},"expected":"=\n","template":"=\n {{=@ @=}}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Pair with Padding","data":{},"expected":"||","template":"|{{= @ @ =}}|","desc":"Superfluous in-tag whitespace should be ignored."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.yml b/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.yml
new file mode 100644
index 0000000000..ce80b17cd1
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/delimiters.yml
@@ -0,0 +1,158 @@
+overview: |
+ Set Delimiter tags are used to change the tag delimiters for all content
+ following the tag in the current compilation unit.
+
+ The tag's content MUST be any two non-whitespace sequences (separated by
+ whitespace) EXCEPT an equals sign ('=') followed by the current closing
+ delimiter.
+
+ Set Delimiter tags SHOULD be treated as standalone when appropriate.
+tests:
+ - name: Pair Behavior
+ desc: The equals sign (used on both sides) should permit delimiter changes.
+ data: { text: 'Hey!' }
+ template: '{{=<% %>=}}(<%text%>)'
+ expected: '(Hey!)'
+
+ - name: Special Characters
+ desc: Characters with special meaning regexen should be valid delimiters.
+ data: { text: 'It worked!' }
+ template: '({{=[ ]=}}[text])'
+ expected: '(It worked!)'
+
+ - name: Sections
+ desc: Delimiters set outside sections should persist.
+ data: { section: true, data: 'I got interpolated.' }
+ template: |
+ [
+ {{#section}}
+ {{data}}
+ |data|
+ {{/section}}
+
+ {{= | | =}}
+ |#section|
+ {{data}}
+ |data|
+ |/section|
+ ]
+ expected: |
+ [
+ I got interpolated.
+ |data|
+
+ {{data}}
+ I got interpolated.
+ ]
+
+ - name: Inverted Sections
+ desc: Delimiters set outside inverted sections should persist.
+ data: { section: false, data: 'I got interpolated.' }
+ template: |
+ [
+ {{^section}}
+ {{data}}
+ |data|
+ {{/section}}
+
+ {{= | | =}}
+ |^section|
+ {{data}}
+ |data|
+ |/section|
+ ]
+ expected: |
+ [
+ I got interpolated.
+ |data|
+
+ {{data}}
+ I got interpolated.
+ ]
+
+ - name: Partial Inheritence
+ desc: Delimiters set in a parent template should not affect a partial.
+ data: { value: 'yes' }
+ partials:
+ include: '.{{value}}.'
+ template: |
+ [ {{>include}} ]
+ {{= | | =}}
+ [ |>include| ]
+ expected: |
+ [ .yes. ]
+ [ .yes. ]
+
+ - name: Post-Partial Behavior
+ desc: Delimiters set in a partial should not affect the parent template.
+ data: { value: 'yes' }
+ partials:
+ include: '.{{value}}. {{= | | =}} .|value|.'
+ template: |
+ [ {{>include}} ]
+ [ .{{value}}. .|value|. ]
+ expected: |
+ [ .yes. .yes. ]
+ [ .yes. .|value|. ]
+
+ # Whitespace Sensitivity
+
+ - name: Surrounding Whitespace
+ desc: Surrounding whitespace should be left untouched.
+ data: { }
+ template: '| {{=@ @=}} |'
+ expected: '| |'
+
+ - name: Outlying Whitespace (Inline)
+ desc: Whitespace should be left untouched.
+ data: { }
+ template: " | {{=@ @=}}\n"
+ expected: " | \n"
+
+ - name: Standalone Tag
+ desc: Standalone lines should be removed from the template.
+ data: { }
+ template: |
+ Begin.
+ {{=@ @=}}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Indented Standalone Tag
+ desc: Indented standalone lines should be removed from the template.
+ data: { }
+ template: |
+ Begin.
+ {{=@ @=}}
+ End.
+ expected: |
+ Begin.
+ End.
+
+ - name: Standalone Line Endings
+ desc: '"\r\n" should be considered a newline for standalone tags.'
+ data: { }
+ template: "|\r\n{{= @ @ =}}\r\n|"
+ expected: "|\r\n|"
+
+ - name: Standalone Without Previous Line
+ desc: Standalone tags should not require a newline to precede them.
+ data: { }
+ template: " {{=@ @=}}\n="
+ expected: "="
+
+ - name: Standalone Without Newline
+ desc: Standalone tags should not require a newline to follow them.
+ data: { }
+ template: "=\n {{=@ @=}}"
+ expected: "=\n"
+
+ # Whitespace Insensitivity
+
+ - name: Pair with Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { }
+ template: '|{{= @ @ =}}|'
+ expected: '||'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.json b/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.json
new file mode 100644
index 0000000000..d1a1a32897
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Interpolation tags are used to integrate dynamic content into the template.\n\nThe tag's content MUST be a non-whitespace character sequence NOT containing\nthe current closing delimiter.\n\nThis tag's content names the data to replace the tag. A single period (`.`)\nindicates that the item currently sitting atop the context stack should be\nused; otherwise, name resolution is as follows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object, the data is the value returned by the\n method with the given name.\n 5) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nData should be coerced into a string (and escaped, if appropriate) before\ninterpolation.\n\nThe Interpolation tags MUST NOT be treated as standalone.\n","tests":[{"name":"No Interpolation","data":{},"expected":"Hello from {Mustache}!\n","template":"Hello from {Mustache}!\n","desc":"Mustache-free templates should render as-is."},{"name":"Basic Interpolation","data":{"subject":"world"},"expected":"Hello, world!\n","template":"Hello, {{subject}}!\n","desc":"Unadorned tags should interpolate content into the template."},{"name":"HTML Escaping","data":{"forbidden":"& \" < >"},"expected":"These characters should be HTML escaped: & " < >\n","template":"These characters should be HTML escaped: {{forbidden}}\n","desc":"Basic interpolation should be HTML escaped."},{"name":"Triple Mustache","data":{"forbidden":"& \" < >"},"expected":"These characters should not be HTML escaped: & \" < >\n","template":"These characters should not be HTML escaped: {{{forbidden}}}\n","desc":"Triple mustaches should interpolate without HTML escaping."},{"name":"Ampersand","data":{"forbidden":"& \" < >"},"expected":"These characters should not be HTML escaped: & \" < >\n","template":"These characters should not be HTML escaped: {{&forbidden}}\n","desc":"Ampersand should interpolate without HTML escaping."},{"name":"Basic Integer Interpolation","data":{"mph":85},"expected":"\"85 miles an hour!\"","template":"\"{{mph}} miles an hour!\"","desc":"Integers should interpolate seamlessly."},{"name":"Triple Mustache Integer Interpolation","data":{"mph":85},"expected":"\"85 miles an hour!\"","template":"\"{{{mph}}} miles an hour!\"","desc":"Integers should interpolate seamlessly."},{"name":"Ampersand Integer Interpolation","data":{"mph":85},"expected":"\"85 miles an hour!\"","template":"\"{{&mph}} miles an hour!\"","desc":"Integers should interpolate seamlessly."},{"name":"Basic Decimal Interpolation","data":{"power":1.21},"expected":"\"1.21 jiggawatts!\"","template":"\"{{power}} jiggawatts!\"","desc":"Decimals should interpolate seamlessly with proper significance."},{"name":"Triple Mustache Decimal Interpolation","data":{"power":1.21},"expected":"\"1.21 jiggawatts!\"","template":"\"{{{power}}} jiggawatts!\"","desc":"Decimals should interpolate seamlessly with proper significance."},{"name":"Ampersand Decimal Interpolation","data":{"power":1.21},"expected":"\"1.21 jiggawatts!\"","template":"\"{{&power}} jiggawatts!\"","desc":"Decimals should interpolate seamlessly with proper significance."},{"name":"Basic Context Miss Interpolation","data":{},"expected":"I () be seen!","template":"I ({{cannot}}) be seen!","desc":"Failed context lookups should default to empty strings."},{"name":"Triple Mustache Context Miss Interpolation","data":{},"expected":"I () be seen!","template":"I ({{{cannot}}}) be seen!","desc":"Failed context lookups should default to empty strings."},{"name":"Ampersand Context Miss Interpolation","data":{},"expected":"I () be seen!","template":"I ({{&cannot}}) be seen!","desc":"Failed context lookups should default to empty strings."},{"name":"Dotted Names - Basic Interpolation","data":{"person":{"name":"Joe"}},"expected":"\"Joe\" == \"Joe\"","template":"\"{{person.name}}\" == \"{{#person}}{{name}}{{/person}}\"","desc":"Dotted names should be considered a form of shorthand for sections."},{"name":"Dotted Names - Triple Mustache Interpolation","data":{"person":{"name":"Joe"}},"expected":"\"Joe\" == \"Joe\"","template":"\"{{{person.name}}}\" == \"{{#person}}{{{name}}}{{/person}}\"","desc":"Dotted names should be considered a form of shorthand for sections."},{"name":"Dotted Names - Ampersand Interpolation","data":{"person":{"name":"Joe"}},"expected":"\"Joe\" == \"Joe\"","template":"\"{{&person.name}}\" == \"{{#person}}{{&name}}{{/person}}\"","desc":"Dotted names should be considered a form of shorthand for sections."},{"name":"Dotted Names - Arbitrary Depth","data":{"a":{"b":{"c":{"d":{"e":{"name":"Phil"}}}}}},"expected":"\"Phil\" == \"Phil\"","template":"\"{{a.b.c.d.e.name}}\" == \"Phil\"","desc":"Dotted names should be functional to any level of nesting."},{"name":"Dotted Names - Broken Chains","data":{"a":{}},"expected":"\"\" == \"\"","template":"\"{{a.b.c}}\" == \"\"","desc":"Any falsey value prior to the last part of the name should yield ''."},{"name":"Dotted Names - Broken Chain Resolution","data":{"a":{"b":{}},"c":{"name":"Jim"}},"expected":"\"\" == \"\"","template":"\"{{a.b.c.name}}\" == \"\"","desc":"Each part of a dotted name should resolve only against its parent."},{"name":"Dotted Names - Initial Resolution","data":{"a":{"b":{"c":{"d":{"e":{"name":"Phil"}}}}},"b":{"c":{"d":{"e":{"name":"Wrong"}}}}},"expected":"\"Phil\" == \"Phil\"","template":"\"{{#a}}{{b.c.d.e.name}}{{/a}}\" == \"Phil\"","desc":"The first part of a dotted name should resolve as any other name."},{"name":"Interpolation - Surrounding Whitespace","data":{"string":"---"},"expected":"| --- |","template":"| {{string}} |","desc":"Interpolation should not alter surrounding whitespace."},{"name":"Triple Mustache - Surrounding Whitespace","data":{"string":"---"},"expected":"| --- |","template":"| {{{string}}} |","desc":"Interpolation should not alter surrounding whitespace."},{"name":"Ampersand - Surrounding Whitespace","data":{"string":"---"},"expected":"| --- |","template":"| {{&string}} |","desc":"Interpolation should not alter surrounding whitespace."},{"name":"Interpolation - Standalone","data":{"string":"---"},"expected":" ---\n","template":" {{string}}\n","desc":"Standalone interpolation should not alter surrounding whitespace."},{"name":"Triple Mustache - Standalone","data":{"string":"---"},"expected":" ---\n","template":" {{{string}}}\n","desc":"Standalone interpolation should not alter surrounding whitespace."},{"name":"Ampersand - Standalone","data":{"string":"---"},"expected":" ---\n","template":" {{&string}}\n","desc":"Standalone interpolation should not alter surrounding whitespace."},{"name":"Interpolation With Padding","data":{"string":"---"},"expected":"|---|","template":"|{{ string }}|","desc":"Superfluous in-tag whitespace should be ignored."},{"name":"Triple Mustache With Padding","data":{"string":"---"},"expected":"|---|","template":"|{{{ string }}}|","desc":"Superfluous in-tag whitespace should be ignored."},{"name":"Ampersand With Padding","data":{"string":"---"},"expected":"|---|","template":"|{{& string }}|","desc":"Superfluous in-tag whitespace should be ignored."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.yml b/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.yml
new file mode 100644
index 0000000000..2237b55f8d
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/interpolation.yml
@@ -0,0 +1,230 @@
+overview: |
+ Interpolation tags are used to integrate dynamic content into the template.
+
+ The tag's content MUST be a non-whitespace character sequence NOT containing
+ the current closing delimiter.
+
+ This tag's content names the data to replace the tag. A single period (`.`)
+ indicates that the item currently sitting atop the context stack should be
+ used; otherwise, name resolution is as follows:
+ 1) Split the name on periods; the first part is the name to resolve, any
+ remaining parts should be retained.
+ 2) Walk the context stack from top to bottom, finding the first context
+ that is a) a hash containing the name as a key OR b) an object responding
+ to a method with the given name.
+ 3) If the context is a hash, the data is the value associated with the
+ name.
+ 4) If the context is an object, the data is the value returned by the
+ method with the given name.
+ 5) If any name parts were retained in step 1, each should be resolved
+ against a context stack containing only the result from the former
+ resolution. If any part fails resolution, the result should be considered
+ falsey, and should interpolate as the empty string.
+ Data should be coerced into a string (and escaped, if appropriate) before
+ interpolation.
+
+ The Interpolation tags MUST NOT be treated as standalone.
+tests:
+ - name: No Interpolation
+ desc: Mustache-free templates should render as-is.
+ data: { }
+ template: |
+ Hello from {Mustache}!
+ expected: |
+ Hello from {Mustache}!
+
+ - name: Basic Interpolation
+ desc: Unadorned tags should interpolate content into the template.
+ data: { subject: "world" }
+ template: |
+ Hello, {{subject}}!
+ expected: |
+ Hello, world!
+
+ - name: HTML Escaping
+ desc: Basic interpolation should be HTML escaped.
+ data: { forbidden: '& " < >' }
+ template: |
+ These characters should be HTML escaped: {{forbidden}}
+ expected: |
+ These characters should be HTML escaped: & " < >
+
+ - name: Triple Mustache
+ desc: Triple mustaches should interpolate without HTML escaping.
+ data: { forbidden: '& " < >' }
+ template: |
+ These characters should not be HTML escaped: {{{forbidden}}}
+ expected: |
+ These characters should not be HTML escaped: & " < >
+
+ - name: Ampersand
+ desc: Ampersand should interpolate without HTML escaping.
+ data: { forbidden: '& " < >' }
+ template: |
+ These characters should not be HTML escaped: {{&forbidden}}
+ expected: |
+ These characters should not be HTML escaped: & " < >
+
+ - name: Basic Integer Interpolation
+ desc: Integers should interpolate seamlessly.
+ data: { mph: 85 }
+ template: '"{{mph}} miles an hour!"'
+ expected: '"85 miles an hour!"'
+
+ - name: Triple Mustache Integer Interpolation
+ desc: Integers should interpolate seamlessly.
+ data: { mph: 85 }
+ template: '"{{{mph}}} miles an hour!"'
+ expected: '"85 miles an hour!"'
+
+ - name: Ampersand Integer Interpolation
+ desc: Integers should interpolate seamlessly.
+ data: { mph: 85 }
+ template: '"{{&mph}} miles an hour!"'
+ expected: '"85 miles an hour!"'
+
+ - name: Basic Decimal Interpolation
+ desc: Decimals should interpolate seamlessly with proper significance.
+ data: { power: 1.210 }
+ template: '"{{power}} jiggawatts!"'
+ expected: '"1.21 jiggawatts!"'
+
+ - name: Triple Mustache Decimal Interpolation
+ desc: Decimals should interpolate seamlessly with proper significance.
+ data: { power: 1.210 }
+ template: '"{{{power}}} jiggawatts!"'
+ expected: '"1.21 jiggawatts!"'
+
+ - name: Ampersand Decimal Interpolation
+ desc: Decimals should interpolate seamlessly with proper significance.
+ data: { power: 1.210 }
+ template: '"{{&power}} jiggawatts!"'
+ expected: '"1.21 jiggawatts!"'
+
+ # Context Misses
+
+ - name: Basic Context Miss Interpolation
+ desc: Failed context lookups should default to empty strings.
+ data: { }
+ template: "I ({{cannot}}) be seen!"
+ expected: "I () be seen!"
+
+ - name: Triple Mustache Context Miss Interpolation
+ desc: Failed context lookups should default to empty strings.
+ data: { }
+ template: "I ({{{cannot}}}) be seen!"
+ expected: "I () be seen!"
+
+ - name: Ampersand Context Miss Interpolation
+ desc: Failed context lookups should default to empty strings.
+ data: { }
+ template: "I ({{&cannot}}) be seen!"
+ expected: "I () be seen!"
+
+ # Dotted Names
+
+ - name: Dotted Names - Basic Interpolation
+ desc: Dotted names should be considered a form of shorthand for sections.
+ data: { person: { name: 'Joe' } }
+ template: '"{{person.name}}" == "{{#person}}{{name}}{{/person}}"'
+ expected: '"Joe" == "Joe"'
+
+ - name: Dotted Names - Triple Mustache Interpolation
+ desc: Dotted names should be considered a form of shorthand for sections.
+ data: { person: { name: 'Joe' } }
+ template: '"{{{person.name}}}" == "{{#person}}{{{name}}}{{/person}}"'
+ expected: '"Joe" == "Joe"'
+
+ - name: Dotted Names - Ampersand Interpolation
+ desc: Dotted names should be considered a form of shorthand for sections.
+ data: { person: { name: 'Joe' } }
+ template: '"{{&person.name}}" == "{{#person}}{{&name}}{{/person}}"'
+ expected: '"Joe" == "Joe"'
+
+ - name: Dotted Names - Arbitrary Depth
+ desc: Dotted names should be functional to any level of nesting.
+ data:
+ a: { b: { c: { d: { e: { name: 'Phil' } } } } }
+ template: '"{{a.b.c.d.e.name}}" == "Phil"'
+ expected: '"Phil" == "Phil"'
+
+ - name: Dotted Names - Broken Chains
+ desc: Any falsey value prior to the last part of the name should yield ''.
+ data:
+ a: { }
+ template: '"{{a.b.c}}" == ""'
+ expected: '"" == ""'
+
+ - name: Dotted Names - Broken Chain Resolution
+ desc: Each part of a dotted name should resolve only against its parent.
+ data:
+ a: { b: { } }
+ c: { name: 'Jim' }
+ template: '"{{a.b.c.name}}" == ""'
+ expected: '"" == ""'
+
+ - name: Dotted Names - Initial Resolution
+ desc: The first part of a dotted name should resolve as any other name.
+ data:
+ a: { b: { c: { d: { e: { name: 'Phil' } } } } }
+ b: { c: { d: { e: { name: 'Wrong' } } } }
+ template: '"{{#a}}{{b.c.d.e.name}}{{/a}}" == "Phil"'
+ expected: '"Phil" == "Phil"'
+
+ # Whitespace Sensitivity
+
+ - name: Interpolation - Surrounding Whitespace
+ desc: Interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: '| {{string}} |'
+ expected: '| --- |'
+
+ - name: Triple Mustache - Surrounding Whitespace
+ desc: Interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: '| {{{string}}} |'
+ expected: '| --- |'
+
+ - name: Ampersand - Surrounding Whitespace
+ desc: Interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: '| {{&string}} |'
+ expected: '| --- |'
+
+ - name: Interpolation - Standalone
+ desc: Standalone interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: " {{string}}\n"
+ expected: " ---\n"
+
+ - name: Triple Mustache - Standalone
+ desc: Standalone interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: " {{{string}}}\n"
+ expected: " ---\n"
+
+ - name: Ampersand - Standalone
+ desc: Standalone interpolation should not alter surrounding whitespace.
+ data: { string: '---' }
+ template: " {{&string}}\n"
+ expected: " ---\n"
+
+ # Whitespace Insensitivity
+
+ - name: Interpolation With Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { string: "---" }
+ template: '|{{ string }}|'
+ expected: '|---|'
+
+ - name: Triple Mustache With Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { string: "---" }
+ template: '|{{{ string }}}|'
+ expected: '|---|'
+
+ - name: Ampersand With Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { string: "---" }
+ template: '|{{& string }}|'
+ expected: '|---|'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/inverted.json b/docs/build/node_modules/hogan.js/test/spec/specs/inverted.json
new file mode 100644
index 0000000000..c9b550b964
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/inverted.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Inverted Section tags and End Section tags are used in combination to wrap a\nsection of the template.\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Inverted Section tag MUST be\nfollowed by an End Section tag with the same content within the same\nsection.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 5) Otherwise, the data is the value returned by calling the method with\n the given name.\n 6) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nThis section MUST NOT be rendered unless the data list is empty.\n\nInverted Section and End Section tags SHOULD be treated as standalone when\nappropriate.\n","tests":[{"name":"Falsey","data":{"boolean":false},"expected":"\"This should be rendered.\"","template":"\"{{^boolean}}This should be rendered.{{/boolean}}\"","desc":"Falsey sections should have their contents rendered."},{"name":"Truthy","data":{"boolean":true},"expected":"\"\"","template":"\"{{^boolean}}This should not be rendered.{{/boolean}}\"","desc":"Truthy sections should have their contents omitted."},{"name":"Context","data":{"context":{"name":"Joe"}},"expected":"\"\"","template":"\"{{^context}}Hi {{name}}.{{/context}}\"","desc":"Objects and hashes should behave like truthy values."},{"name":"List","data":{"list":[{"n":1},{"n":2},{"n":3}]},"expected":"\"\"","template":"\"{{^list}}{{n}}{{/list}}\"","desc":"Lists should behave like truthy values."},{"name":"Empty List","data":{"list":[]},"expected":"\"Yay lists!\"","template":"\"{{^list}}Yay lists!{{/list}}\"","desc":"Empty lists should behave like falsey values."},{"name":"Doubled","data":{"two":"second","bool":false},"expected":"* first\n* second\n* third\n","template":"{{^bool}}\n* first\n{{/bool}}\n* {{two}}\n{{^bool}}\n* third\n{{/bool}}\n","desc":"Multiple inverted sections per template should be permitted."},{"name":"Nested (Falsey)","data":{"bool":false},"expected":"| A B C D E |","template":"| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |","desc":"Nested falsey sections should have their contents rendered."},{"name":"Nested (Truthy)","data":{"bool":true},"expected":"| A E |","template":"| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |","desc":"Nested truthy sections should be omitted."},{"name":"Context Misses","data":{},"expected":"[Cannot find key 'missing'!]","template":"[{{^missing}}Cannot find key 'missing'!{{/missing}}]","desc":"Failed context lookups should be considered falsey."},{"name":"Dotted Names - Truthy","data":{"a":{"b":{"c":true}}},"expected":"\"\" == \"\"","template":"\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"\"","desc":"Dotted names should be valid for Inverted Section tags."},{"name":"Dotted Names - Falsey","data":{"a":{"b":{"c":false}}},"expected":"\"Not Here\" == \"Not Here\"","template":"\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"","desc":"Dotted names should be valid for Inverted Section tags."},{"name":"Dotted Names - Broken Chains","data":{"a":{}},"expected":"\"Not Here\" == \"Not Here\"","template":"\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"","desc":"Dotted names that cannot be resolved should be considered falsey."},{"name":"Surrounding Whitespace","data":{"boolean":false},"expected":" | \t|\t | \n","template":" | {{^boolean}}\t|\t{{/boolean}} | \n","desc":"Inverted sections should not alter surrounding whitespace."},{"name":"Internal Whitespace","data":{"boolean":false},"expected":" | \n | \n","template":" | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n","desc":"Inverted should not alter internal whitespace."},{"name":"Indented Inline Sections","data":{"boolean":false},"expected":" NO\n WAY\n","template":" {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n","desc":"Single-line sections should not alter surrounding whitespace."},{"name":"Standalone Lines","data":{"boolean":false},"expected":"| This Is\n|\n| A Line\n","template":"| This Is\n{{^boolean}}\n|\n{{/boolean}}\n| A Line\n","desc":"Standalone lines should be removed from the template."},{"name":"Standalone Indented Lines","data":{"boolean":false},"expected":"| This Is\n|\n| A Line\n","template":"| This Is\n {{^boolean}}\n|\n {{/boolean}}\n| A Line\n","desc":"Standalone indented lines should be removed from the template."},{"name":"Standalone Line Endings","data":{"boolean":false},"expected":"|\r\n|","template":"|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{"boolean":false},"expected":"^\n/","template":" {{^boolean}}\n^{{/boolean}}\n/","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{"boolean":false},"expected":"^\n/\n","template":"^{{^boolean}}\n/\n {{/boolean}}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Padding","data":{"boolean":false},"expected":"|=|","template":"|{{^ boolean }}={{/ boolean }}|","desc":"Superfluous in-tag whitespace should be ignored."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/inverted.yml b/docs/build/node_modules/hogan.js/test/spec/specs/inverted.yml
new file mode 100644
index 0000000000..5f8e2b2f3c
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/inverted.yml
@@ -0,0 +1,193 @@
+overview: |
+ Inverted Section tags and End Section tags are used in combination to wrap a
+ section of the template.
+
+ These tags' content MUST be a non-whitespace character sequence NOT
+ containing the current closing delimiter; each Inverted Section tag MUST be
+ followed by an End Section tag with the same content within the same
+ section.
+
+ This tag's content names the data to replace the tag. Name resolution is as
+ follows:
+ 1) Split the name on periods; the first part is the name to resolve, any
+ remaining parts should be retained.
+ 2) Walk the context stack from top to bottom, finding the first context
+ that is a) a hash containing the name as a key OR b) an object responding
+ to a method with the given name.
+ 3) If the context is a hash, the data is the value associated with the
+ name.
+ 4) If the context is an object and the method with the given name has an
+ arity of 1, the method SHOULD be called with a String containing the
+ unprocessed contents of the sections; the data is the value returned.
+ 5) Otherwise, the data is the value returned by calling the method with
+ the given name.
+ 6) If any name parts were retained in step 1, each should be resolved
+ against a context stack containing only the result from the former
+ resolution. If any part fails resolution, the result should be considered
+ falsey, and should interpolate as the empty string.
+ If the data is not of a list type, it is coerced into a list as follows: if
+ the data is truthy (e.g. `!!data == true`), use a single-element list
+ containing the data, otherwise use an empty list.
+
+ This section MUST NOT be rendered unless the data list is empty.
+
+ Inverted Section and End Section tags SHOULD be treated as standalone when
+ appropriate.
+tests:
+ - name: Falsey
+ desc: Falsey sections should have their contents rendered.
+ data: { boolean: false }
+ template: '"{{^boolean}}This should be rendered.{{/boolean}}"'
+ expected: '"This should be rendered."'
+
+ - name: Truthy
+ desc: Truthy sections should have their contents omitted.
+ data: { boolean: true }
+ template: '"{{^boolean}}This should not be rendered.{{/boolean}}"'
+ expected: '""'
+
+ - name: Context
+ desc: Objects and hashes should behave like truthy values.
+ data: { context: { name: 'Joe' } }
+ template: '"{{^context}}Hi {{name}}.{{/context}}"'
+ expected: '""'
+
+ - name: List
+ desc: Lists should behave like truthy values.
+ data: { list: [ { n: 1 }, { n: 2 }, { n: 3 } ] }
+ template: '"{{^list}}{{n}}{{/list}}"'
+ expected: '""'
+
+ - name: Empty List
+ desc: Empty lists should behave like falsey values.
+ data: { list: [ ] }
+ template: '"{{^list}}Yay lists!{{/list}}"'
+ expected: '"Yay lists!"'
+
+ - name: Doubled
+ desc: Multiple inverted sections per template should be permitted.
+ data: { bool: false, two: 'second' }
+ template: |
+ {{^bool}}
+ * first
+ {{/bool}}
+ * {{two}}
+ {{^bool}}
+ * third
+ {{/bool}}
+ expected: |
+ * first
+ * second
+ * third
+
+ - name: Nested (Falsey)
+ desc: Nested falsey sections should have their contents rendered.
+ data: { bool: false }
+ template: "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |"
+ expected: "| A B C D E |"
+
+ - name: Nested (Truthy)
+ desc: Nested truthy sections should be omitted.
+ data: { bool: true }
+ template: "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |"
+ expected: "| A E |"
+
+ - name: Context Misses
+ desc: Failed context lookups should be considered falsey.
+ data: { }
+ template: "[{{^missing}}Cannot find key 'missing'!{{/missing}}]"
+ expected: "[Cannot find key 'missing'!]"
+
+ # Dotted Names
+
+ - name: Dotted Names - Truthy
+ desc: Dotted names should be valid for Inverted Section tags.
+ data: { a: { b: { c: true } } }
+ template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == ""'
+ expected: '"" == ""'
+
+ - name: Dotted Names - Falsey
+ desc: Dotted names should be valid for Inverted Section tags.
+ data: { a: { b: { c: false } } }
+ template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == "Not Here"'
+ expected: '"Not Here" == "Not Here"'
+
+ - name: Dotted Names - Broken Chains
+ desc: Dotted names that cannot be resolved should be considered falsey.
+ data: { a: { } }
+ template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == "Not Here"'
+ expected: '"Not Here" == "Not Here"'
+
+ # Whitespace Sensitivity
+
+ - name: Surrounding Whitespace
+ desc: Inverted sections should not alter surrounding whitespace.
+ data: { boolean: false }
+ template: " | {{^boolean}}\t|\t{{/boolean}} | \n"
+ expected: " | \t|\t | \n"
+
+ - name: Internal Whitespace
+ desc: Inverted should not alter internal whitespace.
+ data: { boolean: false }
+ template: " | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n"
+ expected: " | \n | \n"
+
+ - name: Indented Inline Sections
+ desc: Single-line sections should not alter surrounding whitespace.
+ data: { boolean: false }
+ template: " {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n"
+ expected: " NO\n WAY\n"
+
+ - name: Standalone Lines
+ desc: Standalone lines should be removed from the template.
+ data: { boolean: false }
+ template: |
+ | This Is
+ {{^boolean}}
+ |
+ {{/boolean}}
+ | A Line
+ expected: |
+ | This Is
+ |
+ | A Line
+
+ - name: Standalone Indented Lines
+ desc: Standalone indented lines should be removed from the template.
+ data: { boolean: false }
+ template: |
+ | This Is
+ {{^boolean}}
+ |
+ {{/boolean}}
+ | A Line
+ expected: |
+ | This Is
+ |
+ | A Line
+
+ - name: Standalone Line Endings
+ desc: '"\r\n" should be considered a newline for standalone tags.'
+ data: { boolean: false }
+ template: "|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|"
+ expected: "|\r\n|"
+
+ - name: Standalone Without Previous Line
+ desc: Standalone tags should not require a newline to precede them.
+ data: { boolean: false }
+ template: " {{^boolean}}\n^{{/boolean}}\n/"
+ expected: "^\n/"
+
+ - name: Standalone Without Newline
+ desc: Standalone tags should not require a newline to follow them.
+ data: { boolean: false }
+ template: "^{{^boolean}}\n/\n {{/boolean}}"
+ expected: "^\n/\n"
+
+ # Whitespace Insensitivity
+
+ - name: Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { boolean: false }
+ template: '|{{^ boolean }}={{/ boolean }}|'
+ expected: '|=|'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/partials.json b/docs/build/node_modules/hogan.js/test/spec/specs/partials.json
new file mode 100644
index 0000000000..e5f21a2a48
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/partials.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Partial tags are used to expand an external template into the current\ntemplate.\n\nThe tag's content MUST be a non-whitespace character sequence NOT containing\nthe current closing delimiter.\n\nThis tag's content names the partial to inject. Set Delimiter tags MUST NOT\naffect the parsing of a partial. The partial MUST be rendered against the\ncontext stack local to the tag. If the named partial cannot be found, the\nempty string SHOULD be used instead, as in interpolations.\n\nPartial tags SHOULD be treated as standalone when appropriate. If this tag\nis used standalone, any whitespace preceding the tag should treated as\nindentation, and prepended to each line of the partial before rendering.\n","tests":[{"name":"Basic Behavior","data":{},"expected":"\"from partial\"","template":"\"{{>text}}\"","desc":"The greater-than operator should expand to the named partial.","partials":{"text":"from partial"}},{"name":"Failed Lookup","data":{},"expected":"\"\"","template":"\"{{>text}}\"","desc":"The empty string should be used when the named partial is not found.","partials":{}},{"name":"Context","data":{"text":"content"},"expected":"\"*content*\"","template":"\"{{>partial}}\"","desc":"The greater-than operator should operate within the current context.","partials":{"partial":"*{{text}}*"}},{"name":"Recursion","data":{"content":"X","nodes":[{"content":"Y","nodes":[]}]},"expected":"X
>","template":"{{>node}}","desc":"The greater-than operator should properly recurse.","partials":{"node":"{{content}}<{{#nodes}}{{>node}}{{/nodes}}>"}},{"name":"Surrounding Whitespace","data":{},"expected":"| \t|\t |","template":"| {{>partial}} |","desc":"The greater-than operator should not alter surrounding whitespace.","partials":{"partial":"\t|\t"}},{"name":"Inline Indentation","data":{"data":"|"},"expected":" | >\n>\n","template":" {{data}} {{> partial}}\n","desc":"Whitespace should be left untouched.","partials":{"partial":">\n>"}},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n>|","template":"|\r\n{{>partial}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags.","partials":{"partial":">"}},{"name":"Standalone Without Previous Line","data":{},"expected":" >\n >>","template":" {{>partial}}\n>","desc":"Standalone tags should not require a newline to precede them.","partials":{"partial":">\n>"}},{"name":"Standalone Without Newline","data":{},"expected":">\n >\n >","template":">\n {{>partial}}","desc":"Standalone tags should not require a newline to follow them.","partials":{"partial":">\n>"}},{"name":"Standalone Indentation","data":{"content":"<\n->"},"expected":"\\\n |\n <\n->\n |\n/\n","template":"\\\n {{>partial}}\n/\n","desc":"Each line of the partial should be indented before rendering.","partials":{"partial":"|\n{{{content}}}\n|\n"}},{"name":"Padding Whitespace","data":{"boolean":true},"expected":"|[]|","template":"|{{> partial }}|","desc":"Superfluous in-tag whitespace should be ignored.","partials":{"partial":"[]"}}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/partials.yml b/docs/build/node_modules/hogan.js/test/spec/specs/partials.yml
new file mode 100644
index 0000000000..8c415439f2
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/partials.yml
@@ -0,0 +1,109 @@
+overview: |
+ Partial tags are used to expand an external template into the current
+ template.
+
+ The tag's content MUST be a non-whitespace character sequence NOT containing
+ the current closing delimiter.
+
+ This tag's content names the partial to inject. Set Delimiter tags MUST NOT
+ affect the parsing of a partial. The partial MUST be rendered against the
+ context stack local to the tag. If the named partial cannot be found, the
+ empty string SHOULD be used instead, as in interpolations.
+
+ Partial tags SHOULD be treated as standalone when appropriate. If this tag
+ is used standalone, any whitespace preceding the tag should treated as
+ indentation, and prepended to each line of the partial before rendering.
+tests:
+ - name: Basic Behavior
+ desc: The greater-than operator should expand to the named partial.
+ data: { }
+ template: '"{{>text}}"'
+ partials: { text: 'from partial' }
+ expected: '"from partial"'
+
+ - name: Failed Lookup
+ desc: The empty string should be used when the named partial is not found.
+ data: { }
+ template: '"{{>text}}"'
+ partials: { }
+ expected: '""'
+
+ - name: Context
+ desc: The greater-than operator should operate within the current context.
+ data: { text: 'content' }
+ template: '"{{>partial}}"'
+ partials: { partial: '*{{text}}*' }
+ expected: '"*content*"'
+
+ - name: Recursion
+ desc: The greater-than operator should properly recurse.
+ data: { content: "X", nodes: [ { content: "Y", nodes: [] } ] }
+ template: '{{>node}}'
+ partials: { node: '{{content}}<{{#nodes}}{{>node}}{{/nodes}}>' }
+ expected: 'X>'
+
+ # Whitespace Sensitivity
+
+ - name: Surrounding Whitespace
+ desc: The greater-than operator should not alter surrounding whitespace.
+ data: { }
+ template: '| {{>partial}} |'
+ partials: { partial: "\t|\t" }
+ expected: "| \t|\t |"
+
+ - name: Inline Indentation
+ desc: Whitespace should be left untouched.
+ data: { data: '|' }
+ template: " {{data}} {{> partial}}\n"
+ partials: { partial: ">\n>" }
+ expected: " | >\n>\n"
+
+ - name: Standalone Line Endings
+ desc: '"\r\n" should be considered a newline for standalone tags.'
+ data: { }
+ template: "|\r\n{{>partial}}\r\n|"
+ partials: { partial: ">" }
+ expected: "|\r\n>|"
+
+ - name: Standalone Without Previous Line
+ desc: Standalone tags should not require a newline to precede them.
+ data: { }
+ template: " {{>partial}}\n>"
+ partials: { partial: ">\n>"}
+ expected: " >\n >>"
+
+ - name: Standalone Without Newline
+ desc: Standalone tags should not require a newline to follow them.
+ data: { }
+ template: ">\n {{>partial}}"
+ partials: { partial: ">\n>" }
+ expected: ">\n >\n >"
+
+ - name: Standalone Indentation
+ desc: Each line of the partial should be indented before rendering.
+ data: { content: "<\n->" }
+ template: |
+ \
+ {{>partial}}
+ /
+ partials:
+ partial: |
+ |
+ {{{content}}}
+ |
+ expected: |
+ \
+ |
+ <
+ ->
+ |
+ /
+
+ # Whitespace Insensitivity
+
+ - name: Padding Whitespace
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { boolean: true }
+ template: "|{{> partial }}|"
+ partials: { partial: "[]" }
+ expected: '|[]|'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/sections.json b/docs/build/node_modules/hogan.js/test/spec/specs/sections.json
new file mode 100644
index 0000000000..b0aa352e10
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/sections.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Section tags and End Section tags are used in combination to wrap a section\nof the template for iteration\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Section tag MUST be followed\nby an End Section tag with the same content within the same section.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 5) Otherwise, the data is the value returned by calling the method with\n the given name.\n 6) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nFor each element in the data list, the element MUST be pushed onto the\ncontext stack, the section MUST be rendered, and the element MUST be popped\noff the context stack.\n\nSection and End Section tags SHOULD be treated as standalone when\nappropriate.\n","tests":[{"name":"Truthy","data":{"boolean":true},"expected":"\"This should be rendered.\"","template":"\"{{#boolean}}This should be rendered.{{/boolean}}\"","desc":"Truthy sections should have their contents rendered."},{"name":"Falsey","data":{"boolean":false},"expected":"\"\"","template":"\"{{#boolean}}This should not be rendered.{{/boolean}}\"","desc":"Falsey sections should have their contents omitted."},{"name":"Context","data":{"context":{"name":"Joe"}},"expected":"\"Hi Joe.\"","template":"\"{{#context}}Hi {{name}}.{{/context}}\"","desc":"Objects and hashes should be pushed onto the context stack."},{"name":"Deeply Nested Contexts","data":{"a":{"one":1},"b":{"two":2},"c":{"three":3},"d":{"four":4},"e":{"five":5}},"expected":"1\n121\n12321\n1234321\n123454321\n1234321\n12321\n121\n1\n","template":"{{#a}}\n{{one}}\n{{#b}}\n{{one}}{{two}}{{one}}\n{{#c}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{#d}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{#e}}\n{{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}\n{{/e}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{/d}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{/c}}\n{{one}}{{two}}{{one}}\n{{/b}}\n{{one}}\n{{/a}}\n","desc":"All elements on the context stack should be accessible."},{"name":"List","data":{"list":[{"item":1},{"item":2},{"item":3}]},"expected":"\"123\"","template":"\"{{#list}}{{item}}{{/list}}\"","desc":"Lists should be iterated; list items should visit the context stack."},{"name":"Empty List","data":{"list":[]},"expected":"\"\"","template":"\"{{#list}}Yay lists!{{/list}}\"","desc":"Empty lists should behave like falsey values."},{"name":"Doubled","data":{"two":"second","bool":true},"expected":"* first\n* second\n* third\n","template":"{{#bool}}\n* first\n{{/bool}}\n* {{two}}\n{{#bool}}\n* third\n{{/bool}}\n","desc":"Multiple sections per template should be permitted."},{"name":"Nested (Truthy)","data":{"bool":true},"expected":"| A B C D E |","template":"| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |","desc":"Nested truthy sections should have their contents rendered."},{"name":"Nested (Falsey)","data":{"bool":false},"expected":"| A E |","template":"| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |","desc":"Nested falsey sections should be omitted."},{"name":"Context Misses","data":{},"expected":"[]","template":"[{{#missing}}Found key 'missing'!{{/missing}}]","desc":"Failed context lookups should be considered falsey."},{"name":"Implicit Iterator - String","data":{"list":["a","b","c","d","e"]},"expected":"\"(a)(b)(c)(d)(e)\"","template":"\"{{#list}}({{.}}){{/list}}\"","desc":"Implicit iterators should directly interpolate strings."},{"name":"Implicit Iterator - Integer","data":{"list":[1,2,3,4,5]},"expected":"\"(1)(2)(3)(4)(5)\"","template":"\"{{#list}}({{.}}){{/list}}\"","desc":"Implicit iterators should cast integers to strings and interpolate."},{"name":"Implicit Iterator - Decimal","data":{"list":[1.1,2.2,3.3,4.4,5.5]},"expected":"\"(1.1)(2.2)(3.3)(4.4)(5.5)\"","template":"\"{{#list}}({{.}}){{/list}}\"","desc":"Implicit iterators should cast decimals to strings and interpolate."},{"name":"Dotted Names - Truthy","data":{"a":{"b":{"c":true}}},"expected":"\"Here\" == \"Here\"","template":"\"{{#a.b.c}}Here{{/a.b.c}}\" == \"Here\"","desc":"Dotted names should be valid for Section tags."},{"name":"Dotted Names - Falsey","data":{"a":{"b":{"c":false}}},"expected":"\"\" == \"\"","template":"\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"","desc":"Dotted names should be valid for Section tags."},{"name":"Dotted Names - Broken Chains","data":{"a":{}},"expected":"\"\" == \"\"","template":"\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"","desc":"Dotted names that cannot be resolved should be considered falsey."},{"name":"Surrounding Whitespace","data":{"boolean":true},"expected":" | \t|\t | \n","template":" | {{#boolean}}\t|\t{{/boolean}} | \n","desc":"Sections should not alter surrounding whitespace."},{"name":"Internal Whitespace","data":{"boolean":true},"expected":" | \n | \n","template":" | {{#boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n","desc":"Sections should not alter internal whitespace."},{"name":"Indented Inline Sections","data":{"boolean":true},"expected":" YES\n GOOD\n","template":" {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n","desc":"Single-line sections should not alter surrounding whitespace."},{"name":"Standalone Lines","data":{"boolean":true},"expected":"| This Is\n|\n| A Line\n","template":"| This Is\n{{#boolean}}\n|\n{{/boolean}}\n| A Line\n","desc":"Standalone lines should be removed from the template."},{"name":"Indented Standalone Lines","data":{"boolean":true},"expected":"| This Is\n|\n| A Line\n","template":"| This Is\n {{#boolean}}\n|\n {{/boolean}}\n| A Line\n","desc":"Indented standalone lines should be removed from the template."},{"name":"Standalone Line Endings","data":{"boolean":true},"expected":"|\r\n|","template":"|\r\n{{#boolean}}\r\n{{/boolean}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{"boolean":true},"expected":"#\n/","template":" {{#boolean}}\n#{{/boolean}}\n/","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{"boolean":true},"expected":"#\n/\n","template":"#{{#boolean}}\n/\n {{/boolean}}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Padding","data":{"boolean":true},"expected":"|=|","template":"|{{# boolean }}={{/ boolean }}|","desc":"Superfluous in-tag whitespace should be ignored."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/sections.yml b/docs/build/node_modules/hogan.js/test/spec/specs/sections.yml
new file mode 100644
index 0000000000..f62d9cb30a
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/sections.yml
@@ -0,0 +1,256 @@
+overview: |
+ Section tags and End Section tags are used in combination to wrap a section
+ of the template for iteration
+
+ These tags' content MUST be a non-whitespace character sequence NOT
+ containing the current closing delimiter; each Section tag MUST be followed
+ by an End Section tag with the same content within the same section.
+
+ This tag's content names the data to replace the tag. Name resolution is as
+ follows:
+ 1) Split the name on periods; the first part is the name to resolve, any
+ remaining parts should be retained.
+ 2) Walk the context stack from top to bottom, finding the first context
+ that is a) a hash containing the name as a key OR b) an object responding
+ to a method with the given name.
+ 3) If the context is a hash, the data is the value associated with the
+ name.
+ 4) If the context is an object and the method with the given name has an
+ arity of 1, the method SHOULD be called with a String containing the
+ unprocessed contents of the sections; the data is the value returned.
+ 5) Otherwise, the data is the value returned by calling the method with
+ the given name.
+ 6) If any name parts were retained in step 1, each should be resolved
+ against a context stack containing only the result from the former
+ resolution. If any part fails resolution, the result should be considered
+ falsey, and should interpolate as the empty string.
+ If the data is not of a list type, it is coerced into a list as follows: if
+ the data is truthy (e.g. `!!data == true`), use a single-element list
+ containing the data, otherwise use an empty list.
+
+ For each element in the data list, the element MUST be pushed onto the
+ context stack, the section MUST be rendered, and the element MUST be popped
+ off the context stack.
+
+ Section and End Section tags SHOULD be treated as standalone when
+ appropriate.
+tests:
+ - name: Truthy
+ desc: Truthy sections should have their contents rendered.
+ data: { boolean: true }
+ template: '"{{#boolean}}This should be rendered.{{/boolean}}"'
+ expected: '"This should be rendered."'
+
+ - name: Falsey
+ desc: Falsey sections should have their contents omitted.
+ data: { boolean: false }
+ template: '"{{#boolean}}This should not be rendered.{{/boolean}}"'
+ expected: '""'
+
+ - name: Context
+ desc: Objects and hashes should be pushed onto the context stack.
+ data: { context: { name: 'Joe' } }
+ template: '"{{#context}}Hi {{name}}.{{/context}}"'
+ expected: '"Hi Joe."'
+
+ - name: Deeply Nested Contexts
+ desc: All elements on the context stack should be accessible.
+ data:
+ a: { one: 1 }
+ b: { two: 2 }
+ c: { three: 3 }
+ d: { four: 4 }
+ e: { five: 5 }
+ template: |
+ {{#a}}
+ {{one}}
+ {{#b}}
+ {{one}}{{two}}{{one}}
+ {{#c}}
+ {{one}}{{two}}{{three}}{{two}}{{one}}
+ {{#d}}
+ {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}
+ {{#e}}
+ {{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}
+ {{/e}}
+ {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}
+ {{/d}}
+ {{one}}{{two}}{{three}}{{two}}{{one}}
+ {{/c}}
+ {{one}}{{two}}{{one}}
+ {{/b}}
+ {{one}}
+ {{/a}}
+ expected: |
+ 1
+ 121
+ 12321
+ 1234321
+ 123454321
+ 1234321
+ 12321
+ 121
+ 1
+
+ - name: List
+ desc: Lists should be iterated; list items should visit the context stack.
+ data: { list: [ { item: 1 }, { item: 2 }, { item: 3 } ] }
+ template: '"{{#list}}{{item}}{{/list}}"'
+ expected: '"123"'
+
+ - name: Empty List
+ desc: Empty lists should behave like falsey values.
+ data: { list: [ ] }
+ template: '"{{#list}}Yay lists!{{/list}}"'
+ expected: '""'
+
+ - name: Doubled
+ desc: Multiple sections per template should be permitted.
+ data: { bool: true, two: 'second' }
+ template: |
+ {{#bool}}
+ * first
+ {{/bool}}
+ * {{two}}
+ {{#bool}}
+ * third
+ {{/bool}}
+ expected: |
+ * first
+ * second
+ * third
+
+ - name: Nested (Truthy)
+ desc: Nested truthy sections should have their contents rendered.
+ data: { bool: true }
+ template: "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |"
+ expected: "| A B C D E |"
+
+ - name: Nested (Falsey)
+ desc: Nested falsey sections should be omitted.
+ data: { bool: false }
+ template: "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |"
+ expected: "| A E |"
+
+ - name: Context Misses
+ desc: Failed context lookups should be considered falsey.
+ data: { }
+ template: "[{{#missing}}Found key 'missing'!{{/missing}}]"
+ expected: "[]"
+
+ # Implicit Iterators
+
+ - name: Implicit Iterator - String
+ desc: Implicit iterators should directly interpolate strings.
+ data:
+ list: [ 'a', 'b', 'c', 'd', 'e' ]
+ template: '"{{#list}}({{.}}){{/list}}"'
+ expected: '"(a)(b)(c)(d)(e)"'
+
+ - name: Implicit Iterator - Integer
+ desc: Implicit iterators should cast integers to strings and interpolate.
+ data:
+ list: [ 1, 2, 3, 4, 5 ]
+ template: '"{{#list}}({{.}}){{/list}}"'
+ expected: '"(1)(2)(3)(4)(5)"'
+
+ - name: Implicit Iterator - Decimal
+ desc: Implicit iterators should cast decimals to strings and interpolate.
+ data:
+ list: [ 1.10, 2.20, 3.30, 4.40, 5.50 ]
+ template: '"{{#list}}({{.}}){{/list}}"'
+ expected: '"(1.1)(2.2)(3.3)(4.4)(5.5)"'
+
+ # Dotted Names
+
+ - name: Dotted Names - Truthy
+ desc: Dotted names should be valid for Section tags.
+ data: { a: { b: { c: true } } }
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == "Here"'
+ expected: '"Here" == "Here"'
+
+ - name: Dotted Names - Falsey
+ desc: Dotted names should be valid for Section tags.
+ data: { a: { b: { c: false } } }
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == ""'
+ expected: '"" == ""'
+
+ - name: Dotted Names - Broken Chains
+ desc: Dotted names that cannot be resolved should be considered falsey.
+ data: { a: { } }
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == ""'
+ expected: '"" == ""'
+
+ # Whitespace Sensitivity
+
+ - name: Surrounding Whitespace
+ desc: Sections should not alter surrounding whitespace.
+ data: { boolean: true }
+ template: " | {{#boolean}}\t|\t{{/boolean}} | \n"
+ expected: " | \t|\t | \n"
+
+ - name: Internal Whitespace
+ desc: Sections should not alter internal whitespace.
+ data: { boolean: true }
+ template: " | {{#boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n"
+ expected: " | \n | \n"
+
+ - name: Indented Inline Sections
+ desc: Single-line sections should not alter surrounding whitespace.
+ data: { boolean: true }
+ template: " {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n"
+ expected: " YES\n GOOD\n"
+
+ - name: Standalone Lines
+ desc: Standalone lines should be removed from the template.
+ data: { boolean: true }
+ template: |
+ | This Is
+ {{#boolean}}
+ |
+ {{/boolean}}
+ | A Line
+ expected: |
+ | This Is
+ |
+ | A Line
+
+ - name: Indented Standalone Lines
+ desc: Indented standalone lines should be removed from the template.
+ data: { boolean: true }
+ template: |
+ | This Is
+ {{#boolean}}
+ |
+ {{/boolean}}
+ | A Line
+ expected: |
+ | This Is
+ |
+ | A Line
+
+ - name: Standalone Line Endings
+ desc: '"\r\n" should be considered a newline for standalone tags.'
+ data: { boolean: true }
+ template: "|\r\n{{#boolean}}\r\n{{/boolean}}\r\n|"
+ expected: "|\r\n|"
+
+ - name: Standalone Without Previous Line
+ desc: Standalone tags should not require a newline to precede them.
+ data: { boolean: true }
+ template: " {{#boolean}}\n#{{/boolean}}\n/"
+ expected: "#\n/"
+
+ - name: Standalone Without Newline
+ desc: Standalone tags should not require a newline to follow them.
+ data: { boolean: true }
+ template: "#{{#boolean}}\n/\n {{/boolean}}"
+ expected: "#\n/\n"
+
+ # Whitespace Insensitivity
+
+ - name: Padding
+ desc: Superfluous in-tag whitespace should be ignored.
+ data: { boolean: true }
+ template: '|{{# boolean }}={{/ boolean }}|'
+ expected: '|=|'
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.json b/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.json
new file mode 100644
index 0000000000..3c58bf851e
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.json
@@ -0,0 +1 @@
+{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Lambdas are a special-cased data type for use in interpolations and\nsections.\n\nWhen used as the data value for an Interpolation tag, the lambda MUST be\ntreatable as an arity 0 function, and invoked as such. The returned value\nMUST be rendered against the default delimiters, then interpolated in place\nof the lambda.\n\nWhen used as the data value for a Section tag, the lambda MUST be treatable\nas an arity 1 function, and invoked as such (passing a String containing the\nunprocessed section contents). The returned value MUST be rendered against\nthe current delimiters, then interpolated in place of the section.\n","tests":[{"name":"Interpolation","data":{"lambda":{"php":"return \"world\";","clojure":"(fn [] \"world\")","__tag__":"code","perl":"sub { \"world\" }","python":"lambda: \"world\"","ruby":"proc { \"world\" }","js":"function() { return \"world\" }"}},"expected":"Hello, world!","template":"Hello, {{lambda}}!","desc":"A lambda's return value should be interpolated."},{"name":"Interpolation - Expansion","data":{"planet":"world","lambda":{"php":"return \"{{planet}}\";","clojure":"(fn [] \"{{planet}}\")","__tag__":"code","perl":"sub { \"{{planet}}\" }","python":"lambda: \"{{planet}}\"","ruby":"proc { \"{{planet}}\" }","js":"function() { return \"{{planet}}\" }"}},"expected":"Hello, world!","template":"Hello, {{lambda}}!","desc":"A lambda's return value should be parsed."},{"name":"Interpolation - Alternate Delimiters","data":{"planet":"world","lambda":{"php":"return \"|planet| => {{planet}}\";","clojure":"(fn [] \"|planet| => {{planet}}\")","__tag__":"code","perl":"sub { \"|planet| => {{planet}}\" }","python":"lambda: \"|planet| => {{planet}}\"","ruby":"proc { \"|planet| => {{planet}}\" }","js":"function() { return \"|planet| => {{planet}}\" }"}},"expected":"Hello, (|planet| => world)!","template":"{{= | | =}}\nHello, (|&lambda|)!","desc":"A lambda's return value should parse with the default delimiters."},{"name":"Interpolation - Multiple Calls","data":{"lambda":{"php":"global $calls; return ++$calls;","clojure":"(def g (atom 0)) (fn [] (swap! g inc))","__tag__":"code","perl":"sub { no strict; $calls += 1 }","python":"lambda: globals().update(calls=globals().get(\"calls\",0)+1) or calls","ruby":"proc { $calls ||= 0; $calls += 1 }","js":"function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }"}},"expected":"1 == 2 == 3","template":"{{lambda}} == {{{lambda}}} == {{lambda}}","desc":"Interpolated lambdas should not be cached."},{"name":"Escaping","data":{"lambda":{"php":"return \">\";","clojure":"(fn [] \">\")","__tag__":"code","perl":"sub { \">\" }","python":"lambda: \">\"","ruby":"proc { \">\" }","js":"function() { return \">\" }"}},"expected":"<>>","template":"<{{lambda}}{{{lambda}}}","desc":"Lambda results should be appropriately escaped."},{"name":"Section","data":{"x":"Error!","lambda":{"php":"return ($text == \"{{x}}\") ? \"yes\" : \"no\";","clojure":"(fn [text] (if (= text \"{{x}}\") \"yes\" \"no\"))","__tag__":"code","perl":"sub { $_[0] eq \"{{x}}\" ? \"yes\" : \"no\" }","python":"lambda text: text == \"{{x}}\" and \"yes\" or \"no\"","ruby":"proc { |text| text == \"{{x}}\" ? \"yes\" : \"no\" }","js":"function(txt) { return (txt == \"{{x}}\" ? \"yes\" : \"no\") }"}},"expected":"","template":"<{{#lambda}}{{x}}{{/lambda}}>","desc":"Lambdas used for sections should receive the raw section string."},{"name":"Section - Expansion","data":{"planet":"Earth","lambda":{"php":"return $text . \"{{planet}}\" . $text;","clojure":"(fn [text] (str text \"{{planet}}\" text))","__tag__":"code","perl":"sub { $_[0] . \"{{planet}}\" . $_[0] }","python":"lambda text: \"%s{{planet}}%s\" % (text, text)","ruby":"proc { |text| \"#{text}{{planet}}#{text}\" }","js":"function(txt) { return txt + \"{{planet}}\" + txt }"}},"expected":"<-Earth->","template":"<{{#lambda}}-{{/lambda}}>","desc":"Lambdas used for sections should have their results parsed."},{"name":"Section - Alternate Delimiters","data":{"planet":"Earth","lambda":{"php":"return $text . \"{{planet}} => |planet|\" . $text;","clojure":"(fn [text] (str text \"{{planet}} => |planet|\" text))","__tag__":"code","perl":"sub { $_[0] . \"{{planet}} => |planet|\" . $_[0] }","python":"lambda text: \"%s{{planet}} => |planet|%s\" % (text, text)","ruby":"proc { |text| \"#{text}{{planet}} => |planet|#{text}\" }","js":"function(txt) { return txt + \"{{planet}} => |planet|\" + txt }"}},"expected":"<-{{planet}} => Earth->","template":"{{= | | =}}<|#lambda|-|/lambda|>","desc":"Lambdas used for sections should parse with the current delimiters."},{"name":"Section - Multiple Calls","data":{"lambda":{"php":"return \"__\" . $text . \"__\";","clojure":"(fn [text] (str \"__\" text \"__\"))","__tag__":"code","perl":"sub { \"__\" . $_[0] . \"__\" }","python":"lambda text: \"__%s__\" % (text)","ruby":"proc { |text| \"__#{text}__\" }","js":"function(txt) { return \"__\" + txt + \"__\" }"}},"expected":"__FILE__ != __LINE__","template":"{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}","desc":"Lambdas used for sections should not be cached."},{"name":"Inverted Section","data":{"static":"static","lambda":{"php":"return false;","clojure":"(fn [text] false)","__tag__":"code","perl":"sub { 0 }","python":"lambda text: 0","ruby":"proc { |text| false }","js":"function(txt) { return false }"}},"expected":"<>","template":"<{{^lambda}}{{static}}{{/lambda}}>","desc":"Lambdas used for inverted sections should be considered truthy."}]}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.yml b/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.yml
new file mode 100644
index 0000000000..b9fb4d0f85
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/spec/specs/~lambdas.yml
@@ -0,0 +1,149 @@
+overview: |
+ Lambdas are a special-cased data type for use in interpolations and
+ sections.
+
+ When used as the data value for an Interpolation tag, the lambda MUST be
+ treatable as an arity 0 function, and invoked as such. The returned value
+ MUST be rendered against the default delimiters, then interpolated in place
+ of the lambda.
+
+ When used as the data value for a Section tag, the lambda MUST be treatable
+ as an arity 1 function, and invoked as such (passing a String containing the
+ unprocessed section contents). The returned value MUST be rendered against
+ the current delimiters, then interpolated in place of the section.
+tests:
+ - name: Interpolation
+ desc: A lambda's return value should be interpolated.
+ data:
+ lambda: !code
+ ruby: 'proc { "world" }'
+ perl: 'sub { "world" }'
+ js: 'function() { return "world" }'
+ php: 'return "world";'
+ python: 'lambda: "world"'
+ clojure: '(fn [] "world")'
+ template: "Hello, {{lambda}}!"
+ expected: "Hello, world!"
+
+ - name: Interpolation - Expansion
+ desc: A lambda's return value should be parsed.
+ data:
+ planet: "world"
+ lambda: !code
+ ruby: 'proc { "{{planet}}" }'
+ perl: 'sub { "{{planet}}" }'
+ js: 'function() { return "{{planet}}" }'
+ php: 'return "{{planet}}";'
+ python: 'lambda: "{{planet}}"'
+ clojure: '(fn [] "{{planet}}")'
+ template: "Hello, {{lambda}}!"
+ expected: "Hello, world!"
+
+ - name: Interpolation - Alternate Delimiters
+ desc: A lambda's return value should parse with the default delimiters.
+ data:
+ planet: "world"
+ lambda: !code
+ ruby: 'proc { "|planet| => {{planet}}" }'
+ perl: 'sub { "|planet| => {{planet}}" }'
+ js: 'function() { return "|planet| => {{planet}}" }'
+ php: 'return "|planet| => {{planet}}";'
+ python: 'lambda: "|planet| => {{planet}}"'
+ clojure: '(fn [] "|planet| => {{planet}}")'
+ template: "{{= | | =}}\nHello, (|&lambda|)!"
+ expected: "Hello, (|planet| => world)!"
+
+ - name: Interpolation - Multiple Calls
+ desc: Interpolated lambdas should not be cached.
+ data:
+ lambda: !code
+ ruby: 'proc { $calls ||= 0; $calls += 1 }'
+ perl: 'sub { no strict; $calls += 1 }'
+ js: 'function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }'
+ php: 'global $calls; return ++$calls;'
+ python: 'lambda: globals().update(calls=globals().get("calls",0)+1) or calls'
+ clojure: '(def g (atom 0)) (fn [] (swap! g inc))'
+ template: '{{lambda}} == {{{lambda}}} == {{lambda}}'
+ expected: '1 == 2 == 3'
+
+ - name: Escaping
+ desc: Lambda results should be appropriately escaped.
+ data:
+ lambda: !code
+ ruby: 'proc { ">" }'
+ perl: 'sub { ">" }'
+ js: 'function() { return ">" }'
+ php: 'return ">";'
+ python: 'lambda: ">"'
+ clojure: '(fn [] ">")'
+ template: "<{{lambda}}{{{lambda}}}"
+ expected: "<>>"
+
+ - name: Section
+ desc: Lambdas used for sections should receive the raw section string.
+ data:
+ x: 'Error!'
+ lambda: !code
+ ruby: 'proc { |text| text == "{{x}}" ? "yes" : "no" }'
+ perl: 'sub { $_[0] eq "{{x}}" ? "yes" : "no" }'
+ js: 'function(txt) { return (txt == "{{x}}" ? "yes" : "no") }'
+ php: 'return ($text == "{{x}}") ? "yes" : "no";'
+ python: 'lambda text: text == "{{x}}" and "yes" or "no"'
+ clojure: '(fn [text] (if (= text "{{x}}") "yes" "no"))'
+ template: "<{{#lambda}}{{x}}{{/lambda}}>"
+ expected: ""
+
+ - name: Section - Expansion
+ desc: Lambdas used for sections should have their results parsed.
+ data:
+ planet: "Earth"
+ lambda: !code
+ ruby: 'proc { |text| "#{text}{{planet}}#{text}" }'
+ perl: 'sub { $_[0] . "{{planet}}" . $_[0] }'
+ js: 'function(txt) { return txt + "{{planet}}" + txt }'
+ php: 'return $text . "{{planet}}" . $text;'
+ python: 'lambda text: "%s{{planet}}%s" % (text, text)'
+ clojure: '(fn [text] (str text "{{planet}}" text))'
+ template: "<{{#lambda}}-{{/lambda}}>"
+ expected: "<-Earth->"
+
+ - name: Section - Alternate Delimiters
+ desc: Lambdas used for sections should parse with the current delimiters.
+ data:
+ planet: "Earth"
+ lambda: !code
+ ruby: 'proc { |text| "#{text}{{planet}} => |planet|#{text}" }'
+ perl: 'sub { $_[0] . "{{planet}} => |planet|" . $_[0] }'
+ js: 'function(txt) { return txt + "{{planet}} => |planet|" + txt }'
+ php: 'return $text . "{{planet}} => |planet|" . $text;'
+ python: 'lambda text: "%s{{planet}} => |planet|%s" % (text, text)'
+ clojure: '(fn [text] (str text "{{planet}} => |planet|" text))'
+ template: "{{= | | =}}<|#lambda|-|/lambda|>"
+ expected: "<-{{planet}} => Earth->"
+
+ - name: Section - Multiple Calls
+ desc: Lambdas used for sections should not be cached.
+ data:
+ lambda: !code
+ ruby: 'proc { |text| "__#{text}__" }'
+ perl: 'sub { "__" . $_[0] . "__" }'
+ js: 'function(txt) { return "__" + txt + "__" }'
+ php: 'return "__" . $text . "__";'
+ python: 'lambda text: "__%s__" % (text)'
+ clojure: '(fn [text] (str "__" text "__"))'
+ template: '{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}'
+ expected: '__FILE__ != __LINE__'
+
+ - name: Inverted Section
+ desc: Lambdas used for inverted sections should be considered truthy.
+ data:
+ static: 'static'
+ lambda: !code
+ ruby: 'proc { |text| false }'
+ perl: 'sub { 0 }'
+ js: 'function(txt) { return false }'
+ php: 'return false;'
+ python: 'lambda text: 0'
+ clojure: '(fn [text] false)'
+ template: "<{{^lambda}}{{static}}{{/lambda}}>"
+ expected: "<>"
diff --git a/docs/build/node_modules/hogan.js/test/templates/list.mustache b/docs/build/node_modules/hogan.js/test/templates/list.mustache
new file mode 100644
index 0000000000..9bb653a3be
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/test/templates/list.mustache
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/tools/release.js b/docs/build/node_modules/hogan.js/tools/release.js
new file mode 100644
index 0000000000..dda0d3f871
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/tools/release.js
@@ -0,0 +1,74 @@
+/*
+ * 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 fs = require('fs');
+var path = require('path');
+var Hogan = require(__dirname + '/../lib/hogan');
+var minlicense = '/**\n* @preserve Copyright 2012 Twitter, Inc.\n* @license http://www.apache.org/licenses/LICENSE-2.0.txt\n*/\n';
+
+function read(path) {
+ return fs.readFileSync(path).toString()
+}
+
+// Good enough for little js files
+function copy(src, dst) {
+ return fs.writeFileSync(dst, read(src));
+}
+
+function uglify(src, dst) {
+ var jsp = require("uglify-js").parser;
+ var pro = require("uglify-js").uglify;
+ var orig_code = read(src);
+ var ast = jsp.parse(orig_code); // parse code and get the initial AST
+ ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+ fs.writeFileSync(dst, minlicense + pro.gen_code(ast));
+}
+
+var packageJSON = JSON.parse(read('package.json'));
+var version = packageJSON.version.substring(0, packageJSON.version.indexOf('-'));
+
+function removeFirstComment(text) {
+ return text.substring(text.indexOf('*/') + 2);
+}
+
+var context = {
+ template: removeFirstComment(read(__dirname + '/../lib/template.js')),
+ compiler: removeFirstComment(read(__dirname + '/../lib/compiler.js'))
+};
+
+var wrapperPath = '/../wrappers/';
+var wrappers = fs.readdirSync(__dirname + wrapperPath).map(function(f) {
+ return __dirname + wrapperPath + f;
+});
+
+var distPath = __dirname + '/../dist/';
+wrappers.forEach(function(wrapper) {
+ var tail = path.basename(wrapper, '.mustache');
+ var target = distPath + 'hogan-' + version + '.' + tail;
+ var uglified = distPath + 'hogan-' + version + '.min.' + tail;
+ fs.writeFileSync(target, Hogan.compile(read(wrapper)).render(context));
+ uglify(target, uglified);
+});
+
+// Also release Hogan.Template on its own.
+var templateTarget = distPath + 'template-' + version + '.js';
+fs.writeFileSync(templateTarget, read(__dirname + '/../lib/template.js'));
+uglify(templateTarget, distPath + 'template-' + version + '.min.js');
+
+// Add packageJSON to node distribution
+packageJSON.version = version;
+fs.writeFileSync(__dirname + '/../dist/nodejs/package.json',
+ JSON.stringify(packageJSON, null, " "));
diff --git a/docs/build/node_modules/hogan.js/tools/web_templates.js b/docs/build/node_modules/hogan.js/tools/web_templates.js
new file mode 100644
index 0000000000..f00acd3c3e
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/tools/web_templates.js
@@ -0,0 +1,32 @@
+/*
+ * 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 = require(__dirname + '/../lib/hogan.js');
+var fs = require('fs');
+var path = require('path');
+
+// Substitute variables in the homepage with values from package.json
+var homeTemplatePath = __dirname + '/../build/gh-pages/index.html.mustache';
+var contextPath = __dirname + '/../dist/nodejs/package.json';
+
+var homepage = fs.readFileSync(homeTemplatePath).toString();
+var context = JSON.parse(fs.readFileSync(contextPath).toString());
+
+var template = Hogan.compile(homepage);
+
+fs.writeFileSync(path.dirname(homeTemplatePath) + '/index.html',
+ template.render(context));
+
+fs.unlinkSync(homeTemplatePath);
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/1.0.0/hogan.js b/docs/build/node_modules/hogan.js/web/1.0.0/hogan.js
new file mode 100644
index 0000000000..09170d635f
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/1.0.0/hogan.js
@@ -0,0 +1,500 @@
+/*
+ * 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 HoganTemplate = (function () {
+
+ function constructor(text) {
+ this.text = text;
+ };
+
+ constructor.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials) {
+ return this.r(context, partials);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ return partial.render(context, partials);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '';
+ var tail = context[context.length - 1];
+ if (!isArray(tail)) {
+ buf = section(context, partials);
+ return buf;
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end) {
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (!inverted && typeof val == 'function') {
+ val = this.ls(val, ctx, partials, start, end);
+ }
+
+ var pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ var names = key.split('.');
+ var val = this.f(names[0], ctx, partials, returnFound);
+ var cx = null;
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false;
+ var v = null;
+ var found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text) {
+ var t = val.call(cx, text, function(t) {
+ return Hogan.compile(t).render(cx);
+ });
+ var s = Hogan.compile(t.toString()).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, start, end) {
+ var cx = ctx[ctx.length - 1];
+ if (val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end));
+ }
+ var t = val.call(cx);
+ if (typeof t == 'function') {
+ return this.ho(t, cx, partials, this.text.substring(start, end));
+ }
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ return Hogan.compile(val.call(cx).toString()).render(cx, partials);
+ }
+ };
+
+ var rAmp = /&/g, rLt = //g, rApos =/\'/g,
+ rQuot = /\"/g, hChars =/[&<>\"\']/;
+ function hoganEscape(str) {
+ var s = String(str === null ? '' : str);
+ return hChars.test(s) ? s.replace(rAmp,'&')
+ .replace(rLt,'<').replace(rGt,'>')
+ .replace(rApos,''').replace(rQuot, '"') : s;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ }
+
+ return constructor;
+})();
+
+var Hogan = (function () {
+
+ function scan(text) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) == null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'})
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag;
+ var closeIndex = text.indexOf(close, index);
+ var delimiters = trim(text.substring(text.indexOf('=', index) + 1,
+ closeIndex)).split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ return closeIndex + close.length - 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text[i] == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text[i];
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ var tag = tagTypes[text[i + 1]];
+ tagType = tag ? text[i + 1] : '_v';
+ seenTag = i;
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ } else {
+ if (tagChange(ctag, text, i)) {
+ i += ctag.length - 1;
+ tokens.push({tag: tagType, n: trim(buf),
+ i: (tagType == '/') ? seenTag - 1 : i + 1});
+ buf = '';
+ state = IN_TEXT;
+ if (tagType == '{') {
+ i++;
+ }
+ } else {
+ buf += text[i];
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/;
+
+ var tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ function tagChange(tag, text, index) {
+ if (text[index] != tag[0]) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text[index + i] != tag[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' ||
+ isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length == 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function generate(tree, text, options) {
+ var code = 'var c = [cx];var b = "";var _ = this;' +
+ walk(tree) + 'return b;';
+ if (options.asString) {
+ return 'function(cx,p){' + code + ';};';
+ }
+
+ var template = new HoganTemplate(text);
+ template.r = new Function('cx', 'p', code);
+ return template;
+ }
+
+ var rQuot = /\"/g, rNewline = /\n/g, rCr = /\r/g, rSlash = /\\/g;
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r')
+ };
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i].n);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('\n');
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text(tree[i]);
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end) {
+ var code = 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),';
+ code += 'c,p,0,' + start + ',' + end + ')){';
+ code += 'b += _.rs(c,p,';
+ code += 'function(c,p){ var b = "";';
+ code += walk(nodes);
+ code += 'return b;});c.pop();}';
+ code += 'else{b += _.b; _.b = ""};';
+ return code;
+ }
+
+ function invertedSection(nodes, id, method) {
+ var code = 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0)){';
+ code += walk(nodes);
+ code += '};';
+ return code;
+ }
+
+ function partial(id) {
+ return 'b += _.rp("' + esc(id) + '",c[c.length - 1],p);';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += "' + esc(id) + '";';
+ }
+
+ return ({
+ scan: scan,
+
+ parse: function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ cache: {},
+
+ compile: function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ options = options || {};
+
+ var t = this.cache[text];
+ if (t) {
+ return t;
+ }
+ t = generate(this.parse(scan(text), options), text, options);
+ return this.cache[text] = t;
+ }
+ });
+})();
+
+// Export the hogan constructor for Node.js and CommonJS.
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Hogan;
+ module.exports.Template = HoganTemplate;
+} else if (typeof exports !== 'undefined') {
+ exports.Hogan = Hogan;
+ exports.HoganTemplate = HoganTemplate;
+}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/1.0.0/hogan.min.js b/docs/build/node_modules/hogan.js/web/1.0.0/hogan.min.js
new file mode 100644
index 0000000000..13ec535aae
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/1.0.0/hogan.min.js
@@ -0,0 +1,14 @@
+/*
+ * 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 HoganTemplate=function(){function a(a){this.text=a}function h(a){var h=String(a===null?"":a);return g.test(h)?h.replace(b,"&").replace(c,"<").replace(d,">").replace(e,"'").replace(f,"""):h}a.prototype={r:function(a,b){return""},v:h,render:function(a,b){return this.r(a,b)},rp:function(a,b,c,d){var e=c[a];return e?e.render(b,c):""},rs:function(a,b,c){var d="",e=a[a.length-1];if(!i(e))return d=c(a,b),d;for(var f=0;f=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d){var e=a.call(b,d,function(a){return Hogan.compile(a).render(b)}),f=Hogan.compile(e.toString()).render(b,c);return this.b=f,!1},b:"",ls:function(a,b,c,d,e){var f=b[b.length-1];if(a.length>0)return this.ho(a,f,c,this.text.substring(d,e));var g=a.call(f);return typeof g=="function"?this.ho(g,f,c,this.text.substring(d,e)):g},lv:function(a,b,c){var d=b[b.length-1];return Hogan.compile(a.call(d).toString()).render(d,c)}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"};return a}(),Hogan=function(){function a(a){function s(){l.length>0&&(m.push(new String(l)),l="")}function t(){var a=!0;for(var b=p;b0){j=a.shift();if(j.tag=="#"||j.tag=="^"||g(j,d))c.push(j),j.nodes=f(a,j.tag,c,d),e.push(j);else{if(j.tag=="/"){if(c.length==0)throw new Error("Closing tag without opener: /"+j.n);i=c.pop();if(j.n!=i.n&&!h(j.n,i.n,d))throw new Error("Nesting error: "+i.n+" vs. "+j.n);return i.end=j.i,e}e.push(j)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function g(a,b){for(var c=0,d=b.length;c"?b+=s(a[c].n):e=="{"||e=="&"?b+=t(a[c].n,o(a[c].n)):e=="\n"?b+=v("\n"):e=="_v"?b+=u(a[c].n,o(a[c].n)):e===undefined&&(b+=v(a[c]))}return b}function q(a,b,c,d,e){var f="if(_.s(_."+c+'("'+n(b)+'",c,p,1),';return f+="c,p,0,"+d+","+e+")){",f+="b += _.rs(c,p,",f+='function(c,p){ var b = "";',f+=p(a),f+="return b;});c.pop();}",f+='else{b += _.b; _.b = ""};',f}function r(a,b,c){var d="if (!_.s(_."+c+'("'+n(b)+'",c,p,1),c,p,1,0,0)){';return d+=p(a),d+="};",d}function s(a){return'b += _.rp("'+n(a)+'",c[c.length - 1],p);'}function t(a,b){return"b += (_."+b+'("'+n(a)+'",c,p,0));'}function u(a,b){return"b += (_.v(_."+b+'("'+n(a)+'",c,p,0)));'}function v(a){return'b += "'+n(a)+'";'}var c=/\S/,d={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10},j=/\"/g,k=/\n/g,l=/\r/g,m=/\\/g;return{scan:a,parse:function(a,b){return b=b||{},f(a,"",[],b.sectionTags||[])},cache:{},compile:function(b,c){c=c||{};var d=this.cache[b];return d?d:(d=i(this.parse(a(b),c),b,c),this.cache[b]=d)}}}();typeof module!="undefined"&&module.exports?(module.exports=Hogan,module.exports.Template=HoganTemplate):typeof exports!="undefined"&&(exports.Hogan=Hogan,exports.HoganTemplate=HoganTemplate);
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.js b/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.js
new file mode 100644
index 0000000000..09170d635f
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.js
@@ -0,0 +1,500 @@
+/*
+ * 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 HoganTemplate = (function () {
+
+ function constructor(text) {
+ this.text = text;
+ };
+
+ constructor.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials) {
+ return this.r(context, partials);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ return partial.render(context, partials);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '';
+ var tail = context[context.length - 1];
+ if (!isArray(tail)) {
+ buf = section(context, partials);
+ return buf;
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end) {
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (!inverted && typeof val == 'function') {
+ val = this.ls(val, ctx, partials, start, end);
+ }
+
+ var pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ var names = key.split('.');
+ var val = this.f(names[0], ctx, partials, returnFound);
+ var cx = null;
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false;
+ var v = null;
+ var found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text) {
+ var t = val.call(cx, text, function(t) {
+ return Hogan.compile(t).render(cx);
+ });
+ var s = Hogan.compile(t.toString()).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, start, end) {
+ var cx = ctx[ctx.length - 1];
+ if (val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end));
+ }
+ var t = val.call(cx);
+ if (typeof t == 'function') {
+ return this.ho(t, cx, partials, this.text.substring(start, end));
+ }
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ return Hogan.compile(val.call(cx).toString()).render(cx, partials);
+ }
+ };
+
+ var rAmp = /&/g, rLt = //g, rApos =/\'/g,
+ rQuot = /\"/g, hChars =/[&<>\"\']/;
+ function hoganEscape(str) {
+ var s = String(str === null ? '' : str);
+ return hChars.test(s) ? s.replace(rAmp,'&')
+ .replace(rLt,'<').replace(rGt,'>')
+ .replace(rApos,''').replace(rQuot, '"') : s;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ }
+
+ return constructor;
+})();
+
+var Hogan = (function () {
+
+ function scan(text) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) == null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'})
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag;
+ var closeIndex = text.indexOf(close, index);
+ var delimiters = trim(text.substring(text.indexOf('=', index) + 1,
+ closeIndex)).split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ return closeIndex + close.length - 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text[i] == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text[i];
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ var tag = tagTypes[text[i + 1]];
+ tagType = tag ? text[i + 1] : '_v';
+ seenTag = i;
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ } else {
+ if (tagChange(ctag, text, i)) {
+ i += ctag.length - 1;
+ tokens.push({tag: tagType, n: trim(buf),
+ i: (tagType == '/') ? seenTag - 1 : i + 1});
+ buf = '';
+ state = IN_TEXT;
+ if (tagType == '{') {
+ i++;
+ }
+ } else {
+ buf += text[i];
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/;
+
+ var tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ function tagChange(tag, text, index) {
+ if (text[index] != tag[0]) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text[index + i] != tag[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' ||
+ isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length == 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function generate(tree, text, options) {
+ var code = 'var c = [cx];var b = "";var _ = this;' +
+ walk(tree) + 'return b;';
+ if (options.asString) {
+ return 'function(cx,p){' + code + ';};';
+ }
+
+ var template = new HoganTemplate(text);
+ template.r = new Function('cx', 'p', code);
+ return template;
+ }
+
+ var rQuot = /\"/g, rNewline = /\n/g, rCr = /\r/g, rSlash = /\\/g;
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r')
+ };
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i].n);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('\n');
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text(tree[i]);
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end) {
+ var code = 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),';
+ code += 'c,p,0,' + start + ',' + end + ')){';
+ code += 'b += _.rs(c,p,';
+ code += 'function(c,p){ var b = "";';
+ code += walk(nodes);
+ code += 'return b;});c.pop();}';
+ code += 'else{b += _.b; _.b = ""};';
+ return code;
+ }
+
+ function invertedSection(nodes, id, method) {
+ var code = 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0)){';
+ code += walk(nodes);
+ code += '};';
+ return code;
+ }
+
+ function partial(id) {
+ return 'b += _.rp("' + esc(id) + '",c[c.length - 1],p);';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += "' + esc(id) + '";';
+ }
+
+ return ({
+ scan: scan,
+
+ parse: function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ cache: {},
+
+ compile: function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ options = options || {};
+
+ var t = this.cache[text];
+ if (t) {
+ return t;
+ }
+ t = generate(this.parse(scan(text), options), text, options);
+ return this.cache[text] = t;
+ }
+ });
+})();
+
+// Export the hogan constructor for Node.js and CommonJS.
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Hogan;
+ module.exports.Template = HoganTemplate;
+} else if (typeof exports !== 'undefined') {
+ exports.Hogan = Hogan;
+ exports.HoganTemplate = HoganTemplate;
+}
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.min.js b/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.min.js
new file mode 100644
index 0000000000..13ec535aae
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.0/hogan.min.js
@@ -0,0 +1,14 @@
+/*
+ * 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 HoganTemplate=function(){function a(a){this.text=a}function h(a){var h=String(a===null?"":a);return g.test(h)?h.replace(b,"&").replace(c,"<").replace(d,">").replace(e,"'").replace(f,"""):h}a.prototype={r:function(a,b){return""},v:h,render:function(a,b){return this.r(a,b)},rp:function(a,b,c,d){var e=c[a];return e?e.render(b,c):""},rs:function(a,b,c){var d="",e=a[a.length-1];if(!i(e))return d=c(a,b),d;for(var f=0;f=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d){var e=a.call(b,d,function(a){return Hogan.compile(a).render(b)}),f=Hogan.compile(e.toString()).render(b,c);return this.b=f,!1},b:"",ls:function(a,b,c,d,e){var f=b[b.length-1];if(a.length>0)return this.ho(a,f,c,this.text.substring(d,e));var g=a.call(f);return typeof g=="function"?this.ho(g,f,c,this.text.substring(d,e)):g},lv:function(a,b,c){var d=b[b.length-1];return Hogan.compile(a.call(d).toString()).render(d,c)}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"};return a}(),Hogan=function(){function a(a){function s(){l.length>0&&(m.push(new String(l)),l="")}function t(){var a=!0;for(var b=p;b0){j=a.shift();if(j.tag=="#"||j.tag=="^"||g(j,d))c.push(j),j.nodes=f(a,j.tag,c,d),e.push(j);else{if(j.tag=="/"){if(c.length==0)throw new Error("Closing tag without opener: /"+j.n);i=c.pop();if(j.n!=i.n&&!h(j.n,i.n,d))throw new Error("Nesting error: "+i.n+" vs. "+j.n);return i.end=j.i,e}e.push(j)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function g(a,b){for(var c=0,d=b.length;c"?b+=s(a[c].n):e=="{"||e=="&"?b+=t(a[c].n,o(a[c].n)):e=="\n"?b+=v("\n"):e=="_v"?b+=u(a[c].n,o(a[c].n)):e===undefined&&(b+=v(a[c]))}return b}function q(a,b,c,d,e){var f="if(_.s(_."+c+'("'+n(b)+'",c,p,1),';return f+="c,p,0,"+d+","+e+")){",f+="b += _.rs(c,p,",f+='function(c,p){ var b = "";',f+=p(a),f+="return b;});c.pop();}",f+='else{b += _.b; _.b = ""};',f}function r(a,b,c){var d="if (!_.s(_."+c+'("'+n(b)+'",c,p,1),c,p,1,0,0)){';return d+=p(a),d+="};",d}function s(a){return'b += _.rp("'+n(a)+'",c[c.length - 1],p);'}function t(a,b){return"b += (_."+b+'("'+n(a)+'",c,p,0));'}function u(a,b){return"b += (_.v(_."+b+'("'+n(a)+'",c,p,0)));'}function v(a){return'b += "'+n(a)+'";'}var c=/\S/,d={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10},j=/\"/g,k=/\n/g,l=/\r/g,m=/\\/g;return{scan:a,parse:function(a,b){return b=b||{},f(a,"",[],b.sectionTags||[])},cache:{},compile:function(b,c){c=c||{};var d=this.cache[b];return d?d:(d=i(this.parse(a(b),c),b,c),this.cache[b]=d)}}}();typeof module!="undefined"&&module.exports?(module.exports=Hogan,module.exports.Template=HoganTemplate):typeof exports!="undefined"&&(exports.Hogan=Hogan,exports.HoganTemplate=HoganTemplate);
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.js b/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.js
new file mode 100644
index 0000000000..4f6f6d22f1
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.js
@@ -0,0 +1,545 @@
+/*
+ * 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 HoganTemplate = (function () {
+
+ function constructor(text) {
+ this.text = text;
+ }
+
+ constructor.prototype = {
+
+ // render: replaced by generated code.
+ r: function (context, partials, indent) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials, indent) {
+ return this.r(context, partials, indent);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ return partial.r(context, partials, indent);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '',
+ tail = context[context.length - 1];
+
+ if (!isArray(tail)) {
+ return buf = section(context, partials);
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end, tags) {
+ var pass;
+
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (!inverted && typeof val == 'function') {
+ val = this.ls(val, ctx, partials, start, end, tags);
+ }
+
+ pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+
+ var names = key.split('.'),
+ val = this.f(names[0], ctx, partials, returnFound),
+ cx = null;
+
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false,
+ v = null,
+ found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var t = val.call(cx, text, function(t) {
+ return Hogan.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = Hogan.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = val.call(cx);
+
+ if (val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ if (typeof t == 'function') {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ return Hogan.compile(val.call(cx).toString()).render(cx, partials);
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String(str === null ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+ return constructor;
+
+})();
+
+var Hogan = (function () {
+
+ // Setup regex assignments
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/,
+ rQuot = /\"/g,
+ rNewline = /\n/g,
+ rCr = /\r/g,
+ rSlash = /\\/g,
+ tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ function scan(text, delimiters) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ tag = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart, next; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ if ((next = tokens[j+1]) && next.tag == '>') {
+ // set indent to token value
+ next.indent = tokens[j].toString()
+ }
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'});
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag,
+ closeIndex = text.indexOf(close, index),
+ delimiters = trim(
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
+ ).split(' ');
+
+ otag = delimiters[0];
+ ctag = delimiters[1];
+
+ return closeIndex + close.length - 1;
+ }
+
+ if (delimiters) {
+ delimiters = delimiters.split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text.charAt(i) == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ tag = tagTypes[text.charAt(i + 1)];
+ tagType = tag ? text.charAt(i + 1) : '_v';
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ seenTag = i;
+ } else {
+ if (tagChange(ctag, text, i)) {
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
+ buf = '';
+ i += ctag.length - 1;
+ state = IN_TEXT;
+ if (tagType == '{') {
+ i++;
+ }
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ function tagChange(tag, text, index) {
+ if (text.charAt(index) != tag.charAt(0)) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text.charAt(index + i) != tag.charAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length === 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function generate(tree, text, options) {
+ var code = 'i = i || "";var c = [cx];var b = i + "";var _ = this;'
+ + walk(tree)
+ + 'return b;';
+
+ if (options.asString) {
+ return 'function(cx,p,i){' + code + ';}';
+ }
+
+ var template = new HoganTemplate(text);
+ template.r = new Function('cx', 'p', 'i', code);
+ return template;
+ }
+
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r');
+ }
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i]);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text('"' + esc(tree[i]) + '"');
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end, tags) {
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
+ 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
+ 'b += _.rs(c,p,' +
+ 'function(c,p){ var b = "";' +
+ walk(nodes) +
+ 'return b;});c.pop();}' +
+ 'else{b += _.b; _.b = ""};';
+ }
+
+ function invertedSection(nodes, id, method) {
+ return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
+ walk(nodes) +
+ '};';
+ }
+
+ function partial(tok) {
+ return 'b += _.rp("' + esc(tok.n) + '",c[c.length - 1],p,"' + (tok.indent || '') + '");';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += ' + id + ';';
+ }
+
+ return ({
+ scan: scan,
+
+ parse: function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ cache: {},
+
+ compile: function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ // delimiters: A string that overrides the default delimiters.
+ // Example: "<% %>"
+ //
+ options = options || {};
+
+ var t = this.cache[text];
+
+ if (t) {
+ return t;
+ }
+
+ t = generate(this.parse(scan(text, options.delimiters), options), text, options);
+ return this.cache[text] = t;
+ }
+ });
+})();
+
+// Export the hogan constructor for Node.js and CommonJS.
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Hogan;
+ module.exports.Template = HoganTemplate;
+} else if (typeof define === 'function' && define.amd) {
+ define(function () { return Hogan; });
+} else if (typeof exports !== 'undefined') {
+ exports.Hogan = Hogan;
+ exports.HoganTemplate = HoganTemplate;
+}
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.min.js b/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.min.js
new file mode 100644
index 0000000000..0af8a36fdd
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.3/hogan.min.js
@@ -0,0 +1,5 @@
+/**
+* @preserve Copyright 2012 Twitter, Inc.
+* @license http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+var HoganTemplate=function(){function a(a){this.text=a}function h(a){return a=String(a===null?"":a),g.test(a)?a.replace(b,"&").replace(c,"<").replace(d,">").replace(e,"'").replace(f,"""):a}a.prototype={r:function(a,b,c){return""},v:h,render:function(b,c,d){return this.r(b,c,d)},rp:function(a,b,c,d){var e=c[a];return e?e.r(b,c,d):""},rs:function(a,b,c){var d="",e=a[a.length-1];if(!i(e))return d=c(a,b);for(var f=0;f=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=a.call(b,d,function(a){return Hogan.compile(a,{delimiters:e}).render(b,c)}),g=Hogan.compile(f.toString(),{delimiters:e}).render(b,c);return this.b=g,!1},b:"",ls:function(a,b,c,d,e,f){var g=b[b.length-1],h=a.call(g);return a.length>0?this.ho(a,g,c,this.text.substring(d,e),f):typeof h=="function"?this.ho(h,g,c,this.text.substring(d,e),f):h},lv:function(a,b,c){var d=b[b.length-1];return Hogan.compile(a.call(d).toString()).render(d,c)}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"};return a}(),Hogan=function(){function g(b,c){function u(){n.length>0&&(o.push(new String(n)),n="")}function v(){var b=!0;for(var c=r;c"&&(d.indent=o[c].toString()),o.splice(c,1));else b||o.push({tag:"\n"});p=!1,r=o.length}function x(a,b){var c="="+t,d=a.indexOf(c,b),e=h(a.substring(a.indexOf("=",b)+1,d)).split(" ");return s=e[0],t=e[1],d+c.length-1}var d=b.length,e=0,g=1,j=2,k=e,l=null,m=null,n="",o=[],p=!1,q=0,r=0,s="{{",t="}}";c&&(c=c.split(" "),s=c[0],t=c[1]);for(q=0;q0){g=a.shift();if(g.tag=="#"||g.tag=="^"||k(g,d))c.push(g),g.nodes=j(a,g.tag,c,d),e.push(g);else{if(g.tag=="/"){if(c.length===0)throw new Error("Closing tag without opener: /"+g.n);f=c.pop();if(g.n!=f.n&&!l(g.n,f.n,d))throw new Error("Nesting error: "+f.n+" vs. "+g.n);return f.end=g.i,e}e.push(g)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function k(a,b){for(var c=0,d=b.length;c"?b+=s(a[c]):e=="{"||e=="&"?b+=t(a[c].n,o(a[c].n)):e=="\n"?b+=v('"\\n"'+(a.length-1==c?"":" + i")):e=="_v"?b+=u(a[c].n,o(a[c].n)):e===undefined&&(b+=v('"'+n(a[c])+'"'))}return b}function q(a,b,c,d,e,f){return"if(_.s(_."+c+'("'+n(b)+'",c,p,1),'+"c,p,0,"+d+","+e+', "'+f+'")){'+"b += _.rs(c,p,"+'function(c,p){ var b = "";'+p(a)+"return b;});c.pop();}"+'else{b += _.b; _.b = ""};'}function r(a,b,c){return"if (!_.s(_."+c+'("'+n(b)+'",c,p,1),c,p,1,0,0,"")){'+p(a)+"};"}function s(a){return'b += _.rp("'+n(a.n)+'",c[c.length - 1],p,"'+(a.indent||"")+'");'}function t(a,b){return"b += (_."+b+'("'+n(a)+'",c,p,0));'}function u(a,b){return"b += (_.v(_."+b+'("'+n(a)+'",c,p,0)));'}function v(a){return"b += "+a+";"}var a=/\S/,b=/\"/g,c=/\n/g,d=/\r/g,e=/\\/g,f={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10};return{scan:g,parse:function(a,b){return b=b||{},j(a,"",[],b.sectionTags||[])},cache:{},compile:function(a,b){b=b||{};var c=this.cache[a];return c?c:(c=m(this.parse(g(a,b.delimiters),b),a,b),this.cache[a]=c)}}}();typeof module!="undefined"&&module.exports?(module.exports=Hogan,module.exports.Template=HoganTemplate):typeof define=="function"&&define.amd?define(function(){return Hogan}):typeof exports!="undefined"&&(exports.Hogan=Hogan,exports.HoganTemplate=HoganTemplate)
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.amd.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.amd.js
new file mode 100644
index 0000000000..ec55a5d3ab
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.amd.js
@@ -0,0 +1,576 @@
+/*
+ * 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 = {};
+
+(function (Hogan) {
+ Hogan.Template = function constructor(renderFunc, text, compiler) {
+ if (renderFunc) {
+ this.r = renderFunc;
+ }
+ this.c = compiler;
+ this.text = text || '';
+ }
+
+ Hogan.Template.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials, indent) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials, indent) {
+ return this.ri([context], partials || {}, indent);
+ },
+
+ // render internal -- a hook for overrides that catches partials too
+ ri: function (context, partials, indent) {
+ return this.r(context, partials, indent);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ if (this.c && typeof partial == 'string') {
+ partial = this.c.compile(partial);
+ }
+
+ return partial.ri(context, partials, indent);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '',
+ tail = context[context.length - 1];
+
+ if (!isArray(tail)) {
+ return buf = section(context, partials);
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end, tags) {
+ var pass;
+
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (typeof val == 'function') {
+ val = this.ls(val, ctx, partials, inverted, start, end, tags);
+ }
+
+ pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ var names = key.split('.'),
+ val = this.f(names[0], ctx, partials, returnFound),
+ cx = null;
+
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false,
+ v = null,
+ found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var compiler = this.c;
+ var t = val.call(cx, text, function(t) {
+ return compiler.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = null;
+
+ if (!inverted && this.c && val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ t = val.call(cx);
+
+ if (typeof t == 'function') {
+ if (inverted) {
+ return true;
+ } else if (this.c) {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ var result = val.call(cx);
+ if (typeof result == 'function') {
+ result = result.call(cx);
+ }
+ result = result.toString();
+
+ if (this.c && ~result.indexOf("{{")) {
+ return this.c.compile(result).render(cx, partials);
+ }
+
+ return result;
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String((str === null || str === undefined) ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+
+
+(function (Hogan) {
+ // Setup regex assignments
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/,
+ rQuot = /\"/g,
+ rNewline = /\n/g,
+ rCr = /\r/g,
+ rSlash = /\\/g,
+ tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ Hogan.scan = function scan(text, delimiters) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ tag = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart, next; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ if ((next = tokens[j+1]) && next.tag == '>') {
+ // set indent to token value
+ next.indent = tokens[j].toString()
+ }
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'});
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag,
+ closeIndex = text.indexOf(close, index),
+ delimiters = trim(
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
+ ).split(' ');
+
+ otag = delimiters[0];
+ ctag = delimiters[1];
+
+ return closeIndex + close.length - 1;
+ }
+
+ if (delimiters) {
+ delimiters = delimiters.split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text.charAt(i) == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ tag = tagTypes[text.charAt(i + 1)];
+ tagType = tag ? text.charAt(i + 1) : '_v';
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ seenTag = i;
+ } else {
+ if (tagChange(ctag, text, i)) {
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
+ buf = '';
+ i += ctag.length - 1;
+ state = IN_TEXT;
+ if (tagType == '{') {
+ if (ctag == '}}') {
+ i++;
+ } else {
+ cleanTripleStache(tokens[tokens.length - 1]);
+ }
+ }
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function cleanTripleStache(token) {
+ if (token.n.substr(token.n.length - 1) === '}') {
+ token.n = token.n.substring(0, token.n.length - 1);
+ }
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ function tagChange(tag, text, index) {
+ if (text.charAt(index) != tag.charAt(0)) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text.charAt(index + i) != tag.charAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length === 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function writeCode(tree) {
+ return 'i = i || "";var b = i + "";var _ = this;' + walk(tree) + 'return b;';
+ }
+
+ Hogan.generate = function (code, text, options) {
+ if (options.asString) {
+ return 'function(c,p,i){' + code + ';}';
+ }
+
+ return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan);
+ }
+
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r');
+ }
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i]);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text('"' + esc(tree[i]) + '"');
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end, tags) {
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
+ 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
+ 'b += _.rs(c,p,' +
+ 'function(c,p){ var b = "";' +
+ walk(nodes) +
+ 'return b;});c.pop();}' +
+ 'else{b += _.b; _.b = ""};';
+ }
+
+ function invertedSection(nodes, id, method) {
+ return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
+ walk(nodes) +
+ '};';
+ }
+
+ function partial(tok) {
+ return 'b += _.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '");';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += ' + id + ';';
+ }
+
+ Hogan.parse = function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ Hogan.cache = {};
+
+ Hogan.compile = function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ // delimiters: A string that overrides the default delimiters.
+ // Example: "<% %>"
+ //
+ options = options || {};
+
+ var key = text + '||' + !!options.asString;
+
+ var t = this.cache[key];
+
+ if (t) {
+ return t;
+ }
+
+ t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), options)), text, options);
+ return this.cache[key] = t;
+ };
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+if (typeof define === 'function' && define.amd) {
+ define(Hogan);
+}
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.common.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.common.js
new file mode 100644
index 0000000000..7520652356
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.common.js
@@ -0,0 +1,576 @@
+/*
+ * 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 = {};
+
+(function (Hogan) {
+ Hogan.Template = function constructor(renderFunc, text, compiler) {
+ if (renderFunc) {
+ this.r = renderFunc;
+ }
+ this.c = compiler;
+ this.text = text || '';
+ }
+
+ Hogan.Template.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials, indent) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials, indent) {
+ return this.ri([context], partials || {}, indent);
+ },
+
+ // render internal -- a hook for overrides that catches partials too
+ ri: function (context, partials, indent) {
+ return this.r(context, partials, indent);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ if (this.c && typeof partial == 'string') {
+ partial = this.c.compile(partial);
+ }
+
+ return partial.ri(context, partials, indent);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '',
+ tail = context[context.length - 1];
+
+ if (!isArray(tail)) {
+ return buf = section(context, partials);
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end, tags) {
+ var pass;
+
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (typeof val == 'function') {
+ val = this.ls(val, ctx, partials, inverted, start, end, tags);
+ }
+
+ pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ var names = key.split('.'),
+ val = this.f(names[0], ctx, partials, returnFound),
+ cx = null;
+
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false,
+ v = null,
+ found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var compiler = this.c;
+ var t = val.call(cx, text, function(t) {
+ return compiler.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = null;
+
+ if (!inverted && this.c && val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ t = val.call(cx);
+
+ if (typeof t == 'function') {
+ if (inverted) {
+ return true;
+ } else if (this.c) {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ var result = val.call(cx);
+ if (typeof result == 'function') {
+ result = result.call(cx);
+ }
+ result = result.toString();
+
+ if (this.c && ~result.indexOf("{{")) {
+ return this.c.compile(result).render(cx, partials);
+ }
+
+ return result;
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String((str === null || str === undefined) ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+
+
+(function (Hogan) {
+ // Setup regex assignments
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/,
+ rQuot = /\"/g,
+ rNewline = /\n/g,
+ rCr = /\r/g,
+ rSlash = /\\/g,
+ tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ Hogan.scan = function scan(text, delimiters) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ tag = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart, next; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ if ((next = tokens[j+1]) && next.tag == '>') {
+ // set indent to token value
+ next.indent = tokens[j].toString()
+ }
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'});
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag,
+ closeIndex = text.indexOf(close, index),
+ delimiters = trim(
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
+ ).split(' ');
+
+ otag = delimiters[0];
+ ctag = delimiters[1];
+
+ return closeIndex + close.length - 1;
+ }
+
+ if (delimiters) {
+ delimiters = delimiters.split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text.charAt(i) == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ tag = tagTypes[text.charAt(i + 1)];
+ tagType = tag ? text.charAt(i + 1) : '_v';
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ seenTag = i;
+ } else {
+ if (tagChange(ctag, text, i)) {
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
+ buf = '';
+ i += ctag.length - 1;
+ state = IN_TEXT;
+ if (tagType == '{') {
+ if (ctag == '}}') {
+ i++;
+ } else {
+ cleanTripleStache(tokens[tokens.length - 1]);
+ }
+ }
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function cleanTripleStache(token) {
+ if (token.n.substr(token.n.length - 1) === '}') {
+ token.n = token.n.substring(0, token.n.length - 1);
+ }
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ function tagChange(tag, text, index) {
+ if (text.charAt(index) != tag.charAt(0)) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text.charAt(index + i) != tag.charAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length === 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function writeCode(tree) {
+ return 'i = i || "";var b = i + "";var _ = this;' + walk(tree) + 'return b;';
+ }
+
+ Hogan.generate = function (code, text, options) {
+ if (options.asString) {
+ return 'function(c,p,i){' + code + ';}';
+ }
+
+ return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan);
+ }
+
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r');
+ }
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i]);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text('"' + esc(tree[i]) + '"');
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end, tags) {
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
+ 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
+ 'b += _.rs(c,p,' +
+ 'function(c,p){ var b = "";' +
+ walk(nodes) +
+ 'return b;});c.pop();}' +
+ 'else{b += _.b; _.b = ""};';
+ }
+
+ function invertedSection(nodes, id, method) {
+ return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
+ walk(nodes) +
+ '};';
+ }
+
+ function partial(tok) {
+ return 'b += _.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '");';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += ' + id + ';';
+ }
+
+ Hogan.parse = function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ Hogan.cache = {};
+
+ Hogan.compile = function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ // delimiters: A string that overrides the default delimiters.
+ // Example: "<% %>"
+ //
+ options = options || {};
+
+ var key = text + '||' + !!options.asString;
+
+ var t = this.cache[key];
+
+ if (t) {
+ return t;
+ }
+
+ t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), options)), text, options);
+ return this.cache[key] = t;
+ };
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Hogan;
+}
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.js
new file mode 100644
index 0000000000..1807562608
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.js
@@ -0,0 +1,572 @@
+/*
+ * 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 = {};
+
+(function (Hogan) {
+ Hogan.Template = function constructor(renderFunc, text, compiler) {
+ if (renderFunc) {
+ this.r = renderFunc;
+ }
+ this.c = compiler;
+ this.text = text || '';
+ }
+
+ Hogan.Template.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials, indent) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials, indent) {
+ return this.ri([context], partials || {}, indent);
+ },
+
+ // render internal -- a hook for overrides that catches partials too
+ ri: function (context, partials, indent) {
+ return this.r(context, partials, indent);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ if (this.c && typeof partial == 'string') {
+ partial = this.c.compile(partial);
+ }
+
+ return partial.ri(context, partials, indent);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '',
+ tail = context[context.length - 1];
+
+ if (!isArray(tail)) {
+ return buf = section(context, partials);
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end, tags) {
+ var pass;
+
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (typeof val == 'function') {
+ val = this.ls(val, ctx, partials, inverted, start, end, tags);
+ }
+
+ pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ var names = key.split('.'),
+ val = this.f(names[0], ctx, partials, returnFound),
+ cx = null;
+
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false,
+ v = null,
+ found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var compiler = this.c;
+ var t = val.call(cx, text, function(t) {
+ return compiler.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = null;
+
+ if (!inverted && this.c && val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ t = val.call(cx);
+
+ if (typeof t == 'function') {
+ if (inverted) {
+ return true;
+ } else if (this.c) {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ var result = val.call(cx);
+ if (typeof result == 'function') {
+ result = result.call(cx);
+ }
+ result = result.toString();
+
+ if (this.c && ~result.indexOf("{{")) {
+ return this.c.compile(result).render(cx, partials);
+ }
+
+ return result;
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String((str === null || str === undefined) ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+
+
+(function (Hogan) {
+ // Setup regex assignments
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/,
+ rQuot = /\"/g,
+ rNewline = /\n/g,
+ rCr = /\r/g,
+ rSlash = /\\/g,
+ tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ Hogan.scan = function scan(text, delimiters) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ tag = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart, next; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ if ((next = tokens[j+1]) && next.tag == '>') {
+ // set indent to token value
+ next.indent = tokens[j].toString()
+ }
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'});
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag,
+ closeIndex = text.indexOf(close, index),
+ delimiters = trim(
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
+ ).split(' ');
+
+ otag = delimiters[0];
+ ctag = delimiters[1];
+
+ return closeIndex + close.length - 1;
+ }
+
+ if (delimiters) {
+ delimiters = delimiters.split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text.charAt(i) == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ tag = tagTypes[text.charAt(i + 1)];
+ tagType = tag ? text.charAt(i + 1) : '_v';
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ seenTag = i;
+ } else {
+ if (tagChange(ctag, text, i)) {
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
+ buf = '';
+ i += ctag.length - 1;
+ state = IN_TEXT;
+ if (tagType == '{') {
+ if (ctag == '}}') {
+ i++;
+ } else {
+ cleanTripleStache(tokens[tokens.length - 1]);
+ }
+ }
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function cleanTripleStache(token) {
+ if (token.n.substr(token.n.length - 1) === '}') {
+ token.n = token.n.substring(0, token.n.length - 1);
+ }
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ function tagChange(tag, text, index) {
+ if (text.charAt(index) != tag.charAt(0)) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text.charAt(index + i) != tag.charAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length === 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function writeCode(tree) {
+ return 'i = i || "";var b = i + "";var _ = this;' + walk(tree) + 'return b;';
+ }
+
+ Hogan.generate = function (code, text, options) {
+ if (options.asString) {
+ return 'function(c,p,i){' + code + ';}';
+ }
+
+ return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan);
+ }
+
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r');
+ }
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i]);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text('"' + esc(tree[i]) + '"');
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end, tags) {
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
+ 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
+ 'b += _.rs(c,p,' +
+ 'function(c,p){ var b = "";' +
+ walk(nodes) +
+ 'return b;});c.pop();}' +
+ 'else{b += _.b; _.b = ""};';
+ }
+
+ function invertedSection(nodes, id, method) {
+ return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
+ walk(nodes) +
+ '};';
+ }
+
+ function partial(tok) {
+ return 'b += _.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '");';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += ' + id + ';';
+ }
+
+ Hogan.parse = function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ Hogan.cache = {};
+
+ Hogan.compile = function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ // delimiters: A string that overrides the default delimiters.
+ // Example: "<% %>"
+ //
+ options = options || {};
+
+ var key = text + '||' + !!options.asString;
+
+ var t = this.cache[key];
+
+ if (t) {
+ return t;
+ }
+
+ t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), options)), text, options);
+ return this.cache[key] = t;
+ };
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.min.amd.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.min.amd.js
new file mode 100644
index 0000000000..aee5922bc2
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.min.amd.js
@@ -0,0 +1,5 @@
+/**
+* @preserve Copyright 2012 Twitter, Inc.
+* @license http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+var Hogan={};(function(a){function h(a){return a=String(a===null||a===undefined?"":a),g.test(a)?a.replace(b,"&").replace(c,"<").replace(d,">").replace(e,"'").replace(f,"""):a}a.Template=function j(a,b,c){a&&(this.r=a),this.c=c,this.text=b||""},a.Template.prototype={r:function(a,b,c){return""},v:h,render:function(b,c,d){return this.ri([b],c||{},d)},ri:function(a,b,c){return this.r(a,b,c)},rp:function(a,b,c,d){var e=c[a];return e?(this.c&&typeof e=="string"&&(e=this.c.compile(e)),e.ri(b,c,d)):""},rs:function(a,b,c){var d="",e=a[a.length-1];if(!i(e))return d=c(a,b);for(var f=0;f=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=this.c,g=a.call(b,d,function(a){return f.compile(a,{delimiters:e}).render(b,c)}),h=f.compile(g.toString(),{delimiters:e}).render(b,c);return this.b=h,!1},b:"",ls:function(a,b,c,d,e,f,g){var h=b[b.length-1],i=null;if(!d&&this.c&&a.length>0)return this.ho(a,h,c,this.text.substring(e,f),g);i=a.call(h);if(typeof i=="function"){if(d)return!0;if(this.c)return this.ho(i,h,c,this.text.substring(e,f),g)}return i},lv:function(a,b,c){var d=b[b.length-1],e=a.call(d);return typeof e=="function"&&(e=e.call(d)),e=e.toString(),this.c&&~e.indexOf("{{")?this.c.compile(e).render(d,c):e}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(typeof exports!="undefined"?exports:Hogan),function(a){function h(a){a.n.substr(a.n.length-1)==="}"&&(a.n=a.n.substring(0,a.n.length-1))}function i(a){return a.trim?a.trim():a.replace(/^\s*|\s*$/g,"")}function j(a,b,c){if(b.charAt(c)!=a.charAt(0))return!1;for(var d=1,e=a.length;d0){g=a.shift();if(g.tag=="#"||g.tag=="^"||l(g,d))c.push(g),g.nodes=k(a,g.tag,c,d),e.push(g);else{if(g.tag=="/"){if(c.length===0)throw new Error("Closing tag without opener: /"+g.n);f=c.pop();if(g.n!=f.n&&!m(g.n,f.n,d))throw new Error("Nesting error: "+f.n+" vs. "+g.n);return f.end=g.i,e}e.push(g)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function l(a,b){for(var c=0,d=b.length;c"?b+=t(a[c]):e=="{"||e=="&"?b+=u(a[c].n,p(a[c].n)):e=="\n"?b+=w('"\\n"'+(a.length-1==c?"":" + i")):e=="_v"?b+=v(a[c].n,p(a[c].n)):e===undefined&&(b+=w('"'+o(a[c])+'"'))}return b}function r(a,b,c,d,e,f){return"if(_.s(_."+c+'("'+o(b)+'",c,p,1),'+"c,p,0,"+d+","+e+', "'+f+'")){'+"b += _.rs(c,p,"+'function(c,p){ var b = "";'+q(a)+"return b;});c.pop();}"+'else{b += _.b; _.b = ""};'}function s(a,b,c){return"if (!_.s(_."+c+'("'+o(b)+'",c,p,1),c,p,1,0,0,"")){'+q(a)+"};"}function t(a){return'b += _.rp("'+o(a.n)+'",c,p,"'+(a.indent||"")+'");'}function u(a,b){return"b += (_."+b+'("'+o(a)+'",c,p,0));'}function v(a,b){return"b += (_.v(_."+b+'("'+o(a)+'",c,p,0)));'}function w(a){return"b += "+a+";"}var b=/\S/,c=/\"/g,d=/\n/g,e=/\r/g,f=/\\/g,g={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10};a.scan=function(c,d){function w(){p.length>0&&(q.push(new String(p)),p="")}function x(){var a=!0;for(var c=t;c"&&(d.indent=q[c].toString()),q.splice(c,1));else b||q.push({tag:"\n"});r=!1,t=q.length}function z(a,b){var c="="+v,d=a.indexOf(c,b),e=i(a.substring(a.indexOf("=",b)+1,d)).split(" ");return u=e[0],v=e[1],d+c.length-1}var e=c.length,f=0,k=1,l=2,m=f,n=null,o=null,p="",q=[],r=!1,s=0,t=0,u="{{",v="}}";d&&(d=d.split(" "),u=d[0],v=d[1]);for(s=0;s=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=this.c,g=a.call(b,d,function(a){return f.compile(a,{delimiters:e}).render(b,c)}),h=f.compile(g.toString(),{delimiters:e}).render(b,c);return this.b=h,!1},b:"",ls:function(a,b,c,d,e,f,g){var h=b[b.length-1],i=null;if(!d&&this.c&&a.length>0)return this.ho(a,h,c,this.text.substring(e,f),g);i=a.call(h);if(typeof i=="function"){if(d)return!0;if(this.c)return this.ho(i,h,c,this.text.substring(e,f),g)}return i},lv:function(a,b,c){var d=b[b.length-1],e=a.call(d);return typeof e=="function"&&(e=e.call(d)),e=e.toString(),this.c&&~e.indexOf("{{")?this.c.compile(e).render(d,c):e}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(typeof exports!="undefined"?exports:Hogan),function(a){function h(a){a.n.substr(a.n.length-1)==="}"&&(a.n=a.n.substring(0,a.n.length-1))}function i(a){return a.trim?a.trim():a.replace(/^\s*|\s*$/g,"")}function j(a,b,c){if(b.charAt(c)!=a.charAt(0))return!1;for(var d=1,e=a.length;d0){g=a.shift();if(g.tag=="#"||g.tag=="^"||l(g,d))c.push(g),g.nodes=k(a,g.tag,c,d),e.push(g);else{if(g.tag=="/"){if(c.length===0)throw new Error("Closing tag without opener: /"+g.n);f=c.pop();if(g.n!=f.n&&!m(g.n,f.n,d))throw new Error("Nesting error: "+f.n+" vs. "+g.n);return f.end=g.i,e}e.push(g)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function l(a,b){for(var c=0,d=b.length;c"?b+=t(a[c]):e=="{"||e=="&"?b+=u(a[c].n,p(a[c].n)):e=="\n"?b+=w('"\\n"'+(a.length-1==c?"":" + i")):e=="_v"?b+=v(a[c].n,p(a[c].n)):e===undefined&&(b+=w('"'+o(a[c])+'"'))}return b}function r(a,b,c,d,e,f){return"if(_.s(_."+c+'("'+o(b)+'",c,p,1),'+"c,p,0,"+d+","+e+', "'+f+'")){'+"b += _.rs(c,p,"+'function(c,p){ var b = "";'+q(a)+"return b;});c.pop();}"+'else{b += _.b; _.b = ""};'}function s(a,b,c){return"if (!_.s(_."+c+'("'+o(b)+'",c,p,1),c,p,1,0,0,"")){'+q(a)+"};"}function t(a){return'b += _.rp("'+o(a.n)+'",c,p,"'+(a.indent||"")+'");'}function u(a,b){return"b += (_."+b+'("'+o(a)+'",c,p,0));'}function v(a,b){return"b += (_.v(_."+b+'("'+o(a)+'",c,p,0)));'}function w(a){return"b += "+a+";"}var b=/\S/,c=/\"/g,d=/\n/g,e=/\r/g,f=/\\/g,g={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10};a.scan=function(c,d){function w(){p.length>0&&(q.push(new String(p)),p="")}function x(){var a=!0;for(var c=t;c"&&(d.indent=q[c].toString()),q.splice(c,1));else b||q.push({tag:"\n"});r=!1,t=q.length}function z(a,b){var c="="+v,d=a.indexOf(c,b),e=i(a.substring(a.indexOf("=",b)+1,d)).split(" ");return u=e[0],v=e[1],d+c.length-1}var e=c.length,f=0,k=1,l=2,m=f,n=null,o=null,p="",q=[],r=!1,s=0,t=0,u="{{",v="}}";d&&(d=d.split(" "),u=d[0],v=d[1]);for(s=0;s=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=this.c,g=a.call(b,d,function(a){return f.compile(a,{delimiters:e}).render(b,c)}),h=f.compile(g.toString(),{delimiters:e}).render(b,c);return this.b=h,!1},b:"",ls:function(a,b,c,d,e,f,g){var h=b[b.length-1],i=null;if(!d&&this.c&&a.length>0)return this.ho(a,h,c,this.text.substring(e,f),g);i=a.call(h);if(typeof i=="function"){if(d)return!0;if(this.c)return this.ho(i,h,c,this.text.substring(e,f),g)}return i},lv:function(a,b,c){var d=b[b.length-1],e=a.call(d);return typeof e=="function"&&(e=e.call(d)),e=e.toString(),this.c&&~e.indexOf("{{")?this.c.compile(e).render(d,c):e}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(typeof exports!="undefined"?exports:Hogan),function(a){function h(a){a.n.substr(a.n.length-1)==="}"&&(a.n=a.n.substring(0,a.n.length-1))}function i(a){return a.trim?a.trim():a.replace(/^\s*|\s*$/g,"")}function j(a,b,c){if(b.charAt(c)!=a.charAt(0))return!1;for(var d=1,e=a.length;d0){g=a.shift();if(g.tag=="#"||g.tag=="^"||l(g,d))c.push(g),g.nodes=k(a,g.tag,c,d),e.push(g);else{if(g.tag=="/"){if(c.length===0)throw new Error("Closing tag without opener: /"+g.n);f=c.pop();if(g.n!=f.n&&!m(g.n,f.n,d))throw new Error("Nesting error: "+f.n+" vs. "+g.n);return f.end=g.i,e}e.push(g)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function l(a,b){for(var c=0,d=b.length;c"?b+=t(a[c]):e=="{"||e=="&"?b+=u(a[c].n,p(a[c].n)):e=="\n"?b+=w('"\\n"'+(a.length-1==c?"":" + i")):e=="_v"?b+=v(a[c].n,p(a[c].n)):e===undefined&&(b+=w('"'+o(a[c])+'"'))}return b}function r(a,b,c,d,e,f){return"if(_.s(_."+c+'("'+o(b)+'",c,p,1),'+"c,p,0,"+d+","+e+', "'+f+'")){'+"b += _.rs(c,p,"+'function(c,p){ var b = "";'+q(a)+"return b;});c.pop();}"+'else{b += _.b; _.b = ""};'}function s(a,b,c){return"if (!_.s(_."+c+'("'+o(b)+'",c,p,1),c,p,1,0,0,"")){'+q(a)+"};"}function t(a){return'b += _.rp("'+o(a.n)+'",c,p,"'+(a.indent||"")+'");'}function u(a,b){return"b += (_."+b+'("'+o(a)+'",c,p,0));'}function v(a,b){return"b += (_.v(_."+b+'("'+o(a)+'",c,p,0)));'}function w(a){return"b += "+a+";"}var b=/\S/,c=/\"/g,d=/\n/g,e=/\r/g,f=/\\/g,g={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10};a.scan=function(c,d){function w(){p.length>0&&(q.push(new String(p)),p="")}function x(){var a=!0;for(var c=t;c"&&(d.indent=q[c].toString()),q.splice(c,1));else b||q.push({tag:"\n"});r=!1,t=q.length}function z(a,b){var c="="+v,d=a.indexOf(c,b),e=i(a.substring(a.indexOf("=",b)+1,d)).split(" ");return u=e[0],v=e[1],d+c.length-1}var e=c.length,f=0,k=1,l=2,m=f,n=null,o=null,p="",q=[],r=!1,s=0,t=0,u="{{",v="}}";d&&(d=d.split(" "),u=d[0],v=d[1]);for(s=0;s=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=this.c,g=a.call(b,d,function(a){return f.compile(a,{delimiters:e}).render(b,c)}),h=f.compile(g.toString(),{delimiters:e}).render(b,c);return this.b=h,!1},b:"",ls:function(a,b,c,d,e,f,g){var h=b[b.length-1],i=null;if(!d&&this.c&&a.length>0)return this.ho(a,h,c,this.text.substring(e,f),g);i=a.call(h);if(typeof i=="function"){if(d)return!0;if(this.c)return this.ho(i,h,c,this.text.substring(e,f),g)}return i},lv:function(a,b,c){var d=b[b.length-1],e=a.call(d);return typeof e=="function"&&(e=e.call(d)),e=e.toString(),this.c&&~e.indexOf("{{")?this.c.compile(e).render(d,c):e}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(typeof exports!="undefined"?exports:Hogan),function(a){function h(a){a.n.substr(a.n.length-1)==="}"&&(a.n=a.n.substring(0,a.n.length-1))}function i(a){return a.trim?a.trim():a.replace(/^\s*|\s*$/g,"")}function j(a,b,c){if(b.charAt(c)!=a.charAt(0))return!1;for(var d=1,e=a.length;d0){g=a.shift();if(g.tag=="#"||g.tag=="^"||l(g,d))c.push(g),g.nodes=k(a,g.tag,c,d),e.push(g);else{if(g.tag=="/"){if(c.length===0)throw new Error("Closing tag without opener: /"+g.n);f=c.pop();if(g.n!=f.n&&!m(g.n,f.n,d))throw new Error("Nesting error: "+f.n+" vs. "+g.n);return f.end=g.i,e}e.push(g)}}if(c.length>0)throw new Error("missing closing tag: "+c.pop().n);return e}function l(a,b){for(var c=0,d=b.length;c"?b+=t(a[c]):e=="{"||e=="&"?b+=u(a[c].n,p(a[c].n)):e=="\n"?b+=w('"\\n"'+(a.length-1==c?"":" + i")):e=="_v"?b+=v(a[c].n,p(a[c].n)):e===undefined&&(b+=w('"'+o(a[c])+'"'))}return b}function r(a,b,c,d,e,f){return"if(_.s(_."+c+'("'+o(b)+'",c,p,1),'+"c,p,0,"+d+","+e+', "'+f+'")){'+"b += _.rs(c,p,"+'function(c,p){ var b = "";'+q(a)+"return b;});c.pop();}"+'else{b += _.b; _.b = ""};'}function s(a,b,c){return"if (!_.s(_."+c+'("'+o(b)+'",c,p,1),c,p,1,0,0,"")){'+q(a)+"};"}function t(a){return'b += _.rp("'+o(a.n)+'",c,p,"'+(a.indent||"")+'");'}function u(a,b){return"b += (_."+b+'("'+o(a)+'",c,p,0));'}function v(a,b){return"b += (_.v(_."+b+'("'+o(a)+'",c,p,0)));'}function w(a){return"b += "+a+";"}var b=/\S/,c=/\"/g,d=/\n/g,e=/\r/g,f=/\\/g,g={"#":1,"^":2,"/":3,"!":4,">":5,"<":6,"=":7,_v:8,"{":9,"&":10};a.scan=function(c,d){function w(){p.length>0&&(q.push(new String(p)),p="")}function x(){var a=!0;for(var c=t;c"&&(d.indent=q[c].toString()),q.splice(c,1));else b||q.push({tag:"\n"});r=!1,t=q.length}function z(a,b){var c="="+v,d=a.indexOf(c,b),e=i(a.substring(a.indexOf("=",b)+1,d)).split(" ");return u=e[0],v=e[1],d+c.length-1}var e=c.length,f=0,k=1,l=2,m=f,n=null,o=null,p="",q=[],r=!1,s=0,t=0,u="{{",v="}}";d&&(d=d.split(" "),u=d[0],v=d[1]);for(s=0;s= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var compiler = this.c;
+ var t = val.call(cx, text, function(t) {
+ return compiler.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = null;
+
+ if (!inverted && this.c && val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ t = val.call(cx);
+
+ if (typeof t == 'function') {
+ if (inverted) {
+ return true;
+ } else if (this.c) {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ var result = val.call(cx);
+ if (typeof result == 'function') {
+ result = result.call(cx);
+ }
+ result = result.toString();
+
+ if (this.c && ~result.indexOf("{{")) {
+ return this.c.compile(result).render(cx, partials);
+ }
+
+ return result;
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String((str === null || str === undefined) ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+
+
+(function (Hogan) {
+ // Setup regex assignments
+ // remove whitespace according to Mustache spec
+ var rIsWhitespace = /\S/,
+ rQuot = /\"/g,
+ rNewline = /\n/g,
+ rCr = /\r/g,
+ rSlash = /\\/g,
+ tagTypes = {
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
+ };
+
+ Hogan.scan = function scan(text, delimiters) {
+ var len = text.length,
+ IN_TEXT = 0,
+ IN_TAG_TYPE = 1,
+ IN_TAG = 2,
+ state = IN_TEXT,
+ tagType = null,
+ tag = null,
+ buf = '',
+ tokens = [],
+ seenTag = false,
+ i = 0,
+ lineStart = 0,
+ otag = '{{',
+ ctag = '}}';
+
+ function addBuf() {
+ if (buf.length > 0) {
+ tokens.push(new String(buf));
+ buf = '';
+ }
+ }
+
+ function lineIsWhitespace() {
+ var isAllWhitespace = true;
+ for (var j = lineStart; j < tokens.length; j++) {
+ isAllWhitespace =
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
+ if (!isAllWhitespace) {
+ return false;
+ }
+ }
+
+ return isAllWhitespace;
+ }
+
+ function filterLine(haveSeenTag, noNewLine) {
+ addBuf();
+
+ if (haveSeenTag && lineIsWhitespace()) {
+ for (var j = lineStart, next; j < tokens.length; j++) {
+ if (!tokens[j].tag) {
+ if ((next = tokens[j+1]) && next.tag == '>') {
+ // set indent to token value
+ next.indent = tokens[j].toString()
+ }
+ tokens.splice(j, 1);
+ }
+ }
+ } else if (!noNewLine) {
+ tokens.push({tag:'\n'});
+ }
+
+ seenTag = false;
+ lineStart = tokens.length;
+ }
+
+ function changeDelimiters(text, index) {
+ var close = '=' + ctag,
+ closeIndex = text.indexOf(close, index),
+ delimiters = trim(
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
+ ).split(' ');
+
+ otag = delimiters[0];
+ ctag = delimiters[1];
+
+ return closeIndex + close.length - 1;
+ }
+
+ if (delimiters) {
+ delimiters = delimiters.split(' ');
+ otag = delimiters[0];
+ ctag = delimiters[1];
+ }
+
+ for (i = 0; i < len; i++) {
+ if (state == IN_TEXT) {
+ if (tagChange(otag, text, i)) {
+ --i;
+ addBuf();
+ state = IN_TAG_TYPE;
+ } else {
+ if (text.charAt(i) == '\n') {
+ filterLine(seenTag);
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ } else if (state == IN_TAG_TYPE) {
+ i += otag.length - 1;
+ tag = tagTypes[text.charAt(i + 1)];
+ tagType = tag ? text.charAt(i + 1) : '_v';
+ if (tagType == '=') {
+ i = changeDelimiters(text, i);
+ state = IN_TEXT;
+ } else {
+ if (tag) {
+ i++;
+ }
+ state = IN_TAG;
+ }
+ seenTag = i;
+ } else {
+ if (tagChange(ctag, text, i)) {
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
+ buf = '';
+ i += ctag.length - 1;
+ state = IN_TEXT;
+ if (tagType == '{') {
+ if (ctag == '}}') {
+ i++;
+ } else {
+ cleanTripleStache(tokens[tokens.length - 1]);
+ }
+ }
+ } else {
+ buf += text.charAt(i);
+ }
+ }
+ }
+
+ filterLine(seenTag, true);
+
+ return tokens;
+ }
+
+ function cleanTripleStache(token) {
+ if (token.n.substr(token.n.length - 1) === '}') {
+ token.n = token.n.substring(0, token.n.length - 1);
+ }
+ }
+
+ function trim(s) {
+ if (s.trim) {
+ return s.trim();
+ }
+
+ return s.replace(/^\s*|\s*$/g, '');
+ }
+
+ function tagChange(tag, text, index) {
+ if (text.charAt(index) != tag.charAt(0)) {
+ return false;
+ }
+
+ for (var i = 1, l = tag.length; i < l; i++) {
+ if (text.charAt(index + i) != tag.charAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function buildTree(tokens, kind, stack, customTags) {
+ var instructions = [],
+ opener = null,
+ token = null;
+
+ while (tokens.length > 0) {
+ token = tokens.shift();
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
+ stack.push(token);
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
+ instructions.push(token);
+ } else if (token.tag == '/') {
+ if (stack.length === 0) {
+ throw new Error('Closing tag without opener: /' + token.n);
+ }
+ opener = stack.pop();
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
+ }
+ opener.end = token.i;
+ return instructions;
+ } else {
+ instructions.push(token);
+ }
+ }
+
+ if (stack.length > 0) {
+ throw new Error('missing closing tag: ' + stack.pop().n);
+ }
+
+ return instructions;
+ }
+
+ function isOpener(token, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].o == token.n) {
+ token.tag = '#';
+ return true;
+ }
+ }
+ }
+
+ function isCloser(close, open, tags) {
+ for (var i = 0, l = tags.length; i < l; i++) {
+ if (tags[i].c == close && tags[i].o == open) {
+ return true;
+ }
+ }
+ }
+
+ function writeCode(tree) {
+ return 'i = i || "";var b = i + "";var _ = this;' + walk(tree) + 'return b;';
+ }
+
+ Hogan.generate = function (code, text, options) {
+ if (options.asString) {
+ return 'function(c,p,i){' + code + ';}';
+ }
+
+ return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan);
+ }
+
+ function esc(s) {
+ return s.replace(rSlash, '\\\\')
+ .replace(rQuot, '\\\"')
+ .replace(rNewline, '\\n')
+ .replace(rCr, '\\r');
+ }
+
+ function chooseMethod(s) {
+ return (~s.indexOf('.')) ? 'd' : 'f';
+ }
+
+ function walk(tree) {
+ var code = '';
+ for (var i = 0, l = tree.length; i < l; i++) {
+ var tag = tree[i].tag;
+ if (tag == '#') {
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
+ } else if (tag == '^') {
+ code += invertedSection(tree[i].nodes, tree[i].n,
+ chooseMethod(tree[i].n));
+ } else if (tag == '<' || tag == '>') {
+ code += partial(tree[i]);
+ } else if (tag == '{' || tag == '&') {
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag == '\n') {
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
+ } else if (tag == '_v') {
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
+ } else if (tag === undefined) {
+ code += text('"' + esc(tree[i]) + '"');
+ }
+ }
+ return code;
+ }
+
+ function section(nodes, id, method, start, end, tags) {
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
+ 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
+ 'b += _.rs(c,p,' +
+ 'function(c,p){ var b = "";' +
+ walk(nodes) +
+ 'return b;});c.pop();}' +
+ 'else{b += _.b; _.b = ""};';
+ }
+
+ function invertedSection(nodes, id, method) {
+ return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
+ walk(nodes) +
+ '};';
+ }
+
+ function partial(tok) {
+ return 'b += _.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '");';
+ }
+
+ function tripleStache(id, method) {
+ return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
+ }
+
+ function variable(id, method) {
+ return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
+ }
+
+ function text(id) {
+ return 'b += ' + id + ';';
+ }
+
+ Hogan.parse = function(tokens, options) {
+ options = options || {};
+ return buildTree(tokens, '', [], options.sectionTags || []);
+ },
+
+ Hogan.cache = {};
+
+ Hogan.compile = function(text, options) {
+ // options
+ //
+ // asString: false (default)
+ //
+ // sectionTags: [{o: '_foo', c: 'foo'}]
+ // An array of object with o and c fields that indicate names for custom
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
+ //
+ // delimiters: A string that overrides the default delimiters.
+ // Example: "<% %>"
+ //
+ options = options || {};
+
+ var key = text + '||' + !!options.asString;
+
+ var t = this.cache[key];
+
+ if (t) {
+ return t;
+ }
+
+ t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), options)), text, options);
+ return this.cache[key] = t;
+ };
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
+
+var Mustache = (function (Hogan) {
+
+ // Mustache.js has non-spec partial context behavior
+ function mustachePartial(name, context, partials, indent) {
+ var partialScope = this.f(name, context, partials, 0);
+ var cx = context;
+ if (partialScope) {
+ cx = cx.concat(partialScope);
+ }
+
+ return Hogan.Template.prototype.rp.call(this, name, cx, partials, indent);
+ }
+
+ var HoganTemplateWrapper = function(renderFunc, text, compiler){
+ this.rp = mustachePartial;
+ Hogan.Template.call(this, renderFunc, text, compiler);
+ };
+ HoganTemplateWrapper.prototype = Hogan.Template.prototype;
+
+ // Add a wrapper for Hogan's generate method. Mustache and Hogan keep
+ // separate caches, and Mustache returns wrapped templates.
+ var wrapper;
+ var HoganWrapper = function(){
+ this.cache = {};
+ this.generate = function(code, text, options) {
+ return new HoganTemplateWrapper(new Function('c', 'p', 'i', code), text, wrapper);
+ }
+ };
+ HoganWrapper.prototype = Hogan;
+ wrapper = new HoganWrapper();
+
+ return {
+ to_html: function(text, data, partials, sendFun) {
+ var template = wrapper.compile(text);
+ var result = template.render(data, partials);
+ if (!sendFun) {
+ return result;
+ }
+
+ sendFun(result);
+ }
+ }
+
+})(Hogan);
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.js
new file mode 100644
index 0000000000..8958a70a16
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.js
@@ -0,0 +1,233 @@
+/*
+ * 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 = {};
+
+(function (Hogan) {
+ Hogan.Template = function constructor(renderFunc, text, compiler) {
+ if (renderFunc) {
+ this.r = renderFunc;
+ }
+ this.c = compiler;
+ this.text = text || '';
+ }
+
+ Hogan.Template.prototype = {
+ // render: replaced by generated code.
+ r: function (context, partials, indent) { return ''; },
+
+ // variable escaping
+ v: hoganEscape,
+
+ render: function render(context, partials, indent) {
+ return this.ri([context], partials || {}, indent);
+ },
+
+ // render internal -- a hook for overrides that catches partials too
+ ri: function (context, partials, indent) {
+ return this.r(context, partials, indent);
+ },
+
+ // tries to find a partial in the curent scope and render it
+ rp: function(name, context, partials, indent) {
+ var partial = partials[name];
+
+ if (!partial) {
+ return '';
+ }
+
+ if (this.c && typeof partial == 'string') {
+ partial = this.c.compile(partial);
+ }
+
+ return partial.ri(context, partials, indent);
+ },
+
+ // render a section
+ rs: function(context, partials, section) {
+ var buf = '',
+ tail = context[context.length - 1];
+
+ if (!isArray(tail)) {
+ return buf = section(context, partials);
+ }
+
+ for (var i = 0; i < tail.length; i++) {
+ context.push(tail[i]);
+ buf += section(context, partials);
+ context.pop();
+ }
+
+ return buf;
+ },
+
+ // maybe start a section
+ s: function(val, ctx, partials, inverted, start, end, tags) {
+ var pass;
+
+ if (isArray(val) && val.length === 0) {
+ return false;
+ }
+
+ if (typeof val == 'function') {
+ val = this.ls(val, ctx, partials, inverted, start, end, tags);
+ }
+
+ pass = (val === '') || !!val;
+
+ if (!inverted && pass && ctx) {
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
+ }
+
+ return pass;
+ },
+
+ // find values with dotted names
+ d: function(key, ctx, partials, returnFound) {
+ var names = key.split('.'),
+ val = this.f(names[0], ctx, partials, returnFound),
+ cx = null;
+
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
+ return ctx[ctx.length - 1];
+ }
+
+ for (var i = 1; i < names.length; i++) {
+ if (val && typeof val == 'object' && names[i] in val) {
+ cx = val;
+ val = val[names[i]];
+ } else {
+ val = '';
+ }
+ }
+
+ if (returnFound && !val) {
+ return false;
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ ctx.push(cx);
+ val = this.lv(val, ctx, partials);
+ ctx.pop();
+ }
+
+ return val;
+ },
+
+ // find values with normal names
+ f: function(key, ctx, partials, returnFound) {
+ var val = false,
+ v = null,
+ found = false;
+
+ for (var i = ctx.length - 1; i >= 0; i--) {
+ v = ctx[i];
+ if (v && typeof v == 'object' && key in v) {
+ val = v[key];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return (returnFound) ? false : "";
+ }
+
+ if (!returnFound && typeof val == 'function') {
+ val = this.lv(val, ctx, partials);
+ }
+
+ return val;
+ },
+
+ // higher order templates
+ ho: function(val, cx, partials, text, tags) {
+ var compiler = this.c;
+ var t = val.call(cx, text, function(t) {
+ return compiler.compile(t, {delimiters: tags}).render(cx, partials);
+ });
+ var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
+ this.b = s;
+ return false;
+ },
+
+ // higher order template result buffer
+ b: '',
+
+ // lambda replace section
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
+ var cx = ctx[ctx.length - 1],
+ t = null;
+
+ if (!inverted && this.c && val.length > 0) {
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
+ }
+
+ t = val.call(cx);
+
+ if (typeof t == 'function') {
+ if (inverted) {
+ return true;
+ } else if (this.c) {
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
+ }
+ }
+
+ return t;
+ },
+
+ // lambda replace variable
+ lv: function(val, ctx, partials) {
+ var cx = ctx[ctx.length - 1];
+ var result = val.call(cx);
+ if (typeof result == 'function') {
+ result = result.call(cx);
+ }
+ result = result.toString();
+
+ if (this.c && ~result.indexOf("{{")) {
+ return this.c.compile(result).render(cx, partials);
+ }
+
+ return result;
+ }
+
+ };
+
+ var rAmp = /&/g,
+ rLt = //g,
+ rApos =/\'/g,
+ rQuot = /\"/g,
+ hChars =/[&<>\"\']/;
+
+ function hoganEscape(str) {
+ str = String((str === null || str === undefined) ? '' : str);
+ return hChars.test(str) ?
+ str
+ .replace(rAmp,'&')
+ .replace(rLt,'<')
+ .replace(rGt,'>')
+ .replace(rApos,''')
+ .replace(rQuot, '"') :
+ str;
+ }
+
+ var isArray = Array.isArray || function(a) {
+ return Object.prototype.toString.call(a) === '[object Array]';
+ };
+
+})(typeof exports !== 'undefined' ? exports : Hogan);
+
diff --git a/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.min.js b/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.min.js
new file mode 100644
index 0000000000..4ec5796047
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/builds/1.0.5/template-1.0.5.min.js
@@ -0,0 +1,5 @@
+/**
+* @preserve Copyright 2012 Twitter, Inc.
+* @license http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+var Hogan={};(function(a){function h(a){return a=String(a===null||a===undefined?"":a),g.test(a)?a.replace(b,"&").replace(c,"<").replace(d,">").replace(e,"'").replace(f,"""):a}a.Template=function j(a,b,c){a&&(this.r=a),this.c=c,this.text=b||""},a.Template.prototype={r:function(a,b,c){return""},v:h,render:function(b,c,d){return this.ri([b],c||{},d)},ri:function(a,b,c){return this.r(a,b,c)},rp:function(a,b,c,d){var e=c[a];return e?(this.c&&typeof e=="string"&&(e=this.c.compile(e)),e.ri(b,c,d)):""},rs:function(a,b,c){var d="",e=a[a.length-1];if(!i(e))return d=c(a,b);for(var f=0;f=0;h--){f=b[h];if(f&&typeof f=="object"&&a in f){e=f[a],g=!0;break}}return g?(!d&&typeof e=="function"&&(e=this.lv(e,b,c)),e):d?!1:""},ho:function(a,b,c,d,e){var f=this.c,g=a.call(b,d,function(a){return f.compile(a,{delimiters:e}).render(b,c)}),h=f.compile(g.toString(),{delimiters:e}).render(b,c);return this.b=h,!1},b:"",ls:function(a,b,c,d,e,f,g){var h=b[b.length-1],i=null;if(!d&&this.c&&a.length>0)return this.ho(a,h,c,this.text.substring(e,f),g);i=a.call(h);if(typeof i=="function"){if(d)return!0;if(this.c)return this.ho(i,h,c,this.text.substring(e,f),g)}return i},lv:function(a,b,c){var d=b[b.length-1],e=a.call(d);return typeof e=="function"&&(e=e.call(d)),e=e.toString(),this.c&&~e.indexOf("{{")?this.c.compile(e).render(d,c):e}};var b=/&/g,c=//g,e=/\'/g,f=/\"/g,g=/[&<>\"\']/,i=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(typeof exports!="undefined"?exports:Hogan)
\ No newline at end of file
diff --git a/docs/build/node_modules/hogan.js/web/favicon.ico b/docs/build/node_modules/hogan.js/web/favicon.ico
new file mode 100644
index 0000000000..627ee837aa
Binary files /dev/null and b/docs/build/node_modules/hogan.js/web/favicon.ico differ
diff --git a/docs/build/node_modules/hogan.js/web/images/logo.png b/docs/build/node_modules/hogan.js/web/images/logo.png
new file mode 100644
index 0000000000..d25879da6a
Binary files /dev/null and b/docs/build/node_modules/hogan.js/web/images/logo.png differ
diff --git a/docs/build/node_modules/hogan.js/web/images/noise.png b/docs/build/node_modules/hogan.js/web/images/noise.png
new file mode 100644
index 0000000000..99ce7572c2
Binary files /dev/null and b/docs/build/node_modules/hogan.js/web/images/noise.png differ
diff --git a/docs/build/node_modules/hogan.js/web/images/small-hogan-icon.png b/docs/build/node_modules/hogan.js/web/images/small-hogan-icon.png
new file mode 100644
index 0000000000..0558ef1788
Binary files /dev/null and b/docs/build/node_modules/hogan.js/web/images/small-hogan-icon.png differ
diff --git a/docs/build/node_modules/hogan.js/web/images/stripes.png b/docs/build/node_modules/hogan.js/web/images/stripes.png
new file mode 100644
index 0000000000..adf332d301
Binary files /dev/null and b/docs/build/node_modules/hogan.js/web/images/stripes.png differ
diff --git a/docs/build/node_modules/hogan.js/web/index.html.mustache b/docs/build/node_modules/hogan.js/web/index.html.mustache
new file mode 100755
index 0000000000..75fcbfb6c1
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/index.html.mustache
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+ Hogan.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Getting started
+
+ Hogan.js is a 2.5k JS templating engine developed at Twitter. Use it as a part of your asset packager to compile templates ahead of time or include it in your browser to handle dynamic templates.
+
+
+ If you're developing with Node.js, just use NPM to add the Hogan package.
+
+
$ npm install hogan.js
+
+ Alternatively, drop hogan.js in your browser by adding the following script.
+
+
<script src="http://twitter.github.com/hogan.js/builds/{{version}}/hogan.js"></script>
+
+
+
+
+
+
+
+
+
+
Templates
+
+ Hogan.js was developed against the mustache test suite, so everything that holds true for templates as specified here, is also the case for hogan.js.
+
+
+ That means you get variables, sections, lambdas, partials, filters, and everything else you've come to expect from mustache templating - only much, much faster.
+
+
+
+
+
+
+
+
+
+
Compiling
+
+ Use hogan.compile()
to precompile your templates into vanilla JS.
+
+
+ It's best to serve your templates precompiled whenever you can (rather than the raw templates), as parsing is the most time consuming operation.
+
+
+
+
+
+
+
+
+
+
+
+
Rendering
+
+ Once compiled, call the render()
method with a context and optional partials object.
+
+
+ If supplying partials, you can compile them ahead of time, or pass string templates.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/build/node_modules/hogan.js/web/stylesheets/layout.css b/docs/build/node_modules/hogan.js/web/stylesheets/layout.css
new file mode 100755
index 0000000000..c9e3e350d2
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/stylesheets/layout.css
@@ -0,0 +1,206 @@
+
+
+/* #Reset & Basics (Inspired by E. Meyers)
+================================================== */
+ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline; }
+ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
+ display: block; }
+ body {
+ line-height: 1; }
+ ol, ul {
+ list-style: none; }
+ blockquote, q {
+ quotes: none; }
+ blockquote:before, blockquote:after,
+ q:before, q:after {
+ content: '';
+ content: none; }
+ table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+
+/* #Basic Styles
+================================================== */
+ body {
+ background: #fff;
+ font: 14px/24px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #000;
+ -webkit-font-smoothing: antialiased; /* Fix for webkit rendering */
+ -webkit-text-size-adjust: 100%;
+ }
+ a {
+ color: #999113;
+ text-decoration: none;
+ }
+ a:hover {
+ color: #7b750e;
+ text-decoration: underline;
+ }
+
+
+/* #Typography
+================================================== */
+ h1, h2, h3, h4, h5, h6 {
+ font-weight: bold; }
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
+ h1 { font-size: 75px; line-height: 80px; margin-bottom: 14px;}
+ h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }
+ h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }
+ h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }
+ h5 { font-size: 17px; line-height: 24px; }
+ h6 { font-size: 14px; line-height: 21px; }
+ p { margin-bottom: 22px; }
+
+
+/* #Main styles
+================================================== */
+
+/* Hogan Hero */
+.hogan-hero {
+ position: relative;
+ background: #333; /* Old browsers */
+ background: -moz-radial-gradient(center, ellipse cover, #333 0%, #000 100%); /* FF3.6+ */
+ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#333), color-stop(100%,#000)); /* Chrome,Safari4+ */
+ background: -webkit-radial-gradient(center, ellipse cover, #333 0%,#000 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-radial-gradient(center, ellipse cover, #333 0%,#000 100%); /* Opera 12+ */
+ background: -ms-radial-gradient(center, ellipse cover, #333 0%,#000 100%); /* IE10+ */
+ background: radial-gradient(center, ellipse cover, #333 0%,#000 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#333', endColorstr='#000',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
+}
+.hogan-hero .container {
+ padding: 180px 0;
+}
+.hogan-hero h1 {
+ letter-spacing: -3px;
+ color: #fff;
+ position: relative;
+ margin-bottom: 5px;
+}
+.hogan-hero h3 {
+ max-width: 650px;
+ margin-bottom: 20px;
+ color: #fff;
+}
+.hogan-hero .noise,
+.hogan-hero .stripes {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.hogan-hero .noise {
+ background: url(../images/noise.png) repeat;
+}
+.hogan-hero .stripes {
+ background: url(../images/stripes.png) repeat;
+}
+
+/* Primary content container */
+.primary.container {
+ padding-top: 100px;
+}
+
+/*Hogan divider */
+.hogan-divider {
+ padding-top: 60px;
+ border-bottom: 1px solid #ddd;
+ margin-bottom: 60px;
+ clear: both;
+ position: relative;
+}
+.hogan-icon {
+ width: 40px;
+ height: 30px;
+ position: absolute;
+ left: 50%;
+ top: 46px;
+ margin-left: -20px;
+ background: url('../images/small-hogan-icon.png') white no-repeat center center;
+}
+
+/* Button style */
+.button {
+ display: inline-block;
+ cursor: pointer;
+ background: #dfd52e;
+ border-radius: 3px;
+ margin-bottom: 20px;
+ color: #000;
+ text-transform: uppercase;
+ text-decoration: none;
+ font-size: 15px;
+ padding: 0 34px;
+ line-height: 46px;
+ font-weight: bold;
+ -webkit-transition: background-color .3s ease-in-out;
+ -moz-transition: background-color .3s ease-in-out;
+ transition: background-color .3s ease-in-out;
+
+}
+.button:hover {
+ text-decoration: inherit;
+ color: inherit;
+ background-color: #f5e810;
+}
+
+/* Hogan footer */
+.hogan-footer {
+ border-top: 1px solid #ddd;
+ margin-top: 60px;
+ padding: 20px 0 40px;
+ color: #999;
+ font-size: 12px;
+}
+.hogan-footer .copyright {
+ float: left;
+}
+.hogan-footer .colophon {
+ float: right;
+}
+
+pre, code {
+ background: #F8F8FF;
+ border: 1px solid #DDD;
+ padding: 5px 10px;
+ margin-bottom: 20px;
+ font-family: courier;
+ overflow: hidden;
+}
+
+pre code {
+ border: 0;
+ padding: 0;
+ margin-bottom: 0;
+}
+
+
+/* #Media Queries
+================================================== */
+
+ /* Smaller than standard 960 (devices and browsers) */
+ @media only screen and (max-width: 959px) {}
+
+ /* Tablet Portrait size to standard 960 (devices and browsers) */
+ @media only screen and (min-width: 768px) and (max-width: 959px) {}
+
+ /* All Mobile Sizes (devices and browser) */
+ @media only screen and (max-width: 767px) {
+ .hogan-hero .container {
+ padding: 100px 0;
+ }
+ }
+
+ /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
+ @media only screen and (min-width: 480px) and (max-width: 767px) {}
+
+ /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
+ @media only screen and (max-width: 479px) {}
+
diff --git a/docs/build/node_modules/hogan.js/web/stylesheets/skeleton.css b/docs/build/node_modules/hogan.js/web/stylesheets/skeleton.css
new file mode 100755
index 0000000000..d0264a40b3
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/web/stylesheets/skeleton.css
@@ -0,0 +1,236 @@
+/*
+* Skeleton V1.1
+* Copyright 2011, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 8/17/2011
+*/
+
+
+/* Table of Contents
+==================================================
+ #Base 960 Grid
+ #Tablet (Portrait)
+ #Mobile (Portrait)
+ #Mobile (Landscape)
+ #Clearing */
+
+
+
+/* #Base 960 Grid
+================================================== */
+
+ .container { position: relative; width: 960px; margin: 0 auto; padding: 0; }
+ .column, .columns { float: left; display: inline; margin-left: 10px; margin-right: 10px; }
+ .row { margin-bottom: 20px; }
+
+ /* Nested Column Classes */
+ .column.alpha, .columns.alpha { margin-left: 0; }
+ .column.omega, .columns.omega { margin-right: 0; }
+
+ /* Base Grid */
+ .container .one.column { width: 40px; }
+ .container .two.columns { width: 100px; }
+ .container .three.columns { width: 160px; }
+ .container .four.columns { width: 220px; }
+ .container .five.columns { width: 280px; }
+ .container .six.columns { width: 340px; }
+ .container .seven.columns { width: 400px; }
+ .container .eight.columns { width: 460px; }
+ .container .nine.columns { width: 520px; }
+ .container .ten.columns { width: 580px; }
+ .container .eleven.columns { width: 640px; }
+ .container .twelve.columns { width: 700px; }
+ .container .thirteen.columns { width: 760px; }
+ .container .fourteen.columns { width: 820px; }
+ .container .fifteen.columns { width: 880px; }
+ .container .sixteen.columns { width: 940px; }
+
+ .container .one-third.column { width: 300px; }
+ .container .two-thirds.column { width: 620px; }
+
+ /* Offsets */
+ .container .offset-by-one { padding-left: 60px; }
+ .container .offset-by-two { padding-left: 120px; }
+ .container .offset-by-three { padding-left: 180px; }
+ .container .offset-by-four { padding-left: 240px; }
+ .container .offset-by-five { padding-left: 300px; }
+ .container .offset-by-six { padding-left: 360px; }
+ .container .offset-by-seven { padding-left: 420px; }
+ .container .offset-by-eight { padding-left: 480px; }
+ .container .offset-by-nine { padding-left: 540px; }
+ .container .offset-by-ten { padding-left: 600px; }
+ .container .offset-by-eleven { padding-left: 660px; }
+ .container .offset-by-twelve { padding-left: 720px; }
+ .container .offset-by-thirteen { padding-left: 780px; }
+ .container .offset-by-fourteen { padding-left: 840px; }
+ .container .offset-by-fifteen { padding-left: 900px; }
+
+
+
+/* #Tablet (Portrait)
+================================================== */
+
+ /* Note: Design for a width of 768px */
+
+ @media only screen and (min-width: 768px) and (max-width: 959px) {
+ .container { width: 768px; }
+ .container .column,
+ .container .columns { margin-left: 10px; margin-right: 10px; }
+ .column.alpha, .columns.alpha { margin-left: 0; margin-right: 10px; }
+ .column.omega, .columns.omega { margin-right: 0; margin-left: 10px; }
+
+ .container .one.column { width: 28px; }
+ .container .two.columns { width: 76px; }
+ .container .three.columns { width: 124px; }
+ .container .four.columns { width: 172px; }
+ .container .five.columns { width: 220px; }
+ .container .six.columns { width: 268px; }
+ .container .seven.columns { width: 316px; }
+ .container .eight.columns { width: 364px; }
+ .container .nine.columns { width: 412px; }
+ .container .ten.columns { width: 460px; }
+ .container .eleven.columns { width: 508px; }
+ .container .twelve.columns { width: 556px; }
+ .container .thirteen.columns { width: 604px; }
+ .container .fourteen.columns { width: 652px; }
+ .container .fifteen.columns { width: 700px; }
+ .container .sixteen.columns { width: 748px; }
+
+ .container .one-third.column { width: 236px; }
+ .container .two-thirds.column { width: 492px; }
+
+ /* Offsets */
+ .container .offset-by-one { padding-left: 48px; }
+ .container .offset-by-two { padding-left: 96px; }
+ .container .offset-by-three { padding-left: 144px; }
+ .container .offset-by-four { padding-left: 192px; }
+ .container .offset-by-five { padding-left: 240px; }
+ .container .offset-by-six { padding-left: 288px; }
+ .container .offset-by-seven { padding-left: 336px; }
+ .container .offset-by-eight { padding-left: 348px; }
+ .container .offset-by-nine { padding-left: 432px; }
+ .container .offset-by-ten { padding-left: 480px; }
+ .container .offset-by-eleven { padding-left: 528px; }
+ .container .offset-by-twelve { padding-left: 576px; }
+ .container .offset-by-thirteen { padding-left: 624px; }
+ .container .offset-by-fourteen { padding-left: 672px; }
+ .container .offset-by-fifteen { padding-left: 720px; }
+ }
+
+
+/* #Mobile (Portrait)
+================================================== */
+
+ /* Note: Design for a width of 320px */
+
+ @media only screen and (max-width: 767px) {
+ .container { width: 300px; }
+ .columns, .column { margin: 0; }
+
+ .container .one.column,
+ .container .two.columns,
+ .container .three.columns,
+ .container .four.columns,
+ .container .five.columns,
+ .container .six.columns,
+ .container .seven.columns,
+ .container .eight.columns,
+ .container .nine.columns,
+ .container .ten.columns,
+ .container .eleven.columns,
+ .container .twelve.columns,
+ .container .thirteen.columns,
+ .container .fourteen.columns,
+ .container .fifteen.columns,
+ .container .sixteen.columns,
+ .container .one-third.column,
+ .container .two-thirds.column { width: 300px; }
+
+ /* Offsets */
+ .container .offset-by-one,
+ .container .offset-by-two,
+ .container .offset-by-three,
+ .container .offset-by-four,
+ .container .offset-by-five,
+ .container .offset-by-six,
+ .container .offset-by-seven,
+ .container .offset-by-eight,
+ .container .offset-by-nine,
+ .container .offset-by-ten,
+ .container .offset-by-eleven,
+ .container .offset-by-twelve,
+ .container .offset-by-thirteen,
+ .container .offset-by-fourteen,
+ .container .offset-by-fifteen { padding-left: 0; }
+
+ }
+
+
+/* #Mobile (Landscape)
+================================================== */
+
+ /* Note: Design for a width of 480px */
+
+ @media only screen and (min-width: 480px) and (max-width: 767px) {
+ .container { width: 420px; }
+ .columns, .column { margin: 0; }
+
+ .container .one.column,
+ .container .two.columns,
+ .container .three.columns,
+ .container .four.columns,
+ .container .five.columns,
+ .container .six.columns,
+ .container .seven.columns,
+ .container .eight.columns,
+ .container .nine.columns,
+ .container .ten.columns,
+ .container .eleven.columns,
+ .container .twelve.columns,
+ .container .thirteen.columns,
+ .container .fourteen.columns,
+ .container .fifteen.columns,
+ .container .sixteen.columns,
+ .container .one-third.column,
+ .container .two-thirds.column { width: 420px; }
+ }
+
+
+/* #Clearing
+================================================== */
+
+ /* Self Clearing Goodness */
+ .container:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; }
+
+ /* Use clearfix class on parent to clear nested columns,
+ or wrap each row of columns in a */
+ .clearfix:before,
+ .clearfix:after,
+ .row:before,
+ .row:after {
+ content: '\0020';
+ display: block;
+ overflow: hidden;
+ visibility: hidden;
+ width: 0;
+ height: 0; }
+ .row:after,
+ .clearfix:after {
+ clear: both; }
+ .row,
+ .clearfix {
+ zoom: 1; }
+
+ /* You can also use a
to clear columns */
+ .clear {
+ clear: both;
+ display: block;
+ overflow: hidden;
+ visibility: hidden;
+ width: 0;
+ height: 0;
+ }
+
+
diff --git a/docs/build/node_modules/hogan.js/wrappers/amd.js.mustache b/docs/build/node_modules/hogan.js/wrappers/amd.js.mustache
new file mode 100644
index 0000000000..d91ef77ca2
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/wrappers/amd.js.mustache
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+{{{template}}}
+{{{compiler}}}
+
+if (typeof define === 'function' && define.amd) {
+ define(Hogan);
+}
diff --git a/docs/build/node_modules/hogan.js/wrappers/common.js.mustache b/docs/build/node_modules/hogan.js/wrappers/common.js.mustache
new file mode 100644
index 0000000000..e823e83a08
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/wrappers/common.js.mustache
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+{{{template}}}
+{{{compiler}}}
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Hogan;
+}
diff --git a/docs/build/node_modules/hogan.js/wrappers/js.mustache b/docs/build/node_modules/hogan.js/wrappers/js.mustache
new file mode 100644
index 0000000000..9f311f08d4
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/wrappers/js.mustache
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+{{{template}}}
+{{{compiler}}}
diff --git a/docs/build/node_modules/hogan.js/wrappers/mustache.js.mustache b/docs/build/node_modules/hogan.js/wrappers/mustache.js.mustache
new file mode 100644
index 0000000000..d3a3d70df9
--- /dev/null
+++ b/docs/build/node_modules/hogan.js/wrappers/mustache.js.mustache
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+// A wrapper for compatibility with Mustache.js, quirks and all
+
+{{{template}}}
+{{{compiler}}}
+
+var Mustache = (function (Hogan) {
+
+ // Mustache.js has non-spec partial context behavior
+ function mustachePartial(name, context, partials, indent) {
+ var partialScope = this.f(name, context, partials, 0);
+ var cx = context;
+ if (partialScope) {
+ cx = cx.concat(partialScope);
+ }
+
+ return Hogan.Template.prototype.rp.call(this, name, cx, partials, indent);
+ }
+
+ var HoganTemplateWrapper = function(renderFunc, text, compiler){
+ this.rp = mustachePartial;
+ Hogan.Template.call(this, renderFunc, text, compiler);
+ };
+ HoganTemplateWrapper.prototype = Hogan.Template.prototype;
+
+ // Add a wrapper for Hogan's generate method. Mustache and Hogan keep
+ // separate caches, and Mustache returns wrapped templates.
+ var wrapper;
+ var HoganWrapper = function(){
+ this.cache = {};
+ this.generate = function(code, text, options) {
+ return new HoganTemplateWrapper(new Function('c', 'p', 'i', code), text, wrapper);
+ }
+ };
+ HoganWrapper.prototype = Hogan;
+ wrapper = new HoganWrapper();
+
+ return {
+ to_html: function(text, data, partials, sendFun) {
+ var template = wrapper.compile(text);
+ var result = template.render(data, partials);
+ if (!sendFun) {
+ return result;
+ }
+
+ sendFun(result);
+ }
+ }
+
+})(Hogan);
diff --git a/docs/build/package.json b/docs/build/package.json
new file mode 100644
index 0000000000..97ab25909b
--- /dev/null
+++ b/docs/build/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "bootstrap-doc-builder"
+, "version": "0.0.1"
+, "description": "build bootstrap docs"
+, "dependencies": { "hogan.js": "1.0.5-dev" }
+}
diff --git a/docs/components.html b/docs/components.html
new file mode 100644
index 0000000000..d989e4e1a2
--- /dev/null
+++ b/docs/components.html
@@ -0,0 +1,1515 @@
+
+
+
+
+
Bootstrap, from Twitter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Components
+ Dozens of reusable components are built into Bootstrap to provide navigation, alerts, popovers, and much more.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lightweight defaults Same markup, different classes
+
+
+
Powerful base class
+
All nav components here—tabs, pills, and lists—share the same base markup and styles through the .nav
class.
+
Why tabs and pills
+
Tabs and pills in Bootstrap are built on a <ul>
with the same core HTML, a list of links. Swap between tabs or pills with only a class.
+
Both options are great for sub-sections of content or navigating between pages of related content.
+
+
+
Basic tabs
+
Take a regular <ul>
of links and add .nav-tabs
:
+
+
+<ul class="nav nav-tabs">
+ <li class="active">
+ <a href="#">Home</a>
+ </li>
+ <li><a href="#">...</a></li>
+ <li><a href="#">...</a></li>
+</ul>
+
+
+
+
Basic pills
+
Take that same HTML, but use .nav-pills
instead:
+
+
+<ul class="nav nav-pills">
+ <li class="active">
+ <a href="#">Home</a>
+ </li>
+ <li><a href="#">...</a></li>
+ <li><a href="#">...</a></li>
+</ul>
+
+
+
+
+ Stackable Make tabs or pills vertical
+
+
+
How to stack 'em
+
As tabs and pills are horizontal by default, just add a second class, .nav-stacked
, to make them appear vertically stacked.
+
+
+
Stacked tabs
+
+
+<ul class="nav nav-tabs nav-stacked">
+ ...
+</ul>
+
+
+
+
Stacked pills
+
+
+<ul class="nav nav-pills nav-stacked">
+ ...
+</ul>
+
+
+
+
+ Dropdowns For advanced nav components
+
+
+
Rich menus made easy
+
Dropdown menus in Bootstrap tabs and pills are super easy and require only a little extra HTML and a lightweight jQuery plugin.
+
Head over to the Javascript page to read the docs on initializing dropdowns in Bootstrap.
+
+
+
Tabs with dropdowns
+
+
+<ul class="nav nav-tabs">
+ <li class="dropdown">
+ <a class="dropdown-toggle"
+ data-toggle="dropdown"
+ href="#">
+ Dropdown
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <!-- links -->
+ </ul>
+ </li>
+</ul>
+
+
+
+
Pills with dropdowns
+
+
+<ul class="nav nav-pills">
+ <li class="dropdown">
+ <a class="dropdown-toggle"
+ data-toggle="dropdown"
+ href="#">
+ Dropdown
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <!-- links -->
+ </ul>
+ </li>
+</ul>
+
+
+
+
+ Nav lists Build simple stacked navs, great for sidebars
+
+
+
Application-style navigation
+
Nav lists provide a simple and easy way to build groups of nav links with optional headers. They're best used in sidebars like the Finder in OS X.
+
Structurally, they're built on the same core nav styles as tabs and pills, so usage and customization are straightforward.
+
With icons
+
Nav lists are also easy to equip with icons. Add the proper <i>
tag with class and you're set.
+
+
+
Example nav list
+
Take a list of links and add class="nav nav-list"
:
+
+
+<ul class="nav nav-list">
+ <li class="nav-header">
+ List header
+ </li>
+ <li class="active">
+ <a href="#">Home</a>
+ </li>
+ <li>
+ <a href="#">Library</a>
+ </li>
+ ...
+</ul>
+
+
+
+
Example with icons
+
Same example, but with <i>
tags for icons.
+
+
+<ul class="nav nav-list">
+ ...
+ <li>
+ <a href="#">
+ <i class="icon-book"></i>
+ Library
+ </a>
+ </li>
+ ...
+</ul>
+
+
+
+
+
+ Tabbable nav Bring tabs to life via javascript
+
+
+
What's included
+
Bring your tabs to life with a simple plugin to toggle between content via tabs. Bootstrap integrates tabbable tabs in four styles: top (default), right, bottom, and left.
+
Changing between them is easy and only requires changing very little markup.
+
+
+
Tabbable example
+
To make tabs tabbable, wrap the .nav-tabs
in another div with class .tabbable
.
+
+
+
+
+
+
Howdy, I'm in Section 2.
+
+
+
What up girl, this is Section 3.
+
+
+
+
+
+
Custom jQuery plugin
+
All tabbable tabs are powered by our lightweight jQuery plugin. Read more about how to bring tabbable tabs to life on the javascript docs page.
+
Get the javascript →
+
+
+
+ Straightforward markup
+ Using tabbable tabs requires a wrapping div, a set of tabs, and a set of tabbable panes of content.
+
+<div class="tabbable">
+ <ul class="nav nav-tabs">
+ <li class="active"><a href="#1" data-toggle="tab">Section 1</a></li>
+ <li><a href="#2" data-toggle="tab">Section 2</a></li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" id="1">
+ <p>I'm in Section 1.</p>
+ </div>
+ <div class="tab-pane" id="2">
+ <p>Howdy, I'm in Section 2.</p>
+ </div>
+ </div>
+</div>
+
+
+ Tabbable in any direction
+
+
+
Tabs on the bottom
+
Flip the order of the HTML and add a class to put tabs on the bottom.
+
+
+
+
+
Howdy, I'm in Section B.
+
+
+
What up girl, this is Section C.
+
+
+
+
+
+<div class="tabbable tabs-below">
+ <div class="tab-content">
+ ...
+ </div>
+ <ul class="nav nav-tabs">
+ ...
+ </ul>
+</div>
+
+
+
+
Tabs on the left
+
Swap the class to put tabs on the left.
+
+
+
+
+
+
Howdy, I'm in Section B.
+
+
+
What up girl, this is Section C.
+
+
+
+
+<div class="tabbable tabs-left">
+ <ul class="nav nav-tabs">
+ ...
+ </ul>
+ <div class="tab-content">
+ ...
+ </div>
+</div>
+
+
+
+
Tabs on the right
+
Swap the class to put tabs on the right.
+
+
+
+
+
+
Howdy, I'm in Section B.
+
+
+
What up girl, this is Section C.
+
+
+
+
+<div class="tabbable tabs-right">
+ <ul class="nav nav-tabs">
+ ...
+ </ul>
+ <div class="tab-content">
+ ...
+ </div>
+</div>
+
+
+
+
+
+
+
+
+
+
+
+ Static navbar example
+ An example of a static (not fixed to the top) navbar with project name, navigation, and search form.
+
+
+
+
+
Navbar scaffolding
+
The navbar requires only a few divs to structure it well for static or fixed display.
+
+<div class="navbar">
+ <div class="navbar-inner">
+ <div class="container">
+ ...
+ </div>
+ </div>
+</div>
+
+
To make the navbar fixed to the top of the viewport, add .navbar-fixed-top
to the outermost div, .navbar
. In your CSS, you will also need to account for the overlap it causes by adding padding-top: 40px;
to your <body>
.
+
+<div class="navbar navbar-fixed-top">
+ ...
+</div>
+
+
Brand name
+
A simple link to show your brand or project name only requires an anchor tag.
+
+<a class="brand" href="#">
+ Project name
+</a>
+
+
Search form
+
Search forms receive custom styles in the navbar with the .navbar-search
class. Include .pull-left
or .pull-right
on the form
to align it.
+
+<form class="navbar-search pull-left">
+ <input type="text" class="search-query" placeholder="Search">
+</form>
+
+
Optional responsive variation
+
Depending on the amount of content in your topbar, you might want to implement the responsive options. To do so, wrap your nav content in a containing div, .nav-collapse.collapse
, and add the navbar toggle button, .btn-navbar
.
+
+<div class="navbar">
+ <div class="navbar-inner">
+ <div class="container">
+
+ <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+
+ <!-- Be sure to leave the brand out there if you want it shown -->
+ <a class="brand" href="#">Project name</a>
+
+ <!-- Everything you want hidden at 940px or less, place within here -->
+ <div class="nav-collapse">
+ <!-- .nav, .navbar-search, .navbar-form, etc -->
+ </div>
+
+ </div>
+ </div>
+</div>
+
+
+
+
+
+
Nav links
+
Nav items are simple to add via unordered lists.
+
+<ul class="nav">
+ <li class="active">
+ <a href="#">Home</a>
+ </li>
+ <li><a href="#">Link</a></li>
+ <li><a href="#">Link</a></li>
+</ul>
+
+
Adding dropdowns
+
Adding dropdowns to the nav is super simple, but does require the use of our javascript plugin.
+
+<ul class="nav">
+ <li class="dropdown">
+ <a href="#"
+ class="dropdown-toggle"
+ data-toggle="dropdown">
+ Account
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ ...
+ </ul>
+ </li>
+</ul>
+
+
Get the javascript →
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Why use them
+
Breadcrumb navigation is used as a way to show users where they are within an app or a site, but not for primary navigation. Keep their use sparse and succinct to be most effective.
+
+
Examples
+
A single example shown as it might be displayed across multiple pages.
+
+
+
+
+
+
Markup
+
HTML is your standard unordered list with links.
+
+<ul class="breadcrumb">
+ <li>
+ <a href="#">Home</a> <span class="divider">/</span>
+ </li>
+ <li>
+ <a href="#">Library</a> <span class="divider">/</span>
+ </li>
+ <li class="active">
+ <a href="#">Data</a>
+ </li>
+</ul>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Labels |
+ Markup |
+
+
+
+
+
+ Default
+ |
+
+ <span class="label">Default</span>
+ |
+
+
+
+ New
+ |
+
+ <span class="label label-success">New</span>
+ |
+
+
+
+ Warning
+ |
+
+ <span class="label label-warning">Warning</span>
+ |
+
+
+
+ Important
+ |
+
+ <span class="label label-important">Important</span>
+ |
+
+
+
+ Info
+ |
+
+ <span class="label label-info">Info</span>
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Default thumbnails
+
By default, Bootstrap's thumbnails are designed to showcase linked images with minimal required markup.
+
+
+
+
Highly customizable
+
With a bit of extra markup, it's possible to add any kind of HTML content like headings, paragraphs, or buttons into thumbnails.
+
+ -
+
+

+
+
Thumbnail label
+
Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.
+
Action Action
+
+
+
+ -
+
+

+
+
Thumbnail label
+
Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.
+
Action Action
+
+
+
+
+
+
+
+
+
+
Why use thumbnails
+
Thumbnails (previously .media-grid
up until v1.4) are great for grids of photos or videos, image search results, retail products, portfolios, and much more. They can be links or static content.
+
+
+
Simple, flexible markup
+
Thumbnail markup is simple—a ul
with any number of li
elements is all that is required. It's also super flexible, allowing for any type of content with just a bit more markup to wrap your contents.
+
+
+
Uses grid column sizes
+
Lastly, the thumbnails component uses existing grid system classes—like .span2
or .span3
—for control of thumbnail dimensions.
+
+
+
+
+
+
The markup
+
As mentioned previously, the required markup for thumbnails is light and straightforward. Here's a look at the default setup for linked images:
+
+<ul class="thumbnails">
+ <li class="span3">
+ <a href="#" class="thumbnail">
+ <img src="http://placehold.it/260x180" alt="">
+ </a>
+ </li>
+ ...
+</ul>
+
+
For custom HTML content in thumbnails, the markup changes slightly. To allow block level content anywhere, we swap the <a>
for a <div>
like so:
+
+<ul class="thumbnails">
+ <li class="span3">
+ <div class="thumbnail">
+ <img src="http://placehold.it/260x180" alt="">
+ <h5>Thumbnail label</h5>
+ <p>Thumbnail caption right here...</p>
+ </div>
+ </li>
+ ...
+</ul>
+
+
+
+
More examples
+
Explore all your options with the various grid classes available to you. You can also mix and match different sizes.
+
+
+
+
+
+
+
+
+
+
+
+
+ Lightweight defaults
+
+
+
Rewritten base class
+
With Bootstrap 2, we've simplified the base class: .alert
instead of .alert-message
. We've also reduced the minimum required markup—no <p>
is required by default, just the outter <div>
.
+
Single alert message
+
For a more durable component with less code, we've removed the differentiating look for block alerts, messages that come with more padding and typically more text. The class also has changed to .alert-block
.
+
+
Goes great with javascript
+
Bootstrap comes with a great jQuery plugin that supports alert messages, making dismissing them quick and easy.
+
Get the plugin »
+
+
+
Example alerts
+
Wrap your message and an optional close icon in a div with simple class.
+
+
×
+
Warning! Best check yo self, you’re not looking too good.
+
+
+<div class="alert">
+ <a class="close">×</a>
+ <strong>Warning!</strong> Best check yo self, you’re not looking too good.
+</div>
+
+
Easily extend the standard alert message with two optional classes: .alert-block
for more padding and text controls and .alert-heading
for a matching heading.
+
+
×
+
Warning!
+
Best check yo self, you’re not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
+
+
+<div class="alert alert-block">
+ <a class="close">×</a>
+ <h4 class="alert-heading">Warning!</h4>
+ Best check yo self, you’re not...
+</div>
+
+
+
+
+ Contextual alternatives Add optional classes to change an alert's connotation
+
+
+
Error or danger
+
+
×
+
Oh snap! Change a few things up and try submitting again.
+
+
+<div class="alert alert-error">
+ ...
+</div>
+
+
+
+
Success
+
+
×
+
Well done! You successfully read this important alert message.
+
+
+<div class="alert alert-success">
+ ...
+</div>
+
+
+
+
Information
+
+
×
+
Heads up! This alert needs your attention, but it’s not super important.
+
+
+<div class="alert alert-info">
+ ...
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+ Examples and markup
+
+
+
Basic
+
Default progress bar with a vertical gradient.
+
+
+<div class="progress">
+ <div class="bar"
+ style="width: 60%;"></div>
+</div>
+
+
+
+
Striped
+
Uses a gradient to create a striped effect.
+
+
+<div class="progress progress-info
+ progress-striped">
+ <div class="bar"
+ style="width: 20%;"></div>
+</div>
+
+
+
+
Animated
+
Takes the striped example and animates it.
+
+
+<div class="progress progress-danger
+ progress-striped active">
+ <div class="bar"
+ style="width: 40%;"></div>
+</div>
+
+
+
+
+ Options and browser support
+
+
+
Additional colors
+
Progress bars utilize some of the same class names as buttons and alerts for similar styling.
+
+ .progress-info
+ .progress-success
+ .progress-danger
+
+
Alternatively, you can customize the LESS files and roll your own colors and sizes.
+
+
+
Behavior
+
Progress bars use CSS3 transitions, so if you dynamically adjust the width via javascript, it will smoothly resize.
+
If you use the .active
class, your .progress-striped
progress bars will animate the stripes left to right.
+
+
+
Browser support
+
Progress bars use CSS3 gradients, transitions, and animations to achieve all their effects. These features are not supported in IE7-8 or older versions of Firefox.
+
Opera does not support animations at this time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Wells
+
Use the well as a simple effect on an element to give it an inset effect.
+
+ Look, I'm in a well!
+
+
+<div class="well">
+ ...
+</div>
+
+
+
+
Badges
+
Use a badge on an element for an unread count or as a simple indicator.
+
<span class="badge">3</div>
+
+
+
Close icon
+
Use the generic close icon for dismissing content like modals and alerts.
+
×
+
<a class="close">×</a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/download.html b/docs/download.html
new file mode 100644
index 0000000000..8367e2e831
--- /dev/null
+++ b/docs/download.html
@@ -0,0 +1,358 @@
+
+
+
+
+
Bootstrap, from Twitter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Customize and download
+ Download the full repository or customize your entire Bootstrap build by selecting only the components, javascript plugins, and assets you need.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Customize and Download
+
What's included?
+
Downloads include compiled CSS, compiled and minified CSS, and compiled jQuery plugins, all nicely packed up into a zipball for your convenience.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/examples.html b/docs/examples.html
new file mode 100644
index 0000000000..83188c77f1
--- /dev/null
+++ b/docs/examples.html
@@ -0,0 +1,168 @@
+
+
+
+
+
Bootstrap, from Twitter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Heads up! This page is still under construction and is missing plenty of documentation. Hang tight!
+
+
+
+
+
+
+
+ -
+
+
+
+ Basic marketing site
+
+
+ -
+
+
+
+ Fluid layout
+
+
+ -
+
+
+
+ Fluid layout reversed
+
+
+ -
+
+
+
+ Container application
+
+
+ -
+
+
+
+ Fullscreen
+
+
+ -
+
+
+
+ Simple layout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/index.html b/docs/index.html
index e12fa8063d..d744248523 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -3,6 +3,7 @@
Bootstrap, from Twitter
+
@@ -12,2029 +13,235 @@
-
+
+
-
-
-
-
+
+
+
+
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
Hotlink the CSS
-
For the quickest and easiest start, just copy this snippet into your webpage.
-
-
-
-
Use it with Less
-
A fan of using Less? No problem, just clone the repo and add these lines:
-
-
-
-
Fork on GitHub
-
Download, fork, pull, file issues, and more with the official Bootstrap repo on Github.
-
Bootstrap on GitHub »
-
Currently v1.4.0
-
-
-
-
-
-
-
-
-
-
-
-
-
History
-
Engineers at Twitter have historically used almost any library they were familiar with to meet front-end requirements. Bootstrap began as an answer to the challenges that presented. With the help of many awesome folks, Bootstrap has grown significantly.
-
Read more on dev.twitter.com ›
-
-
-
-
-
-
-
Browser support
-
Bootstrap is tested and supported in major modern browsers like Chrome, Safari, Internet Explorer, and Firefox.
-

-
- - Latest Safari
- - Latest Google Chrome
- - Firefox 4+
- - Internet Explorer 7+
- - Opera 11
-
-
-
-
What's included
-
Bootstrap comes complete with compiled CSS, uncompiled, and example templates.
-
-
-
-
-
-
-
Quick-start examples
-
Need some quick templates? Check out these basic examples we've put together:
-
-
-
-
-
-
-
-
-
-
-
-
-
Default grid
-
The default grid system provided as part of Bootstrap is a 940px wide 16-column grid. It’s a flavor of the popular 960 grid system, but without the additional margin/padding on the left and right sides.
-
-
-
Example grid markup
-
As shown here, a basic layout can be created with two "columns," each spanning a number of the 16 foundational columns we defined as part of our grid system. See the examples below for more variations.
-
-<div class="row">
- <div class="span6">
- ...
- </div>
- <div class="span10">
- ...
- </div>
-</div>
-
-
-
-
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
-
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
-
-
3
-
3
-
3
-
3
-
3
-
1
-
-
-
-
-
-
-
-
-
-
-
- Offsetting columns
-
-
-
-
4 offset 4
-
4 offset 4
-
-
-
5 offset 3
-
5 offset 3
-
-
-
-
-
-
-
-
Nesting columns
-
Nest your content if you must by creating a .row
within an existing column.
-
-
-
Example of nested columns
-
-
- Level 1 of column
-
-
- Level 2
-
-
- Level 2
-
-
-
-
-
-<div class="row">
- <div class="span12">
- Level 1 of column
- <div class="row">
- <div class="span6">
- Level 2
- </div>
- <div class="span6">
- Level 2
- </div>
- </div>
- </div>
-</div>
-
-
+
+
+
+
+
Designed for everyone, everywhere.
+
Need reasons to love Bootstrap? Look no further.
-
Roll your own grid
-
Built into Bootstrap are a handful of variables for customizing the default 940px grid system. With a bit of customization, you can modify the size of columns, their gutters, and the container they reside in.
+

+
Built for and by nerds
+
Like you, we love building awesome products on the web. We love it so much, we decided to help people just like us do it easier, better, and faster. Bootstrap is built for you.
-
-
Inside the grid
-
The variables needed to modify the grid system currently all reside in variables.less
.
-
-
-
- Variable |
- Default value |
- Description |
-
-
-
-
- @gridColumns |
- 16 |
- The number of columns within the grid |
-
-
- @gridColumnWidth |
- 40px |
- The width of each column within the grid |
-
-
- @gridGutterWidth |
- 20px |
- The negative space between each column |
-
-
- @siteWidth |
- Computed sum of all columns and gutters |
- We use some basic math to count the number of columns and gutters and set the width of the .fixed-container() mixin. |
-
-
-
-
Now to customize
-
Modifying the grid means changing the three @grid-*
variables and recompiling the Less files.
-
Bootstrap comes equipped to handle a grid system with up to 24 columns; the default is just 16. Here's how your grid variables would look customized to a 24-column grid.
-
@gridColumns: 24;
-@gridColumnWidth: 20px;
-@gridGutterWidth: 20px;
-
Once recompiled, you'll be set!
+
+

+
For all skill levels
+
Bootstrap is designed to help people of all skill level—designer or developer, huge nerd or early beginner. Use it as a complete kit or use to start something more complex.
-
-
-
-
-
-
-
-
-
-
-
-
Fixed layout
-
The default and simple 940px-wide, centered layout for just about any website or page provided by a single <div.container>
.
-
-
-<body>
- <div class="container">
- ...
- </div>
-</body>
-
-
-
-
Fluid layout
-
An alternative, flexible fluid page structure with min- and max-widths and a left-hand sidebar. Great for apps and docs.
-
-
-<body>
- <div class="container-fluid">
- <div class="sidebar">
- ...
- </div>
- <div class="content">
- ...
- </div>
- </div>
-</body>
-
-
-
-
-
-
-
-
-
-
-
-
+
+

+
Cross-everything
+
Originally built with only modern browsers in mind, Bootstrap has evolved to include support for all major browsers (even IE7!) and, with Bootstrap 2, tablets and smartphones, too.
+
+
-
Headings & copy
-
A standard typographic hierarchy for structuring your webpages.
-
The entire typographic grid is based on two Less variables in our variables.less file: @basefont
and @baseline
. The first is the base font-size used throughout and the second is the base line-height.
-
We use those variables, and some math, to create the margins, paddings, and line-heights of all our type and more.
+

+
12-column grid
+
Grid systems aren't everything, but having a durable and flexible one at the core of your work can make development much simpler. Use our built-in grid classes or roll your own.
-
h1. Heading 1
-
h2. Heading 2
-
h3. Heading 3
-
h4. Heading 4
-
h5. Heading 5
-
h6. Heading 6
+

+
Responsive design
+
With Bootstrap 2, we've gone fully responsive. Our components are scaled according to a range of resolutions and devices to provide a consistent experience, no matter what.
-
-
Example paragraph
-
Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit.
-
Example heading Has sub-heading…
+
+

+
Styleguide docs
+
Unlike other front-end toolkits, Bootstrap was designed first and foremost as a styleguide to document not only our features, but best practices and living, coded examples.
-
-
-
+
-
Misc. elements
-
Using emphasis, addresses, & abbreviations
-
- <strong>
- <em>
- <address>
- <abbr>
-
+

+
Growing library
+
Despite being only 10kb (gzipped), Bootstrap is one of the most complete front-end toolkits out there with dozens of fully functional components ready to be put to use.
-
-
When to use
-
Emphasis tags (<strong>
and <em>
) should be used to indicate additional importance or emphasis of a word or phrase relative to its surrounding copy. Use <strong>
for importance and <em>
for stress emphasis.
-
Emphasis in a paragraph
-
Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Maecenas faucibus mollis interdum. Nulla vitae elit libero, a pharetra augue.
-
Note: It's still okay to use <b>
and <i>
tags in HTML5 and they don't have to be styled bold and italic, respectively (although if there is a more semantic element, use it). <b>
is meant to highlight words or phrases without conveying additional importance, while <i>
is mostly for voice, technical terms, etc.
-
Addresses
-
The <address>
element is used for contact information for its nearest ancestor, or the entire body of work. Here are two examples of how it could be used:
-
-
-
-
- Twitter, Inc.
- 795 Folsom Ave, Suite 600
- San Francisco, CA 94107
- P: (123) 456-7890
-
-
-
-
-
-
Note: Each line in an <address>
must end with a line-break (<br />
) or be wrapped in a block-level tag (e.g., <p>
) to properly structure the content.
-
Abbreviations
-
For abbreviations and acronyms, use the <abbr>
tag (<acronym>
is deprecated in HTML5). Put the shorthand form within the tag and set a title for the complete name.
+
+

+
Custom jQuery plugins
+
What good is an awesome design component without easy-to-use, proper, and extensible interactions? With Bootstrap, you get custom-built jQuery plugins to bring your projects to life.
-
-
-
+
+

+
Built on LESS
+
Where vanilla CSS falters, LESS excels. Variables, nesting, operations, and mixins in LESS makes coding CSS faster and more efficient with minimal overhead.
+
+
-
-
Blockquotes
-
- <blockquote>
- <p>
- <small>
-
+
+

+
HTML5
+
Built to support new HTML5 elements and syntax.
-
-
How to quote
-
To include a blockquote, wrap <blockquote>
around <p>
and <small>
tags. Use the <small>
element to cite your source and you'll get an em dash —
before it.
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
- Dr. Julius Hibbert
-
-
-<blockquote>
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</p>
- <small>Dr. Julius Hibbert</small>
-</blockquote>
-
+
+

+
CSS3
+
Progressively enhanced components for ultimate style.
-
-
-
Lists
-
-
-
Unordered <ul>
-
- - Lorem ipsum dolor sit amet
- - Consectetur adipiscing elit
- - Integer molestie lorem at massa
- - Facilisis in pretium nisl aliquet
- - Nulla volutpat aliquam velit
-
- - Phasellus iaculis neque
- - Purus sodales ultricies
- - Vestibulum laoreet porttitor sem
- - Ac tristique libero volutpat at
-
-
- - Faucibus porta lacus fringilla vel
- - Aenean sit amet erat nunc
- - Eget porttitor lorem
-
+
+

+
Open-source
+
Built for and maintained by the community via GitHub.
-
-
Unstyled <ul.unstyled>
-
- - Lorem ipsum dolor sit amet
- - Consectetur adipiscing elit
- - Integer molestie lorem at massa
- - Facilisis in pretium nisl aliquet
- - Nulla volutpat aliquam velit
-
- - Phasellus iaculis neque
- - Purus sodales ultricies
- - Vestibulum laoreet porttitor sem
- - Ac tristique libero volutpat at
-
-
- - Faucibus porta lacus fringilla vel
- - Aenean sit amet erat nunc
- - Eget porttitor lorem
-
+
-
-
Ordered <ol>
-
- - Lorem ipsum dolor sit amet
- - Consectetur adipiscing elit
- - Integer molestie lorem at massa
- - Facilisis in pretium nisl aliquet
- - Nulla volutpat aliquam velit
- - Faucibus porta lacus fringilla vel
- - Aenean sit amet erat nunc
- - Eget porttitor lorem
-
-
-
-
Description dl
-
- - Description lists
- - A description list is perfect for defining terms.
- - Euismod
- - Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit.
- - Donec id elit non mi porta gravida at eget metus.
- - Malesuada porta
- - Etiam porta sem malesuada magna mollis euismod.
-
-
-
+
+
-
-
-
-
Code
-
- <code>
- <pre>
-
-
Pimp your code in style with two simple tags. For even more awesomeness through javascript, drop in Google's code prettify library and you're set.
-
-
-
Presenting code
-
Code, blocks of or just snippets inline, can be displayed with style just by wrapping in the right tag. For blocks of code spanning multiple lines, use the <pre>
element. For inline code, use the <code>
element.
-
-
-
- Element |
- Result |
-
-
-
-
- <code> |
- In a line of text like this, your wrapped code will look like this <html> element. |
-
-
- <pre> |
-
-<div>
- <h1>Heading</h1>
- <p>Something right here...</p>
-</div>
- Note: Be sure to keep code within <pre> tags as close to the left as possible; it will render all tabs.
- |
-
-
- <pre class="prettyprint"> |
-
- Using the google-code-prettify library, your blocks of code get a slightly different visual style and automatic syntax highlighting.
-<div>
- <h1>Heading</h1>
- <p>Something right here...</p>
-</div>
- Download google-code-prettify and view the readme for how to use.
- |
-
-
-
-
-
-
-
-
-
-
Inline labels
-
- <span class="label">
-
-
Call attention to or flag any phrase in your body text.
-
-
-
Label anything
-
Ever needed one of those fancy New! or Important flags when writing code? Well, now you have them. Here's what's included by default:
-
-
-
- Label |
- Result |
-
-
-
-
-
- <span class="label">Default</span>
- |
-
- Default
- |
-
-
-
- <span class="label success">New</span>
- |
-
- New
- |
-
-
-
- <span class="label warning">Warning</span>
- |
-
- Warning
- |
-
-
-
- <span class="label important">Important</span>
- |
-
- Important
- |
-
-
-
- <span class="label notice">Notice</span>
- |
-
- Notice
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Building tables
-
- <table>
- <thead>
- <tbody>
- <tr>
- <th>
- <td>
- <colspan>
- <caption>
-
-
Tables are great—for a lot of things. Great tables, however, need a bit of markup love to be useful, scalable, and readable (at the code level). Here are a few tips to help.
-
Always wrap your column headers in a <thead>
such that hierarchy is <thead>
> <tr>
> <th>
.
-
Similar to the column headers, all your table’s body content should be wrapped in a <tbody>
so your hierarchy is <tbody>
> <tr>
> <td>
.
-
-
-
Example: Default table styles
-
All tables will be automatically styled with only the essential borders to ensure readability and maintain structure. No need to add extra classes or attributes.
-
-
-
- # |
- First Name |
- Last Name |
- Language |
-
-
-
-
- 1 |
- Some |
- One |
- English |
-
-
- 2 |
- Joe |
- Sixpack |
- English |
-
-
- 3 |
- Stu |
- Dent |
- Code |
-
-
-
-
-<table>
- ...
-</table>
-
Example: Condensed table
-
For tables that require more data in tighter spaces, use the condensed flavor that cuts padding in half. It can also be used in conjunction with borders and zebra-stripes, just like the default table styles.
-
-
-
- # |
- First Name |
- Last Name |
- Language |
-
-
-
-
- 1 |
- Some |
- One |
- English |
-
-
- 2 |
- Joe |
- Sixpack |
- English |
-
-
- 3 |
- Stu |
- Dent |
- Code |
-
-
-
-
-<table class="condensed-table">
- ...
-</table>
-
Example: Bordered table
-
Make your tables look just a wee bit sleeker by rounding their corners and adding borders on all sides.
-
-
-
- # |
- First Name |
- Last Name |
- Language |
-
-
-
-
- 1 |
- Some |
- One |
- English |
-
-
- 2 |
- Joe |
- Sixpack |
- English |
-
-
- 3 |
- Stu |
- Dent |
- Code |
-
-
-
-
-<table class="bordered-table">
- ...
-</table>
-
Example: Zebra-striped
-
Get a little fancy with your tables by adding zebra-striping—just add the .zebra-striped
class.
-
-
-
- # |
- First Name |
- Last Name |
- Language |
-
-
-
-
- 1 |
- Some |
- One |
- English |
-
-
- 2 |
- Joe |
- Sixpack |
- English |
-
-
- 3 |
- Stu |
- Dent |
- Code |
-
-
-
- span 4 columns
- |
-
-
-
- span 2 columns
- |
-
- span 2 columns
- |
-
-
-
-
Note: Zebra-striping is a progressive enhancement not available for older browsers like IE8 and below.
-
-<table class="zebra-striped">
- ...
-</table>
-
Example: Zebra-striped w/ TableSorter.js
-
Taking the previous example, we improve the usefulness of our tables by providing sorting functionality via jQuery and the Tablesorter plugin. Click any column’s header to change the sort.
-
-
-
- # |
- First Name |
- Last Name |
- Language |
-
-
-
-
- 1 |
- Your |
- One |
- English |
-
-
- 2 |
- Joe |
- Sixpack |
- English |
-
-
- 3 |
- Stu |
- Dent |
- Code |
-
-
-
-
-<script src="js/jquery/jquery.tablesorter.min.js"></script>
-<script >
- $(function() {
- $("table#sortTableExample").tablesorter({ sortList: [[1,0]] });
- });
-</script>
-<table class="zebra-striped">
- ...
-</table>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Fixed topbar
-
-
-
-
-
What is it
-
Our topbar is a fixed bar that houses a website’s logo or name, primary navigation, and search form.
-
-
-
Customizable
-
All elements within, and the entire topbar as well, are optional. You can choose to include a logo/name, nav, search, and a secondary nav—or any combination of that.
-
-
-
Dropdowns included
-
As part of the main navigation, we’ve included the ability for you to add dropdowns to your nav. Check out the secondary nav above (right aligned) to see how it’s done. Dropdowns li
tags also support .active
for showing current page selection.
-
-
- Note: When using the topbar on any page, be sure to account for the overlap it causes by adding padding-top: 40px;
to your body
.
-
-
-
-
-
-
Tabs and pills
-
Create simple secondary navigation with a <ul>
. Swap between tabs or pills by adding the appropriate class.
-
Great for sub-sections of content like our account settings pages and user timelines for toggling between pages of like content. Available in tabbed or pill styles.
-
-
-
Basic tabs example
-
Tabs can be used as regular navigation (loading external pages in the same tab) or as tabbable content areas for swapping out panes of content. We have a tabs plugin that can be used to integrate the latter.
-
-
-<ul class="tabs">
- <li class="active"><a href="#">Home</a></li>
- <li><a href="#">Profile</a></li>
- <li><a href="#">Messages</a></li>
- <li><a href="#">Settings</a></li>
- <li><a href="#">Contact</a></li>
-</ul>
-
-
Basic pills example
-
-
-<ul class="pills">
- <li class="active"><a href="#">Home</a></li>
- <li><a href="#">Profile</a></li>
- <li><a href="#">Messages</a></li>
- <li><a href="#">Settings</a></li>
- <li><a href="#">Contact</a></li>
-</ul>
-
-
-
-
-
-
-
-
Breadcrumbs
-
Breadcrumb navigation is used as a way to show users where they are within an app or a site, but not for primary navigation.
-
-
-
-
-
-
-
-<ul class="breadcrumb">
- <li><a href="#">Home</a> <span class="divider">/</span></li>
- <li><a href="#">Middle page</a> <span class="divider">/</span></li>
- <li><a href="#">Another one</a> <span class="divider">/</span></li>
- <li class="active">You are here</li>
-</ul>
-
-
-
-
-
-
-
-
Pagination
-
Ultra simplistic and minimally styled pagination inspired by Rdio. The large block is hard to miss, easily scalable, and provides large click areas.
-
-
-
-
-
-
-<div class="pagination">
- <ul>
- <li class="prev disabled"><a href="#">← Previous</a></li>
- <li class="active"><a href="#">1</a></li>
- <li><a href="#">2</a></li>
- <li><a href="#">3</a></li>
- <li><a href="#">4</a></li>
- <li><a href="#">5</a></li>
- <li class="next"><a href="#">Next →</a></li>
- </ul>
-</div>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Basic alerts
-
.alert-message
-
One-line messages for highlighting the failure, possible failure, or success of an action. Particularly useful for forms.
-
Get the javascript »
-
-
-
-
-
×
-
Oh snap! Change this and that and try again.
-
-
-
×
-
Well done! You successfully read this alert message.
-
-
-
×
-
Heads up! This is an alert that needs your attention, but it’s not a huge priority just yet.
-
-
-
Example code
-
-<div class="alert-message warning">
- <a class="close" href="#">×</a>
- <p><strong>Holy guacamole!</strong> Best check yo self, you’re not looking too good.</p>
-</div>
-
-
-
-
-
-
-
Block messages
-
.alert-message.block-message
-
For messages that require a bit of explanation, we have paragraph style alerts. These are perfect for bubbling up longer error messages, warning a user of a pending action, or just presenting information for more emphasis on the page.
-
Get the javascript »
-
-
-
-
×
-
Holy guacamole! This is a warning! Best check yo self, you’re not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
-
-
-
-
×
-
Oh snap! You got an error! Change this and that and try again.
-
- - Duis mollis est non commodo luctus
- - Nisi erat porttitor ligula
- - Eget lacinia odio sem nec elit
-
-
-
-
-
×
-
Well done! You successfully read this alert message. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas faucibus mollis interdum.
-
-
-
-
×
-
Heads up! This is an alert that needs your attention, but it’s not a huge priority just yet.
-
-
-
-
Example code
-
-<div class="alert-message block-message warning">
- <a class="close" href="#">×</a>
- <p><strong>Holy guacamole! This is a warning!</strong> Best check yo self, you’re not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</p>
- <div class="alert-actions">
- <a class="btn small" href="#">Take this action</a> <a class="btn small" href="#">Or do this</a>
- </div>
-</div>
-
-
-
-
-
-
-
-
-
-
-
-
Modals
-
Modals—dialogs or lightboxes—are great for contextual actions in situations where it’s important that the background context be maintained.
-
Get the javascript »
-
-
-
-
-
-
-
-
Tooltips
-
Twipsies are super useful for aiding a confused user and pointing them in the right direction.
-
Get the javascript »
-
-
-
-
-
-Lorem ipsum dolar sit amet illo error ipsum veritatis aut iste perspiciatis iste voluptas natus illo quasi odit aut natus consequuntur consequuntur, aut natus illo voluptatem odit perspiciatis laudantium rem doloremque totam voluptas. Voluptasdicta eaque beatae aperiam ut enim voluptatem explicabo explicabo, voluptas quia odit fugit accusantium totam totam architecto explicabo sit quasi fugit fugit, totam doloremque unde sunt sed dicta quae accusantium fugit voluptas nemo voluptas voluptatem rem quae aut veritatis quasi quae.
-
-
-
-
-
-
-
-
-
-
Popovers
-
Use popovers to provide subtextual information to a page without affecting layout.
-
Get the javascript »
-
-
-
-
-
-
-
-
Popover Title
-
-
Etiam porta sem malesuada magna mollis euismod. Maecenas faucibus mollis interdum. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
Getting started
-
Integrating javascript with the Bootstrap library is super easy. Below we go over the basics and provide you with some awesome plugins to get you started!
-
View javascript docs »
-
-
-
What's included
-
Bring some of Bootstrap's primary components to life with new custom plugins that work with jQuery and Ender. We encourage you to extend and modify them to fit your specific development needs.
-
-
-
- File |
- Description |
-
-
-
-
- bootstrap-modal.js |
- Our Modal plugin is a super slim take on the traditional modal js plugin! We took special care to include only the bare functionality that we require at twitter. |
-
-
- bootstrap-alerts.js |
- The alert plugin is a super tiny class for adding close functionality to alerts. |
-
-
- bootstrap-dropdown.js |
- This plugin is for adding dropdown interaction to the bootstrap topbar or tabbed navigations. |
-
-
- bootstrap-scrollspy.js |
- The ScrollSpy plugin is for adding an auto updating nav based on scroll position to the bootstrap topbar. |
-
-
- bootstrap-buttons.js |
- This plugin offers additional functionality for managing button state. |
-
-
- bootstrap-tabs.js |
- This plugin adds quick, dynamic tab and pill functionality for cycling through local content. |
-
-
- bootstrap-twipsy.js |
- Based on the excellent jQuery.tipsy plugin written by Jason Frame; twipsy is an updated version, which doesn't rely on images, uses css3 for animations, and data-attributes for local title storage! |
-
-
- bootstrap-popover.js |
- The popover plugin provides a simple interface for adding popovers to your application. It extends the boostrap-twipsy.js plugin, so be sure to grab that file as well when including popovers in your project! |
-
-
-
-
Is javascript necessary?
-
Nope! Bootstrap is designed first and foremost to be a CSS library. This javascript provides a basic interactive layer on top of the included styles.
-
However, for those who do need javascript, we've provided the plugins above to help you understand how to integrate Bootstrap with javascript and to give you a quick, lightweight option for the basic functionality right away.
-
For more information and to see some live demos, please refer to our plugin documentation page.
-
-
-
-
-
-
-
-
-
-
Bootstrap was built from Preboot, an open-source pack of mixins and variables to be used in conjunction with Less, a CSS preprocessor for faster and easier web development.
-
Check out how we used Preboot in Bootstrap and how you can make use of it should you choose to run Less on your next project.
-
-
-
How to use it
-
Use this option to make full use of Bootstrap’s Less variables, mixins, and nesting in CSS via javascript in your browser.
-
-<link rel="stylesheet/less" href="less/bootstrap.less" media="all" />
-<script src="js/less-1.1.4.min.js"></script>
-
Not feeling the .js solution? Try the Less Mac app or use Node.js to compile when you deploy your code.
-
-
What’s included
-
Here are some of the highlights of what’s included in Twitter Bootstrap as part of Bootstrap. Head over to the Bootstrap website or Github project page to download and learn more.
-
Variables
-
Variables in Less are perfect for maintaining and updating your CSS headache free. When you want to change a color value or a frequently used value, update it in one spot and you’re set.
-
-// Links
-@linkColor: #8b59c2;
-@linkColorHover: darken(@linkColor, 10);
-
-// Grays
-@black: #000;
-@grayDark: lighten(@black, 25%);
-@gray: lighten(@black, 50%);
-@grayLight: lighten(@black, 70%);
-@grayLighter: lighten(@black, 90%);
-@white: #fff;
-
-// Accent Colors
-@blue: #08b5fb;
-@green: #46a546;
-@red: #9d261d;
-@yellow: #ffc40d;
-@orange: #f89406;
-@pink: #c3325f;
-@purple: #7a43b6;
-
-// Baseline grid
-@basefont: 13px;
-@baseline: 18px;
-
-
-
Commenting
-
Less also provides another style of commenting in addition to CSS’s normal /* ... */
syntax.
-
-// This is a comment
-/* This is also a comment */
-
-
-
Mixins up the wazoo
-
Mixins are basically includes or partials for CSS, allowing you to combine a block of code into one. They’re great for vendor prefixed properties like box-shadow
, cross-browser gradients, font stacks, and more. Below is a sample of the mixins that are included with Bootstrap.
-
Font stacks
-
-#font {
- .shorthand(@weight: normal, @size: 14px, @lineHeight: 20px) {
- font-size: @size;
- font-weight: @weight;
- line-height: @lineHeight;
- }
- .sans-serif(@weight: normal, @size: 14px, @lineHeight: 20px) {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: @size;
- font-weight: @weight;
- line-height: @lineHeight;
- }
- ...
-}
-
-
Gradients
-
-#gradient {
- ...
- .vertical (@startColor: #555, @endColor: #333) {
- background-color: @endColor;
- background-repeat: repeat-x;
- background-image: -khtml-gradient(linear, left top, left bottom, from(@startColor), to(@endColor)); // Konqueror
- background-image: -moz-linear-gradient(@startColor, @endColor); // FF 3.6+
- background-image: -ms-linear-gradient(@startColor, @endColor); // IE10
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, @startColor), color-stop(100%, @endColor)); // Safari 4+, Chrome 2+
- background-image: -webkit-linear-gradient(@startColor, @endColor); // Safari 5.1+, Chrome 10+
- background-image: -o-linear-gradient(@startColor, @endColor); // Opera 11.10
- background-image: linear-gradient(@startColor, @endColor); // The standard
- }
- ...
-}
-
-
-
Operations
-
Get fancy and perform some math to generate flexible and powerful mixins like the one below.
-
-// Griditude
-@gridColumns: 16;
-@gridColumnWidth: 40px;
-@gridGutterWidth: 20px;
-@siteWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
-
-// Make some columns
-.columns(@columnSpan: 1) {
- width: (@gridColumnWidth * @columnSpan) + (@gridGutterWidth * (@columnSpan - 1));
-}
-
-
-
Compiling Less
-
After modifying the .less
files in /lib/, you'll need to recompile them in order to regenerate the bootstrap-*.*.*.css and bootstrap-*.*.*.min.css files. If you're submitting a pull request to GitHub, you must always recompile.
-
Ways to compile
-
-
-
- Method |
- Steps |
-
-
-
-
- Node with makefile |
-
- Install the less command line compiler with npm by running the following command:
- $ npm install less
- Once installed just run make from the root of your bootstrap directory and you're all set.
- Additionally, if you have watchr installed, you may run make watch to have bootstrap automatically rebuilt every time you edit a file in the bootstrap lib (this isn't required, just a convenience method).
- |
-
- Javascript |
-
- Download the latest Less.js and include the path to it (and Bootstrap) in the head .
-
-<link rel="stylesheet/less" href="/path/to/bootstrap.less">
-<script src="/path/to/less.js"></script>
-
- To recompile the .less files, just save them and reload your page. Less.js compiles them and stores them in local storage.
- |
-
-
- Command line |
-
- If you already have the less command line tool installed, simply run the following command:
- $ lessc ./lib/bootstrap.less > bootstrap.css
- Be sure to include --compress in that command if you're trying to save some bytes!
- |
-
-
- Less Mac app |
-
- The unofficial Mac app watches directories of .less files and compiles the code to local files after every save of a watched .less file.
- If you like, you can toggle preferences in the app for automatic minifying and which directory the compiled files end up in.
- |
-
-
-
-
-
-
-
+ Built with Bootstrap.
+ For even more sites built with Bootstrap, visit the unofficial Tumblr or browse the examples.
+
+
+
+
-
-
-
-
+
+
+
+
-
+
+
+
-
+
+
+
+
+
+
+
-
diff --git a/docs/javascript.html b/docs/javascript.html
index 10d81a0c30..188d26e34e 100644
--- a/docs/javascript.html
+++ b/docs/javascript.html
@@ -3,6 +3,7 @@
Bootstrap, from Twitter
+
@@ -11,87 +12,246 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
-
+
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Heads up! All javascript plugins require the latest version of jQuery.
+
+
+
+
-
-
+
-
-
Our Modal plugin is a super slim take on the traditional modal js plugin, taking special care to include only the bare functionality that we require here at twitter.
-
Download
+
+
About modals
+
A streamlined, but flexible, take on the traditional javascript modal plugin with only the minimum required functionality and smart defaults.
+
Download file
-
-
Using bootstrap-modal
-
$('#my-modal').modal(options)
+
+
Static example
+
Below is a statically rendered modal.
+
+
+
Live demo
+
Toggle a modal via javascript by clicking the button below. It will slide down and fade in from the top of the page.
+
+
+
+
+
Text in a modal
+
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem.
+
+
Popover in a modal
+
This button should trigger a popover on hover.
+
+
Tooltips in a modal
+
This link and that link should have tooltips on hover.
+
+
+
+
Launch demo modal
+
+
+
+
Using bootstrap-modal
+
Call the modal via javascript:
+
$('#myModal').modal(options)
Options
-
+
Name |
@@ -103,53 +263,62 @@
backdrop |
- boolean, string |
- false |
- Includes a modal-backdrop element. Set backdrop to "static" if you do not want the modal closed when the backdrop is clicked. |
+ boolean |
+ true |
+ Includes a modal-backdrop element |
keyboard |
boolean |
- false |
+ true |
Closes the modal when escape key is pressed |
-
- show |
- boolean |
- false |
- Opens modal on class initialization |
-
Markup
- You can activate modals on your page easily without having to write a single line of javascript. Just give an element a data-controls-modal
attribute which corresponds to a modal element id, and when clicked, it will launch your modal. To add modal options, just include them as data attributes as well.
+ You can activate modals on your page easily without having to write a single line of javascript. Just set data-toggle="modal"
on a controller element with a data-target="#foo"
or href="#foo"
which corresponds to a modal element id, and when clicked, it will launch your modal.
+ Also, to add options to your modal instance, just include them as additional data attributes on either the control element or the modal markup itself.
-<a class="btn" data-controls-modal="my-modal" data-backdrop="static" >Launch Modal</a>
+<a class="btn" data-toggle="modal" href="#myModal" >Launch Modal</a>
- Notice If you want your modal to animate in and out, just add a .fade
class to your .modal
element (refer to the demo to see this in action).
+
+
+<div class="modal">
+ <div class="modal-header">
+ <a class="close" data-dismiss="modal">×</a>
+ <h3>Modal header</h3>
+ </div>
+ <div class="modal-body">
+ <p>One fine body…</p>
+ </div>
+ <div class="modal-footer">
+ <a href="#" class="btn btn-primary">Save changes</a>
+ <a href="#" class="btn">Close</a>
+ </div>
+</div>
+
+
+ Heads up! If you want your modal to animate in and out, just add a .fade
class to the .modal
element (refer to the demo to see this in action) and include bootstrap-transition.js.
+
Methods
.modal(options)
- Activates your content as a modal. Accepts an optional options object
.
+
Activates your content as a modal. Accepts an optional options object
.
-$('#my-modal').modal({
- keyboard: true
+$('#myModal').modal({
+ keyboard: false
})
.modal('toggle')
Manually toggles a modal.
- $('#my-modal').modal('toggle')
+ $('#myModal').modal('toggle')
.modal('show')
Manually opens a modal.
- $('#my-modal').modal('show')
+ $('#myModal').modal('show')
.modal('hide')
Manually hides a modal.
- $('#my-modal').modal('hide')
- .modal(true)
- Returns an elements modal class instance.
- $('#my-modal').modal(true)
- Notice Alternatively, this can be retrieved with $().data('modal')
.
+ $('#myModal').modal('hide')
Events
- Bootstrap's modal class exposes a few events for hooking into modal functionality.
-
+ Bootstrap's modal class exposes a few events for hooking into modal functionality.
+
Event |
@@ -177,570 +346,215 @@ $('#my-modal').modal({
-$('#my-modal').bind('hidden', function () {
- // do something ...
+$('#myModal').on('hidden', function () {
+ // do something…
})
- Demo
-
-
-
-
+
-
-
+
-
-
This plugin is for adding dropdown interaction to the bootstrap topbar or tabbed navigations.
-
Download
+
+
About dropdowns
+
Add dropdown menus to nearly anything in Bootstrap with this simple plugin. Bootstrap features full dropdown menu support on in the navbar, tabs, and pills.
+
Download file
-
-
Using bootstrap-dropdown.js
-
$('#topbar').dropdown()
-
Markup
-
To quickly add dropdown functionality to any nav element, use the data-dropdown
attribute. Any valid bootstrap dropdown will automatically be activated.
-
-<ul class="tabs">
- <li class="active"><a href="#">Home</a></li>
- <li class="dropdown" data-dropdown="dropdown" >
- <a href="#" class="dropdown-toggle">Dropdown</a>
- <ul class="dropdown-menu">
- <li><a href="#">Secondary link</a></li>
- <li><a href="#">Something else here</a></li>
- <li class="divider"></li>
- <li><a href="#">Another link</a></li>
- </ul>
- </li>
-</ul>
-
Notice If your ui has several dropdowns, consider adding the data-dropdown
attribute to a more significant container element like .tabs
or .topbar
.
-
Methods
-
$().dropdown()
-
- A programatic api for activating menus for a given topbar or tabbed navigation.
-
-
Demo
-
-
-
-
+
+
Examples
+
Click on the dropdown nav links in the navbar and pills below to test dropdowns.
+
+
+
+
+
+
+
Using bootstrap-dropdown.js
+
Call the dropdowns via javascript:
+
$('.dropdown-toggle').dropdown()
+
Markup
+
To quickly add dropdown functionality to any element just add data-toggle="dropdown"
and any valid bootstrap dropdown will automatically be activated.
+
+ Heads up! You may optionally target a specific dropdown by using data-target="#fat"
or href="#fat"
.
+
+
+<ul class="nav pills">
+ <li class="active"><a href="#">Regular link</a></li>
+ <li class="dropdown" id="menu1">
+ <a class="dropdown-toggle" data-toggle="dropdown" href="#menu1">
+ Dropdown
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Action</a></li>
+ <li><a href="#">Another action</a></li>
+ <li><a href="#">Something else here</a></li>
+ <li class="divider"></li>
+ <li><a href="#">Separated link</a></li>
+ </ul>
+ </li>
+ ...
+</ul>
+
Methods
+
$().dropdown()
+
A programatic api for activating menus for a given navbar or tabbed navigation.
+
+
-