var marko = require('./index'); 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 || marko.createOut; return extend(target, { createOut: createOut, renderToString: function(data, callback) { var localData = data || {}; var render = renderFunc || this._; var out = createOut(localData.$global); 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 out = createOut(localData.$global); out.sync(); 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 = null; } } else { finalData = {}; } if (out && out.isAsyncOut){ 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); } finalOut.global.template = finalOut.global.template || this; render(finalData, finalOut); return shouldEnd ? finalOut.end() : finalOut; } }); };