UNPKG

3.78 kBJavaScriptView Raw
1var defaultCreateOut = require("./createOut");
2var setImmediate = require("./setImmediate");
3var extend = require("raptor-util/extend");
4
5function safeRender(renderFunc, finalData, finalOut, shouldEnd) {
6 try {
7 renderFunc(finalData, finalOut);
8
9 if (shouldEnd) {
10 finalOut.end();
11 }
12 } catch (err) {
13 var actualEnd = finalOut.end;
14 finalOut.end = function() {};
15
16 setImmediate(function() {
17 finalOut.end = actualEnd;
18 finalOut.error(err);
19 });
20 }
21 return finalOut;
22}
23
24module.exports = function(target, renderer) {
25 var renderFunc =
26 renderer && (renderer.renderer || renderer.render || renderer);
27 var createOut = target.createOut || renderer.createOut || defaultCreateOut;
28
29 return extend(target, {
30 createOut: createOut,
31
32 renderToString: function(data, callback) {
33 var localData = data || {};
34 var render = renderFunc || this._;
35 var globalData = localData.$global;
36 var out = createOut(globalData);
37
38 out.global.template = this;
39
40 if (globalData) {
41 localData.$global = undefined;
42 }
43
44 if (callback) {
45 out
46 .on("finish", function() {
47 callback(null, out.toString(), out);
48 })
49 .once("error", callback);
50
51 return safeRender(render, localData, out, true);
52 } else {
53 out.sync();
54 render(localData, out);
55 return out.toString();
56 }
57 },
58
59 renderSync: function(data) {
60 var localData = data || {};
61 var render = renderFunc || this._;
62 var globalData = localData.$global;
63 var out = createOut(globalData);
64 out.sync();
65
66 out.global.template = this;
67
68 if (globalData) {
69 localData.$global = undefined;
70 }
71
72 render(localData, out);
73 return out.___getResult();
74 },
75
76 /**
77 * Renders a template to either a stream (if the last
78 * argument is a Stream instance) or
79 * provides the output to a callback function (if the last
80 * argument is a Function).
81 *
82 * Supported signatures:
83 *
84 * render(data)
85 * render(data, out)
86 * render(data, stream)
87 * render(data, callback)
88 *
89 * @param {Object} data The view model data for the template
90 * @param {AsyncStream/AsyncVDOMBuilder} out A Stream, an AsyncStream/AsyncVDOMBuilder instance, or a callback function
91 * @return {AsyncStream/AsyncVDOMBuilder} Returns the AsyncStream/AsyncVDOMBuilder instance that the template is rendered to
92 */
93 render: function(data, out) {
94 var callback;
95 var finalOut;
96 var finalData;
97 var globalData;
98 var render = renderFunc || this._;
99 var shouldBuffer = this.___shouldBuffer;
100 var shouldEnd = true;
101
102 if (data) {
103 finalData = data;
104 if ((globalData = data.$global)) {
105 finalData.$global = undefined;
106 }
107 } else {
108 finalData = {};
109 }
110
111 if (out && out.___isOut) {
112 finalOut = out;
113 shouldEnd = false;
114 extend(out.global, globalData);
115 } else if (typeof out == "function") {
116 finalOut = createOut(globalData);
117 callback = out;
118 } else {
119 finalOut = createOut(
120 globalData, // global
121 out, // writer(AsyncStream) or parentNode(AsyncVDOMBuilder)
122 undefined, // parentOut
123 shouldBuffer // ignored by AsyncVDOMBuilder
124 );
125 }
126
127 if (callback) {
128 finalOut
129 .on("finish", function() {
130 callback(null, finalOut.___getResult(), finalOut);
131 })
132 .once("error", callback);
133 }
134
135 globalData = finalOut.global;
136
137 globalData.template = globalData.template || this;
138
139 return safeRender(render, finalData, finalOut, shouldEnd);
140 }
141 });
142};