diff --git a/lib/amd/build/mustache.min.js b/lib/amd/build/mustache.min.js index e28c52846bb..c795aedcc4e 100644 --- a/lib/amd/build/mustache.min.js +++ b/lib/amd/build/mustache.min.js @@ -1 +1 @@ -!function(a,b){"object"==typeof exports&&exports&&"string"!=typeof exports.nodeName?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a.Mustache={},b(a.Mustache))}(this,function(a){function b(a){return"function"==typeof a}function c(a){return p(a)?"array":typeof a}function d(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function e(a,b){return null!=a&&"object"==typeof a&&b in a}function f(a,b){return q.call(a,b)}function g(a){return!f(r,a)}function h(a){return String(a).replace(/[&<>"'`=\/]/g,function(a){return s[a]})}function i(b,c){function e(){if(r&&!s)for(;q.length;)delete o[q.pop()];else q=[];r=!1,s=!1}function f(a){if("string"==typeof a&&(a=a.split(u,2)),!p(a)||2!==a.length)throw new Error("Invalid tags: "+a);h=new RegExp(d(a[0])+"\\s*"),i=new RegExp("\\s*"+d(a[1])),m=new RegExp("\\s*"+d("}"+a[1]))}if(!b)return[];var h,i,m,n=[],o=[],q=[],r=!1,s=!1;f(c||a.tags);for(var y,z,A,B,C,D,E=new l(b);!E.eos();){if(y=E.pos,A=E.scanUntil(h))for(var F=0,G=A.length;F0?f[f.length-1][4]:d;break;default:e.push(b)}return d}function l(a){this.string=a,this.tail=a,this.pos=0}function m(a,b){this.view=a,this.blocks={},this.cache={".":this.view},this.parent=b}function n(){this.cache={}}var o=Object.prototype.toString,p=Array.isArray||function(a){return"[object Array]"===o.call(a)},q=RegExp.prototype.test,r=/\S/,s={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},t=/\s*/,u=/\s+/,v=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!|\$|0)for(c=h.view,f=a.split("."),g=0;null!=c&&g"===f?g=this.renderPartial(e,b,c,d):"<"===f?g=this.renderBlock(e,b,c,d):"$"===f?g=this.renderBlockVariable(e,b,c,d):"&"===f?g=this.unescapedValue(e,b):"name"===f?g=this.escapedValue(e,b):"text"===f&&(g=this.rawValue(e)),void 0!==g&&(h+=g);return h},n.prototype.renderSection=function(a,c,d,e){function f(a){return g.render(a,c,d)}var g=this,h="",i=c.lookup(a[1]);if(i){if(p(i))for(var j=0,k=i.length;j"'`=\/]/g,function(a){return t[a]})}function j(b,c){function e(){if(r&&!s)for(;p.length;)delete o[p.pop()];else p=[];r=!1,s=!1}function f(a){if("string"==typeof a&&(a=a.split(v,2)),!q(a)||2!==a.length)throw new Error("Invalid tags: "+a);g=new RegExp(d(a[0])+"\\s*"),i=new RegExp("\\s*"+d(a[1])),j=new RegExp("\\s*"+d("}"+a[1]))}if(!b)return[];var g,i,j,n=[],o=[],p=[],r=!1,s=!1;f(c||a.tags);for(var t,z,A,B,C,D,E=new m(b);!E.eos();){if(t=E.pos,A=E.scanUntil(g))for(var F=0,G=A.length;F0?f[f.length-1][4]:d;break;default:e.push(b)}return d}function m(a){this.string=a,this.tail=a,this.pos=0}function n(a,b){this.view=a,this.blocks={},this.cache={".":this.view},this.parent=b}function o(){this.cache={}}var p=Object.prototype.toString,q=Array.isArray||function(a){return"[object Array]"===p.call(a)},r=RegExp.prototype.test,s=/\S/,t={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},u=/\s*/,v=/\s+/,w=/\s*=/,x=/\s*\}/,y=/#|\^|\/|>|\{|&|=|!|\$|0)for(g=j.view,h=a.split("."),i=0;null!=g&&i"===g?h=this.renderPartial(f,b,c,e):"<"===g?h=this.renderBlock(f,b,c,d):"$"===g?h=this.renderBlockVariable(f,b,c,d):"&"===g?h=this.unescapedValue(f,b):"name"===g?h=this.escapedValue(f,b):"text"===g&&(h=this.rawValue(f)),void 0!==h&&(i+=h);return i},o.prototype.renderSection=function(a,c,d,e){function f(a){return g.render(a,c,d)}var g=this,h="",i=c.lookup(a[1]);if(i){if(q(i))for(var j=0,k=i.length;j 0) { - value = context.view; + intermediateValue = context.view; names = name.split('.'); index = 0; @@ -469,20 +482,51 @@ * * This is specially necessary for when the value has been set to * `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; + } context = context.parent; } @@ -513,15 +557,17 @@ }; /** - * 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. */ Writer.prototype.parse = function parse (template, tags) { 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 + ':' + (tags || mustache.tags).join(':')] = parseTemplate(template, tags); + tokens = cache[cacheKey] = parseTemplate(template, tags); return tokens; }; @@ -534,11 +580,15 @@ * names and templates of partials that are used in the template. It may * also be a function that is used to load partial templates on the fly * 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); - return this.renderTokens(tokens, context, partials, template); + return this.renderTokens(tokens, context, partials, template, tags); }; /** @@ -550,7 +600,7 @@ * If the template doesn't use higher-order sections, this argument may * be omitted. */ - Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) { + Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, tags) { var buffer = ''; var token, symbol, value; @@ -561,7 +611,7 @@ 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.renderPartial(token, context, partials, tags); else if (symbol === '<') value = this.renderBlock(token, context, partials, originalTemplate); else if (symbol === '$') value = this.renderBlockVariable(token, context, partials, originalTemplate); else if (symbol === '&') value = this.unescapedValue(token, context); @@ -618,12 +668,12 @@ return this.renderTokens(token[4], context, partials, originalTemplate); }; - Writer.prototype.renderPartial = function renderPartial (token, context, partials) { + Writer.prototype.renderPartial = function renderPartial (token, context, partials, tags) { 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); + return this.renderTokens(this.parse(value, tags), context, partials, value); }; Writer.prototype.renderBlock = function renderBlock (token, context, partials, originalTemplate) { @@ -671,7 +721,7 @@ }; mustache.name = 'mustache.js'; - mustache.version = '2.3.0'; + mustache.version = '3.0.1'; mustache.tags = [ '{{', '}}' ]; // All high-level mustache.* functions use this writer. @@ -695,16 +745,18 @@ /** * 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') { 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); + return defaultWriter.render(template, view, partials, tags); }; // This is here for backwards compatibility with 0.4.x., diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index b511bd1a6ee..55b718bca4c 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -198,7 +198,7 @@ amd/src/mustache.js Mustache.js MIT - 2.3.0 + 3.0.1 graphlib.php