From 47e3003b8754b5c684c7148e5ccda64427496f74 Mon Sep 17 00:00:00 2001 From: Kieling Date: Tue, 5 Feb 2019 20:16:19 -0200 Subject: [PATCH 1/5] Added pipeline helper, with tests Can write with | and |> to use this function. --- mustache.js | 37 +++++++++++++++++++++++--- mustache.min.js | 2 +- test/_files/pipeline.js | 25 ++++++++++++++++++ test/_files/pipeline.mustache | 50 +++++++++++++++++++++++++++++++++++ test/_files/pipeline.txt | 50 +++++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 test/_files/pipeline.js create mode 100644 test/_files/pipeline.mustache create mode 100644 test/_files/pipeline.txt diff --git a/mustache.js b/mustache.js index 8ec1b44cc..944c3f5b6 100644 --- a/mustache.js +++ b/mustache.js @@ -49,7 +49,7 @@ * Safe way of detecting whether or not the given thing is a primitive and * whether it has the given property */ - function primitiveHasOwnProperty (primitive, propName) { + function primitiveHasOwnProperty (primitive, propName) { return ( primitive != null && typeof primitive !== 'object' @@ -92,6 +92,7 @@ var equalsRe = /\s*=/; var curlyRe = /\s*\}/; var tagRe = /#|\^|\/|>|\{|&|=|!/; + var pipelineRe = /\|\>?/; /** * Breaks up the given `template` string into a tree of tokens. If the `tags` @@ -379,14 +380,37 @@ return new Context(view, this); }; + Context.prototype.resolvePipelineOperator = function resolvePipelineOperator(value, pipelines){ + var self = this; + return pipelines.reduce(function(val, func){ + if(self.view.hasOwnProperty(func)){ + return self.view[func](val); + }else if(self.parent && self.parent.view.hasOwnProperty(func)){ + return self.parent.view[func](val); + }else{ + return value; + } + } + ,value); + } + /** * Returns the value of the given name in this context, traversing * up the context hierarchy if the value is absent in this context's view. */ Context.prototype.lookup = function lookup (name) { - var cache = this.cache; + // {{variable | pipelineOne |> pipelineTwo}} + // output: [variable,pipelineOne, pipelineTwo ] + // Can use | or |>. + var replacedName = name + .replace(new RegExp(spaceRe, "g"),'') + .split(pipelineRe) - var value; + pipelines = replacedName.slice(1); + name = replacedName[0]; + + var cache = this.cache; + var value if (cache.hasOwnProperty(name)) { value = cache[name]; } else { @@ -418,7 +442,7 @@ while (intermediateValue != null && index < names.length) { if (index === names.length - 1) lookupHit = ( - hasProperty(intermediateValue, names[index]) + hasProperty(intermediateValue, names[index]) || primitiveHasOwnProperty(intermediateValue, names[index]) ); @@ -460,9 +484,14 @@ cache[name] = value; } + if (isFunction(value)) value = value.call(this.view); + if(pipelines){ + value = this.resolvePipelineOperator(value, pipelines); + } + return value; }; diff --git a/mustache.min.js b/mustache.min.js index 7ad4c009c..308cada01 100644 --- a/mustache.min.js +++ b/mustache.min.js @@ -1 +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}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;i0?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")value=this.renderPartial(token,context,partials,tags);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":">",'"':""","'":"'","/":"/","`":"`","=":"="};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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;return pipelines.reduce(function(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return value}},value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);pipelines=replacedName.slice(1);name=replacedName[0];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")value=this.renderPartial(token,context,partials,tags);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{ + return value + 1; + }, + upper:(value)=>{ + return value.toUpperCase() + }, + lower: (value)=>{ + return value.toLowerCase() + }, + firstUpper:(value) =>{ + value = value.split('') + value[0] = value[0].toUpperCase() + value = value.join('') + return value; + }, + setNameFuncion:(value)=>{ + return value + ": This is a value" + } +}) diff --git a/test/_files/pipeline.mustache b/test/_files/pipeline.mustache new file mode 100644 index 000000000..7d40575f5 --- /dev/null +++ b/test/_files/pipeline.mustache @@ -0,0 +1,50 @@ +-- Use | +{{name | upper}} +{{name |upper}} +{{name| upper}} +{{name|upper}} +{{name|underscore}} +{{name|underscore }} +{{name|lower}} +{{name | lower}} +{{name |lower}} +{{name |lower | upper}} +{{name |lower | upper | lower | upper}} +{{name |lower | firstUpper}} +{{name | upper | firstUpper}} +{{job.name | upper}} +{{job.name | lower | firstUpper}} +{{#numbers}} +{{. | sumOne}} +{{/numbers}} +{{#numbers}} +{{. | sumOne | setNameFuncion}} +{{/numbers}} +{{#numbers}} +{{. | sumOne | setNameFuncion | lower}} +{{/numbers}} +-- Use |> +{{name |> upper}} +{{name |>upper}} +{{name|> upper}} +{{name|>upper}} +{{name|>underscore}} +{{name|>underscore }} +{{name|>lower}} +{{name |> lower}} +{{name |>lower}} +{{name |>lower |> upper}} +{{name |>lower |> upper |> lower |> upper}} +{{name |>lower |> firstUpper}} +{{name |> upper |> firstUpper}} +{{job.name |> upper}} +{{job.name |> lower |> firstUpper}} +{{#numbers}} +{{. |> sumOne}} +{{/numbers}} +{{#numbers}} +{{. |> sumOne |> setNameFuncion}} +{{/numbers}} +{{#numbers}} +{{. |> sumOne |> setNameFuncion |> lower}} +{{/numbers}} diff --git a/test/_files/pipeline.txt b/test/_files/pipeline.txt new file mode 100644 index 000000000..1a11b2d78 --- /dev/null +++ b/test/_files/pipeline.txt @@ -0,0 +1,50 @@ +-- Use | +NAME +NAME +NAME +NAME +name +name +name +name +name +NAME +NAME +Name +NAME +DEVELOPER +Developer +2 +3 +4 +2: This is a value +3: This is a value +4: This is a value +2: this is a value +3: this is a value +4: this is a value +-- Use |> +NAME +NAME +NAME +NAME +name +name +name +name +name +NAME +NAME +Name +NAME +DEVELOPER +Developer +2 +3 +4 +2: This is a value +3: This is a value +4: This is a value +2: this is a value +3: this is a value +4: this is a value From 10c33811413bcc2226ca063e6386afcd28303f92 Mon Sep 17 00:00:00 2001 From: Kieling Date: Tue, 5 Feb 2019 20:24:18 -0200 Subject: [PATCH 2/5] Use shift to get name from replacedName --- mustache.js | 4 ++-- mustache.min.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mustache.js b/mustache.js index 944c3f5b6..c3a997759 100644 --- a/mustache.js +++ b/mustache.js @@ -406,8 +406,8 @@ .replace(new RegExp(spaceRe, "g"),'') .split(pipelineRe) - pipelines = replacedName.slice(1); - name = replacedName[0]; + name = replacedName.shift(); + pipelines = replacedName; var cache = this.cache; var value diff --git a/mustache.min.js b/mustache.min.js index 308cada01..fb78ce6ed 100644 --- a/mustache.min.js +++ b/mustache.min.js @@ -1 +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}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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;return pipelines.reduce(function(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return value}},value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);pipelines=replacedName.slice(1);name=replacedName[0];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")value=this.renderPartial(token,context,partials,tags);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":">",'"':""","'":"'","/":"/","`":"`","=":"="};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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;return pipelines.reduce(function(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return value}},value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);name=replacedName.shift();pipelines=replacedName;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")value=this.renderPartial(token,context,partials,tags);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 Date: Tue, 5 Feb 2019 23:24:49 -0200 Subject: [PATCH 3/5] Fixed eslint --- mustache.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mustache.js b/mustache.js index c3a997759..602244623 100644 --- a/mustache.js +++ b/mustache.js @@ -380,19 +380,19 @@ return new Context(view, this); }; - Context.prototype.resolvePipelineOperator = function resolvePipelineOperator(value, pipelines){ + Context.prototype.resolvePipelineOperator = function resolvePipelineOperator (value, pipelines){ var self = this; - return pipelines.reduce(function(val, func){ - if(self.view.hasOwnProperty(func)){ + var pipelineResolver = function pipelineResolver (val, func){ + if (self.view.hasOwnProperty(func)){ return self.view[func](val); - }else if(self.parent && self.parent.view.hasOwnProperty(func)){ + } else if (self.parent && self.parent.view.hasOwnProperty(func)){ return self.parent.view[func](val); - }else{ + } else { return value; } - } - ,value); - } + }; + return pipelines.reduce(pipelineResolver,value); + }; /** * Returns the value of the given name in this context, traversing @@ -403,14 +403,14 @@ // output: [variable,pipelineOne, pipelineTwo ] // Can use | or |>. var replacedName = name - .replace(new RegExp(spaceRe, "g"),'') - .split(pipelineRe) + .replace(new RegExp(spaceRe, 'g'),'') + .split(pipelineRe); name = replacedName.shift(); pipelines = replacedName; var cache = this.cache; - var value + var value; if (cache.hasOwnProperty(name)) { value = cache[name]; } else { @@ -488,7 +488,7 @@ if (isFunction(value)) value = value.call(this.view); - if(pipelines){ + if (pipelines){ value = this.resolvePipelineOperator(value, pipelines); } From 9e0ddbcd3174d476a4e7041a93800fc45ebc2cbf Mon Sep 17 00:00:00 2001 From: Kieling Date: Wed, 6 Feb 2019 11:04:58 -0200 Subject: [PATCH 4/5] Fixed a problem with undefined function. The default value was returned. But i need the value returned from pipelines --- mustache.js | 2 +- mustache.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mustache.js b/mustache.js index 602244623..b33e3dd6c 100644 --- a/mustache.js +++ b/mustache.js @@ -388,7 +388,7 @@ } else if (self.parent && self.parent.view.hasOwnProperty(func)){ return self.parent.view[func](val); } else { - return value; + return val; } }; return pipelines.reduce(pipelineResolver,value); diff --git a/mustache.min.js b/mustache.min.js index fb78ce6ed..882f99554 100644 --- a/mustache.min.js +++ b/mustache.min.js @@ -1 +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}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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;return pipelines.reduce(function(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return value}},value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);name=replacedName.shift();pipelines=replacedName;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")value=this.renderPartial(token,context,partials,tags);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":">",'"':""","'":"'","/":"/","`":"`","=":"="};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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;var pipelineResolver=function pipelineResolver(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return val}};return pipelines.reduce(pipelineResolver,value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);name=replacedName.shift();pipelines=replacedName;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")value=this.renderPartial(token,context,partials,tags);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 Date: Fri, 22 Feb 2019 16:35:25 -0300 Subject: [PATCH 5/5] Pipeline with recursive search. To take a function with parent --- mustache.js | 15 +++++++++------ mustache.min.js | 2 +- package.json | 6 +++--- test/_files/cli_output.txt | 1 + test/_files/pipeline.js | 9 +++++++++ test/_files/pipeline.mustache | 7 +++++++ test/_files/pipeline.txt | 5 +++++ 7 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 test/_files/cli_output.txt diff --git a/mustache.js b/mustache.js index b33e3dd6c..ee14306f2 100644 --- a/mustache.js +++ b/mustache.js @@ -383,13 +383,16 @@ Context.prototype.resolvePipelineOperator = function resolvePipelineOperator (value, pipelines){ var self = this; var pipelineResolver = function pipelineResolver (val, func){ - if (self.view.hasOwnProperty(func)){ - return self.view[func](val); - } else if (self.parent && self.parent.view.hasOwnProperty(func)){ - return self.parent.view[func](val); - } else { - return val; + var findFunction = function(instance, functionToFind, valueToPutInFindedFunction, depth){ + if(depth <= 0 || !instance) return null; + if(instance.view.hasOwnProperty(functionToFind)) return instance.view[func](valueToPutInFindedFunction); + + return findFunction(instance.parent, functionToFind, val, depth) } + + var findedFunction = findFunction(self, func, val, 20) + + return findedFunction ? findedFunction : val }; return pipelines.reduce(pipelineResolver,value); }; diff --git a/mustache.min.js b/mustache.min.js index 882f99554..e60ea823a 100644 --- a/mustache.min.js +++ b/mustache.min.js @@ -1 +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}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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;var pipelineResolver=function pipelineResolver(val,func){if(self.view.hasOwnProperty(func)){return self.view[func](val)}else if(self.parent&&self.parent.view.hasOwnProperty(func)){return self.parent.view[func](val)}else{return val}};return pipelines.reduce(pipelineResolver,value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);name=replacedName.shift();pipelines=replacedName;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")value=this.renderPartial(token,context,partials,tags);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":">",'"':""","'":"'","/":"/","`":"`","=":"="};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=/#|\^|\/|>|\{|&|=|!/;var pipelineRe=/\|\>?/;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;i0?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.resolvePipelineOperator=function resolvePipelineOperator(value,pipelines){var self=this;var pipelineResolver=function pipelineResolver(val,func){var findFunction=function(instance,functionToFind,valueToPutInFindedFunction,depth){if(depth<=0||!instance)return null;if(instance.view.hasOwnProperty(functionToFind))return instance.view[func](valueToPutInFindedFunction);return findFunction(instance.parent,functionToFind,val,depth)};var findedFunction=findFunction(self,func,val,20);return findedFunction?findedFunction:val};return pipelines.reduce(pipelineResolver,value)};Context.prototype.lookup=function lookup(name){var replacedName=name.replace(new RegExp(spaceRe,"g"),"").split(pipelineRe);name=replacedName.shift();pipelines=replacedName;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")value=this.renderPartial(token,context,partials,tags);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", "homepage": "https://github.com/janl/mustache.js", @@ -44,7 +44,7 @@ "eslint": "2.5.1", "jshint": "^2.9.5", "mocha": "^3.0.2", - "uglify-js": "^3.4.6", + "uglify-js": "^3.4.6" "zuul": "^3.11.0", "zuul-ngrok": "nolanlawson/zuul-ngrok#patch-1" }, diff --git a/test/_files/cli_output.txt b/test/_files/cli_output.txt new file mode 100644 index 000000000..66556fe0a --- /dev/null +++ b/test/_files/cli_output.txt @@ -0,0 +1 @@ +Howdy LeBron, CLI rox \ No newline at end of file diff --git a/test/_files/pipeline.js b/test/_files/pipeline.js index 3dc4cca75..543a57abb 100644 --- a/test/_files/pipeline.js +++ b/test/_files/pipeline.js @@ -3,6 +3,15 @@ job: { name: 'Developer' }, + attributes:[ + { + name: 'good', + options: [ + 'outgoing', + 'shy' + ] + } + ], numbers:[1,2,3], sumOne:(value)=>{ return value + 1; diff --git a/test/_files/pipeline.mustache b/test/_files/pipeline.mustache index 7d40575f5..3eba2da07 100644 --- a/test/_files/pipeline.mustache +++ b/test/_files/pipeline.mustache @@ -48,3 +48,10 @@ {{#numbers}} {{. |> sumOne |> setNameFuncion |> lower}} {{/numbers}} +-- Level Array +{{#attributes}} +{{#options}} +{{name |> upper}} +{{. |> upper}} +{{/options}} +{{/attributes}} \ No newline at end of file diff --git a/test/_files/pipeline.txt b/test/_files/pipeline.txt index 1a11b2d78..492c4f6b8 100644 --- a/test/_files/pipeline.txt +++ b/test/_files/pipeline.txt @@ -48,3 +48,8 @@ Developer 2: this is a value 3: this is a value 4: this is a value +-- Level Array +GOOD +OUTGOING +GOOD +SHY