package/package.json000644 000765 000024 0000003344 13013351063013014 0ustar00000000 000000 { "name": "consolidate", "description": "Template engine consolidation library", "version": "0.14.5", "author": "TJ Holowaychuk ", "dependencies": { "bluebird": "^3.1.1" }, "devDependencies": { "arc-templates": "^0.5.1", "atpl": ">=0.7.6", "babel-core": "^6.7.6", "babel-preset-react": "^6.5.0", "bracket-template": "^1.0.3", "dot": "^1.0.1", "dust": "^0.3.0", "dustjs-helpers": "^1.1.1", "dustjs-linkedin": "^2.7.2", "eco": "^1.1.0-rc-3", "ect": "^0.5.9", "ejs": "^2.3.4", "eslint": "^3.7.1", "eslint-config-standard": "^6.2.0", "eslint-plugin-promise": "^3.3.1", "eslint-plugin-standard": "^2.0.1", "haml-coffee": "^1.4.0", "hamlet": "^0.3.3", "hamljs": "^0.6.1", "handlebars": "^4.0.5", "hogan.js": "^3.0.2", "htmling": "^0.0.7", "jade": "^1.9.1", "jazz": "^0.0.18", "jqtpl": "~1.1.0", "just": "^0.1.8", "liquor": "^0.0.5", "lodash": "^4.0.0", "marko": "^3.12.0", "mocha": "^3.1.2", "mote": "^0.2.0", "mustache": "^2.2.1", "nunjucks": "^3.0.0", "pug": "^2.0.0-beta6", "qejs": "^3.0.5", "ractive": "^0.8.4", "react": "^15.3.2", "react-dom": "^15.3.2", "should": "*", "slm": "^0.5.0", "swig": "^1.4.1", "templayed": ">=0.2.3", "tinyliquid": "^0.2.22", "toffee": "^0.1.12", "twig": "^0.10.0", "underscore": "^1.3.3", "vash": "^0.12.2", "walrus": "^0.10.1", "whiskers": "^0.4.0" }, "keywords": [ "engine", "template", "view" ], "license": "MIT", "main": "index", "repository": { "type": "git", "url": "https://github.com/visionmedia/consolidate.js.git" }, "scripts": { "test": "mocha" } } package/.npmignore000644 000765 000024 0000000035 13011401336012514 0ustar00000000 000000 support test examples *.sock package/index.js000644 000765 000024 0000000056 13011401336012165 0ustar00000000 000000 module.exports = require('./lib/consolidate');package/Readme.md000644 000765 000024 0000021407 13013351032012241 0ustar00000000 000000 # Consolidate.js Template engine consolidation library. ## Installation $ npm install consolidate ## Supported template engines - [atpl](https://github.com/soywiz/atpl.js) - [bracket](https://github.com/danlevan/bracket-template) - [doT.js](https://github.com/olado/doT) [(website)](http://olado.github.io/doT/) - [dust (unmaintained)](https://github.com/akdubya/dustjs) [(website)](http://akdubya.github.com/dustjs/) - [dustjs-linkedin (maintained fork of dust)](https://github.com/linkedin/dustjs) [(website)](http://linkedin.github.io/dustjs/) - [eco](https://github.com/sstephenson/eco) - [ect](https://github.com/baryshev/ect) [(website)](http://ectjs.com/) - [ejs](https://github.com/mde/ejs) [(website)](http://ejs.co/) - [haml](https://github.com/visionmedia/haml.js) - [haml-coffee](https://github.com/9elements/haml-coffee) - [hamlet](https://github.com/gregwebs/hamlet.js) - [handlebars](https://github.com/wycats/handlebars.js/) [(website)](http://handlebarsjs.com/) - [hogan](https://github.com/twitter/hogan.js) [(website)](http://twitter.github.com/hogan.js/) - [htmling](https://github.com/codemix/htmling) - [jade](https://github.com/visionmedia/jade) [(website)](http://jade-lang.com/) - [jazz](https://github.com/shinetech/jazz) - [jqtpl](https://github.com/kof/jqtpl) - [JUST](https://github.com/baryshev/just) - [liquor](https://github.com/chjj/liquor) - [lodash](https://github.com/bestiejs/lodash) [(website)](http://lodash.com/) - [marko](https://github.com/marko-js/marko) [(website)](http://markojs.com) - [mote](https://github.com/satchmorun/mote) [(website)](http://satchmorun.github.io/mote/) - [mustache](https://github.com/janl/mustache.js) - [nunjucks](https://github.com/mozilla/nunjucks) [(website)](https://mozilla.github.io/nunjucks) - [pug (formerly jade)](https://github.com/pugjs/pug) [(website)](http://jade-lang.com/) - [QEJS](https://github.com/jepso/QEJS) - [ractive](https://github.com/Rich-Harris/Ractive) - [react](https://github.com/facebook/react) - [slm](https://github.com/slm-lang/slm) - [swig (unmaintained)](https://github.com/paularmstrong/swig) - [templayed](http://archan937.github.com/templayed.js/) - [twig](https://github.com/justjohn/twig.js) - [liquid](https://github.com/leizongmin/tinyliquid) [(website)](http://liquidmarkup.org/) - [toffee](https://github.com/malgorithms/toffee) - [underscore](https://github.com/documentcloud/underscore) [(website)](http://underscorejs.org/#template) - [vash](https://github.com/kirbysayshi/vash) - [walrus](https://github.com/jeremyruppel/walrus) [(website)](http://documentup.com/jeremyruppel/walrus/) - [whiskers](https://github.com/gsf/whiskers.js) __NOTE__: you must still install the engines you wish to use, add them to your package.json dependencies. ## API All templates supported by this library may be rendered using the signature `(path[, locals], callback)` as shown below, which happens to be the signature that Express 3.x supports so any of these engines may be used within Express. __NOTE__: All this example code uses cons.swig for the swig template engine. Replace swig with whatever templating you are using. For example, use cons.hogan for hogan.js, cons.jade for jade, etc. `console.log(cons)` for the full list of identifiers. ```js var cons = require('consolidate'); cons.swig('views/page.html', { user: 'tobi' }, function(err, html){ if (err) throw err; console.log(html); }); ``` Or without options / local variables: ```js var cons = require('consolidate'); cons.swig('views/page.html', function(err, html){ if (err) throw err; console.log(html); }); ``` To dynamically pass the engine, simply use the subscript operator and a variable: ```js var cons = require('consolidate') , name = 'swig'; cons[name]('views/page.html', { user: 'tobi' }, function(err, html){ if (err) throw err; console.log(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. ```js var cons = require('consolidate'); cons.swig('views/page.html', { cache: false, user: 'tobi' }, function(err, html){ if (err) throw err; console.log(html); }); ``` ## Express 3.x example ```js var express = require('express') , cons = require('consolidate') , app = express(); // assign the swig engine to .html files app.engine('html', cons.swig); // set .html as the default extension app.set('view engine', 'html'); app.set('views', __dirname + '/views'); var users = []; users.push({ name: 'tobi' }); users.push({ name: 'loki' }); users.push({ name: 'jane' }); app.get('/', function(req, res){ res.render('index', { title: 'Consolidate.js' }); }); app.get('/users', function(req, res){ res.render('users', { title: 'Users', users: users }); }); app.listen(3000); console.log('Express server listening on port 3000'); ``` ## Template Engine Instances Template engines are exposed via the `cons.requires` object, but they are not instantiated until you've called the `cons[engine].render()` method. You can instantiate them manually beforehand if you want to add filters, globals, mixins, or other engine features. ```js var cons = require('consolidate'), nunjucks = require('nunjucks'); // add nunjucks to requires so filters can be // added and the same instance will be used inside the render method cons.requires.nunjucks = nunjucks.configure(); cons.requires.nunjucks.addFilter('foo', function () { return 'bar'; }); ``` ## Notes * If you're using Nunjucks, please take a look at the `exports.nunjucks.render` function in `lib.consolidate.js`. You can pass your own engine/environment via `options.nunjucksEnv`, or if you want to support Express you can pass `options.settings.views`, or if you have another use case, pass `options.nunjucks` (see the code for more insight). * You can pass **partials** with `options.partials` * For using **template inheritance** with nunjucks, you can pass a loader with `options.loader`. * To use **filters** with tinyliquid, use `options.filters` and specify an array of properties, each of which is a named filter function. A filter function takes a string as a parameter and returns a modified version of it. * To use **custom tags** with tinyliquid, use `options.customTags` to specify an array of tag functions that follow the tinyliquid [custom tag](https://github.com/leizongmin/tinyliquid/wiki/Custom-Tag) definition. * The default directory used with the **include** tag with tinyliquid is the current working directory. To override this, use `options.includeDir`. * `React` To render content into a html base template (eg. `index.html` of your React app), pass the path of the template with `options.base`. ## Running tests Install dev deps: $ npm install -d Run the tests: $ make test ## License (The MIT License) Copyright (c) 2011-2016 TJ Holowaychuk <tj@vision-media.ca> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/History.md000644 000765 000024 0000004432 13011401336012505 0ustar00000000 000000 0.14.0 / 2016-01-24 =================== * add slm support * add vash support * add twig support * fixes lodash 4 options * fixes liquid file extensions and path resolving 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 ================== * fix aptl tests * update jade caching * add HTMLing support * add hamlet support * readme updates * add tinyliquid support * pass `options` to ECT.js * update ractive * update travis-ci to test 0.10, 0.12, and iojs 0.10.0 / 2013-11-23 ================== * add lodash support * add nunjucks support 0.9.1 / 2013-04-29 ================== * Update ECT version * Added support for Handlebars helpers with test. * Invalidates built-in dust cache if caching disabled 0.9.0 / 2013-03-28 ================== * dust-helpers support, latest version of dust * Re-add doT - global leaks fixed * improving templayed support 0.8.0 / 2013-01-23 ================== * add templayed support * add `then-jade` as an alternative to `jade` 0.7.0 / 2012-12-28 ================== * add atpl support 0.6.0 2012-12-22 ================== * add partials support * add support for toffee templates * remove dot it still leaks and the author has not fixed it 0.5.0 / 2012-10-29 ================== * add `mote` support * add support to `dust` partials * add support for `ECT` * add support for rendering without file * add support for `JUST` * improve Haml-Coffee caching. 0.4.0 / 2012-07-30 ================== * add doT support [sannis] * add mustache support [ForbesLindesay] * add walrus support [kagd] 0.3.1 / 2012-06-28 ================== * add QEJS support * add underscore support * change whiskers to use pre-defined `.__express` * remove engines. Closes #37 * remove kernel, cannot comply with our caching 0.3.0 / 2012-04-18 ================== * Added partials loading for whiskers [gsf] * Added dustjs-linkedin support 0.2.0 / 2012-04-04 ================== * Added support for dust [fatjonny] * Added handlebars support [jstewmon] 0.1.0 / 2012-01-03 ================== * Added support for several more engines 0.0.1 / 2010-01-03 ================== * Initial release package/Makefile000644 000765 000024 0000000154 13011401336012157 0ustar00000000 000000 REPORTER = spec test: @./node_modules/.bin/mocha \ --slow 30 \ --reporter $(REPORTER) .PHONY: testpackage/.eslintrc000644 000765 000024 0000000650 13011401336012344 0ustar00000000 000000 { "extends": "standard", "rules": { "padded-blocks": 0, "semi": 0, "curly": 0, "space-before-function-paren": 0, "space-before-blocks": 0, "brace-style": 0, "quotes": 0, "new-cap": 0, "no-multiple-empty-lines": 0, "promise/param-names": 0, "spaced-comment": 0, "yoda": 0, "keyword-spacing": 0, "standard/object-curly-even-spacing": 0, "comma-spacing": 0 } } package/lib/consolidate.js000644 000765 000024 0000100525 13013351032014131 0ustar00000000 000000 'use strict'; /* * Engines which do not support caching of their file contents * should use the `read()` function defined in consolidate.js * On top of this, when an engine compiles to a `Function`, * these functions should either be cached within consolidate.js * or the engine itself via `options.cache`. This will allow * users and frameworks to pass `options.cache = true` for * `NODE_ENV=production`, however edit the file(s) without * re-loading the application in development. */ /** * Module dependencies. */ var fs = require('fs'); var path = require('path'); var Promise = require('bluebird'); var join = path.join; var resolve = path.resolve; var extname = path.extname; var dirname = path.dirname; var readCache = {}; /** * Require cache. */ var cacheStore = {}; /** * Require cache. */ var requires = {}; /** * Clear the cache. * * @api public */ exports.clearCache = function(){ cacheStore = {}; }; /** * Conditionally cache `compiled` template based * on the `options` filename and `.cache` boolean. * * @param {Object} options * @param {Function} compiled * @return {Function} * @api private */ function cache(options, compiled) { // cachable if (compiled && options.filename && options.cache) { delete readCache[options.filename]; cacheStore[options.filename] = compiled; return compiled; } // check cache if (options.filename && options.cache) { return cacheStore[options.filename]; } return compiled; } /** * Read `path` with `options` with * callback `(err, str)`. When `options.cache` * is true the template string will be cached. * * @param {String} options * @param {Function} fn * @api private */ function read(path, options, fn) { var str = readCache[path]; var cached = options.cache && str && typeof str === 'string'; // cached (only if cached is a string and not a compiled template function) if (cached) return fn(null, str); // read fs.readFile(path, 'utf8', function(err, str){ if (err) return fn(err); // remove extraneous utf8 BOM marker str = str.replace(/^\uFEFF/, ''); if (options.cache) readCache[path] = str; fn(null, str); }); } /** * Read `path` with `options` with * callback `(err, str)`. When `options.cache` * is true the partial string will be cached. * * @param {String} options * @param {Function} fn * @api private */ function readPartials(path, options, fn) { if (!options.partials) return fn(); var partials = options.partials; var keys = Object.keys(partials); function next(index) { if (index === keys.length) return fn(null); var key = keys[index]; var file = join(dirname(path), partials[key] + extname(path)); read(file, options, function(err, str){ if (err) return fn(err); options.partials[key] = str; next(++index); }); } next(0); } /** * promisify */ function promisify(fn, exec) { return new Promise(function (res, rej) { fn = fn || function (err, html) { if (err) { return rej(err); } res(html); }; exec(fn); }); } /** * fromStringRenderer */ function fromStringRenderer(name) { return function(path, options, fn){ options.filename = path; return promisify(fn, function(fn) { 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); }); } }); }); }; } /** * Liquid support. */ exports.liquid = fromStringRenderer('liquid'); /** * Liquid string support. */ /** * Note that in order to get filters and custom tags we've had to push * all user-defined locals down into @locals. However, just to make things * backwards-compatible, any property of `options` that is left after * processing and removing `locals`, `meta`, `filters`, `customTags` and * `includeDir` will also become a local. */ exports.liquid.render = function(str, options, fn){ 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: */ 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); } catch (err) { fn(err); } }); }; /** * Jade support. */ exports.jade = function(path, options, fn){ return promisify(fn, function (fn) { var engine = requires.jade; if (!engine) { try { 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); } }); }; /** * Jade string support. */ exports.jade.render = function(str, options, fn){ return promisify(fn, function (fn) { var engine = requires.jade; if (!engine) { try { 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); } }); }; /** * Dust support. */ exports.dust = fromStringRenderer('dust'); /** * Dust string support. */ exports.dust.render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires.dust; if (!engine) { try { engine = requires.dust = require('dust'); } catch (err) { try { engine = requires.dust = require('dustjs-helpers'); } catch (err) { engine = requires.dust = require('dustjs-linkedin'); } } } var ext = 'dust'; var 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 = {}; 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); } }); }; /** * Swig support. */ exports.swig = fromStringRenderer('swig'); /** * Swig string support. */ exports.swig.render = function(str, options, fn){ 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); } }); }; /** * Atpl support. */ exports.atpl = fromStringRenderer('atpl'); /** * Atpl string support. */ exports.atpl.render = function(str, options, fn){ 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); } }); }; /** * Liquor support, */ exports.liquor = fromStringRenderer('liquor'); /** * Liquor string support. */ exports.liquor.render = function(str, options, fn){ 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); } }); }; /** * Twig support. */ exports.twig = fromStringRenderer('twig'); /** * Twig string support. */ exports.twig.render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires.twig || (requires.twig = require('twig').twig); var templateData = { data: str }; try { var tmpl = cache(templateData) || cache(templateData, engine(templateData)); fn(null, tmpl.render(options)); } catch (err) { fn(err); } }); }; /** * EJS support. */ exports.ejs = fromStringRenderer('ejs'); /** * EJS string support. */ exports.ejs.render = function(str, options, fn){ 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); } }); }; /** * Eco support. */ exports.eco = fromStringRenderer('eco'); /** * Eco string support. */ exports.eco.render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires.eco || (requires.eco = require('eco')); try { fn(null, engine.render(str, options)); } catch (err) { fn(err); } }); }; /** * Jazz support. */ exports.jazz = fromStringRenderer('jazz'); /** * Jazz string support. */ exports.jazz.render = function(str, options, fn){ 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); } }); }; /** * JQTPL support. */ exports.jqtpl = fromStringRenderer('jqtpl'); /** * JQTPL string support. */ exports.jqtpl.render = function(str, options, fn){ 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); } }); }; /** * Haml support. */ exports.haml = fromStringRenderer('haml'); /** * Haml string support. */ exports.haml.render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires.haml || (requires.haml = require('hamljs')); try { options.locals = options; fn(null, engine.render(str, options).trimLeft()); } catch (err) { fn(err); } }); }; /** * Hamlet support. */ exports.hamlet = fromStringRenderer('hamlet'); /** * Hamlet string support. */ exports.hamlet.render = function(str, options, fn){ 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); } }); }; /** * Whiskers support. */ exports.whiskers = function(path, options, fn){ return promisify(fn, function (fn) { var engine = requires.whiskers || (requires.whiskers = require('whiskers')); engine.__express(path, options, fn); }); }; /** * Whiskers string support. */ exports.whiskers.render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires.whiskers || (requires.whiskers = require('whiskers')); try { fn(null, engine.render(str, options)); } catch (err) { fn(err); } }); }; /** * Coffee-HAML support. */ exports['haml-coffee'] = fromStringRenderer('haml-coffee'); /** * Coffee-HAML string support. */ exports['haml-coffee'].render = function(str, options, fn){ return promisify(fn, function(fn) { var engine = requires['haml-coffee'] || (requires['haml-coffee'] = require('haml-coffee')); try { var tmpl = cache(options) || cache(options, engine.compile(str, options)); fn(null, tmpl(options)); } catch (err) { fn(err); } }); }; /** * Hogan support. */ exports.hogan = fromStringRenderer('hogan'); /** * Hogan string support. */ exports.hogan.render = function(str, options, fn){ 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); } }); }; /** * templayed.js support. */ exports.templayed = fromStringRenderer('templayed'); /** * templayed.js string support. */ exports.templayed.render = function(str, options, fn){ 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); } }); }; /** * Handlebars support. */ exports.handlebars = fromStringRenderer('handlebars'); /** * Handlebars string support. */ exports.handlebars.render = function(str, options, fn) { 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); } }); }; /** * Underscore support. */ exports.underscore = fromStringRenderer('underscore'); /** * Underscore string support. */ exports.underscore.render = function(str, options, fn) { 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); } }); }; /** * Lodash support. */ exports.lodash = fromStringRenderer('lodash'); /** * Lodash string support. */ exports.lodash.render = function(str, options, fn) { return promisify(fn, function (fn) { var engine = requires.lodash || (requires.lodash = require('lodash')); try { var tmpl = cache(options) || cache(options, engine.template(str, options)); fn(null, tmpl(options).replace(/\n$/, '')); } catch (err) { fn(err); } }); }; /** * Pug support. (formerly Jade) */ exports.pug = function(path, options, fn){ return promisify(fn, function (fn) { var engine = requires.pug; if (!engine) { try { engine = requires.pug = require('pug'); } catch (err) { try { engine = requires.pug = require('then-pug'); } catch (otherError) { throw err; } } } try { var tmpl = cache(options) || cache(options, engine.compileFile(path, options)); fn(null, tmpl(options)); } catch (err) { fn(err); } }); }; /** * Pug string support. */ exports.pug.render = function(str, options, fn){ return promisify(fn, function (fn) { var engine = requires.pug; if (!engine) { try { engine = requires.pug = require('pug'); } catch (err) { try { engine = requires.pug = require('then-pug'); } catch (otherError) { throw err; } } } try { var tmpl = cache(options) || cache(options, engine.compile(str, options)); fn(null, tmpl(options)); } catch (err) { fn(err); } }); }; /** * QEJS support. */ exports.qejs = fromStringRenderer('qejs'); /** * QEJS string support. */ exports.qejs.render = function (str, options, fn) { 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); } }); }; /** * Walrus support. */ exports.walrus = fromStringRenderer('walrus'); /** * Walrus string support. */ exports.walrus.render = function (str, options, fn) { 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); } }); }; /** * Mustache support. */ exports.mustache = fromStringRenderer('mustache'); /** * Mustache string support. */ exports.mustache.render = function(str, options, fn) { 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); } }); }; /** * Just support. */ exports.just = function(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); }); }; /** * Just string support. */ exports.just.render = function(str, options, fn){ return promisify(fn, function (fn) { var JUST = require('just'); var engine = new JUST({ root: { page: str }}); engine.render('page', options, fn); }); }; /** * ECT support. */ exports.ect = function(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); }); }; /** * ECT string support. */ exports.ect.render = function(str, options, fn){ return promisify(fn, function (fn) { var ECT = require('ect'); var engine = new ECT({ root: { page: str }}); engine.render('page', options, fn); }); }; /** * mote support. */ exports.mote = fromStringRenderer('mote'); /** * mote string support. */ exports.mote.render = function(str, options, fn){ 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); } }); }; /** * Toffee support. */ exports.toffee = function(path, options, fn){ return promisify(fn, function (fn) { var toffee = requires.toffee || (requires.toffee = require('toffee')); toffee.__consolidate_engine_render(path, options, fn); }); }; /** * Toffee string support. */ exports.toffee.render = function(str, options, fn) { return promisify(fn, function (fn) { var engine = requires.toffee || (requires.toffee = require('toffee')); try { engine.str_render(str, options,fn); } catch (err) { fn(err); } }); }; /** * doT support. */ exports.dot = fromStringRenderer('dot'); /** * doT string support. */ exports.dot.render = function (str, options, fn) { 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); } }); }; /** * bracket support. */ exports.bracket = fromStringRenderer('bracket'); /** * bracket string support. */ exports.bracket.render = function (str, options, fn) { return promisify(fn, function (fn) { var engine = requires.bracket || (requires.bracket = require('bracket-template')); try { var tmpl = cache(options) || cache(options, engine.default.compile(str)); fn(null, tmpl(options)); } catch (err) { fn(err); } }); }; /** * Ractive support. */ exports.ractive = fromStringRenderer('ractive'); /** * Ractive string support. */ exports.ractive.render = function(str, options, fn){ 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; 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); // 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); } }); }; /** * Nunjucks support. */ exports.nunjucks = fromStringRenderer('nunjucks'); /** * Nunjucks string support. */ exports.nunjucks.render = function (str, options, fn) { return promisify(fn, function (fn) { try { var engine = options.nunjucksEnv || requires.nunjucks || (requires.nunjucks = require('nunjucks')); var env = engine; // deprecated fallback support for express // // if (options.settings && options.settings.views) env = engine.configure(options.settings.views); else if (options.nunjucks && options.nunjucks.configure) env = engine.configure.apply(engine, options.nunjucks.configure); // // because `renderString` does not initiate loaders // we must manually create a loader for it based off // either `options.settings.views` or `options.nunjucks` or `options.nunjucks.root` // // // // // // note that the below code didn't work nor make sense before // because loaders should take different options from rendering // /* var loader = options.loader; if (loader) { var env = new engine.Environment(new loader(options)); env.renderString(str, options, fn); } else { engine.renderString(str, options, fn); } */ // so instead we simply check if we passed a custom loader // otherwise we create a simple file based loader if (options.loader) { env = new engine.Environment(options.loader); } else if (options.settings && options.settings.views) { env = new engine.Environment( new engine.FileSystemLoader(options.settings.views) ); } else if (options.nunjucks && options.nunjucks.loader) { if (typeof options.nunjucks.loader === 'string') env = new engine.Environment(new engine.FileSystemLoader(options.nunjucks.loader)); else env = new engine.Environment( new engine.FileSystemLoader( options.nunjucks.loader[0], options.nunjucks.loader[1] ) ); } env.renderString(str, options, fn); } catch (err) { throw fn(err); } }); }; /** * HTMLing support. */ exports.htmling = fromStringRenderer('htmling'); /** * HTMLing string support. */ exports.htmling.render = function(str, options, fn) { 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); } }); }; /** * Rendering function */ function requireReact(module, filename) { var babel = requires.babel || (requires.babel = require('babel-core')); var compiled = babel.transformFileSync(filename, { presets: [ 'react' ] }).code return module._compile(compiled, filename); } exports.requireReact = requireReact; /** * Converting a string into a node module. */ function requireReactString(src, filename) { var babel = requires.babel || (requires.babel = require('babel-core')); if (!filename) filename = ''; var m = new module.constructor(); filename = filename || ''; // Compile Using React var compiled = babel.transform(src, { presets: [ 'react' ] }).code; // Compile as a module m.paths = module.paths; m._compile(compiled, filename); return m.exports; } /** * A naive helper to replace {{tags}} with options.tags content */ function reactBaseTmpl(data, options){ var exp; var regex; // Iterates through the keys in file object // and interpolate / replace {{key}} with it's value for (var k in options){ if (options.hasOwnProperty(k)){ exp = '{{' + k + '}}'; regex = new RegExp(exp, 'g'); if (data.match(regex)) { data = data.replace(regex, options[k]); } } } return data; } /** * The main render parser for React bsaed templates */ function reactRenderer(type){ if (require.extensions) { // Ensure JSX is transformed on require if (!require.extensions['.jsx']) { require.extensions['.jsx'] = requireReact; } // Supporting .react extension as well as test cases // Using .react extension is not recommended. if (!require.extensions['.react']) { require.extensions['.react'] = requireReact; } } // Return rendering fx return function(str, options, fn) { return promisify(fn, function(fn) { // React Import var ReactDOM = requires.ReactDOM || (requires.ReactDOM = require('react-dom/server')); var react = requires.react || (requires.react = require('react')); // Assign HTML Base var base = options.base; delete options.base; var enableCache = options.cache; delete options.cache; var isNonStatic = options.isNonStatic; delete options.isNonStatic; // Start Conversion try { var Code; var Factory; var baseStr; var content; var parsed; if (!cache(options)){ // Parsing Code = (type === 'path') ? require(resolve(str)) : requireReactString(str); Factory = cache(options, react.createFactory(Code)); } else { Factory = cache(options); } parsed = new Factory(options); content = (isNonStatic) ? ReactDOM.renderToString(parsed) : ReactDOM.renderToStaticMarkup(parsed); if (base){ baseStr = readCache[str] || fs.readFileSync(resolve(base), 'utf8'); if (enableCache){ readCache[str] = baseStr; } options.content = content; content = reactBaseTmpl(baseStr, options); } fn(null, content); } catch (err) { fn(err); } }); }; } /** * React JS Support */ exports.react = reactRenderer('path'); /** * React JS string support. */ exports.react.render = reactRenderer('string'); /** * ARC-templates support. */ exports['arc-templates'] = fromStringRenderer('arc-templates'); /** * ARC-templates string support. */ exports['arc-templates'].render = function(str, options, fn) { var readFileWithOptions = Promise.promisify(read); var consolidateFileSystem = {}; consolidateFileSystem.readFile = function (path) { return readFileWithOptions(path, options); }; return promisify(fn, function (fn) { try { var engine = requires['arc-templates']; if (!engine) { var Engine = require('arc-templates/dist/es5'); engine = requires['arc-templates'] = new Engine({ filesystem: consolidateFileSystem }); } var compiler = cache(options) || cache(options, engine.compileString(str, options.filename)); compiler.then(function (func) { return func(options); }) .then(function (result) { fn(null, result.content); }) .catch(fn); } catch (err) { fn(err); } }); }; /** * Vash support */ exports.vash = fromStringRenderer('vash'); /** * Vash string support */ exports.vash.render = function(str, options, fn) { return promisify(fn, function(fn) { var engine = requires.vash || (requires.vash = require('vash')); try { // helper system : https://github.com/kirbysayshi/vash#helper-system if (options.helpers) { for (var key in options.helpers) { if (!options.helpers.hasOwnProperty(key) || typeof options.helpers[key] !== 'function') { continue; } engine.helpers[key] = options.helpers[key]; } } var tmpl = cache(options) || cache(options, engine.compile(str, options)); fn(null, tmpl(options).replace(/\n$/, '')); } catch (err) { fn(err); } }); }; /** * Slm support. */ exports.slm = fromStringRenderer('slm'); /** * Slm string support. */ exports.slm.render = function(str, options, fn) { return promisify(fn, function (fn) { var engine = requires.slm || (requires.slm = require('slm')); try { var tmpl = cache(options) || cache(options, engine.compile(str, options)); fn(null, tmpl(options)); } catch (err) { fn(err); } }); }; /** * Marko support. */ exports.marko = function(path, options, fn){ return promisify(fn, function (fn) { var engine = requires.marko || (requires.marko = require('marko')); options.writeToDisk = !!options.cache; try { var tmpl = cache(options) || cache(options, engine.load(path, options)); tmpl.render(options, fn) } catch (err) { fn(err); } }); }; /** * Marko string support. */ exports.marko.render = function(str, options, fn) { return promisify(fn, function (fn) { var engine = requires.marko || (requires.marko = require('marko')); options.writeToDisk = !!options.cache; try { var tmpl = cache(options) || cache(options, engine.load('string.marko', str, options)); tmpl.render(options, fn) } catch (err) { fn(err); } }); }; /** * expose the instance of the engine */ exports.requires = requires; package/.travis.yml000644 000765 000024 0000000247 13011401336012633 0ustar00000000 000000 sudo: false language: node_js node_js: - "5" - "4" - "0.12" - "0.10" matrix: fast_finish: true allow_failures: - node_js: "0.10" - node_js: "0.12"