Simplified and optimized template loading

This commit is contained in:
Patrick Steele-Idem 2014-05-05 12:03:14 -06:00
parent 3b7a0a60b3
commit 510e063ea2
2 changed files with 105 additions and 37 deletions

View File

@ -25,56 +25,126 @@ var Context = renderContext.Context;
var helpers = require('./helpers'); var helpers = require('./helpers');
var loader = require('./loader'); var loader = require('./loader');
var cache = {}; var cache = {};
var Readable;
exports.Context = Context; exports.Context = Context;
var stream;
var STREAM = 'stream';
var streamPath;
try {
streamPath = require.resolve(STREAM);
} catch(e) {}
if (streamPath) {
stream = require(streamPath);
}
function Template(renderFunc) {
this._ = renderFunc;
}
Template.prototype = {
render: function(data, callback, context) {
if (data == null) {
data = {};
}
if (typeof callback === 'function') {
context = new Context();
context
.on('end', function() {
callback(null, context.getOutput());
})
.on('error', callback);
this._(data, context); //Invoke the template rendering function with the required arguments
context.end();
} else {
// A context object was provided instead of a callback
context = callback;
callback = null;
this._(data, context); //Invoke the template rendering function with the required arguments
}
return context;
},
stream: function(data) {
if (!stream) {
return function() {
throw new Error('Module not found: stream');
};
}
return new Readable(this._, data);
}
};
if (stream) {
Readable = function(template, data) {
Readable.$super.call(this);
this._t = template;
this._d = data;
this._rendered = false;
};
Readable.prototype = {
write: function(data) {
this.push(data);
},
end: function() {
this.push(null);
},
_read: function() {
if (this._rendered) {
return;
}
this._rendered = true;
var template = this._t;
var data = this._d;
var context = exports.createContext(this);
template.render(data, context);
context.end();
}
};
require('raptor-util/inherit')(Readable, stream.Readable);
}
function load(templatePath) { function load(templatePath) {
var templateFunc; var template;
if (typeof templatePath === 'string') { if (typeof templatePath === 'string') {
templateFunc = cache[templatePath]; template = cache[templatePath];
if (!templateFunc) { if (!template) {
templateFunc = cache[templatePath] = loader(templatePath)(helpers); template = cache[templatePath] = new Template(loader(templatePath)(helpers));
} }
} else { } else {
// Instead of a path, assume we got a compiled template module // Instead of a path, assume we got a compiled template module
templateFunc = templatePath._ || (templatePath._ = templatePath(helpers)); template = templatePath._ || (templatePath._ = new Template(templatePath(helpers)));
} }
return templateFunc; return template;
} }
exports.load = load; exports.load = load;
exports.render = function (templatePath, data, callback, context) { exports.render = function (templatePath, data, context) {
if (typeof callback !== 'function') { return load(templatePath).render(data, context);
// A context object was provided instead of a callback };
context = callback;
callback = null;
}
var shouldEnd = false; exports.stream = function(templatePath, data) {
return load(templatePath).stream(data);
if (!context) {
context = new Context();
shouldEnd = true;
}
load(templatePath)(data || {}, context); //Invoke the template rendering function with the required arguments
if (callback) {
context
.on('end', function() {
callback(null, context.getOutput());
})
.on('error', callback);
}
if (shouldEnd) {
context.end();
}
return context;
}; };
exports.unload = function(templatePath) { exports.unload = function(templatePath) {
@ -85,6 +155,4 @@ exports.createContext = function(writer) {
return new Context(writer); return new Context(writer);
}; };
exports.helpers = helpers; exports.helpers = helpers;
exports.stream = require('./render-stream')(exports);

View File

@ -9,5 +9,5 @@ module.exports = function render(input, context) {
}); });
var viewModel = extend(input['*'] || {}, { layoutContent: content }); var viewModel = extend(input['*'] || {}, { layoutContent: content });
input.template(viewModel, context); input.template.render(viewModel, context);
}; };