From 0013abc51c3aac4ebfb97b4522eccd452f1d77d6 Mon Sep 17 00:00:00 2001 From: Nelson Pecora Date: Mon, 30 Mar 2015 16:58:12 -0400 Subject: [PATCH 01/13] docs update for requires The current example should show `nunjucks.configure()`, since that's how to create a new nunjucks env. --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 0917594..98ec8b4 100644 --- a/Readme.md +++ b/Readme.md @@ -137,7 +137,7 @@ var cons = require('consolidate'), // add nunjucks to requires so filters can be // added and the same instance will be used inside the render method -cons.requires.nunjucks = nunjucks; +cons.requires.nunjucks = nunjucks.configure(); cons.requires.nunjucks.addFilter('foo', function () { return 'bar'; From 4a5a329bb40702062e327fd7a99170628b0f1961 Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Thu, 21 May 2015 09:59:04 -0500 Subject: [PATCH 02/13] Removing unnecessary whitespace --- lib/consolidate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 590e1d5..827381a 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -964,7 +964,7 @@ exports.htmling.render = function(str, options, fn) { */ function requireReact(module, filename) { var tools = requires.reactTools || (requires.reactTools = require('react-tools')); - + var content = fs.readFileSync(filename, 'utf8'); var compiled = tools.transform(content, {harmony: true}); @@ -1060,7 +1060,7 @@ function reactRenderer(type){ // Parsing Code = (type === 'path') ? require(resolve(str)) : requireReactString(str); Factory = cache(options, engine.createFactory(Code)); - + } else { Factory = cache(options); } From 3958c136c38a3a79fe93aea2cf5a2b1e4c10980a Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Thu, 21 May 2015 10:44:06 -0500 Subject: [PATCH 03/13] Adding support for Promises when no callback is provided Allows better integration to Promised based environments --- lib/consolidate.js | 770 ++++++++++++++++++++++++------------------- package.json | 3 + test/shared/index.js | 14 + 3 files changed, 448 insertions(+), 339 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 827381a..2732c30 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -22,6 +22,7 @@ var fs = require('fs') , join = path.join , resolve = path.resolve , extname = path.extname + , q = require('q') , dirname = path.dirname; var readCache = {}; @@ -130,6 +131,23 @@ function readPartials(path, options, fn) { next(0); } + +/** + * promisify + */ +function promisify(fn, exec) { + return q.Promise(function (res, rej) { + fn = fn || function (err, html) { + if (err) { + return rej(err); + } + res(html); + }; + exec(fn); + }); +} + + /** * fromStringRenderer */ @@ -137,16 +155,26 @@ function readPartials(path, options, fn) { function fromStringRenderer(name) { return function(path, options, fn){ options.filename = path; - readPartials(path, options, function (err) { - if (err) return fn(err); - if (cache(options)) { - exports[name].render('', options, fn); - } else { - read(path, options, function(err, str){ - if (err) return fn(err); - exports[name].render(str, options, fn); - }); - } + + return q.Promise(function (res, rej) { + fn = fn || function completePromise(err, html) { + if (err) { + return rej(err); + } + res(html); + }; + + readPartials(path, options, function (err) { + if (err) return fn(err); + if (cache(options)) { + exports[name].render('', options, fn); + } else { + read(path, options, function(err, str){ + if (err) return fn(err); + exports[name].render(str, options, fn); + }); + } + }); }); }; } @@ -170,99 +198,101 @@ exports.liquid = fromStringRenderer('liquid'); */ exports.liquid.render = function(str, options, fn){ - var engine = requires.liquid || (requires.liquid = require('tinyliquid')); - try { - var context = engine.newContext(); - var k; + return promisify(fn, function (fn) { + var engine = requires.liquid || (requires.liquid = require('tinyliquid')); + try { + var context = engine.newContext(); + var k; - /** - * Note that there's a bug in the library that doesn't allow us to pass - * the locals to newContext(), hence looping through the keys: - */ + /** + * Note that there's a bug in the library that doesn't allow us to pass + * the locals to newContext(), hence looping through the keys: + */ - if (options.locals){ - for (k in options.locals){ - context.setLocals(k, options.locals[k]); + if (options.locals){ + for (k in options.locals){ + context.setLocals(k, options.locals[k]); + } + delete options.locals; } - delete options.locals; - } - if (options.meta){ - context.setLocals('page', options.meta); - delete options.meta; - } + if (options.meta){ + context.setLocals('page', options.meta); + delete options.meta; + } - /** - * Add any defined filters: - */ + /** + * Add any defined filters: + */ - if (options.filters){ - for (k in options.filters){ - context.setFilter(k, options.filters[k]); + if (options.filters){ + for (k in options.filters){ + context.setFilter(k, options.filters[k]); + } + delete options.filters; } - delete options.filters; - } - /** - * Set up a callback for the include directory: - */ + /** + * Set up a callback for the include directory: + */ - var includeDir = options.includeDir || process.cwd(); + var includeDir = options.includeDir || process.cwd(); - context.onInclude(function (name, callback) { - var basename = path.basename(name); - var extname = path.extname(name) || '.liquid'; - var filename = path.join(includeDir, basename + extname); + context.onInclude(function (name, callback) { + var basename = path.basename(name); + var extname = path.extname(name) || '.liquid'; + var filename = path.join(includeDir, basename + extname); - fs.readFile(filename, {encoding: 'utf8'}, function (err, data){ - if (err) return callback(err); - callback(null, engine.parse(data)); + fs.readFile(filename, {encoding: 'utf8'}, function (err, data){ + if (err) return callback(err); + callback(null, engine.parse(data)); + }); }); - }); - delete options.includeDir; + delete options.includeDir; + + /** + * The custom tag functions need to have their results pushed back + * through the parser, so set up a shim before calling the provided + * callback: + */ + + var compileOptions = { + customTags: {} + }; + + if (options.customTags){ + var tagFunctions = options.customTags; + + for (k in options.customTags){ + /*Tell jshint there's no problem with having this function in the loop */ + /*jshint -W083 */ + compileOptions.customTags[k] = function (context, name, body){ + var tpl = tagFunctions[name](body.trim()); + context.astStack.push(engine.parse(tpl)); + }; + /*jshint +W083 */ + } + delete options.customTags; + } - /** - * The custom tag functions need to have their results pushed back - * through the parser, so set up a shim before calling the provided - * callback: - */ + /** + * Now anything left in `options` becomes a local: + */ - var compileOptions = { - customTags: {} - }; - - if (options.customTags){ - var tagFunctions = options.customTags; - - for (k in options.customTags){ - /*Tell jshint there's no problem with having this function in the loop */ - /*jshint -W083 */ - compileOptions.customTags[k] = function (context, name, body){ - var tpl = tagFunctions[name](body.trim()); - context.astStack.push(engine.parse(tpl)); - }; - /*jshint +W083 */ + for (k in options){ + context.setLocals(k, options[k]); } - delete options.customTags; - } - /** - * Now anything left in `options` becomes a local: - */ + /** + * Finally, execute the template: + */ - for (k in options){ - context.setLocals(k, options[k]); + var tmpl = cache(context) || cache(context, engine.compile(str, compileOptions)); + tmpl(context, fn); + } catch (err) { + fn(err); } - - /** - * Finally, execute the template: - */ - - var tmpl = cache(context) || cache(context, engine.compile(str, compileOptions)); - tmpl(context, fn); - } catch (err) { - fn(err); - } + }); }; /** @@ -296,25 +326,27 @@ exports.jade = function(path, options, fn){ */ exports.jade.render = function(str, options, fn){ - var engine = requires.jade; - if (!engine) { - try { - engine = requires.jade = require('jade'); - } catch (err) { + return promisify(fn, function (fn) { + var engine = requires.jade; + if (!engine) { try { - engine = requires.jade = require('then-jade'); - } catch (otherError) { - throw err; + engine = requires.jade = require('jade'); + } catch (err) { + try { + engine = requires.jade = require('then-jade'); + } catch (otherError) { + throw err; + } } } - } - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -328,41 +360,43 @@ exports.dust = fromStringRenderer('dust'); */ exports.dust.render = function(str, options, fn){ - var engine = requires.dust; - if (!engine) { - try { - engine = requires.dust = require('dust'); - } catch (err) { + return promisify(fn, function(fn) { + var engine = requires.dust; + if (!engine) { try { - engine = requires.dust = require('dustjs-helpers'); + engine = requires.dust = require('dust'); } catch (err) { - engine = requires.dust = require('dustjs-linkedin'); + try { + engine = requires.dust = require('dustjs-helpers'); + } catch (err) { + engine = requires.dust = require('dustjs-linkedin'); + } } } - } - var ext = 'dust' - , views = '.'; + var ext = 'dust' + , views = '.'; - if (options) { - if (options.ext) ext = options.ext; - if (options.views) views = options.views; - if (options.settings && options.settings.views) views = options.settings.views; - } - if (!options || (options && !options.cache)) engine.cache = {}; + if (options) { + if (options.ext) ext = options.ext; + if (options.views) views = options.views; + if (options.settings && options.settings.views) views = options.settings.views; + } + if (!options || (options && !options.cache)) engine.cache = {}; - engine.onLoad = function(path, callback){ - if ('' == extname(path)) path += '.' + ext; - if ('/' !== path[0]) path = views + '/' + path; - read(path, options, callback); - }; + engine.onLoad = function(path, callback){ + if ('' == extname(path)) path += '.' + ext; + if ('/' !== path[0]) path = views + '/' + path; + read(path, options, callback); + }; - try { - var tmpl = cache(options) || cache(options, engine.compileFn(str)); - tmpl(options, fn); - } catch (err) { - fn(err); - } + try { + var tmpl = cache(options) || cache(options, engine.compileFn(str)); + tmpl(options, fn); + } catch (err) { + fn(err); + } + }); }; /** @@ -376,16 +410,18 @@ exports.swig = fromStringRenderer('swig'); */ exports.swig.render = function(str, options, fn){ - var engine = requires.swig || (requires.swig = require('swig')); + return promisify(fn, function(fn) { + var engine = requires.swig || (requires.swig = require('swig')); - try { - if(options.cache === true) options.cache = 'memory'; - engine.setDefaults({ cache: options.cache }); - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + try { + if(options.cache === true) options.cache = 'memory'; + engine.setDefaults({ cache: options.cache }); + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -399,13 +435,15 @@ exports.atpl = fromStringRenderer('atpl'); */ exports.atpl.render = function(str, options, fn){ - var engine = requires.atpl || (requires.atpl = require('atpl')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.atpl || (requires.atpl = require('atpl')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -419,13 +457,15 @@ exports.liquor = fromStringRenderer('liquor'); */ exports.liquor.render = function(str, options, fn){ - var engine = requires.liquor || (requires.liquor = require('liquor')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.liquor || (requires.liquor = require('liquor')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -439,13 +479,15 @@ exports.ejs = fromStringRenderer('ejs'); */ exports.ejs.render = function(str, options, fn){ - var engine = requires.ejs || (requires.ejs = require('ejs')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.ejs || (requires.ejs = require('ejs')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; @@ -460,12 +502,14 @@ exports.eco = fromStringRenderer('eco'); */ exports.eco.render = function(str, options, fn){ - var engine = requires.eco || (requires.eco = require('eco')); - try { - fn(null, engine.render(str, options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.eco || (requires.eco = require('eco')); + try { + fn(null, engine.render(str, options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -479,15 +523,17 @@ exports.jazz = fromStringRenderer('jazz'); */ exports.jazz.render = function(str, options, fn){ - var engine = requires.jazz || (requires.jazz = require('jazz')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - tmpl.eval(options, function(str){ - fn(null, str); - }); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.jazz || (requires.jazz = require('jazz')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + tmpl.eval(options, function(str){ + fn(null, str); + }); + } catch (err) { + fn(err); + } + }); }; /** @@ -501,13 +547,15 @@ exports.jqtpl = fromStringRenderer('jqtpl'); */ exports.jqtpl.render = function(str, options, fn){ - var engine = requires.jqtpl || (requires.jqtpl = require('jqtpl')); - try { - engine.template(str, str); - fn(null, engine.tmpl(str, options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.jqtpl || (requires.jqtpl = require('jqtpl')); + try { + engine.template(str, str); + fn(null, engine.tmpl(str, options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -521,13 +569,15 @@ exports.haml = fromStringRenderer('haml'); */ exports.haml.render = function(str, options, fn){ - var engine = requires.hamljs || (requires.hamljs = require('hamljs')); - try { - options.locals = options; - fn(null, engine.render(str, options).trimLeft()); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.hamljs || (requires.hamljs = require('hamljs')); + try { + options.locals = options; + fn(null, engine.render(str, options).trimLeft()); + } catch (err) { + fn(err); + } + }); }; /** @@ -541,13 +591,15 @@ exports.hamlet = fromStringRenderer('hamlet'); */ exports.hamlet.render = function(str, options, fn){ - var engine = requires.hamlet || (requires.hamlet = require('hamlet')); - try { - options.locals = options; - fn(null, engine.render(str, options).trimLeft()); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.hamlet || (requires.hamlet = require('hamlet')); + try { + options.locals = options; + fn(null, engine.render(str, options).trimLeft()); + } catch (err) { + fn(err); + } + }); }; /** @@ -564,12 +616,14 @@ exports.whiskers = function(path, options, fn){ */ exports.whiskers.render = function(str, options, fn){ - var engine = requires.whiskers || (requires.whiskers = require('whiskers')); - try { - fn(null, engine.render(str, options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.whiskers || (requires.whiskers = require('whiskers')); + try { + fn(null, engine.render(str, options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -583,13 +637,15 @@ exports['haml-coffee'] = fromStringRenderer('haml-coffee'); */ exports['haml-coffee'].render = function(str, options, fn){ - var engine = requires.HAMLCoffee || (requires.HAMLCoffee = require('haml-coffee')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.HAMLCoffee || (requires.HAMLCoffee = require('haml-coffee')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -603,13 +659,15 @@ exports.hogan = fromStringRenderer('hogan'); */ exports.hogan.render = function(str, options, fn){ - var engine = requires.hogan || (requires.hogan = require('hogan.js')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl.render(options, options.partials)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.hogan || (requires.hogan = require('hogan.js')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl.render(options, options.partials)); + } catch (err) { + fn(err); + } + }); }; /** @@ -623,13 +681,15 @@ exports.templayed = fromStringRenderer('templayed'); */ exports.templayed.render = function(str, options, fn){ - var engine = requires.templayed || (requires.templayed = require('templayed')); - try { - var tmpl = cache(options) || cache(options, engine(str)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.templayed || (requires.templayed = require('templayed')); + try { + var tmpl = cache(options) || cache(options, engine(str)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -643,19 +703,21 @@ exports.handlebars = fromStringRenderer('handlebars'); */ exports.handlebars.render = function(str, options, fn) { - var engine = requires.handlebars || (requires.handlebars = require('handlebars')); - try { - for (var partial in options.partials) { - engine.registerPartial(partial, options.partials[partial]); - } - for (var helper in options.helpers) { - engine.registerHelper(helper, options.helpers[helper]); + return promisify(fn, function(fn) { + var engine = requires.handlebars || (requires.handlebars = require('handlebars')); + try { + for (var partial in options.partials) { + engine.registerPartial(partial, options.partials[partial]); + } + for (var helper in options.helpers) { + engine.registerHelper(helper, options.helpers[helper]); + } + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); } - var tmpl = cache(options) || cache(options, engine.compile(str, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + }); } /** @@ -669,13 +731,15 @@ exports.underscore = fromStringRenderer('underscore'); */ exports.underscore.render = function(str, options, fn) { - var engine = requires.underscore || (requires.underscore = require('underscore')); - try { - var tmpl = cache(options) || cache(options, engine.template(str, null, options)); - fn(null, tmpl(options).replace(/\n$/, '')); - } catch (err) { - fn(err); - } + return promisify(fn, function(fn) { + var engine = requires.underscore || (requires.underscore = require('underscore')); + try { + var tmpl = cache(options) || cache(options, engine.template(str, null, options)); + fn(null, tmpl(options).replace(/\n$/, '')); + } catch (err) { + fn(err); + } + }); }; @@ -690,13 +754,15 @@ exports.lodash = fromStringRenderer('lodash'); */ exports.lodash.render = function(str, options, fn) { - var engine = requires.lodash || (requires.lodash = require('lodash')); - try { - var tmpl = cache(options) || cache(options, engine.template(str, null, options)); - fn(null, tmpl(options).replace(/\n$/, '')); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.lodash || (requires.lodash = require('lodash')); + try { + var tmpl = cache(options) || cache(options, engine.template(str, null, options)); + fn(null, tmpl(options).replace(/\n$/, '')); + } catch (err) { + fn(err); + } + }); }; @@ -711,16 +777,18 @@ exports.qejs = fromStringRenderer('qejs'); */ exports.qejs.render = function (str, options, fn) { - try { - var engine = requires.qejs || (requires.qejs = require('qejs')); - engine.render(str, options).then(function (result) { - fn(null, result); - }, function (err) { - fn(err); - }).done(); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + try { + var engine = requires.qejs || (requires.qejs = require('qejs')); + engine.render(str, options).then(function (result) { + fn(null, result); + }, function (err) { + fn(err); + }).done(); + } catch (err) { + fn(err); + } + }); }; @@ -735,13 +803,15 @@ exports.walrus = fromStringRenderer('walrus'); */ exports.walrus.render = function (str, options, fn) { - var engine = requires.walrus || (requires.walrus = require('walrus')); - try { - var tmpl = cache(options) || cache(options, engine.parse(str)); - fn(null, tmpl.compile(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.walrus || (requires.walrus = require('walrus')); + try { + var tmpl = cache(options) || cache(options, engine.parse(str)); + fn(null, tmpl.compile(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -755,12 +825,14 @@ exports.mustache = fromStringRenderer('mustache'); */ exports.mustache.render = function(str, options, fn) { - var engine = requires.mustache || (requires.mustache = require('mustache')); - try { - fn(null, engine.to_html(str, options, options.partials)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.mustache || (requires.mustache = require('mustache')); + try { + fn(null, engine.to_html(str, options, options.partials)); + } catch (err) { + fn(err); + } + }); }; /** @@ -768,13 +840,15 @@ exports.mustache.render = function(str, options, fn) { */ exports.just = function(path, options, fn){ - var engine = requires.just; - if (!engine) { - var JUST = require('just'); - engine = requires.just = new JUST(); - } - engine.configure({ useCache: options.cache }); - engine.render(path, options, fn); + return promisify(fn, function(fn) { + var engine = requires.just; + if (!engine) { + var JUST = require('just'); + engine = requires.just = new JUST(); + } + engine.configure({ useCache: options.cache }); + engine.render(path, options, fn); + }); }; /** @@ -782,9 +856,11 @@ exports.just = function(path, options, fn){ */ exports.just.render = function(str, options, fn){ - var JUST = require('just'); - var engine = new JUST({ root: { page: str }}); - engine.render('page', options, fn); + return promisify(fn, function (fn) { + var JUST = require('just'); + var engine = new JUST({ root: { page: str }}); + engine.render('page', options, fn); + }); }; /** @@ -806,9 +882,11 @@ exports.ect = function(path, options, fn){ */ exports.ect.render = function(str, options, fn){ - var ECT = require('ect'); - var engine = new ECT({ root: { page: str }}); - engine.render('page', options, fn); + return promisify(fn, function (fn) { + var ECT = require('ect'); + var engine = new ECT({ root: { page: str }}); + engine.render('page', options, fn); + }); }; /** @@ -822,13 +900,15 @@ exports.mote = fromStringRenderer('mote'); */ exports.mote.render = function(str, options, fn){ - var engine = requires.mote || (requires.mote = require('mote')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.mote || (requires.mote = require('mote')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -836,8 +916,10 @@ exports.mote.render = function(str, options, fn){ */ exports.toffee = function(path, options, fn){ - var toffee = requires.toffee || (requires.toffee = require('toffee')); - toffee.__consolidate_engine_render(path, options, fn); + return promisify(fn, function (fn) { + var toffee = requires.toffee || (requires.toffee = require('toffee')); + toffee.__consolidate_engine_render(path, options, fn); + }); }; /** @@ -845,12 +927,14 @@ exports.toffee = function(path, options, fn){ */ exports.toffee.render = function(str, options, fn) { - var engine = requires.toffee || (requires.toffee = require('toffee')); - try { - engine.str_render(str, options,fn); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.toffee || (requires.toffee = require('toffee')); + try { + engine.str_render(str, options,fn); + } catch (err) { + fn(err); + } + }); }; /** @@ -864,13 +948,15 @@ exports.dot = fromStringRenderer('dot'); */ exports.dot.render = function (str, options, fn) { - var engine = requires.dot || (requires.dot = require('dot')); - try { - var tmpl = cache(options) || cache(options, engine.compile(str, options && options._def)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.dot || (requires.dot = require('dot')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options && options._def)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -884,32 +970,34 @@ exports.ractive = fromStringRenderer('ractive'); */ exports.ractive.render = function(str, options, fn){ - var engine = requires.ractive || (requires.ractive = require('ractive')); + return promisify(fn, function (fn) { + var engine = requires.ractive || (requires.ractive = require('ractive')); - var template = cache(options) || cache(options, engine.parse(str)); - options.template = template; + var template = cache(options) || cache(options, engine.parse(str)); + options.template = template; - if (options.data === null || options.data === undefined) - { - var extend = (requires.extend || (requires.extend = require('util')._extend)); + if (options.data === null || options.data === undefined) + { + var extend = (requires.extend || (requires.extend = require('util')._extend)); - // Shallow clone the options object - options.data = extend({}, options); + // Shallow clone the options object + options.data = extend({}, options); - // Remove consolidate-specific properties from the clone - var i, length; - var properties = ["template", "filename", "cache", "partials"]; - for (i = 0, length = properties.length; i < length; i++) { - var property = properties[i]; - delete options.data[property]; + // Remove consolidate-specific properties from the clone + var i, length; + var properties = ["template", "filename", "cache", "partials"]; + for (i = 0, length = properties.length; i < length; i++) { + var property = properties[i]; + delete options.data[property]; + } } - } - try { - fn(null, new engine(options).toHTML()); - } catch (err) { - fn(err); - } + try { + fn(null, new engine(options).toHTML()); + } catch (err) { + fn(err); + } + }); }; /** @@ -923,18 +1011,20 @@ exports.nunjucks = fromStringRenderer('nunjucks'); */ exports.nunjucks.render = function(str, options, fn) { - try { - var engine = requires.nunjucks || (requires.nunjucks = require('nunjucks')); - var loader = options.loader; - if (loader) { + return promisify(fn, function (fn) { + try { + var engine = requires.nunjucks || (requires.nunjucks = require('nunjucks')); + var loader = options.loader; + if (loader) { var env = new engine.Environment(new loader(options)); env.renderString(str, options, fn); - } else { + } else { engine.renderString(str, options, fn); - } - } catch (err) { + } + } catch (err) { throw fn(err); - } + } + }); }; @@ -949,13 +1039,15 @@ exports.htmling = fromStringRenderer('htmling'); */ exports.htmling.render = function(str, options, fn) { - var engine = requires.htmling || (requires.htmling = require('htmling')); - try { - var tmpl = cache(options) || cache(options, engine.string(str)); - fn(null, tmpl.render(options)); - } catch (err) { - fn(err); - } + return promisify(fn, function (fn) { + var engine = requires.htmling || (requires.htmling = require('htmling')); + try { + var tmpl = cache(options) || cache(options, engine.string(str)); + fn(null, tmpl.render(options)); + } catch (err) { + fn(err); + } + }); }; diff --git a/package.json b/package.json index 1ae62db..8c6e603 100644 --- a/package.json +++ b/package.json @@ -53,5 +53,8 @@ }, "scripts": { "test": "mocha" + }, + "dependencies": { + "q": "^1.4.1" } } diff --git a/test/shared/index.js b/test/shared/index.js index 6d30fb5..e88d6c7 100644 --- a/test/shared/index.js +++ b/test/shared/index.js @@ -80,6 +80,20 @@ exports.test = function(name) { }); }); + it('should return a promise', function(done){ + var str = fs.readFileSync('test/fixtures/' + name + '/user.' + name).toString(); + var locals = { user: user }; + var result = cons[name].render(str, locals); + + result.then(function (html) { + html.should.equal('

Tobi

'); + done(); + }) + .catch(function (err) { + done(err); + }); + }); + it('should be exposed in the requires object', function(){ var should = require('should'), requiredName; From 8a2d912c017f4e81122c57999ce7bebcfbc7e993 Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Thu, 21 May 2015 10:51:31 -0500 Subject: [PATCH 04/13] Adding more promise support to non-string based rendering --- lib/consolidate.js | 54 ++++++++++++++++++++++++-------------------- test/shared/index.js | 16 ++++++++++++- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 2732c30..b4fa068 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -300,25 +300,27 @@ exports.liquid.render = function(str, options, fn){ */ exports.jade = function(path, options, fn){ - var engine = requires.jade; - if (!engine) { - try { - engine = requires.jade = require('jade'); - } catch (err) { + return promisify(fn, function (fn) { + var engine = requires.jade; + if (!engine) { try { - engine = requires.jade = require('then-jade'); - } catch (otherError) { - throw err; + engine = requires.jade = require('jade'); + } catch (err) { + try { + engine = requires.jade = require('then-jade'); + } catch (otherError) { + throw err; + } } } - } - try { - var tmpl = cache(options) || cache(options, engine.compileFile(path, options)); - fn(null, tmpl(options)); - } catch (err) { - fn(err); - } + try { + var tmpl = cache(options) || cache(options, engine.compileFile(path, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } + }); }; /** @@ -607,8 +609,10 @@ exports.hamlet.render = function(str, options, fn){ */ exports.whiskers = function(path, options, fn){ - var engine = requires.whiskers || (requires.whiskers = require('whiskers')); - engine.__express(path, options, fn); + return promisify(fn, function (fn) { + var engine = requires.whiskers || (requires.whiskers = require('whiskers')); + engine.__express(path, options, fn); + }); }; /** @@ -868,13 +872,15 @@ exports.just.render = function(str, options, fn){ */ exports.ect = function(path, options, fn){ - var engine = requires.ect; - if (!engine) { - var ECT = require('ect'); - engine = requires.ect = new ECT(options); - } - engine.configure({ cache: options.cache }); - engine.render(path, options, fn); + return promisify(fn, function (fn) { + var engine = requires.ect; + if (!engine) { + var ECT = require('ect'); + engine = requires.ect = new ECT(options); + } + engine.configure({ cache: options.cache }); + engine.render(path, options, fn); + }); }; /** diff --git a/test/shared/index.js b/test/shared/index.js index e88d6c7..acd74b7 100644 --- a/test/shared/index.js +++ b/test/shared/index.js @@ -80,7 +80,21 @@ exports.test = function(name) { }); }); - it('should return a promise', function(done){ + it('should return a promise if no callback provided', function(done){ + var path = 'test/fixtures/' + name + '/user.' + name; + var locals = { user: user }; + var result = cons[name](path, locals); + + result.then(function (html) { + html.should.equal('

Tobi

'); + done(); + }) + .catch(function (err) { + done(err); + }); + }); + + it('should return a promise if no callback provided (string)', function(done){ var str = fs.readFileSync('test/fixtures/' + name + '/user.' + name).toString(); var locals = { user: user }; var result = cons[name].render(str, locals); From 8c9525a3b162d834190f02b3658f8bba396aaad8 Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Thu, 21 May 2015 10:58:27 -0500 Subject: [PATCH 05/13] Adding promise support for React --- lib/consolidate.js | 75 ++++++++++++++++++++++---------------------- test/shared/react.js | 27 ++++++++++++++++ 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index b4fa068..32a6d45 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -1130,58 +1130,59 @@ function reactRenderer(type){ // Return rendering fx return function(str, options, fn) { + return promisify(fn, function(fn) { + // React Import + var engine = requires.react || (requires.react = require('react')); - // React Import - var engine = requires.react || (requires.react = require('react')); + // Assign HTML Base + var base = options.base; + delete options.base; - // Assign HTML Base - var base = options.base; - delete options.base; + var enableCache = options.cache; + delete options.cache; - var enableCache = options.cache; - delete options.cache; + var isNonStatic = options.isNonStatic; + delete options.isNonStatic; - var isNonStatic = options.isNonStatic; - delete options.isNonStatic; + // Start Conversion + try { - // Start Conversion - try { + var Code, + Factory; - var Code, - Factory; + var baseStr, + content, + parsed; - var baseStr, - content, - parsed; + if (!cache(options)){ + // Parsing + Code = (type === 'path') ? require(resolve(str)) : requireReactString(str); + Factory = cache(options, engine.createFactory(Code)); - if (!cache(options)){ - // Parsing - Code = (type === 'path') ? require(resolve(str)) : requireReactString(str); - Factory = cache(options, engine.createFactory(Code)); + } else { + Factory = cache(options); + } - } else { - Factory = cache(options); - } + parsed = new Factory(options); + content = (isNonStatic) ? engine.renderToString(parsed) : engine.renderToStaticMarkup(parsed); - parsed = new Factory(options); - content = (isNonStatic) ? engine.renderToString(parsed) : engine.renderToStaticMarkup(parsed); + if (base){ + baseStr = readCache[str] || fs.readFileSync(resolve(base), 'utf8'); - if (base){ - baseStr = readCache[str] || fs.readFileSync(resolve(base), 'utf8'); + if (enableCache){ + readCache[str] = baseStr; + } - if (enableCache){ - readCache[str] = baseStr; + options.content = content; + content = reactBaseTmpl(baseStr, options); } - options.content = content; - content = reactBaseTmpl(baseStr, options); - } - - fn(null, content); + fn(null, content); - } catch (err) { - fn(err); - } + } catch (err) { + fn(err); + } + }); }; } diff --git a/test/shared/react.js b/test/shared/react.js index 4e4df7c..481a399 100644 --- a/test/shared/react.js +++ b/test/shared/react.js @@ -35,6 +35,18 @@ exports.test = function(name) { }); }); + it('should support promises', function(done){ + var path = 'test/fixtures/' + name + '/user.' + name; + var locals = { user: user }; + cons[name](path, locals) + .then(function(html){ + html.should.equal('

Tobi

'); + done(); + }) + .catch(function (err) { + done(err); + }); + }); it('should support rendering a string', function(done){ var str = fs.readFileSync('test/fixtures/' + name + '/user.' + name).toString(); @@ -52,6 +64,21 @@ exports.test = function(name) { }); + it('should support promises from a string', function(done){ + var str = fs.readFileSync('test/fixtures/' + name + '/user.' + name).toString(); + var locals = { user: user }; + + cons[name].render(str, locals) + .then(function(html){ + html.should.equal('

Tobi

'); + done(); + }) + .catch(function (err) { + return done(err); + }); + }); + + it('should support rendering into a base template', function(done){ var path = 'test/fixtures/' + name + '/user.' + name; var locals = { From f781b495946639d55cbf4143f91bdbf6326e4e48 Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Thu, 21 May 2015 11:05:50 -0500 Subject: [PATCH 06/13] Using `promisify` in `fromStringRenderer` --- lib/consolidate.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 32a6d45..2df5854 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -156,14 +156,7 @@ function fromStringRenderer(name) { return function(path, options, fn){ options.filename = path; - return q.Promise(function (res, rej) { - fn = fn || function completePromise(err, html) { - if (err) { - return rej(err); - } - res(html); - }; - + return promisify(fn, function(fn) { readPartials(path, options, function (err) { if (err) return fn(err); if (cache(options)) { From 7af73287e064c8273db6da8ce7cf20588a26efd2 Mon Sep 17 00:00:00 2001 From: Peter deHaan Date: Sat, 23 May 2015 14:50:10 -0700 Subject: [PATCH 07/13] Add license attribute https://docs.npmjs.com/files/package.json#license http://npm1k.org/ --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1ae62db..a32eb20 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "type": "git", "url": "https://github.com/visionmedia/consolidate.js.git" }, + "license": "MIT", "scripts": { "test": "mocha" } From 35d87f746d460a10de5ec03179d5136cba7c610c Mon Sep 17 00:00:00 2001 From: Robert Fleischmann Date: Sun, 24 May 2015 21:53:35 +0100 Subject: [PATCH 08/13] only replace matches in base template for the react renderer --- lib/consolidate.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 590e1d5..1108732 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -1005,7 +1005,9 @@ function reactBaseTmpl(data, options){ if (options.hasOwnProperty(k)){ exp = '{{'+k+'}}'; regex = new RegExp(exp, 'g'); - data = data.replace(regex, options[k]); + if (data.match(regex)) { + data = data.replace(regex, options[k]); + } } } From 8d6a10b7ba5b40cd99cd66c34adffab38e5215cc Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Tue, 26 May 2015 11:10:27 -0500 Subject: [PATCH 09/13] Switching to bluebird promises --- lib/consolidate.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/consolidate.js b/lib/consolidate.js index 2df5854..a98d282 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -22,7 +22,7 @@ var fs = require('fs') , join = path.join , resolve = path.resolve , extname = path.extname - , q = require('q') + , Promise = require('bluebird') , dirname = path.dirname; var readCache = {}; @@ -136,7 +136,7 @@ function readPartials(path, options, fn) { * promisify */ function promisify(fn, exec) { - return q.Promise(function (res, rej) { + return new Promise(function (res, rej) { fn = fn || function (err, html) { if (err) { return rej(err); diff --git a/package.json b/package.json index 8c6e603..a4b7d6b 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,6 @@ "test": "mocha" }, "dependencies": { - "q": "^1.4.1" + "bluebird": "^2.9.26" } } From b27e55bcbde2347ab9895fc1b69e28e68f6555be Mon Sep 17 00:00:00 2001 From: Brian Woodward Date: Tue, 26 May 2015 12:37:45 -0400 Subject: [PATCH 10/13] 0.13.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0562b4..a353064 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "consolidate", - "version": "0.12.1", + "version": "0.13.0", "description": "Template engine consolidation library", "keywords": [ "template", From 43392f5aa9304e866aee5743196ad3cc8ff7e8b7 Mon Sep 17 00:00:00 2001 From: Brian Woodward Date: Tue, 26 May 2015 12:39:17 -0400 Subject: [PATCH 11/13] History.md update --- History.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/History.md b/History.md index 6218538..820a31b 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +0.13.0 / 2015-05-26 +=================== + + * fixes react template error + * adds promises when a callback function is not passed to `render` + * documentation updates + 0.11.0 / 2015-02-07 ================== From 3fa68321222cf556eb56d52f1d8a13ab3e192f7e Mon Sep 17 00:00:00 2001 From: Alex Robertson Date: Tue, 26 May 2015 11:58:26 -0500 Subject: [PATCH 12/13] Adding readme info on promise API --- Readme.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Readme.md b/Readme.md index 98ec8b4..fd6f6ac 100644 --- a/Readme.md +++ b/Readme.md @@ -79,6 +79,22 @@ cons[name]('views/page.html', { user: 'tobi' }, function(err, html){ }); ``` +### Promises + + Additionally, all templates optionally return a promise if no callback function is provided. The promise represents the eventual result of the template function which will either resolve to a string, compiled from the template, or be rejected. Promises expose a `then` method which registers callbacks to receive the promise’s eventual value and a `catch` method which the reason why the promise could not be fulfilled. Promises allow more synchronous-like code structure and solve issues like race conditions. + +```js +var cons = require('consolidate'); + +cons.swig('views/page.html', { user: 'tobi' }) + .then(function (html) { + console.log(html); + }) + .catch(function (err) { + throw err; + }); +``` + ## Caching To enable or disable caching simply pass `{ cache: true/false }`. Engines _may_ use this option to cache things reading the file contents, compiled `Function`s etc. Engines which do _not_ support this may simply ignore it. All engines that consolidate.js implements I/O for will cache the file contents, ideal for production environments. From ab0cbe591f4747c1cfa687c1601d03ffd607c94a Mon Sep 17 00:00:00 2001 From: Brian Woodward Date: Tue, 26 May 2015 14:23:19 -0400 Subject: [PATCH 13/13] 0.13.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a353064..623528a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "consolidate", - "version": "0.13.0", + "version": "0.13.1", "description": "Template engine consolidation library", "keywords": [ "template",