Last active
August 29, 2015 13:56
-
-
Save myndzi/8837944 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = function (app, opts) { | |
var fs = require('fs'), | |
path = require('path'), | |
join = path.join, | |
Promise = require('bluebird'), | |
extend = require('jquery-extend'), | |
dust = opts.helpers ? | |
require('dustjs-helpers') : | |
require('dustjs-linkedin') | |
; | |
opts = opts || { }; | |
opts.extension = app.get('view engine') || 'dust'; | |
opts.publicdir = opts.publicdir || 'public'; | |
opts.viewPath = app.get('views') || '.'; | |
opts.partialCache = opts.partialCache || { }; | |
// in my app, another component keeps these up to date; the { } here is just so the code doesn't die without it | |
opts.mtimes = opts.mtimes || { }; | |
// these are only used by the helpers, you can delete them | |
fs.readFileP = Promise.promisify(fs.readFile.bind(fs)); | |
dust.compileP = Promise.promisify(dust.compile.bind(dust)); | |
dust.renderP = Promise.promisify(dust.render.bind(dust)); | |
var mtimes = opts.mtimes; | |
// helpers for cache busting -- these are just examples, can be used in | |
// a template like {@css url="foo/bar"/} | |
dust.helpers.css = function (chunk, ctx, bodies, params) { | |
var url = dust.helpers.tap(params.url, chunk, ctx), | |
path = join(opts.publicdir, url); | |
if (mtimes[path]) { url = url.replace(/css$/, mtimes[path]+'.css'); } | |
else { console.error('warning:', path, 'mtime=', mtimes[path]); } | |
chunk.write('<link rel="stylesheet" href="'+url+'">'); | |
return chunk; | |
}; | |
dust.helpers.js = function (chunk, ctx, bodies, params) { | |
var url = dust.helpers.tap(params.url, chunk, ctx), | |
path = join(opts.publicdir, url); | |
if (mtimes[path]) { url = url.replace(/js$/, mtimes[path]+'.js'); } | |
chunk.write('<script src="'+bust(params.url)+'"></script>'); | |
return chunk; | |
}; | |
// don't ask me why i put this in a closure, I just wanted a hard separation | |
(function (dust, opts) { | |
var fs = require('fs'), extname = require('path').extname; | |
var ext = opts.extension, | |
views = opts.viewPath, | |
partialCache = opts.partialCache; | |
// setting these functions so that I don't have to re-compile functions every request; | |
// i can just switch between the two | |
dust._onLoadCached = function(path, callback) { | |
if ('' == extname(path)) path += '.' + ext; | |
if ('/' !== path[0]) path = views + '/' + path; | |
if (partialCache[path]) { | |
callback(null, partialCache[path]); | |
} else { | |
read(path, callback); | |
} | |
}; | |
dust._onLoadNoCache = function(path, callback) { | |
if ('' == extname(path)) path += '.' + ext; | |
if ('/' !== path[0]) path = views + '/' + path; | |
read(path, callback); | |
}; | |
function read(path, callback) { | |
fs.readFile(path, function (err, data) { | |
data = data.toString(); | |
if (err) { callback(err); } | |
else { | |
partialCache[path] = data; | |
callback(null, data); | |
} | |
}); | |
} | |
})(dust, opts); | |
var render = function render(path, _opts, callback) { | |
_opts = _opts || { }; | |
_opts.cache = _opts.cache || opts.cache; | |
/* context variables get merged into the second parameter | |
* along with 'settings', 'cache', and '_locals' | |
* this seems weird, but i don't know how else i'm | |
* supposed to get ONLY the context variables! | |
*/ | |
var ctx = dust.makeBase(_opts); | |
delete ctx.settings; | |
delete ctx.cache; | |
delete ctx._locals; | |
var p, tmplName = path.slice(opts.publicdir.length+1); | |
// set the function that fixes the partial paths based on whether it | |
// should return results from the cache or not | |
dust.onLoad = (_opts.cache ? dust._onLoadCached : dust._onLoadNoCache); | |
if (_opts.cache && dust.cache[path]) { | |
p = dust.renderP(tmplName, ctx); | |
} else { | |
p = fs.readFileP(path).then(function (data) { | |
var compiled = dust.compile(data.toString(), tmplName); | |
dust.loadSource(compiled); | |
return dust.renderP(tmplName, ctx); | |
}); | |
} | |
return p.then(callback.bind(null, null), callback.bind(null)); | |
} | |
return render; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment