Comparing version
{ | ||
"name": "Mustache.js", | ||
"name": "mustache.js", | ||
"main": "mustache.js", | ||
"version": "0.8.2", | ||
"version": "1.0.0", | ||
"homepage": "https://github.com/janl/mustache.js", | ||
@@ -6,0 +6,0 @@ "authors": [ |
202
mustache.js
@@ -8,28 +8,12 @@ /*! | ||
(function (root, factory) { | ||
(function (global, factory) { | ||
if (typeof exports === "object" && exports) { | ||
factory(exports); // CommonJS | ||
} else if (typeof define === "function" && define.amd) { | ||
define(['exports'], factory); // AMD | ||
} else { | ||
var mustache = {}; | ||
factory(mustache); | ||
if (typeof define === "function" && define.amd) { | ||
define(mustache); // AMD | ||
} else { | ||
root.Mustache = mustache; // <script> | ||
} | ||
factory(global.Mustache = {}); // <script> | ||
} | ||
}(this, function (mustache) { | ||
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 | ||
// See https://github.com/janl/mustache.js/issues/189 | ||
var RegExp_test = RegExp.prototype.test; | ||
function testRegExp(re, string) { | ||
return RegExp_test.call(re, string); | ||
} | ||
var nonSpaceRe = /\S/; | ||
function isWhitespace(string) { | ||
return !testRegExp(nonSpaceRe, string); | ||
} | ||
var Object_toString = Object.prototype.toString; | ||
@@ -48,2 +32,14 @@ var isArray = Array.isArray || function (object) { | ||
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 | ||
// See https://github.com/janl/mustache.js/issues/189 | ||
var RegExp_test = RegExp.prototype.test; | ||
function testRegExp(re, string) { | ||
return RegExp_test.call(re, string); | ||
} | ||
var nonSpaceRe = /\S/; | ||
function isWhitespace(string) { | ||
return !testRegExp(nonSpaceRe, string); | ||
} | ||
var entityMap = { | ||
@@ -64,13 +60,2 @@ "&": "&", | ||
function escapeTags(tags) { | ||
if (!isArray(tags) || tags.length !== 2) { | ||
throw new Error('Invalid tags: ' + tags); | ||
} | ||
return [ | ||
new RegExp(escapeRegExp(tags[0]) + "\\s*"), | ||
new RegExp("\\s*" + escapeRegExp(tags[1])) | ||
]; | ||
} | ||
var whiteRe = /\s*/; | ||
@@ -105,12 +90,5 @@ var spaceRe = /\s+/; | ||
function parseTemplate(template, tags) { | ||
tags = tags || mustache.tags; | ||
template = template || ''; | ||
if (!template) | ||
return []; | ||
if (typeof tags === 'string') { | ||
tags = tags.split(spaceRe); | ||
} | ||
var tagRes = escapeTags(tags); | ||
var scanner = new Scanner(template); | ||
var sections = []; // Stack to hold section tokens | ||
@@ -126,5 +104,4 @@ var tokens = []; // Buffer to hold the tokens | ||
if (hasTag && !nonSpace) { | ||
while (spaces.length) { | ||
while (spaces.length) | ||
delete tokens[spaces.pop()]; | ||
} | ||
} else { | ||
@@ -138,2 +115,19 @@ spaces = []; | ||
var openingTagRe, closingTagRe, closingCurlyRe; | ||
function compileTags(tags) { | ||
if (typeof tags === 'string') | ||
tags = tags.split(spaceRe, 2); | ||
if (!isArray(tags) || tags.length !== 2) | ||
throw new Error('Invalid tags: ' + tags); | ||
openingTagRe = new RegExp(escapeRegExp(tags[0]) + '\\s*'); | ||
closingTagRe = new RegExp('\\s*' + escapeRegExp(tags[1])); | ||
closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tags[1])); | ||
} | ||
compileTags(tags || mustache.tags); | ||
var scanner = new Scanner(template); | ||
var start, type, value, chr, token, openSection; | ||
@@ -144,5 +138,6 @@ while (!scanner.eos()) { | ||
// Match any text between tags. | ||
value = scanner.scanUntil(tagRes[0]); | ||
value = scanner.scanUntil(openingTagRe); | ||
if (value) { | ||
for (var i = 0, len = value.length; i < len; ++i) { | ||
for (var i = 0, valueLength = value.length; i < valueLength; ++i) { | ||
chr = value.charAt(i); | ||
@@ -156,9 +151,8 @@ | ||
tokens.push(['text', chr, start, start + 1]); | ||
tokens.push([ 'text', chr, start, start + 1 ]); | ||
start += 1; | ||
// Check for whitespace on the current line. | ||
if (chr === '\n') { | ||
if (chr === '\n') | ||
stripSpace(); | ||
} | ||
} | ||
@@ -168,3 +162,5 @@ } | ||
// Match the opening tag. | ||
if (!scanner.scan(tagRes[0])) break; | ||
if (!scanner.scan(openingTagRe)) | ||
break; | ||
hasTag = true; | ||
@@ -180,16 +176,15 @@ | ||
scanner.scan(equalsRe); | ||
scanner.scanUntil(tagRes[1]); | ||
scanner.scanUntil(closingTagRe); | ||
} else if (type === '{') { | ||
value = scanner.scanUntil(new RegExp('\\s*' + escapeRegExp('}' + tags[1]))); | ||
value = scanner.scanUntil(closingCurlyRe); | ||
scanner.scan(curlyRe); | ||
scanner.scanUntil(tagRes[1]); | ||
scanner.scanUntil(closingTagRe); | ||
type = '&'; | ||
} else { | ||
value = scanner.scanUntil(tagRes[1]); | ||
value = scanner.scanUntil(closingTagRe); | ||
} | ||
// Match the closing tag. | ||
if (!scanner.scan(tagRes[1])) { | ||
if (!scanner.scan(closingTagRe)) | ||
throw new Error('Unclosed tag at ' + scanner.pos); | ||
} | ||
@@ -205,8 +200,7 @@ token = [ type, value, start, scanner.pos ]; | ||
if (!openSection) { | ||
if (!openSection) | ||
throw new Error('Unopened section "' + value + '" at ' + start); | ||
} | ||
if (openSection[1] !== value) { | ||
if (openSection[1] !== value) | ||
throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); | ||
} | ||
} else if (type === 'name' || type === '{' || type === '&') { | ||
@@ -216,3 +210,3 @@ nonSpace = true; | ||
// Set the tags for the next time around. | ||
tagRes = escapeTags(tags = value.split(spaceRe)); | ||
compileTags(value); | ||
} | ||
@@ -223,5 +217,5 @@ } | ||
openSection = sections.pop(); | ||
if (openSection) { | ||
if (openSection) | ||
throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); | ||
} | ||
@@ -239,3 +233,3 @@ return nestTokens(squashTokens(tokens)); | ||
var token, lastToken; | ||
for (var i = 0, len = tokens.length; i < len; ++i) { | ||
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { | ||
token = tokens[i]; | ||
@@ -269,3 +263,3 @@ | ||
var token, section; | ||
for (var i = 0, len = tokens.length; i < len; ++i) { | ||
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { | ||
token = tokens[i]; | ||
@@ -317,10 +311,11 @@ | ||
if (match && match.index === 0) { | ||
var string = match[0]; | ||
this.tail = this.tail.substring(string.length); | ||
this.pos += string.length; | ||
return string; | ||
} | ||
if (!match || match.index !== 0) | ||
return ''; | ||
return ""; | ||
var string = match[0]; | ||
this.tail = this.tail.substring(string.length); | ||
this.pos += string.length; | ||
return string; | ||
}; | ||
@@ -376,7 +371,9 @@ | ||
Context.prototype.lookup = function (name) { | ||
var cache = this.cache; | ||
var value; | ||
if (name in this.cache) { | ||
value = this.cache[name]; | ||
if (name in cache) { | ||
value = cache[name]; | ||
} else { | ||
var context = this; | ||
var context = this, names, index; | ||
@@ -386,12 +383,13 @@ while (context) { | ||
value = context.view; | ||
names = name.split('.'); | ||
index = 0; | ||
var names = name.split('.'), i = 0; | ||
while (value != null && i < names.length) { | ||
value = value[names[i++]]; | ||
} | ||
} else { | ||
while (value != null && index < names.length) | ||
value = value[names[index++]]; | ||
} else if (typeof context.view == 'object') { | ||
value = context.view[name]; | ||
} | ||
if (value != null) break; | ||
if (value != null) | ||
break; | ||
@@ -401,8 +399,7 @@ context = context.parent; | ||
this.cache[name] = value; | ||
cache[name] = value; | ||
} | ||
if (isFunction(value)) { | ||
if (isFunction(value)) | ||
value = value.call(this.view); | ||
} | ||
@@ -436,5 +433,4 @@ return value; | ||
if (tokens == null) { | ||
if (tokens == null) | ||
tokens = cache[template] = parseTemplate(template, tags); | ||
} | ||
@@ -479,3 +475,3 @@ return tokens; | ||
var token, value; | ||
for (var i = 0, len = tokens.length; i < len; ++i) { | ||
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { | ||
token = tokens[i]; | ||
@@ -486,6 +482,8 @@ | ||
value = context.lookup(token[1]); | ||
if (!value) continue; | ||
if (!value) | ||
continue; | ||
if (isArray(value)) { | ||
for (var j = 0, jlen = value.length; j < jlen; ++j) { | ||
for (var j = 0, valueLength = value.length; j < valueLength; ++j) { | ||
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate); | ||
@@ -496,5 +494,4 @@ } | ||
} else if (isFunction(value)) { | ||
if (typeof originalTemplate !== 'string') { | ||
if (typeof originalTemplate !== 'string') | ||
throw new Error('Cannot use higher-order sections without the original template'); | ||
} | ||
@@ -504,3 +501,4 @@ // Extract the portion of the original template that the section contains. | ||
if (value != null) buffer += value; | ||
if (value != null) | ||
buffer += value; | ||
} else { | ||
@@ -516,19 +514,29 @@ buffer += this.renderTokens(token[4], context, partials, originalTemplate); | ||
// See https://github.com/janl/mustache.js/issues/186 | ||
if (!value || (isArray(value) && value.length === 0)) { | ||
if (!value || (isArray(value) && value.length === 0)) | ||
buffer += this.renderTokens(token[4], context, partials, originalTemplate); | ||
} | ||
break; | ||
case '>': | ||
if (!partials) continue; | ||
if (!partials) | ||
continue; | ||
value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; | ||
if (value != null) buffer += this.renderTokens(this.parse(value), context, partials, value); | ||
if (value != null) | ||
buffer += this.renderTokens(this.parse(value), context, partials, value); | ||
break; | ||
case '&': | ||
value = context.lookup(token[1]); | ||
if (value != null) buffer += value; | ||
if (value != null) | ||
buffer += value; | ||
break; | ||
case 'name': | ||
value = context.lookup(token[1]); | ||
if (value != null) buffer += mustache.escape(value); | ||
if (value != null) | ||
buffer += mustache.escape(value); | ||
break; | ||
@@ -545,3 +553,3 @@ case 'text': | ||
mustache.name = "mustache.js"; | ||
mustache.version = "0.8.1"; | ||
mustache.version = "1.0.0"; | ||
mustache.tags = [ "{{", "}}" ]; | ||
@@ -548,0 +556,0 @@ |
{ | ||
"name": "mustache", | ||
"version": "0.8.2", | ||
"version": "1.0.0", | ||
"description": "Logic-less {{mustache}} templates with JavaScript", | ||
@@ -10,13 +10,25 @@ "author": "mustache.js Authors <http://github.com/janl/mustache.js>", | ||
}, | ||
"keywords": ["mustache", "template", "templates", "ejs"], | ||
"keywords": [ | ||
"mustache", | ||
"template", | ||
"templates", | ||
"ejs" | ||
], | ||
"main": "./mustache.js", | ||
"devDependencies": { | ||
"mocha": "1.5.0" | ||
}, | ||
"volo": { | ||
"url": "https://raw.github.com/janl/mustache.js/0.7.3/mustache.js" | ||
"url": "https://raw.github.com/janl/mustache.js/{version}/mustache.js" | ||
}, | ||
"scripts": { | ||
"test": "mocha test" | ||
"test": "mocha --reporter spec test" | ||
}, | ||
"devDependencies": { | ||
"mocha": "2.0.1" | ||
}, | ||
"spm": { | ||
"main": "mustache.js", | ||
"ignore": [ | ||
"test", | ||
"wrappers" | ||
] | ||
} | ||
} |
@@ -19,2 +19,6 @@ # mustache.js - Logic-less {{mustache}} templates with JavaScript | ||
And this will be your templates after you use Mustache: | ||
 | ||
## Who uses mustache.js? | ||
@@ -24,2 +28,16 @@ | ||
## Contributing | ||
mustache.js is a mature project, but it continues to actively invite maintainers. You can help out a high-profile project that is used in a lot of places on the web. There is [plenty](https://github.com/janl/mustache.js/issues) of [work](https://github.com/janl/mustache.js/pulls) to do. No big commitment required, if all you do is review a single [Pull Request](https://github.com/janl/mustache.js/pulls), you are a maintainer. And a hero. | ||
### Your First Contribution | ||
- review a [Pull Request](https://github.com/janl/mustache.js/pulls) | ||
- fix an [Issue](https://github.com/janl/mustache.js/issues) | ||
- update the [documentation](https://github.com/janl/mustache.js#usage) | ||
- make a website | ||
- write a tutorial | ||
* * * | ||
## Usage | ||
@@ -44,6 +62,43 @@ | ||
A [mustache](http://mustache.github.com/) template is a string that contains any number of mustache tags. Tags are indicated by the double mustaches that surround them. `{{person}}` is a tag, as is `{{#person}}`. In both examples we refer to `person` as the tag's key. | ||
A [mustache](http://mustache.github.com/) template is a string that contains any number of mustache tags. Tags are indicated by the double mustaches that surround them. `{{person}}` is a tag, as is `{{#person}}`. In both examples we refer to `person` as the tag's key. There are several types of tags available in mustache.js, described below. | ||
There are several types of tags available in mustache.js. | ||
There are several techniques that can be used to load templates and hand them to mustache.js, here are two of them: | ||
#### Include Templates | ||
If you need a template for a dynamic part in a static website, you can consider including the template in the static HTML file to avoid loading templates separately. Here's a small example using `jQuery`: | ||
```html | ||
<html> | ||
<body onload="loadUser"> | ||
<div id="target">Loading...</div> | ||
<script id="template" type="x-tmpl-mustache"> | ||
Hello {{ name }}! | ||
</script> | ||
</body> | ||
</html> | ||
``` | ||
```js | ||
function loadUser() { | ||
var template = $('#template').html(); | ||
Mustache.parse(template); // optional, speeds up future uses | ||
var rendered = Mustache.render(template, {name: "Luke"}); | ||
$('#target').html(rendered); | ||
} | ||
``` | ||
#### Load External Templates | ||
If your templates reside in individual files, you can load them asynchronously and render them when they arrive. Another example using `jQuery`: | ||
```js | ||
function loadUser() { | ||
$.get('template.mst', function(template) { | ||
var rendered = Mustache.render(template, {name: "Luke"}); | ||
$('#target').html(rendered); | ||
}); | ||
} | ||
``` | ||
### Variables | ||
@@ -50,0 +105,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
55883
32.42%25
13.64%1
-50%514
11.98%497
-1.58%1
Infinity%