Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mustache

Package Overview
Dependencies
Maintainers
2
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mustache - npm Package Compare versions

Comparing version 0.7.2 to 0.7.3

.gitmodules

449

mustache.js

@@ -10,20 +10,14 @@ /*!

if (typeof exports === "object" && exports) {
module.exports = factory; // CommonJS
} else if (typeof define === "function" && define.amd) {
define(factory); // AMD
factory(exports); // CommonJS
} else {
root.Mustache = factory; // <script>
var mustache = {};
factory(mustache);
if (typeof define === "function" && define.amd) {
define(mustache); // AMD
} else {
root.Mustache = mustache; // <script>
}
}
}(this, (function () {
}(this, function (mustache) {
var exports = {};
exports.name = "mustache.js";
exports.version = "0.7.2";
exports.tags = ["{{", "}}"];
exports.Scanner = Scanner;
exports.Context = Context;
exports.Writer = Writer;
var whiteRe = /\s*/;

@@ -38,15 +32,21 @@ var spaceRe = /\s+/;

// See https://github.com/janl/mustache.js/issues/189
function testRe(re, string) {
return RegExp.prototype.test.call(re, string);
var RegExp_test = RegExp.prototype.test;
function testRegExp(re, string) {
return RegExp_test.call(re, string);
}
function isWhitespace(string) {
return !testRe(nonSpaceRe, string);
return !testRegExp(nonSpaceRe, string);
}
var isArray = Array.isArray || function (obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
var Object_toString = Object.prototype.toString;
var isArray = Array.isArray || function (object) {
return Object_toString.call(object) === '[object Array]';
};
function escapeRe(string) {
function isFunction(object) {
return typeof object === 'function';
}
function escapeRegExp(string) {
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");

@@ -70,6 +70,2 @@ }

// Export the escaping function so that the user may override it.
// See https://github.com/janl/mustache.js/issues/244
exports.escape = escapeHtml;
function Scanner(string) {

@@ -96,5 +92,6 @@ this.string = string;

if (match && match.index === 0) {
this.tail = this.tail.substring(match[0].length);
this.pos += match[0].length;
return match[0];
var string = match[0];
this.tail = this.tail.substring(string.length);
this.pos += string.length;
return string;
}

@@ -110,8 +107,7 @@

Scanner.prototype.scanUntil = function (re) {
var match, pos = this.tail.search(re);
var index = this.tail.search(re), match;
switch (pos) {
switch (index) {
case -1:
match = this.tail;
this.pos += this.tail.length;
this.tail = "";

@@ -123,7 +119,8 @@ break;

default:
match = this.tail.substring(0, pos);
this.tail = this.tail.substring(pos);
this.pos += pos;
match = this.tail.substring(0, index);
this.tail = this.tail.substring(index);
}
this.pos += match.length;
return match;

@@ -133,5 +130,5 @@ };

function Context(view, parent) {
this.view = view;
this.view = view == null ? {} : view;
this.parent = parent;
this.clearCache();
this._cache = { '.': this.view };
}

@@ -143,6 +140,2 @@

Context.prototype.clearCache = function () {
this._cache = {};
};
Context.prototype.push = function (view) {

@@ -153,29 +146,23 @@ return new Context(view, this);

Context.prototype.lookup = function (name) {
var value = this._cache[name];
var value;
if (name in this._cache) {
value = this._cache[name];
} else {
var context = this;
if (!value) {
if (name === ".") {
value = this.view;
} else {
var context = this;
while (context) {
if (name.indexOf('.') > 0) {
value = context.view;
while (context) {
if (name.indexOf(".") > 0) {
var names = name.split("."), i = 0;
value = context.view;
while (value && i < names.length) {
value = value[names[i++]];
}
} else {
value = context.view[name];
var names = name.split('.'), i = 0;
while (value != null && i < names.length) {
value = value[names[i++]];
}
} else {
value = context.view[name];
}
if (value != null) {
break;
}
if (value != null) break;
context = context.parent;
}
context = context.parent;
}

@@ -186,3 +173,3 @@

if (typeof value === "function") {
if (isFunction(value)) {
value = value.call(this.view);

@@ -207,3 +194,3 @@ }

if (!fn) {
var tokens = exports.parse(template, tags);
var tokens = mustache.parse(template, tags);
fn = this._cache[template] = this.compileTokens(tokens, template);

@@ -221,9 +208,15 @@ }

Writer.prototype.getPartial = function (name) {
if (!(name in this._partialCache) && this._loadPartial) {
this.compilePartial(name, this._loadPartial(name));
}
return this._partialCache[name];
};
Writer.prototype.compileTokens = function (tokens, template) {
var fn = compileTokens(tokens);
var self = this;
return function (view, partials) {
if (partials) {
if (typeof partials === "function") {
if (isFunction(partials)) {
self._loadPartial = partials;

@@ -237,3 +230,3 @@ } else {

return fn(self, Context.make(view), template);
return renderTokens(tokens, self, Context.make(view), template);
};

@@ -246,121 +239,72 @@ };

Writer.prototype._section = function (name, context, text, callback) {
var value = context.lookup(name);
/**
* Low-level function that renders the given `tokens` using the given `writer`
* and `context`. The `template` string is only needed for templates that use
* higher-order sections to extract the portion of the original template that
* was contained in that section.
*/
function renderTokens(tokens, writer, context, template) {
var buffer = '';
switch (typeof value) {
case "object":
if (isArray(value)) {
var buffer = "";
for (var i = 0, len = value.length; i < len; ++i) {
buffer += callback(this, context.push(value[i]));
}
return buffer;
}
return value ? callback(this, context.push(value)) : "";
case "function":
var self = this;
var scopedRender = function (template) {
return self.render(template, context);
};
var result = value.call(context.view, text, scopedRender);
return result != null ? result : "";
default:
if (value) {
return callback(this, context);
}
// This function is used to render an artbitrary template
// in the current context by higher-order functions.
function subRender(template) {
return writer.render(template, context);
}
return "";
};
var token, tokenValue, value;
for (var i = 0, len = tokens.length; i < len; ++i) {
token = tokens[i];
tokenValue = token[1];
Writer.prototype._inverted = function (name, context, callback) {
var value = context.lookup(name);
switch (token[0]) {
case '#':
value = context.lookup(tokenValue);
// Use JavaScript's definition of falsy. Include empty arrays.
// See https://github.com/janl/mustache.js/issues/186
if (!value || (isArray(value) && value.length === 0)) {
return callback(this, context);
}
if (typeof value === 'object' || typeof value === 'string') {
if (isArray(value)) {
for (var j = 0, jlen = value.length; j < jlen; ++j) {
buffer += renderTokens(token[4], writer, context.push(value[j]), template);
}
} else if (value) {
buffer += renderTokens(token[4], writer, context.push(value), template);
}
} else if (isFunction(value)) {
var text = template == null ? null : template.slice(token[3], token[5]);
value = value.call(context.view, text, subRender);
if (value != null) buffer += value;
} else if (value) {
buffer += renderTokens(token[4], writer, context, template);
}
return "";
};
break;
case '^':
value = context.lookup(tokenValue);
Writer.prototype._partial = function (name, context) {
if (!(name in this._partialCache) && this._loadPartial) {
this.compilePartial(name, this._loadPartial(name));
}
// Use JavaScript's definition of falsy. Include empty arrays.
// See https://github.com/janl/mustache.js/issues/186
if (!value || (isArray(value) && value.length === 0)) {
buffer += renderTokens(token[4], writer, context, template);
}
var fn = this._partialCache[name];
return fn ? fn(context) : "";
};
Writer.prototype._name = function (name, context) {
var value = context.lookup(name);
if (typeof value === "function") {
value = value.call(context.view);
}
return (value == null) ? "" : String(value);
};
Writer.prototype._escaped = function (name, context) {
return exports.escape(this._name(name, context));
};
/**
* Low-level function that compiles the given `tokens` into a function
* that accepts three arguments: a Writer, a Context, and the template.
*/
function compileTokens(tokens) {
var subRenders = {};
function subRender(i, tokens, template) {
if (!subRenders[i]) {
var fn = compileTokens(tokens);
subRenders[i] = function (writer, context) {
return fn(writer, context, template);
};
break;
case '>':
value = writer.getPartial(tokenValue);
if (isFunction(value)) buffer += value(context);
break;
case '&':
value = context.lookup(tokenValue);
if (value != null) buffer += value;
break;
case 'name':
value = context.lookup(tokenValue);
if (value != null) buffer += mustache.escape(value);
break;
case 'text':
buffer += tokenValue;
break;
}
return subRenders[i];
}
return function (writer, context, template) {
var buffer = "";
var token, sectionText;
for (var i = 0, len = tokens.length; i < len; ++i) {
token = tokens[i];
switch (token[0]) {
case "#":
sectionText = template.slice(token[3], token[5]);
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;
}
}
return buffer;
};
return buffer;
}

@@ -412,8 +356,10 @@

token = tokens[i];
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
lastToken[1] += token[1];
lastToken[3] = token[3];
} else {
lastToken = token;
squashedTokens.push(token);
if (token) {
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
lastToken[1] += token[1];
lastToken[3] = token[3];
} else {
lastToken = token;
squashedTokens.push(token);
}
}

@@ -427,4 +373,4 @@ }

return [
new RegExp(escapeRe(tags[0]) + "\\s*"),
new RegExp("\\s*" + escapeRe(tags[1]))
new RegExp(escapeRegExp(tags[0]) + "\\s*"),
new RegExp("\\s*" + escapeRegExp(tags[1]))
];

@@ -439,10 +385,8 @@ }

*/
exports.parse = function (template, tags) {
function parseTemplate(template, tags) {
template = template || '';
tags = tags || exports.tags;
tags = tags || mustache.tags;
if (typeof tags === 'string') tags = tags.split(spaceRe);
if (tags.length !== 2) {
throw new Error('Invalid tags: ' + tags.join(', '));
}
if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', '));

@@ -463,3 +407,3 @@ var tagRes = escapeTags(tags);

while (spaces.length) {
tokens.splice(spaces.pop(), 1);
delete tokens[spaces.pop()];
}

@@ -474,7 +418,8 @@ } else {

var start, type, value, chr;
var start, type, value, chr, token, openSection;
while (!scanner.eos()) {
start = scanner.pos;
// Match any text between tags.
value = scanner.scanUntil(tagRes[0]);
if (value) {

@@ -490,35 +435,28 @@ for (var i = 0, len = value.length; i < len; ++i) {

tokens.push(["text", chr, start, start + 1]);
tokens.push(['text', chr, start, start + 1]);
start += 1;
if (chr === "\n") {
stripSpace(); // Check for whitespace on the current line.
}
// Check for whitespace on the current line.
if (chr == '\n') stripSpace();
}
}
start = scanner.pos;
// Match the opening tag.
if (!scanner.scan(tagRes[0])) {
break;
}
if (!scanner.scan(tagRes[0])) break;
hasTag = true;
type = scanner.scan(tagRe) || "name";
// Skip any whitespace between tag and value.
// Get the tag type.
type = scanner.scan(tagRe) || 'name';
scanner.scan(whiteRe);
// Extract the tag value.
if (type === "=") {
// Get the tag value.
if (type === '=') {
value = scanner.scanUntil(eqRe);
scanner.scan(eqRe);
scanner.scanUntil(tagRes[1]);
} else if (type === "{") {
var closeRe = new RegExp("\\s*" + escapeRe("}" + tags[1]));
value = scanner.scanUntil(closeRe);
} else if (type === '{') {
value = scanner.scanUntil(new RegExp('\\s*' + escapeRegExp('}' + tags[1])));
scanner.scan(curlyRe);
scanner.scanUntil(tagRes[1]);
type = "&";
type = '&';
} else {

@@ -529,20 +467,5 @@ value = scanner.scanUntil(tagRes[1]);

// Match the closing tag.
if (!scanner.scan(tagRes[1])) {
throw new Error('Unclosed tag at ' + scanner.pos);
}
if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos);
// Check section nesting.
if (type === '/') {
if (sections.length === 0) {
throw new Error('Unopened section "' + value + '" at ' + start);
}
var section = sections.pop();
if (section[1] !== value) {
throw new Error('Unclosed section "' + section[1] + '" at ' + start);
}
}
var token = [type, value, start, scanner.pos];
token = [type, value, start, scanner.pos];
tokens.push(token);

@@ -552,12 +475,19 @@

sections.push(token);
} else if (type === "name" || type === "{" || type === "&") {
} else if (type === '/') {
// Check section nesting.
openSection = sections.pop();
if (!openSection) {
throw new Error('Unopened section "' + value + '" at ' + start);
}
if (openSection[1] !== value) {
throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
}
} else if (type === 'name' || type === '{' || type === '&') {
nonSpace = true;
} else if (type === "=") {
} else if (type === '=') {
// Set the tags for the next time around.
tags = value.split(spaceRe);
if (tags.length !== 2) {
throw new Error('Invalid tags at ' + start + ': ' + tags.join(', '));
}
tagRes = escapeTags(tags);

@@ -568,19 +498,32 @@ }

// Make sure there are no open sections when we're done.
var section = sections.pop();
if (section) {
throw new Error('Unclosed section "' + section[1] + '" at ' + scanner.pos);
openSection = sections.pop();
if (openSection) {
throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
}
return nestTokens(squashTokens(tokens));
};
}
// The high-level clearCache, compile, compilePartial, and render functions
// use this default writer.
var _writer = new Writer();
mustache.name = "mustache.js";
mustache.version = "0.7.3";
mustache.tags = ["{{", "}}"];
mustache.Scanner = Scanner;
mustache.Context = Context;
mustache.Writer = Writer;
mustache.parse = parseTemplate;
// Export the escaping function so that the user may override it.
// See https://github.com/janl/mustache.js/issues/244
mustache.escape = escapeHtml;
// All Mustache.* functions use this writer.
var defaultWriter = new Writer();
/**
* Clears all cached templates and partials in the default writer.
*/
exports.clearCache = function () {
return _writer.clearCache();
mustache.clearCache = function () {
return defaultWriter.clearCache();
};

@@ -592,4 +535,4 @@

*/
exports.compile = function (template, tags) {
return _writer.compile(template, tags);
mustache.compile = function (template, tags) {
return defaultWriter.compile(template, tags);
};

@@ -601,4 +544,4 @@

*/
exports.compilePartial = function (name, template, tags) {
return _writer.compilePartial(name, template, tags);
mustache.compilePartial = function (name, template, tags) {
return defaultWriter.compilePartial(name, template, tags);
};

@@ -610,4 +553,4 @@

*/
exports.compileTokens = function (tokens, template) {
return _writer.compileTokens(tokens, template);
mustache.compileTokens = function (tokens, template) {
return defaultWriter.compileTokens(tokens, template);
};

@@ -619,11 +562,11 @@

*/
exports.render = function (template, view, partials) {
return _writer.render(template, view, partials);
mustache.render = function (template, view, partials) {
return defaultWriter.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);
mustache.to_html = function (template, view, partials, send) {
var result = mustache.render(template, view, partials);
if (typeof send === "function") {
if (isFunction(send)) {
send(result);

@@ -635,4 +578,2 @@ } else {

return exports;
}())));
}));
{
"name": "mustache",
"version": "0.7.2",
"version": "0.7.3",
"description": "Logic-less {{mustache}} templates with JavaScript",
"author": "mustache.js Authors <http://github.com/janl/mustache.js>",
"repository": {
"type": "git",
"url": "https://github.com/janl/mustache.js.git"
},
"keywords": ["mustache", "template", "templates", "ejs"],

@@ -12,3 +16,3 @@ "main": "./mustache.js",

"volo": {
"url": "https://raw.github.com/janl/mustache.js/0.7.2/mustache.js"
"url": "https://raw.github.com/janl/mustache.js/0.7.3/mustache.js"
},

@@ -15,0 +19,0 @@ "scripts": {

@@ -105,3 +105,3 @@ # mustache.js - Logic-less {{mustache}} templates with JavaScript

If the `person` key does not exist, or exists and has a value of `null`, `undefined`, or `false`, or is an empty list, the block will not be rendered.
If the `person` key does not exist, or exists and has a value of `null`, `undefined`, `false`, `0`, or `NaN`, or is an empty string or an empty list, the block will not be rendered.

@@ -352,3 +352,3 @@ View:

$ rake dojo
$ rake yui
$ rake yui3
$ rake qooxdoo

@@ -358,9 +358,14 @@

The mustache.js test suite uses the [vows](http://vowsjs.org/) testing framework. In order to run the tests you'll need to install [node](http://nodejs.org/). Once that's done you can install vows using [npm](http://npmjs.org/).
The mustache.js test suite uses the [mocha](http://visionmedia.github.com/mocha/) testing framework. In order to run the tests you'll need to install [node](http://nodejs.org/). Once that's done you can install mocha using [npm](http://npmjs.org/).
$ npm install -g vows
$ npm install -g mocha
You also need to install the sub module containing [Mustache specifications](http://github.com/mustache/spec) in the project root.
$ git submodule init
$ git submodule update
Then run the tests.
$ vows --spec
$ mocha test

@@ -379,3 +384,3 @@ The test suite consists of both unit and integration tests. If a template isn't rendering correctly for you, you can make a test for it by doing the following:

$ TEST=mytest vows test/render_test.js
$ TEST=mytest mocha test/render-test.js

@@ -382,0 +387,0 @@ ## Thanks

<ul>
<li><a href="#aa/a">a</a></li>
<li><a href="#aa/b">b</a></li>
<li><a href="#aa/c">c</a></li>
<li>aa/a</li>
<li>aa/b</li>
<li>aa/c</li>
</ul>

@@ -46,2 +46,19 @@ require('./helper');

describe('A Mustache.Context', function () {
var context;
describe('with an empty string in the lookup chain', function () {
var view, context;
beforeEach(function () {
view = { a: '' };
view.a.b = 'value';
context = new Context(view);
});
it('is able to lookup a nested property', function () {
assert.equal(context.lookup('a.b'), view.a.b);
});
});
});
describe('Mustache.Context.make', function () {

@@ -48,0 +65,0 @@ it('returns the same object when given a Context', function () {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc