From aee4f6ee3c375921c62bb9fc444f5408527e40d7 Mon Sep 17 00:00:00 2001 From: Jairo de Morais Date: Mon, 23 Jul 2012 12:05:16 -0300 Subject: [PATCH] helpers included in dust core --- Makefile | 6 +- dist/dust-core-1.0.0.js | 171 ++++++++++++++++++++++++++++++++++++++++ dist/dust-full-1.0.0.js | 171 ++++++++++++++++++++++++++++++++++++++++ lib/dust.js | 2 + 4 files changed, 349 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bcb60d5..b8a1013 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ CORE = dist/dust-core-${VERSION}.js CORE_MIN = dist/dust-core-${VERSION}.min.js FULL = dist/dust-full-${VERSION}.js FULL_MIN = dist/dust-full-${VERSION}.min.js +HELPERS = dustjs-helpers/lib define HEADER // @@ -57,16 +58,19 @@ endef export HEADER +#TODO: REMOVE THE HELPERS IN THE NEXT RELEASE dust: @@mkdir -p dist @@touch ${CORE} @@echo "$$HEADER" > ${CORE} - @@cat ${SRC}/dust.js >> ${CORE} + @@cat ${SRC}/dust.js\ + ${HELPERS}/dust-helpers.js >> ${CORE} @@echo ${CORE} built @@touch ${FULL} @@echo "$$HEADER" > ${FULL} @@cat ${SRC}/dust.js\ + ${HELPERS}/dust-helpers.js\ ${SRC}/compiler.js\ ${SRC}/parser.js >> ${FULL} @@echo ${FULL} built diff --git a/dist/dust-core-1.0.0.js b/dist/dust-core-1.0.0.js index 828abf9..c4d5cd0 100644 --- a/dist/dust-core-1.0.0.js +++ b/dist/dust-core-1.0.0.js @@ -549,8 +549,179 @@ dust.escapeJs = function(s) { })(dust); if (typeof exports !== "undefined") { + //TODO: Remove the helpers from dust core in the next release. + dust.helpers = require("../dust-helpers/lib/dust-helpers").helpers; if (typeof process !== "undefined") { require('./server')(dust); } module.exports = dust; } +(function(dust){ + +/* make a safe version of console if it is not available + * currently supporting: + * _console.log + * */ +var _console = (typeof console !== 'undefined')? console: { + log: function(){ + /* a noop*/ + } +}; + +function isSelect(context) { + var value = context.current(); + return typeof value === "object" && value.isSelect === true; +} + +function filter(chunk, context, bodies, params, filter) { + var params = params || {}, + actual, + expected; + if (params.key) { + actual = helpers.tap(params.key, chunk, context); + } else if (isSelect(context)) { + actual = context.current().selectKey; + if (context.current().isResolved) { + filter = function() { return false; }; + } + } else { + throw "No key specified for filter and no key found in context from select statement"; + } + expected = helpers.tap(params.value, chunk, context); + if (filter(expected, coerce(actual, params.type, context))) { + if (isSelect(context)) { + context.current().isResolved = true; + } + return chunk.render(bodies.block, context); + } else if (bodies['else']) { + return chunk.render(bodies['else'], context); + } + + return chunk.write(''); +} + +function coerce (value, type, context) { + if (value) { + switch (type || typeof(value)) { + case 'number': return +value; + case 'string': return String(value); + case 'boolean': return Boolean(value); + case 'date': return new Date(value); + case 'context': return context.get(value); + } + } + + return value; +} + +var helpers = { + + sep: function(chunk, context, bodies) { + if (context.stack.index === context.stack.of - 1) { + return chunk; + } + return bodies.block(chunk, context); + }, + + idx: function(chunk, context, bodies) { + return bodies.block(chunk, context.push(context.stack.index)); + }, + + contextDump: function(chunk, context, bodies) { + _console.log(JSON.stringify(context.stack)); + return chunk; + }, + + // Utility helping to resolve dust references in the given chunk + tap: function( input, chunk, context ){ + // return given input if there is no dust reference to resolve + var output = input; + // dust compiles a string to function, if there are references + if( typeof input === "function"){ + output = ''; + chunk.tap(function(data){ + output += data; + return ''; + }).render(input, context).untap(); + if( output === '' ){ + output = false; + } + } + return output; + }, + + /** + if helper + @param cond, either a string literal value or a dust reference + a string literal value, is enclosed in double quotes, e.g. cond="2>3" + a dust reference is also enclosed in double quotes, e.g. cond="'{val}'' > 3" + cond argument should evaluate to a valid javascript expression + **/ + + "if": function( chunk, context, bodies, params ){ + if( params && params.cond ){ + var cond = params.cond; + cond = this.tap(cond, chunk, context); + // eval expressions with given dust references + if( eval( cond ) ){ + return chunk.render( bodies.block, context ); + } + if( bodies['else'] ){ + return chunk.render( bodies['else'], context ); + } + } + // no condition + else { + _console.log( "No condition given in the if helper!" ); + } + return chunk; + }, + + /** + select/eq/lt/lte/gt/gte/default helper + @param key, either a string literal value or a dust reference + a string literal value, is enclosed in double quotes, e.g. key="foo" + a dust reference may or may not be enclosed in double quotes, e.g. key="{val}" and key=val are both valid + @param type (optiona), supported types are number, boolean, string, date, context, defaults to string + **/ + select: function(chunk, context, bodies, params) { + if( params && params.key){ + // returns given input as output, if the input is not a dust reference, else does a context lookup + var key = this.tap(params.key, chunk, context); + return chunk.render(bodies.block, context.push({ isSelect: true, isResolved: false, selectKey: key })); + } + // no key + else { + _console.log( "No key given in the select helper!" ); + } + return chunk; + }, + + eq: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual === expected; }); + }, + + lt: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; }); + }, + + lte: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; }); + }, + + gt: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; }); + }, + + gte: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; }); + }, + + "default": function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return true; }); + } +}; + +dust.helpers = helpers; + +})(typeof exports !== 'undefined' ? exports : getGlobal()); diff --git a/dist/dust-full-1.0.0.js b/dist/dust-full-1.0.0.js index 83ef99f..a4e3160 100644 --- a/dist/dust-full-1.0.0.js +++ b/dist/dust-full-1.0.0.js @@ -549,11 +549,182 @@ dust.escapeJs = function(s) { })(dust); if (typeof exports !== "undefined") { + //TODO: Remove the helpers from dust core in the next release. + dust.helpers = require("../dust-helpers/lib/dust-helpers").helpers; if (typeof process !== "undefined") { require('./server')(dust); } module.exports = dust; } +(function(dust){ + +/* make a safe version of console if it is not available + * currently supporting: + * _console.log + * */ +var _console = (typeof console !== 'undefined')? console: { + log: function(){ + /* a noop*/ + } +}; + +function isSelect(context) { + var value = context.current(); + return typeof value === "object" && value.isSelect === true; +} + +function filter(chunk, context, bodies, params, filter) { + var params = params || {}, + actual, + expected; + if (params.key) { + actual = helpers.tap(params.key, chunk, context); + } else if (isSelect(context)) { + actual = context.current().selectKey; + if (context.current().isResolved) { + filter = function() { return false; }; + } + } else { + throw "No key specified for filter and no key found in context from select statement"; + } + expected = helpers.tap(params.value, chunk, context); + if (filter(expected, coerce(actual, params.type, context))) { + if (isSelect(context)) { + context.current().isResolved = true; + } + return chunk.render(bodies.block, context); + } else if (bodies['else']) { + return chunk.render(bodies['else'], context); + } + + return chunk.write(''); +} + +function coerce (value, type, context) { + if (value) { + switch (type || typeof(value)) { + case 'number': return +value; + case 'string': return String(value); + case 'boolean': return Boolean(value); + case 'date': return new Date(value); + case 'context': return context.get(value); + } + } + + return value; +} + +var helpers = { + + sep: function(chunk, context, bodies) { + if (context.stack.index === context.stack.of - 1) { + return chunk; + } + return bodies.block(chunk, context); + }, + + idx: function(chunk, context, bodies) { + return bodies.block(chunk, context.push(context.stack.index)); + }, + + contextDump: function(chunk, context, bodies) { + _console.log(JSON.stringify(context.stack)); + return chunk; + }, + + // Utility helping to resolve dust references in the given chunk + tap: function( input, chunk, context ){ + // return given input if there is no dust reference to resolve + var output = input; + // dust compiles a string to function, if there are references + if( typeof input === "function"){ + output = ''; + chunk.tap(function(data){ + output += data; + return ''; + }).render(input, context).untap(); + if( output === '' ){ + output = false; + } + } + return output; + }, + + /** + if helper + @param cond, either a string literal value or a dust reference + a string literal value, is enclosed in double quotes, e.g. cond="2>3" + a dust reference is also enclosed in double quotes, e.g. cond="'{val}'' > 3" + cond argument should evaluate to a valid javascript expression + **/ + + "if": function( chunk, context, bodies, params ){ + if( params && params.cond ){ + var cond = params.cond; + cond = this.tap(cond, chunk, context); + // eval expressions with given dust references + if( eval( cond ) ){ + return chunk.render( bodies.block, context ); + } + if( bodies['else'] ){ + return chunk.render( bodies['else'], context ); + } + } + // no condition + else { + _console.log( "No condition given in the if helper!" ); + } + return chunk; + }, + + /** + select/eq/lt/lte/gt/gte/default helper + @param key, either a string literal value or a dust reference + a string literal value, is enclosed in double quotes, e.g. key="foo" + a dust reference may or may not be enclosed in double quotes, e.g. key="{val}" and key=val are both valid + @param type (optiona), supported types are number, boolean, string, date, context, defaults to string + **/ + select: function(chunk, context, bodies, params) { + if( params && params.key){ + // returns given input as output, if the input is not a dust reference, else does a context lookup + var key = this.tap(params.key, chunk, context); + return chunk.render(bodies.block, context.push({ isSelect: true, isResolved: false, selectKey: key })); + } + // no key + else { + _console.log( "No key given in the select helper!" ); + } + return chunk; + }, + + eq: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual === expected; }); + }, + + lt: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; }); + }, + + lte: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; }); + }, + + gt: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; }); + }, + + gte: function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; }); + }, + + "default": function(chunk, context, bodies, params) { + return filter(chunk, context, bodies, params, function(expected, actual) { return true; }); + } +}; + +dust.helpers = helpers; + +})(typeof exports !== 'undefined' ? exports : getGlobal()); (function(dust) { dust.compile = function(source, name) { diff --git a/lib/dust.js b/lib/dust.js index 119844b..7565c0f 100644 --- a/lib/dust.js +++ b/lib/dust.js @@ -541,6 +541,8 @@ dust.escapeJs = function(s) { })(dust); if (typeof exports !== "undefined") { + //TODO: Remove the helpers from dust core in the next release. + dust.helpers = require("../dustjs-helpers/lib/dust-helpers").helpers; if (typeof process !== "undefined") { require('./server')(dust); }