Comparing version 0.6.0 to 0.7.0
357
mustache.js
@@ -11,3 +11,3 @@ /*! | ||
(function (exports) { | ||
if (typeof module !== "undefined" && typeof module.exports !== "undefined") { | ||
if (typeof module !== "undefined" && module.exports) { | ||
module.exports = exports; // CommonJS | ||
@@ -20,29 +20,13 @@ } else if (typeof define === "function") { | ||
}((function () { | ||
var exports = {}; | ||
exports.name = "mustache.js"; | ||
exports.version = "0.6.0"; | ||
exports.version = "0.7.0"; | ||
exports.tags = ["{{", "}}"]; | ||
exports.parse = parse; | ||
exports.clearCache = clearCache; | ||
exports.compile = compile; | ||
exports.compilePartial = compilePartial; | ||
exports.render = render; | ||
exports.Scanner = Scanner; | ||
exports.Context = Context; | ||
exports.Renderer = Renderer; | ||
exports.Writer = Writer; | ||
// This is here for backwards compatibility with 0.4.x. | ||
exports.to_html = function (template, view, partials, send) { | ||
var result = render(template, view, partials); | ||
if (typeof send === "function") { | ||
send(result); | ||
} else { | ||
return result; | ||
} | ||
}; | ||
var whiteRe = /\s*/; | ||
@@ -69,13 +53,2 @@ var spaceRe = /\s+/; | ||
// OSWASP Guidelines: Escape all non alphanumeric characters in ASCII space. | ||
var jsCharsRe = /[\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\xFF\u2028\u2029]/gm; | ||
function quote(text) { | ||
var escaped = text.replace(jsCharsRe, function (c) { | ||
return "\\u" + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); | ||
}); | ||
return '"' + escaped + '"'; | ||
} | ||
function escapeRe(string) { | ||
@@ -216,7 +189,7 @@ return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); | ||
function Renderer() { | ||
function Writer() { | ||
this.clearCache(); | ||
} | ||
Renderer.prototype.clearCache = function () { | ||
Writer.prototype.clearCache = function () { | ||
this._cache = {}; | ||
@@ -226,32 +199,39 @@ this._partialCache = {}; | ||
Renderer.prototype.compile = function (tokens, tags) { | ||
if (typeof tokens === "string") { | ||
tokens = parse(tokens, tags); | ||
} | ||
Writer.prototype.compile = function (template, tags) { | ||
return this._compile(this._cache, template, template, tags); | ||
}; | ||
var fn = compileTokens(tokens), | ||
self = this; | ||
return function (view) { | ||
return fn(Context.make(view), self); | ||
}; | ||
Writer.prototype.compilePartial = function (name, template, tags) { | ||
return this._compile(this._partialCache, name, template, tags); | ||
}; | ||
Renderer.prototype.compilePartial = function (name, tokens, tags) { | ||
this._partialCache[name] = this.compile(tokens, tags); | ||
return this._partialCache[name]; | ||
Writer.prototype.render = function (template, view, partials) { | ||
return this.compile(template)(view, partials); | ||
}; | ||
Renderer.prototype.render = function (template, view) { | ||
var fn = this._cache[template]; | ||
Writer.prototype._compile = function (cache, key, template, tags) { | ||
if (!cache[key]) { | ||
var tokens = exports.parse(template, tags); | ||
var fn = compileTokens(tokens); | ||
if (!fn) { | ||
fn = this.compile(template); | ||
this._cache[template] = fn; | ||
var self = this; | ||
cache[key] = function (view, partials) { | ||
if (partials) { | ||
if (typeof partials === "function") { | ||
self._loadPartial = partials; | ||
} else { | ||
for (var name in partials) { | ||
self.compilePartial(name, partials[name]); | ||
} | ||
} | ||
} | ||
return fn(self, Context.make(view), template); | ||
}; | ||
} | ||
return fn(view); | ||
return cache[key]; | ||
}; | ||
Renderer.prototype._section = function (name, context, callback) { | ||
Writer.prototype._section = function (name, context, text, callback) { | ||
var value = context.lookup(name); | ||
@@ -265,3 +245,3 @@ | ||
for (var i = 0, len = value.length; i < len; ++i) { | ||
buffer += callback(context.push(value[i]), this); | ||
buffer += callback(this, context.push(value[i])); | ||
} | ||
@@ -272,8 +252,5 @@ | ||
return value ? callback(context.push(value), this) : ""; | ||
return value ? callback(this, context.push(value)) : ""; | ||
case "function": | ||
// TODO: The text should be passed to the callback plain, not rendered. | ||
var sectionText = callback(context, this), | ||
self = this; | ||
var self = this; | ||
var scopedRender = function (template) { | ||
@@ -283,6 +260,6 @@ return self.render(template, context); | ||
return value.call(context.view, sectionText, scopedRender) || ""; | ||
return value.call(context.view, text, scopedRender) || ""; | ||
default: | ||
if (value) { | ||
return callback(context, this); | ||
return callback(this, context); | ||
} | ||
@@ -294,3 +271,3 @@ } | ||
Renderer.prototype._inverted = function (name, context, callback) { | ||
Writer.prototype._inverted = function (name, context, callback) { | ||
var value = context.lookup(name); | ||
@@ -301,3 +278,3 @@ | ||
if (!value || (isArray(value) && value.length === 0)) { | ||
return callback(context, this); | ||
return callback(this, context); | ||
} | ||
@@ -308,13 +285,13 @@ | ||
Renderer.prototype._partial = function (name, context) { | ||
Writer.prototype._partial = function (name, context) { | ||
if (!(name in this._partialCache) && this._loadPartial) { | ||
this.compilePartial(name, this._loadPartial(name)); | ||
} | ||
var fn = this._partialCache[name]; | ||
if (fn) { | ||
return fn(context); | ||
} | ||
return ""; | ||
return fn ? fn(context) : ""; | ||
}; | ||
Renderer.prototype._name = function (name, context, escape) { | ||
Writer.prototype._name = function (name, context) { | ||
var value = context.lookup(name); | ||
@@ -326,76 +303,85 @@ | ||
var string = (value == null) ? "" : String(value); | ||
return (value == null) ? "" : String(value); | ||
}; | ||
if (escape) { | ||
return exports.escape(string); | ||
Writer.prototype._escaped = function (name, context) { | ||
return exports.escape(this._name(name, context)); | ||
}; | ||
/** | ||
* Calculates the bounds of the section represented by the given `token` in | ||
* the original template by drilling down into nested sections to find the | ||
* last token that is part of that section. Returns an array of [start, end]. | ||
*/ | ||
function sectionBounds(token) { | ||
var start = token[3]; | ||
var end = start; | ||
var tokens; | ||
while ((tokens = token[4]) && tokens.length) { | ||
token = tokens[tokens.length - 1]; | ||
end = token[3]; | ||
} | ||
return string; | ||
}; | ||
return [start, end]; | ||
} | ||
/** | ||
* Low-level function that compiles the given `tokens` into a | ||
* function that accepts two arguments: a Context and a | ||
* Renderer. Returns the body of the function as a string if | ||
* `returnBody` is true. | ||
* Low-level function that compiles the given `tokens` into a function | ||
* that accepts two arguments: a Context and a Writer. | ||
*/ | ||
function compileTokens(tokens, returnBody) { | ||
var body = ['""']; | ||
var token, method, escape; | ||
function compileTokens(tokens) { | ||
var subRenders = {}; | ||
for (var i = 0, len = tokens.length; i < len; ++i) { | ||
token = tokens[i]; | ||
function subRender(i, tokens, template) { | ||
if (!subRenders[i]) { | ||
var fn = compileTokens(tokens); | ||
subRenders[i] = function (writer, context) { | ||
return fn(writer, context, template); | ||
}; | ||
} | ||
switch (token.type) { | ||
case "#": | ||
case "^": | ||
method = (token.type === "#") ? "_section" : "_inverted"; | ||
body.push("r." + method + "(" + quote(token.value) + ", c, function (c, r) {\n" + | ||
" " + compileTokens(token.tokens, true) + "\n" + | ||
"})"); | ||
break; | ||
case "{": | ||
case "&": | ||
case "name": | ||
escape = token.type === "name" ? "true" : "false"; | ||
body.push("r._name(" + quote(token.value) + ", c, " + escape + ")"); | ||
break; | ||
case ">": | ||
body.push("r._partial(" + quote(token.value) + ", c)"); | ||
break; | ||
case "text": | ||
body.push(quote(token.value)); | ||
break; | ||
} | ||
return subRenders[i]; | ||
} | ||
// Convert to a string body. | ||
body = "return " + body.join(" + ") + ";"; | ||
function renderFunction(writer, context, template) { | ||
var buffer = ""; | ||
var token, sectionText; | ||
// Good for debugging. | ||
// console.log(body); | ||
for (var i = 0, len = tokens.length; i < len; ++i) { | ||
token = tokens[i]; | ||
if (returnBody) { | ||
return body; | ||
} | ||
switch (token[0]) { | ||
case "#": | ||
sectionText = template.slice.apply(template, sectionBounds(token)); | ||
buffer += writer._section(token[1], context, sectionText, subRender(i, token[4], template)); | ||
break; | ||
case "^": | ||
buffer += writer._inverted(token[1], context, subRender(i, token[4], template)); | ||
break; | ||
case ">": | ||
buffer += writer._partial(token[1], context); | ||
break; | ||
case "&": | ||
buffer += writer._name(token[1], context); | ||
break; | ||
case "name": | ||
buffer += writer._escaped(token[1], context); | ||
break; | ||
case "text": | ||
buffer += token[1]; | ||
break; | ||
} | ||
} | ||
// For great evil! | ||
return new Function("c, r", body); | ||
} | ||
function escapeTags(tags) { | ||
if (tags.length !== 2) { | ||
throw new Error("Invalid tags: " + tags.join(" ")); | ||
return buffer; | ||
} | ||
return [ | ||
new RegExp(escapeRe(tags[0]) + "\\s*"), | ||
new RegExp("\\s*" + escapeRe(tags[1])) | ||
]; | ||
return renderFunction; | ||
} | ||
/** | ||
* Forms the given linear array of `tokens` into a nested tree structure | ||
* where tokens that represent a section have a "tokens" array property | ||
* that contains all tokens that are in that section. | ||
* Forms the given array of `tokens` into a nested tree structure where | ||
* tokens that represent a section have a fifth item: an array that contains | ||
* all tokens in that section. | ||
*/ | ||
@@ -411,13 +397,13 @@ function nestTokens(tokens) { | ||
switch (token.type) { | ||
switch (token[0]) { | ||
case "#": | ||
case "^": | ||
token.tokens = []; | ||
token[4] = []; | ||
sections.push(token); | ||
collector.push(token); | ||
collector = token.tokens; | ||
collector = token[4]; | ||
break; | ||
case "/": | ||
if (sections.length === 0) { | ||
throw new Error("Unopened section: " + token.value); | ||
throw new Error("Unopened section: " + token[1]); | ||
} | ||
@@ -427,8 +413,8 @@ | ||
if (section.value !== token.value) { | ||
throw new Error("Unclosed section: " + section.value); | ||
if (section[1] !== token[1]) { | ||
throw new Error("Unclosed section: " + section[1]); | ||
} | ||
if (sections.length > 0) { | ||
collector = sections[sections.length - 1].tokens; | ||
collector = sections[sections.length - 1][4]; | ||
} else { | ||
@@ -447,3 +433,3 @@ collector = tree; | ||
if (section) { | ||
throw new Error("Unclosed section: " + section.value); | ||
throw new Error("Unclosed section: " + section[1]); | ||
} | ||
@@ -459,9 +445,10 @@ | ||
function squashTokens(tokens) { | ||
var lastToken; | ||
var token, lastToken; | ||
for (var i = 0; i < tokens.length; ++i) { | ||
var token = tokens[i]; | ||
token = tokens[i]; | ||
if (lastToken && lastToken.type === "text" && token.type === "text") { | ||
lastToken.value += token.value; | ||
if (lastToken && lastToken[0] === "text" && token[0] === "text") { | ||
lastToken[1] += token[1]; | ||
lastToken[3] = token[3]; | ||
tokens.splice(i--, 1); // Remove this token from the array. | ||
@@ -474,2 +461,13 @@ } else { | ||
function escapeTags(tags) { | ||
if (tags.length !== 2) { | ||
throw new Error("Invalid tags: " + tags.join(" ")); | ||
} | ||
return [ | ||
new RegExp(escapeRe(tags[0]) + "\\s*"), | ||
new RegExp("\\s*" + escapeRe(tags[1])) | ||
]; | ||
} | ||
/** | ||
@@ -481,3 +479,3 @@ * Breaks up the given `template` string into a tree of token objects. If | ||
*/ | ||
function parse(template, tags) { | ||
exports.parse = function (template, tags) { | ||
tags = tags || exports.tags; | ||
@@ -495,3 +493,3 @@ | ||
// if there was a {{#tag}} on it and otherwise only space. | ||
var stripSpace = function () { | ||
function stripSpace() { | ||
if (hasTag && !nonSpace) { | ||
@@ -507,7 +505,8 @@ while (spaces.length) { | ||
nonSpace = false; | ||
}; | ||
} | ||
var type, value, chr; | ||
var start, type, value, chr; | ||
while (!scanner.eos()) { | ||
start = scanner.pos; | ||
value = scanner.scanUntil(tagRes[0]); | ||
@@ -525,3 +524,4 @@ | ||
tokens.push({type: "text", value: chr}); | ||
tokens.push(["text", chr, start, start + 1]); | ||
start += 1; | ||
@@ -534,2 +534,4 @@ if (chr === "\n") { | ||
start = scanner.pos; | ||
// Match the opening tag. | ||
@@ -556,2 +558,3 @@ if (!scanner.scan(tagRes[0])) { | ||
scanner.scanUntil(tagRes[1]); | ||
type = "&"; | ||
} else { | ||
@@ -566,3 +569,3 @@ value = scanner.scanUntil(tagRes[1]); | ||
tokens.push({type: type, value: value}); | ||
tokens.push([type, value, start, scanner.pos]); | ||
@@ -583,52 +586,52 @@ if (type === "name" || type === "{" || type === "&") { | ||
return nestTokens(tokens); | ||
} | ||
}; | ||
// The high-level clearCache, compile, compilePartial, and render functions | ||
// use this default renderer. | ||
var _renderer = new Renderer(); | ||
// use this default writer. | ||
var _writer = new Writer(); | ||
/** | ||
* Clears all cached templates and partials. | ||
* Clears all cached templates and partials in the default writer. | ||
*/ | ||
function clearCache() { | ||
_renderer.clearCache(); | ||
} | ||
exports.clearCache = function () { | ||
return _writer.clearCache(); | ||
}; | ||
/** | ||
* High-level API for compiling the given `tokens` down to a reusable | ||
* function. If `tokens` is a string it will be parsed using the given `tags` | ||
* before it is compiled. | ||
* Compiles the given `template` to a reusable function using the default | ||
* writer. | ||
*/ | ||
function compile(tokens, tags) { | ||
return _renderer.compile(tokens, tags); | ||
} | ||
exports.compile = function (template, tags) { | ||
return _writer.compile(template, tags); | ||
}; | ||
/** | ||
* High-level API for compiling the `tokens` for the partial with the given | ||
* `name` down to a reusable function. If `tokens` is a string it will be | ||
* parsed using the given `tags` before it is compiled. | ||
* Compiles the partial with the given `name` and `template` to a reusable | ||
* function using the default writer. | ||
*/ | ||
function compilePartial(name, tokens, tags) { | ||
return _renderer.compilePartial(name, tokens, tags); | ||
} | ||
exports.compilePartial = function (name, template, tags) { | ||
return _writer.compilePartial(name, template, tags); | ||
}; | ||
/** | ||
* High-level API for rendering the `template` using the given `view`. The | ||
* optional `partials` object may be given here for convenience, but note that | ||
* it will cause all partials to be re-compiled, thus hurting performance. Of | ||
* course, this only matters if you're going to render the same template more | ||
* than once. If so, it is best to call `compilePartial` before calling this | ||
* function and to leave the `partials` argument blank. | ||
* Renders the `template` with the given `view` and `partials` using the | ||
* default writer. | ||
*/ | ||
function render(template, view, partials) { | ||
if (partials) { | ||
for (var name in partials) { | ||
compilePartial(name, partials[name]); | ||
} | ||
exports.render = function (template, view, partials) { | ||
return _writer.render(template, view, partials); | ||
}; | ||
// This is here for backwards compatibility with 0.4.x. | ||
exports.to_html = function (template, view, partials, send) { | ||
var result = exports.render(template, view, partials); | ||
if (typeof send === "function") { | ||
send(result); | ||
} else { | ||
return result; | ||
} | ||
}; | ||
return _renderer.render(template, view); | ||
} | ||
return exports; | ||
return exports; | ||
}()))); |
{ | ||
"name": "mustache", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"description": "Logic-less {{mustache}} templates with JavaScript", | ||
@@ -12,3 +12,3 @@ "author": "mustache.js Authors <http://github.com/janl/mustache.js>", | ||
"volo": { | ||
"url": "https://raw.github.com/janl/mustache.js/0.6.0/mustache.js" | ||
"url": "https://raw.github.com/janl/mustache.js/0.7.0/mustache.js" | ||
}, | ||
@@ -15,0 +15,0 @@ "scripts": { |
@@ -6,5 +6,5 @@ ({ | ||
return function (text, render) { | ||
return "<b>" + render(text) + '</b> ' + this.helper; | ||
return text + ' => <b>' + render(text) + '</b> ' + this.helper; | ||
} | ||
} | ||
}) |
@@ -1,1 +0,1 @@ | ||
<b>Hi Tater.</b> To tinker? | ||
Hi {{name}}. => <b>Hi Tater.</b> To tinker? |
@@ -1,4 +0,4 @@ | ||
var assert = require("assert"), | ||
vows = require("vows"), | ||
Context = require("./../mustache").Context; | ||
var assert = require("assert"); | ||
var vows = require("vows"); | ||
var Context = require("./../mustache").Context; | ||
@@ -12,6 +12,6 @@ vows.describe("Mustache.Context").addBatch({ | ||
}, | ||
"should be able to lookup properties of its own view": function (context) { | ||
"is able to lookup properties of its own view": function (context) { | ||
assert.equal(context.lookup("name"), "parent"); | ||
}, | ||
"should be able to lookup nested properties of its own view": function (context) { | ||
"is able to lookup nested properties of its own view": function (context) { | ||
assert.equal(context.lookup("a.b"), "b"); | ||
@@ -24,16 +24,16 @@ }, | ||
}, | ||
"should return the child context": function (context) { | ||
"returns the child context": function (context) { | ||
assert.equal(context.view.name, "child"); | ||
assert.equal(context.parent.view.name, "parent"); | ||
}, | ||
"should be able to lookup properties of its own view": function (context) { | ||
"is able to lookup properties of its own view": function (context) { | ||
assert.equal(context.lookup("name"), "child"); | ||
}, | ||
"should be able to lookup properties of the parent context's view": function (context) { | ||
"is able to lookup properties of the parent context's view": function (context) { | ||
assert.equal(context.lookup("message"), "hi"); | ||
}, | ||
"should be able to lookup nested properties of its own view": function (context) { | ||
"is able to lookup nested properties of its own view": function (context) { | ||
assert.equal(context.lookup("c.d"), "d"); | ||
}, | ||
"should be able to lookup nested properties of its parent view": function (context) { | ||
"is able to lookup nested properties of its parent view": function (context) { | ||
assert.equal(context.lookup("a.b"), "b"); | ||
@@ -44,3 +44,3 @@ } | ||
"make": { | ||
"should return the same object when given a Context": function () { | ||
"returns the same object when given a Context": function () { | ||
var context = new Context; | ||
@@ -47,0 +47,0 @@ assert.strictEqual(Context.make(context), context); |
@@ -1,53 +0,55 @@ | ||
var assert = require("assert"), | ||
vows = require("vows"), | ||
parse = require("./../mustache").parse; | ||
var assert = require('assert'); | ||
var vows = require('vows'); | ||
var Mustache = require('./../mustache'); | ||
// A map of templates to their expected token output. | ||
// A map of templates to their expected token output. Tokens are in the format: | ||
// [type, value, startIndex, endIndex]. | ||
var expectations = { | ||
"{{hi}}" : [ { type: 'name', value: 'hi' } ], | ||
"{{hi.world}}" : [ { type: 'name', value: 'hi.world' } ], | ||
"{{hi . world}}" : [ { type: 'name', value: 'hi . world' } ], | ||
"{{ hi}}" : [ { type: 'name', value: 'hi' } ], | ||
"{{hi }}" : [ { type: 'name', value: 'hi' } ], | ||
"{{ hi }}" : [ { type: 'name', value: 'hi' } ], | ||
"{{{hi}}}" : [ { type: '{', value: 'hi' } ], | ||
"{{!hi}}" : [ { type: '!', value: 'hi' } ], | ||
"{{! hi}}" : [ { type: '!', value: 'hi' } ], | ||
"{{! hi }}" : [ { type: '!', value: 'hi' } ], | ||
"{{ !hi}}" : [ { type: '!', value: 'hi' } ], | ||
"{{ ! hi}}" : [ { type: '!', value: 'hi' } ], | ||
"{{ ! hi }}" : [ { type: '!', value: 'hi' } ], | ||
"a{{hi}}" : [ { type: 'text', value: 'a' }, { type: 'name', value: 'hi' } ], | ||
"a {{hi}}" : [ { type: 'text', value: 'a ' }, { type: 'name', value: 'hi' } ], | ||
" a{{hi}}" : [ { type: 'text', value: ' a' }, { type: 'name', value: 'hi' } ], | ||
" a {{hi}}" : [ { type: 'text', value: ' a ' }, { type: 'name', value: 'hi' } ], | ||
"a{{hi}}b" : [ { type: 'text', value: 'a' }, { type: 'name', value: 'hi' }, { type: 'text', value: 'b' } ], | ||
"a{{hi}} b" : [ { type: 'text', value: 'a' }, { type: 'name', value: 'hi' }, { type: 'text', value: ' b' } ], | ||
"a{{hi}}b " : [ { type: 'text', value: 'a' }, { type: 'name', value: 'hi' }, { type: 'text', value: 'b ' } ], | ||
"a\n{{hi}} b \n" : [ { type: 'text', value: 'a\n' }, { type: 'name', value: 'hi' }, { type: 'text', value: ' b \n' } ], | ||
"a\n {{hi}} \nb" : [ { type: 'text', value: 'a\n ' }, { type: 'name', value: 'hi' }, { type: 'text', value: ' \nb' } ], | ||
"a\n {{!hi}} \nb" : [ { type: 'text', value: 'a\n' }, { type: '!', value: 'hi' }, { type: 'text', value: 'b' } ], | ||
"a\n{{#a}}{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}{{/a}} \nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n{{#a}}\n{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{/a}} \nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n{{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: '#', value: 'b', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: '#', value: 'b', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}} \nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [] }, { type: '#', value: 'b', tokens: [] }, { type: 'text', value: 'b' } ], | ||
"a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [ { type: '#', value: 'b', tokens: [] } ] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [ { type: '#', value: 'b', tokens: [] } ] }, { type: 'text', value: 'b' } ], | ||
"a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb" : [ { type: 'text', value: 'a\n' }, { type: '#', value: 'a', tokens: [ { type: '#', value: 'b', tokens: [] } ] }, { type: 'text', value: 'b' } ], | ||
"{{>abc}}" : [ { type: '>', value: 'abc' } ], | ||
"{{> abc }}" : [ { type: '>', value: 'abc' } ], | ||
"{{ > abc }}" : [ { type: '>', value: 'abc' } ], | ||
"{{=<% %>=}}" : [ { type: '=', value: '<% %>' } ], | ||
"{{= <% %> =}}" : [ { type: '=', value: '<% %>' } ], | ||
"{{=<% %>=}}<%={{ }}=%>" : [ { type: '=', value: '<% %>' }, { type: '=', value: '{{ }}' } ], | ||
"{{=<% %>=}}<%hi%>" : [ { type: '=', value: '<% %>' }, { type: 'name', value: 'hi' } ], | ||
"{{#a}}{{/a}}hi{{#b}}{{/b}}\n" : [ { type: '#', value: 'a', tokens: [] }, { type: 'text', value: 'hi' }, { type: '#', value: 'b', tokens: [] }, { type: 'text', value: '\n' } ], | ||
"{{a}}\n{{b}}\n\n{{#c}}\n{{/c}}\n" : [ { type: 'name', value: 'a' }, { type: 'text', value: '\n' }, { type: 'name', value: 'b' }, { type: 'text', value: '\n\n' }, { type: '#', value: 'c', tokens: [] } ], | ||
"{{#foo}}\n {{#a}}\n {{b}}\n {{/a}}\n{{/foo}}\n" | ||
: [ { type: "#", value: "foo", tokens: [ { type: "#", value: "a", tokens: [ { type: "text", value: " " }, { type: "name", value: "b" }, { type: "text", value: "\n" } ] } ] } ] | ||
'{{hi}}' : [ [ 'name', 'hi', 0, 6 ] ], | ||
'{{hi.world}}' : [ [ 'name', 'hi.world', 0, 12 ] ], | ||
'{{hi . world}}' : [ [ 'name', 'hi . world', 0, 14 ] ], | ||
'{{ hi}}' : [ [ 'name', 'hi', 0, 7 ] ], | ||
'{{hi }}' : [ [ 'name', 'hi', 0, 7 ] ], | ||
'{{ hi }}' : [ [ 'name', 'hi', 0, 8 ] ], | ||
'{{{hi}}}' : [ [ '&', 'hi', 0, 8 ] ], | ||
'{{!hi}}' : [ [ '!', 'hi', 0, 7 ] ], | ||
'{{! hi}}' : [ [ '!', 'hi', 0, 8 ] ], | ||
'{{! hi }}' : [ [ '!', 'hi', 0, 9 ] ], | ||
'{{ !hi}}' : [ [ '!', 'hi', 0, 8 ] ], | ||
'{{ ! hi}}' : [ [ '!', 'hi', 0, 9 ] ], | ||
'{{ ! hi }}' : [ [ '!', 'hi', 0, 10 ] ], | ||
'a\n b' : [ [ 'text', 'a\n b', 0, 4 ] ], | ||
'a{{hi}}' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ] ], | ||
'a {{hi}}' : [ [ 'text', 'a ', 0, 2 ], [ 'name', 'hi', 2, 8 ] ], | ||
' a{{hi}}' : [ [ 'text', ' a', 0, 2 ], [ 'name', 'hi', 2, 8 ] ], | ||
' a {{hi}}' : [ [ 'text', ' a ', 0, 3 ], [ 'name', 'hi', 3, 9 ] ], | ||
'a{{hi}}b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b', 7, 8 ] ], | ||
'a{{hi}} b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', ' b', 7, 9 ] ], | ||
'a{{hi}}b ' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b ', 7, 9 ] ], | ||
'a\n{{hi}} b \n' : [ [ 'text', 'a\n', 0, 2 ], [ 'name', 'hi', 2, 8 ], [ 'text', ' b \n', 8, 12 ] ], | ||
'a\n {{hi}} \nb' : [ [ 'text', 'a\n ', 0, 3 ], [ 'name', 'hi', 3, 9 ], [ 'text', ' \nb', 9, 12 ] ], | ||
'a\n {{!hi}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '!', 'hi', 3, 10 ], [ 'text', 'b', 12, 13 ] ], | ||
'a\n{{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [] ], [ 'text', 'b', 15, 16 ] ], | ||
'a\n {{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ 'text', 'b', 16, 17 ] ], | ||
'a\n {{#a}}{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ 'text', 'b', 17, 18 ] ], | ||
'a\n{{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [] ], [ 'text', 'b', 16, 17 ] ], | ||
'a\n {{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ 'text', 'b', 17, 18 ] ], | ||
'a\n {{#a}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ 'text', 'b', 18, 19 ] ], | ||
'a\n{{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [] ], [ '#', 'b', 16, 22, [] ], [ 'text', 'b', 30, 31 ] ], | ||
'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ '#', 'b', 17, 23, [] ], [ 'text', 'b', 31, 32 ] ], | ||
'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [] ], [ '#', 'b', 17, 23, [] ], [ 'text', 'b', 32, 33 ] ], | ||
'a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [ [ '#', 'b', 9, 15, [] ] ] ], [ 'text', 'b', 30, 31 ] ], | ||
'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [] ] ] ], [ 'text', 'b', 31, 32 ] ], | ||
'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [] ] ] ], [ 'text', 'b', 32, 33 ] ], | ||
'{{>abc}}' : [ [ '>', 'abc', 0, 8 ] ], | ||
'{{> abc }}' : [ [ '>', 'abc', 0, 10 ] ], | ||
'{{ > abc }}' : [ [ '>', 'abc', 0, 11 ] ], | ||
'{{=<% %>=}}' : [ [ '=', '<% %>', 0, 11 ] ], | ||
'{{= <% %> =}}' : [ [ '=', '<% %>', 0, 13 ] ], | ||
'{{=<% %>=}}<%={{ }}=%>' : [ [ '=', '<% %>', 0, 11 ], [ '=', '{{ }}', 11, 22 ] ], | ||
'{{=<% %>=}}<%hi%>' : [ [ '=', '<% %>', 0, 11 ], [ 'name', 'hi', 11, 17 ] ], | ||
'{{#a}}{{/a}}hi{{#b}}{{/b}}\n' : [ [ '#', 'a', 0, 6, [] ], [ 'text', 'hi', 12, 14 ], [ '#', 'b', 14, 20, [] ], [ 'text', '\n', 26, 27 ] ], | ||
'{{a}}\n{{b}}\n\n{{#c}}\n{{/c}}\n' : [ [ 'name', 'a', 0, 5 ], [ 'text', '\n', 5, 6 ], [ 'name', 'b', 6, 11 ], [ 'text', '\n\n', 11, 13 ], [ '#', 'c', 13, 19, [] ] ], | ||
'{{#foo}}\n {{#a}}\n {{b}}\n {{/a}}\n{{/foo}}\n' | ||
: [ [ '#', 'foo', 0, 8, [ [ '#', 'a', 11, 17, [ [ 'text', ' ', 18, 22 ], [ 'name', 'b', 22, 27 ], [ 'text', '\n', 27, 28 ] ] ] ] ] ] | ||
}; | ||
@@ -59,4 +61,4 @@ | ||
(function (template, tokens) { | ||
spec["knows how to parse " + JSON.stringify(template)] = function () { | ||
assert.deepEqual(parse(template), tokens); | ||
spec['knows how to parse ' + JSON.stringify(template)] = function () { | ||
assert.deepEqual(Mustache.parse(template), tokens); | ||
}; | ||
@@ -66,4 +68,4 @@ })(template, expectations[template]); | ||
vows.describe("Mustache.parse").addBatch({ | ||
"parse": spec | ||
vows.describe('Mustache.parse').addBatch({ | ||
'parse': spec | ||
}).export(module); |
@@ -1,14 +0,11 @@ | ||
var fs = require("fs"), | ||
path = require("path"), | ||
assert = require("assert"), | ||
vows = require("vows"); | ||
var fs = require("fs"); | ||
var path = require("path"); | ||
var assert = require("assert"); | ||
var vows = require("vows"); | ||
var Mustache = require("./../mustache"); | ||
var Mustache = require(path.join(__dirname, "..", "mustache")); | ||
var _files = path.join(__dirname, "_files"); | ||
function getContents(testName, ext) { | ||
var file = path.join(_files, testName + "." + ext); | ||
try { | ||
return fs.readFileSync(file, "utf8"); | ||
} catch (e) {} | ||
return fs.readFileSync(path.join(_files, testName + "." + ext), "utf8"); | ||
} | ||
@@ -45,4 +42,10 @@ | ||
var expect = getContents(testName, "txt"); | ||
var partial = getContents(testName, "partial"); | ||
var partial; | ||
try { | ||
partial = getContents(testName, "partial"); | ||
} catch (e) { | ||
// No big deal. | ||
} | ||
spec["knows how to render " + testName] = function () { | ||
@@ -49,0 +52,0 @@ Mustache.clearCache(); |
@@ -1,4 +0,4 @@ | ||
var assert = require("assert"), | ||
vows = require("vows"), | ||
Scanner = require("./../mustache").Scanner; | ||
var assert = require("assert"); | ||
var vows = require("vows"); | ||
var Scanner = require("./../mustache").Scanner; | ||
@@ -9,3 +9,3 @@ vows.describe("Mustache.Scanner").addBatch({ | ||
topic: new Scanner(""), | ||
"should be at the end of the string": function () { | ||
"is at the end of the string": function () { | ||
var scanner = new Scanner(""); | ||
@@ -24,6 +24,6 @@ assert(scanner.eos()); | ||
}, | ||
"it should return the entire string": function (scanner, match) { | ||
"returns the entire string": function (scanner, match) { | ||
assert.equal(match, scanner.string); | ||
}, | ||
"it should be at the end of the string": function (scanner, match) { | ||
"is at the end of the string": function (scanner, match) { | ||
assert(scanner.eos()); | ||
@@ -39,6 +39,6 @@ } | ||
}, | ||
"it should return the portion of the string that was matched": function (scanner, match) { | ||
"returns the portion of the string that was matched": function (scanner, match) { | ||
assert.equal(match, "a"); | ||
}, | ||
"it should advance the internal pointer the length of the match": function (scanner, match) { | ||
"advances the internal pointer the length of the match": function (scanner, match) { | ||
assert.equal(scanner.pos, 1); | ||
@@ -53,6 +53,6 @@ } | ||
}, | ||
"it should return the empty string": function (scanner, match) { | ||
"returns the empty string": function (scanner, match) { | ||
assert.equal(match, ""); | ||
}, | ||
"it should not advance the internal pointer": function (scanner, match) { | ||
"does not advance the internal pointer": function (scanner, match) { | ||
assert.equal(scanner.pos, 0); | ||
@@ -68,6 +68,6 @@ } | ||
}, | ||
"it should return the empty string": function (scanner, match) { | ||
"returns the empty string": function (scanner, match) { | ||
assert.equal(match, ""); | ||
}, | ||
"it should not advance the internal pointer": function (scanner, match) { | ||
"does not advance the internal pointer": function (scanner, match) { | ||
assert.equal(scanner.pos, 0); | ||
@@ -85,6 +85,6 @@ } | ||
}, | ||
"it should return the empty string": function (scanner, match) { | ||
"returns the empty string": function (scanner, match) { | ||
assert.equal(match, "") | ||
}, | ||
"it should not advance the internal pointer": function (scanner, match) { | ||
"does not advance the internal pointer": function (scanner, match) { | ||
assert.equal(scanner.pos, 0); | ||
@@ -99,6 +99,6 @@ } | ||
}, | ||
"it should return the portion of the string it scanned": function (scanner, match) { | ||
"returns the portion of the string it scanned": function (scanner, match) { | ||
assert.equal(match, "a "); | ||
}, | ||
"it should advance the internal pointer the length of the match": function (scanner, match) { | ||
"advances the internal pointer the length of the match": function (scanner, match) { | ||
assert.equal(scanner.pos, 2); | ||
@@ -114,6 +114,6 @@ } | ||
}, | ||
"it should return the entire string": function (scanner, match) { | ||
"returns the entire string": function (scanner, match) { | ||
assert.equal(match, scanner.string); | ||
}, | ||
"it should be at the end of the string": function (scanner, match) { | ||
"is at the end of the string": function (scanner, match) { | ||
assert(scanner.eos()); | ||
@@ -120,0 +120,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
61147
174
1089
3