diff --git a/lib/consolidate.js b/lib/consolidate.js index dbd5b07..d5cf381 100644 --- a/lib/consolidate.js +++ b/lib/consolidate.js @@ -121,14 +121,14 @@ function readPartials(path, options, fn) { if (index === keys.length) return fn(null); var key = keys[index]; var partialPath = partials[key]; - + var file; if (isAbsolute(partialPath)) { if (extname(partialPath) !== '') { file = partialPath; } else { file = join(partialPath + extname(path)); - } + } } else { file = join(dirname(path), partialPath + extname(path)); } @@ -202,27 +202,128 @@ exports.liquid = fromStringRenderer('liquid'); * `includeDir` will also become a local. */ +function _renderTinyliquid(engine, str, options, fn) { + 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: + */ + + if (options.locals) { + for (k in options.locals) { + context.setLocals(k, options.locals[k]); + } + delete options.locals; + } + + if (options.meta) { + context.setLocals('page', options.meta); + delete options.meta; + } + + /** + * Add any defined filters: + */ + + if (options.filters) { + for (k in options.filters) { + context.setFilter(k, options.filters[k]); + } + delete options.filters; + } + + /** + * Set up a callback for the include directory: + */ + + var includeDir = options.includeDir || process.cwd(); + + context.onInclude(function (name, callback) { + var extname = path.extname(name) ? '' : '.liquid'; + var filename = path.resolve(includeDir, name + extname); + + fs.readFile(filename, {encoding: 'utf8'}, function (err, data) { + if (err) return callback(err); + callback(null, engine.parse(data)); + }); + }); + 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; + } + + /** + * Now anything left in `options` becomes a local: + */ + + for (k in options) { + context.setLocals(k, options[k]); + } + + /** + * Finally, execute the template: + */ + + var tmpl = cache(context) || cache(context, engine.compile(str, compileOptions)); + tmpl(context, fn); +} + exports.liquid.render = function(str, options, fn){ return promisify(fn, function (fn) { - var engine = requires.liquid || (requires.liquid = require('tinyliquid')); + var engine = requires.liquid; + var Liquid; + try { - var context = engine.newContext(); - var k; + // set up tinyliquid engine + engine = requires.liquid = require('tinyliquid'); - /** - * 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: - */ + // use tinyliquid engine + _renderTinyliquid(engine, str, options, fn); - if (options.locals){ - for (k in options.locals){ - context.setLocals(k, options.locals[k]); - } - delete options.locals; + return; + + } catch (err) { + + // set up liquid-node engine + try { + Liquid = requires.liquid = require('liquid-node'); + engine = new Liquid.Engine; + } catch (err) { + throw err; } + } + + // use liquid-node engine + try { + var locals = options.locals || {}; + if (options.meta){ - context.setLocals('page', options.meta); + locals.pages = options.meta; delete options.meta; } @@ -230,10 +331,8 @@ exports.liquid.render = function(str, options, fn){ * Add any defined filters: */ - if (options.filters){ - for (k in options.filters){ - context.setFilter(k, options.filters[k]); - } + if (options.filters) { + engine.registerFilters(options.filters); delete options.filters; } @@ -242,16 +341,7 @@ exports.liquid.render = function(str, options, fn){ */ var includeDir = options.includeDir || process.cwd(); - - context.onInclude(function (name, callback) { - var extname = path.extname(name) ? '' : '.liquid'; - var filename = path.resolve(includeDir, name + extname); - - fs.readFile(filename, {encoding: 'utf8'}, function (err, data){ - if (err) return callback(err); - callback(null, engine.parse(data)); - }); - }); + engine.fileSystem = new Liquid.LocalFileSystem(includeDir, 'liquid'); delete options.includeDir; /** @@ -268,13 +358,7 @@ exports.liquid.render = function(str, options, fn){ 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 */ + engine.registerTag(k, tagFunctions[k]); } delete options.customTags; } @@ -283,16 +367,24 @@ exports.liquid.render = function(str, options, fn){ * Now anything left in `options` becomes a local: */ - for (k in options){ - context.setLocals(k, options[k]); + for (var k in options){ + locals[k] = options[k]; } /** * Finally, execute the template: */ - var tmpl = cache(context) || cache(context, engine.compile(str, compileOptions)); - tmpl(context, fn); + return engine + .parseAndRender(str, locals) + .nodeify(function (err, result) { + if (err) { + throw new Error(err); + } else { + return fn(null, result); + } + }); + } catch (err) { fn(err); } diff --git a/package.json b/package.json index 178bba8..16117b2 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "jazz": "^0.0.18", "jqtpl": "~1.1.0", "just": "^0.1.8", + "liquid-node": "^2.6.1", "liquor": "^0.0.5", "lodash": "^4.0.0", "marko": "^3.12.0", @@ -58,7 +59,7 @@ "swig": "^1.4.1", "teacup": "^2.0.0", "templayed": ">=0.2.3", - "tinyliquid": "^0.2.22", + "tinyliquid": "^0.2.30", "toffee": "^0.1.12", "twig": "^0.10.0", "underscore": "^1.3.3", diff --git a/test/shared/includes.js b/test/shared/includes.js index 89f2026..7224e23 100644 --- a/test/shared/includes.js +++ b/test/shared/includes.js @@ -6,7 +6,7 @@ var should = require('should'); exports.test = function(name) { var user = { name: 'Tobi' }; - describe(name, function(){ + describe(name, function() { it('should support includes', function(done) { var str = fs.readFileSync('test/fixtures/' + name + '/include.' + name).toString();