marko/runtime/renderable.js
2017-02-09 18:54:57 -08:00

123 lines
3.9 KiB
JavaScript

var defaultCreateOut = require('./createOut');
var extend = require('raptor-util/extend');
module.exports = function(target, renderer) {
var renderFunc = renderer && (renderer.renderer || renderer.render || renderer);
var createOut = target.createOut || renderer.createOut || defaultCreateOut;
return extend(target, {
createOut: createOut,
renderToString: function(data, callback) {
var localData = data || {};
var render = renderFunc || this._;
var globalData = localData.$global;
var out = createOut(globalData);
out.global.template = this;
if (globalData) {
localData.$global = undefined;
}
if (callback) {
out.on('finish', function() {
callback(null, out.toString(), out);
})
.once('error', callback);
render(localData, out);
return out.end();
} else {
out.sync();
render(localData, out);
return out.toString();
}
},
renderSync: function(data) {
var localData = data || {};
var render = renderFunc || this._;
var globalData = localData.$global;
var out = createOut(globalData);
out.sync();
out.global.template = this;
if (globalData) {
localData.$global = undefined;
}
render(localData, out);
return out.$__getResult();
},
/**
* Renders a template to either a stream (if the last
* argument is a Stream instance) or
* provides the output to a callback function (if the last
* argument is a Function).
*
* Supported signatures:
*
* render(data)
* render(data, out)
* render(data, stream)
* render(data, callback)
*
* @param {Object} data The view model data for the template
* @param {AsyncStream/AsyncVDOMBuilder} out A Stream, an AsyncStream/AsyncVDOMBuilder instance, or a callback function
* @return {AsyncStream/AsyncVDOMBuilder} Returns the AsyncStream/AsyncVDOMBuilder instance that the template is rendered to
*/
render: function(data, out) {
var callback;
var finalOut;
var finalData;
var globalData;
var render = renderFunc || this._;
var shouldBuffer = this.$__shouldBuffer;
var shouldEnd = true;
if (data) {
finalData = data;
if ((globalData = data.$global)) {
finalData.$global = undefined;
}
} else {
finalData = {};
}
if (out && out.$__isOut) {
finalOut = out;
shouldEnd = false;
extend(out.global, globalData);
} else if (typeof out === 'function') {
finalOut = createOut(globalData);
callback = out;
} else {
finalOut = createOut(
globalData, // global
out, // writer(AsyncStream) or parentNode(AsyncVDOMBuilder)
null, // state
shouldBuffer // ignored by AsyncVDOMBuilder
);
}
if (callback) {
finalOut
.on('finish', function() {
callback(null, finalOut.$__getResult());
})
.once('error', callback);
}
globalData = finalOut.global;
globalData.template = globalData.template || this;
render(finalData, finalOut);
return shouldEnd ? finalOut.end() : finalOut;
}
});
};