Comparing version 2.3.2 to 3.0.0
@@ -6,2 +6,96 @@ # Change Log | ||
## [3.0.0] / 16 September 2018 | ||
We are very happy to announce a new major version of mustache.js. We want to be very careful not to break projects | ||
out in the wild, and adhering to [Semantic Versioning](http://semver.org/) we have therefore cut this new major version. | ||
The changes introduced will likely not require any actions for most using projects. The things to look out for that | ||
might cause unexpected rendering results are described in the migration guide below. | ||
A big shout out and thanks to [@raymond-lam] for this release! Without his contributions with code and issue triaging, | ||
this release would never have happened. | ||
### Major | ||
* [#618]: Allow rendering properties of primitive types that are not objects, by [@raymond-lam]. | ||
* [#643]: `Writer.prototype.parse` to cache by tags in addition to template string, by [@raymond-lam]. | ||
* [#664]: Fix `Writer.prototype.parse` cache, by [@seminaoki]. | ||
### Minor | ||
* [#673]: Add `tags` parameter to `Mustache.render()`, by [@raymond-lam]. | ||
### Migrating from mustache.js v2.x to v3.x | ||
#### Rendering properties of primitive types | ||
We have ensured properties of primitive types can be rendered at all times. That means `Array.length`, `String.length` | ||
and similar. A corner case where this could cause unexpected output follows: | ||
View: | ||
``` | ||
{ | ||
stooges: [ | ||
{ name: "Moe" }, | ||
{ name: "Larry" }, | ||
{ name: "Curly" } | ||
] | ||
} | ||
``` | ||
Template: | ||
``` | ||
{{#stooges}} | ||
{{name}}: {{name.length}} characters | ||
{{/stooges}} | ||
``` | ||
Output with v3.0: | ||
``` | ||
Moe: 3 characters | ||
Larry: 5 characters | ||
Curly: 5 characters | ||
``` | ||
Output with v2.x: | ||
``` | ||
Moe: characters | ||
Larry: characters | ||
Curly: characters | ||
``` | ||
#### Caching for templates with custom delimiters | ||
We have improved the templates cache to ensure custom delimiters are taken into consideration for the cache. | ||
This improvement might cause unexpected rendering behaviour for using projects actively using the custom delimiters functionality. | ||
Previously it was possible to use `Mustache.parse()` as a means to set global custom delimiters. If custom | ||
delimiters were provided as an argument, it would affect all following calls to `Mustache.render()`. | ||
Consider the following: | ||
```js | ||
const template = "[[item.title]] [[item.value]]"; | ||
mustache.parse(template, ["[[", "]]"]); | ||
console.log( | ||
mustache.render(template, { | ||
item: { | ||
title: "TEST", | ||
value: 1 | ||
} | ||
}) | ||
); | ||
>> TEST 1 | ||
``` | ||
The above illustrates the fact that `Mustache.parse()` made mustache.js cache the template without considering | ||
the custom delimiters provided. This is no longer true. | ||
We no longer encourage using `Mustache.parse()` for this purpose, but have rather added a fourth argument to | ||
`Mustache.render()` letting you provide custom delimiters when rendering. | ||
If you still need the pre-parse the template and use custom delimiters at the same time, ensure to provide | ||
the custom delimiters as argument to `Mustache.render()` as well. | ||
## [2.3.2] / 17 August 2018 | ||
@@ -231,2 +325,3 @@ | ||
[3.0.0]: https://github.com/janl/mustache.js/compare/v2.3.2...v3.0.0 | ||
[2.3.2]: https://github.com/janl/mustache.js/compare/v2.3.1...v2.3.2 | ||
@@ -284,2 +379,4 @@ [2.3.1]: https://github.com/janl/mustache.js/compare/v2.3.0...v2.3.1 | ||
[#670]: https://github.com/janl/mustache.js/issues/670 | ||
[#618]: https://github.com/janl/mustache.js/issues/618 | ||
[#673]: https://github.com/janl/mustache.js/issues/673 | ||
@@ -286,0 +383,0 @@ [@afc163]: https://github.com/afc163 |
@@ -48,2 +48,15 @@ /*! | ||
/** | ||
* Safe way of detecting whether or not the given thing is a primitive and | ||
* whether it has the given property | ||
*/ | ||
function primitiveHasOwnProperty (primitive, propName) { | ||
return ( | ||
primitive != null | ||
&& typeof primitive !== 'object' | ||
&& primitive.hasOwnProperty | ||
&& primitive.hasOwnProperty(propName) | ||
); | ||
} | ||
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 | ||
@@ -381,7 +394,7 @@ // See https://github.com/janl/mustache.js/issues/189 | ||
} else { | ||
var context = this, names, index, lookupHit = false; | ||
var context = this, intermediateValue, names, index, lookupHit = false; | ||
while (context) { | ||
if (name.indexOf('.') > 0) { | ||
value = context.view; | ||
intermediateValue = context.view; | ||
names = name.split('.'); | ||
@@ -400,16 +413,47 @@ index = 0; | ||
* `undefined` and we want to avoid looking up parent contexts. | ||
* | ||
* In the case where dot notation is used, we consider the lookup | ||
* to be successful even if the last "object" in the path is | ||
* not actually an object but a primitive (e.g., a string, or an | ||
* integer), because it is sometimes useful to access a property | ||
* of an autoboxed primitive, such as the length of a string. | ||
**/ | ||
while (value != null && index < names.length) { | ||
while (intermediateValue != null && index < names.length) { | ||
if (index === names.length - 1) | ||
lookupHit = hasProperty(value, names[index]); | ||
lookupHit = ( | ||
hasProperty(intermediateValue, names[index]) | ||
|| primitiveHasOwnProperty(intermediateValue, names[index]) | ||
); | ||
value = value[names[index++]]; | ||
intermediateValue = intermediateValue[names[index++]]; | ||
} | ||
} else { | ||
value = context.view[name]; | ||
intermediateValue = context.view[name]; | ||
/** | ||
* Only checking against `hasProperty`, which always returns `false` if | ||
* `context.view` is not an object. Deliberately omitting the check | ||
* against `primitiveHasOwnProperty` if dot notation is not used. | ||
* | ||
* Consider this example: | ||
* ``` | ||
* Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"}) | ||
* ``` | ||
* | ||
* If we were to check also against `primitiveHasOwnProperty`, as we do | ||
* in the dot notation case, then render call would return: | ||
* | ||
* "The length of a football field is 9." | ||
* | ||
* rather than the expected: | ||
* | ||
* "The length of a football field is 100 yards." | ||
**/ | ||
lookupHit = hasProperty(context.view, name); | ||
} | ||
if (lookupHit) | ||
if (lookupHit) { | ||
value = intermediateValue; | ||
break; | ||
} | ||
@@ -445,3 +489,4 @@ context = context.parent; | ||
/** | ||
* Parses and caches the given `template` and returns the array of tokens | ||
* Parses and caches the given `template` according to the given `tags` or | ||
* `mustache.tags` if `tags` is omitted, and returns the array of tokens | ||
* that is generated from the parse. | ||
@@ -451,6 +496,7 @@ */ | ||
var cache = this.cache; | ||
var tokens = cache[template]; | ||
var cacheKey = template + ':' + (tags || mustache.tags).join(':'); | ||
var tokens = cache[cacheKey]; | ||
if (tokens == null) | ||
tokens = cache[template] = parseTemplate(template, tags); | ||
tokens = cache[cacheKey] = parseTemplate(template, tags); | ||
@@ -468,5 +514,9 @@ return tokens; | ||
* that takes a single argument: the name of the partial. | ||
* | ||
* If the optional `tags` argument is given here it must be an array with two | ||
* string values: the opening and closing tags used in the template (e.g. | ||
* [ "<%", "%>" ]). The default is to mustache.tags. | ||
*/ | ||
Writer.prototype.render = function render (template, view, partials) { | ||
var tokens = this.parse(template); | ||
Writer.prototype.render = function render (template, view, partials, tags) { | ||
var tokens = this.parse(template, tags); | ||
var context = (view instanceof Context) ? view : new Context(view); | ||
@@ -576,3 +626,3 @@ return this.renderTokens(tokens, context, partials, template); | ||
mustache.name = 'mustache.js'; | ||
mustache.version = '2.3.2'; | ||
mustache.version = '3.0.0'; | ||
mustache.tags = [ '{{', '}}' ]; | ||
@@ -601,5 +651,7 @@ | ||
* Renders the `template` with the given `view` and `partials` using the | ||
* default writer. | ||
* default writer. If the optional `tags` argument is given here it must be an | ||
* array with two string values: the opening and closing tags used in the | ||
* template (e.g. [ "<%", "%>" ]). The default is to mustache.tags. | ||
*/ | ||
mustache.render = function render (template, view, partials) { | ||
mustache.render = function render (template, view, partials, tags) { | ||
if (typeof template !== 'string') { | ||
@@ -611,3 +663,3 @@ throw new TypeError('Invalid template! Template should be a "string" ' + | ||
return defaultWriter.render(template, view, partials); | ||
return defaultWriter.render(template, view, partials, tags); | ||
}; | ||
@@ -614,0 +666,0 @@ |
@@ -1,1 +0,1 @@ | ||
(function defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(global.Mustache)}})(this,function mustacheFactory(mustache){var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i<valueLength;++i){chr=value.charAt(i);if(isWhitespace(chr)){spaces.push(tokens.length)}else{nonSpace=true}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n")stripSpace()}}if(!scanner.scan(openingTagRe))break;hasTag=true;type=scanner.scan(tagRe)||"name";scanner.scan(whiteRe);if(type==="="){value=scanner.scanUntil(equalsRe);scanner.scan(equalsRe);scanner.scanUntil(closingTagRe)}else if(type==="{"){value=scanner.scanUntil(closingCurlyRe);scanner.scan(curlyRe);scanner.scanUntil(closingTagRe);type="&"}else{value=scanner.scanUntil(closingTagRe)}if(!scanner.scan(closingTagRe))throw new Error("Unclosed tag at "+scanner.pos);token=[type,value,start,scanner.pos];tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){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==="="){compileTags(value)}}openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];if(token){if(token[0]==="text"&&lastToken&&lastToken[0]==="text"){lastToken[1]+=token[1];lastToken[3]=token[3]}else{squashedTokens.push(token);lastToken=token}}}return squashedTokens}function nestTokens(tokens){var nestedTokens=[];var collector=nestedTokens;var sections=[];var token,section;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];switch(token[0]){case"#":case"^":collector.push(token);sections.push(token);collector=token[4]=[];break;case"/":section=sections.pop();section[5]=token[2];collector=sections.length>0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(value,names[index]);value=value[names[index++]]}}else{value=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit)break;context=context.parent}cache[name]=value}if(isFunction(value))value=value.call(this.view);return value};function Writer(){this.cache={}}Writer.prototype.clearCache=function clearCache(){this.cache={}};Writer.prototype.parse=function parse(template,tags){var cache=this.cache;var tokens=cache[template];if(tokens==null)tokens=cache[template]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials){var tokens=this.parse(template);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate){var buffer="";var token,symbol,value;for(var i=0,numTokens=tokens.length;i<numTokens;++i){value=undefined;token=tokens[i];symbol=token[0];if(symbol==="#")value=this.renderSection(token,context,partials,originalTemplate);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate);else if(symbol===">")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j<valueLength;++j){buffer+=this.renderTokens(token[4],context.push(value[j]),partials,originalTemplate)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate)}else if(isFunction(value)){if(typeof originalTemplate!=="string")throw new Error("Cannot use higher-order sections without the original template");value=value.call(context.view,originalTemplate.slice(token[3],token[5]),subRender);if(value!=null)buffer+=value}else{buffer+=this.renderTokens(token[4],context,partials,originalTemplate)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate)};Writer.prototype.renderPartial=function renderPartial(token,context,partials){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value),context,partials,value)};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return mustache.escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};mustache.name="mustache.js";mustache.version="2.3.2";mustache.tags=["{{","}}"];var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials)};mustache.to_html=function to_html(template,view,partials,send){var result=mustache.render(template,view,partials);if(isFunction(send)){send(result)}else{return result}};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer;return mustache}); | ||
(function defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(global.Mustache)}})(this,function mustacheFactory(mustache){var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}function primitiveHasOwnProperty(primitive,propName){return primitive!=null&&typeof primitive!=="object"&&primitive.hasOwnProperty&&primitive.hasOwnProperty(propName)}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i<valueLength;++i){chr=value.charAt(i);if(isWhitespace(chr)){spaces.push(tokens.length)}else{nonSpace=true}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n")stripSpace()}}if(!scanner.scan(openingTagRe))break;hasTag=true;type=scanner.scan(tagRe)||"name";scanner.scan(whiteRe);if(type==="="){value=scanner.scanUntil(equalsRe);scanner.scan(equalsRe);scanner.scanUntil(closingTagRe)}else if(type==="{"){value=scanner.scanUntil(closingCurlyRe);scanner.scan(curlyRe);scanner.scanUntil(closingTagRe);type="&"}else{value=scanner.scanUntil(closingTagRe)}if(!scanner.scan(closingTagRe))throw new Error("Unclosed tag at "+scanner.pos);token=[type,value,start,scanner.pos];tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){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==="="){compileTags(value)}}openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];if(token){if(token[0]==="text"&&lastToken&&lastToken[0]==="text"){lastToken[1]+=token[1];lastToken[3]=token[3]}else{squashedTokens.push(token);lastToken=token}}}return squashedTokens}function nestTokens(tokens){var nestedTokens=[];var collector=nestedTokens;var sections=[];var token,section;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];switch(token[0]){case"#":case"^":collector.push(token);sections.push(token);collector=token[4]=[];break;case"/":section=sections.pop();section[5]=token[2];collector=sections.length>0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,intermediateValue,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){intermediateValue=context.view;names=name.split(".");index=0;while(intermediateValue!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(intermediateValue,names[index])||primitiveHasOwnProperty(intermediateValue,names[index]);intermediateValue=intermediateValue[names[index++]]}}else{intermediateValue=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit){value=intermediateValue;break}context=context.parent}cache[name]=value}if(isFunction(value))value=value.call(this.view);return value};function Writer(){this.cache={}}Writer.prototype.clearCache=function clearCache(){this.cache={}};Writer.prototype.parse=function parse(template,tags){var cache=this.cache;var cacheKey=template+":"+(tags||mustache.tags).join(":");var tokens=cache[cacheKey];if(tokens==null)tokens=cache[cacheKey]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials,tags){var tokens=this.parse(template,tags);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate){var buffer="";var token,symbol,value;for(var i=0,numTokens=tokens.length;i<numTokens;++i){value=undefined;token=tokens[i];symbol=token[0];if(symbol==="#")value=this.renderSection(token,context,partials,originalTemplate);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate);else if(symbol===">")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j<valueLength;++j){buffer+=this.renderTokens(token[4],context.push(value[j]),partials,originalTemplate)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate)}else if(isFunction(value)){if(typeof originalTemplate!=="string")throw new Error("Cannot use higher-order sections without the original template");value=value.call(context.view,originalTemplate.slice(token[3],token[5]),subRender);if(value!=null)buffer+=value}else{buffer+=this.renderTokens(token[4],context,partials,originalTemplate)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate)};Writer.prototype.renderPartial=function renderPartial(token,context,partials){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value),context,partials,value)};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return mustache.escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};mustache.name="mustache.js";mustache.version="3.0.0";mustache.tags=["{{","}}"];var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials,tags){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials,tags)};mustache.to_html=function to_html(template,view,partials,send){var result=mustache.render(template,view,partials);if(isFunction(send)){send(result)}else{return result}};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer;return mustache}); |
{ | ||
"name": "mustache", | ||
"version": "2.3.2", | ||
"version": "3.0.0", | ||
"description": "Logic-less {{mustache}} templates with JavaScript", | ||
@@ -5,0 +5,0 @@ "author": "mustache.js Authors <http://github.com/janl/mustache.js>", |
@@ -120,5 +120,6 @@ # mustache.js - Logic-less {{mustache}} templates with JavaScript | ||
Mustache.render( | ||
template : String, | ||
view : Object, | ||
partials? : Object, | ||
template : String, | ||
view : Object, | ||
partials? : Object, | ||
tags = ['{{', '}}'] : Tags, | ||
) => String | ||
@@ -185,3 +186,3 @@ | ||
All variables are HTML-escaped by default. If you want to render unescaped HTML, use the triple mustache: `{{{name}}}`. You can also use `&` to unescape a variable. | ||
All variables are HTML-escaped by default. If you want to render unescaped HTML, use the triple mustache: `{{{name}}}`. You can also use `&` to unescape a variable. | ||
@@ -509,3 +510,3 @@ If you'd like to change HTML-escaping behavior globally (for example, to template non-HTML formats), you can override Mustache's escape function. For example, to disable all escaping: `Mustache.escape = function(text) {return text;};`. | ||
The `Mustache.tags` property holds an array consisting of the opening and closing tag values. Set custom values by passing a new array of tags to `parse()`, which gets honored over the default values, or by overriding the `tags` property itself: | ||
The `Mustache.tags` property holds an array consisting of the opening and closing tag values. Set custom values by passing a new array of tags to `render()`, which gets honored over the default values, or by overriding the `Mustache.tags` property itself: | ||
@@ -516,5 +517,5 @@ ```js | ||
##### Pass Value into Parse Method | ||
##### Pass Value into Render Method | ||
```js | ||
Mustache.parse(template, customTags); | ||
Mustache.render(template, view, {}, customTags); | ||
``` | ||
@@ -521,0 +522,0 @@ |
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
77817
612
646