1 | var Ctx = {
|
2 | anon: {}
|
3 | };
|
4 |
|
5 | Ctx.sync = function(cb) {
|
6 | var jobs = 0;
|
7 | this.await = function() {jobs++;};
|
8 | this.signal = function() {if (--jobs == 0) cb();}
|
9 | };
|
10 |
|
11 | Ctx.res = function(dataProvider, sync) {
|
12 | this.sync = sync;
|
13 | this.dataProvider = dataProvider;
|
14 | this.buffer = [];
|
15 | this.getBlock = Ctx.getBlock;
|
16 | this.init = Ctx.init;
|
17 | this._render = Ctx._render;
|
18 |
|
19 | this.write = function(str) {
|
20 | this.buffer.push(str);
|
21 | };
|
22 | this.fork = function() {
|
23 | var r = new Ctx.res(this.dataProvider, this.sync);
|
24 | this.buffer.push(r);
|
25 | return r;
|
26 | };
|
27 |
|
28 | this._body = function() {
|
29 | var idx = 0;
|
30 | var body = "";
|
31 | while (idx < this.buffer.length) {
|
32 | var b = this.buffer[idx++];
|
33 | if (typeof b !== "undefined" && b._body) {
|
34 | body += b._body();
|
35 | } else {
|
36 | body += b;
|
37 | }
|
38 | }
|
39 | return body;
|
40 | };
|
41 | };
|
42 | Ctx.getBlock = function(name) {
|
43 | var ref = Ctx.schema[name];
|
44 | if (!ref) throw new Error("Could not find block: " + name);
|
45 | if (!ref.class) {
|
46 | ref = Ctx.init(null, ref);
|
47 | }
|
48 | return ref;
|
49 | };
|
50 | Ctx.init = function(seq, block) {
|
51 | var a;
|
52 | if (seq) {
|
53 | a = Ctx.anon[seq];
|
54 | }
|
55 | if (!a) {
|
56 | a = function() {};
|
57 | if (block.parent) {
|
58 | a.prototype = Object.create(Ctx.getBlock(block.parent).class.prototype);
|
59 | }
|
60 | }
|
61 | a.handler = block.handler;
|
62 | for (var f in block)
|
63 | if (typeof block[f] === "function") {
|
64 | a.prototype[f] = block[f];
|
65 | }
|
66 |
|
67 | var a1 = new a();
|
68 | a1.class = a;
|
69 | if (seq) Ctx.anon[seq] = a;
|
70 | return a1;
|
71 | };
|
72 | Ctx._render = function(bl, attrs, res) {
|
73 | this.sync.await();
|
74 | if(bl.class.handler && res.dataProvider) {
|
75 | var h = res.dataProvider.get(bl.class.handler);
|
76 | if (!h) {
|
77 | throw new Error("Could not find data provider " + bl.handler);
|
78 | }
|
79 | res = res.fork();
|
80 | var selfSync = this.sync;
|
81 | h(attrs, function(err, data) {
|
82 | if (err) throw err;
|
83 | bl.body(data, res);
|
84 | selfSync.signal();
|
85 | });
|
86 | } else {
|
87 | bl.body(attrs, res);
|
88 | this.sync.signal();
|
89 | }
|
90 | };
|
91 | Ctx.render = function(name, data, provider, cb) {
|
92 | name = name.replace(/\\/g, "/");
|
93 | var res = new Ctx.res(provider, new Ctx.sync(function() {
|
94 | cb(null, res._body());
|
95 | }));
|
96 | try {
|
97 | res._render(res.getBlock(name), data, res);
|
98 | } catch(e) {
|
99 | cb(e, null);
|
100 | }
|
101 | };
|
102 |
|
103 | if (typeof module !== 'undefined') {module.exports = Ctx;}
|
104 | Ctx.schema = { "anon:A":{ body:function (attrs, res) {res.write((attrs.x));
|
105 | } },
|
106 | "anon:B":{ body:function (attrs, res) {res._render(res.getBlock('anon:A'),{x:(attrs.x),}, res);
|
107 | } },
|
108 | "anon/cascade-named:A":{ def_1:function (attrs, res) {},
|
109 | body:function (attrs, res) {res.write('a');
|
110 | this.def_1(attrs, res);
|
111 | res.write('a');
|
112 | } },
|
113 | "anon/cascade-named:B":{ body:function (attrs, res) {res.write('b');
|
114 | var self = this;
|
115 | res._render(res.init(0, {parent: 'anon/cascade-named:A',def: function(_a, res) {self.def_1(attrs, res);
|
116 | },def_1: function(_a, res) {self.def_1(null, res)},}),{}, res);
|
117 | res.write('b');
|
118 | } },
|
119 | "anon/cascade-named:C":{ body:function (attrs, res) {res.write('c');
|
120 | var self = this;
|
121 | res._render(res.init(1, {parent: 'anon/cascade-named:B',def: function(_a, res) {self.def_1(attrs, res);
|
122 | },def_1: function(_a, res) {self.def_1(null, res)},}),{}, res);
|
123 | res.write('c');
|
124 | } },
|
125 | "anon/cascade-named:D":{ body:function (attrs, res) {res.write('d');
|
126 | this.class.prototype.def_1=function(_a, res) {res.write('hello');
|
127 | };
|
128 | var self = this;
|
129 | res._render(res.init(2, {parent: 'anon/cascade-named:C',def: function(_a, res) {self.def_1(attrs, res);
|
130 | },def_1: function(_a, res) {self.def_1(null, res)},}),{}, res);
|
131 | res.write('d');
|
132 | } },
|
133 | "anon/cascade:A":{ def:function (attrs, res) {},
|
134 | body:function (attrs, res) {res.write('a');
|
135 | this.def(attrs, res);
|
136 | res.write('a');
|
137 | } },
|
138 | "anon/cascade:B":{ body:function (attrs, res) {res.write('b');
|
139 | var self = this;
|
140 | res._render(res.init(0, {parent: 'anon/cascade:A',def: function(_a, res) {self.def(attrs, res);
|
141 | },def: function(_a, res) {self.def(null, res)},}),{}, res);
|
142 | res.write('b');
|
143 | } },
|
144 | "anon/cascade:C":{ body:function (attrs, res) {res.write('c');
|
145 | var self = this;
|
146 | res._render(res.init(1, {parent: 'anon/cascade:B',def: function(_a, res) {self.def(attrs, res);
|
147 | },def: function(_a, res) {self.def(null, res)},}),{}, res);
|
148 | res.write('c');
|
149 | } },
|
150 | "anon/cascade:D":{ body:function (attrs, res) {res.write('d');
|
151 | var self = this;
|
152 | res._render(res.init(2, {parent: 'anon/cascade:C',def: function(_a, res) {res.write('hello');
|
153 | },}),{}, res);
|
154 | res.write('d');
|
155 | } },
|
156 | "anon/new-def:A":{ def_a:function (attrs, res) {},
|
157 | body:function (attrs, res) {res.write('a');
|
158 | this.def_a(attrs, res);
|
159 | res.write('a');
|
160 | } },
|
161 | "anon/new-def:B":{ def_b:function (attrs, res) {},
|
162 | body:function (attrs, res) {res.write('b');
|
163 | this.def_b(attrs, res);
|
164 | res.write('b');
|
165 | } },
|
166 | "anon/new-def:C":{ parent:"anon/new-def:A",
|
167 | def_a:function (attrs, res) {this.class.prototype.def_b=function(_a, res) {self.def_c(attrs, res);
|
168 | };
|
169 | var self = this;
|
170 | res._render(res.init(0, {parent: 'anon/new-def:B',def: function(_a, res) {self.def_b(attrs, res);
|
171 | },def_b: function(_a, res) {self.def_b(null, res)},}),{}, res);
|
172 | } },
|
173 | "anon/new-def:D":{ parent:"anon/new-def:C",
|
174 | def_c:function (attrs, res) {res.write('d');
|
175 | } },
|
176 | "handler/cascade:A":{ handler:"a",
|
177 | body:function (attrs, res) {res.write((attrs.x));
|
178 | } },
|
179 | "handler/cascade:B":{ handler:"b",
|
180 | body:function (attrs, res) {res.write((attrs.z));
|
181 | res._render(res.getBlock('handler/cascade:A'),{y1:'f',}, res);
|
182 | } },
|
183 | "handler/simple:A":{ handler:"a",
|
184 | body:function (attrs, res) {res.write((attrs.x));
|
185 | } },
|
186 | "inheritance/cascade:A":{ def_a:function (attrs, res) {},
|
187 | body:function (attrs, res) {res.write('a1');
|
188 | this.def_a(attrs, res);
|
189 | res.write('a2');
|
190 | } },
|
191 | "inheritance/cascade:B":{ parent:"inheritance/cascade:A",
|
192 | def_a:function (attrs, res) {res.write('b1');
|
193 | this.def_b(attrs, res);
|
194 | res.write('b2');
|
195 | } },
|
196 | "inheritance/cascade:C":{ parent:"inheritance/cascade:B",
|
197 | def_b:function (attrs, res) {res.write('b in C');
|
198 | } },
|
199 | "inheritance/default-defs:A":{ def_a:function (attrs, res) {res.write('a definition');
|
200 | },
|
201 | body:function (attrs, res) {this.def_a(attrs, res);
|
202 | } },
|
203 | "inheritance/default-defs:B":{ parent:"inheritance/default-defs:A" },
|
204 | "inheritance/default-defs:C":{ parent:"inheritance/default-defs:B" },
|
205 | "inheritance/multi:A":{ def:function (attrs, res) {},
|
206 | body:function (attrs, res) {this.def(attrs, res);
|
207 | } },
|
208 | "inheritance/multi:B":{ parent:"inheritance/multi:A",
|
209 | def:function (attrs, res) {res.write('hello from B');
|
210 | } },
|
211 | "inheritance/multi:C":{ parent:"inheritance/multi:B",
|
212 | def:function (attrs, res) {res.write('hello from C');
|
213 | } },
|
214 | "inheritance/named-defs:A":{ def_a:function (attrs, res) {},
|
215 | def_b:function (attrs, res) {},
|
216 | body:function (attrs, res) {this.def_a(attrs, res);
|
217 | this.def_b(attrs, res);
|
218 | } },
|
219 | "inheritance/named-defs:B":{ parent:"inheritance/named-defs:A",
|
220 | def_a:function (attrs, res) {res.write('a in B');
|
221 | },
|
222 | def_b:function (attrs, res) {res.write('b in B');
|
223 | } },
|
224 | "inheritance/named-defs:C":{ parent:"inheritance/named-defs:B",
|
225 | def_a:function (attrs, res) {res.write('a in C');
|
226 | },
|
227 | def_b:function (attrs, res) {res.write('b in C');
|
228 | } },
|
229 | "inheritance/simple:A":{ def:function (attrs, res) {},
|
230 | body:function (attrs, res) {this.def(attrs, res);
|
231 | } },
|
232 | "inheritance/simple:B":{ parent:"inheritance/simple:A",
|
233 | def:function (attrs, res) {res.write('hello');
|
234 | } },
|
235 | "var/for:A":{ def:function (attrs, res) {},
|
236 | body:function (attrs, res) {this.def(attrs, res);
|
237 | } },
|
238 | "var/for:B":{ body:function (attrs, res) {var self = this;
|
239 | res._render(res.init(0, {parent: 'var/for:A',def: function(_a, res) {res.write((attrs.x));
|
240 | },}),{}, res);
|
241 | } },
|
242 | "var/for:C":{ body:function (attrs, res) {res._render(res.getBlock('var/for:B'),{x:'1',}, res);
|
243 | res._render(res.getBlock('var/for:B'),{x:'2',}, res);
|
244 | res._render(res.getBlock('var/for:B'),{x:'3',}, res);
|
245 | } },
|
246 | "var:var":{ body:function (attrs, res) {res.write((attrs.x));
|
247 | } },
|
248 | "var:parent_test":{ parent:"var:var" },
|
249 | "var:_anon_def_test":{ def:function (attrs, res) {},
|
250 | body:function (attrs, res) {this.def(attrs, res);
|
251 | } },
|
252 | "var:anon_def_test":{ parent:"var:_anon_def_test",
|
253 | def:function (attrs, res) {res.write((attrs.x));
|
254 | } },
|
255 | "var:_call_parent":{ def:function (attrs, res) {res.write('parent');
|
256 | },
|
257 | body:function (attrs, res) {this.def(attrs, res);
|
258 | } },
|
259 | "var:call_parent":{ parent:"var:_call_parent",
|
260 | def:function (attrs, res) {res.getBlock('var:_call_parent')['def'](attrs, res);
|
261 | } },
|
262 | "var:__context_":{ def:function (attrs, res) {},
|
263 | body:function (attrs, res) {res.write('0-open '+(attrs.x));
|
264 | this.def(attrs, res);
|
265 | res.write('0-close '+(attrs.x));
|
266 | } },
|
267 | "var:_context":{ def:function (attrs, res) {},
|
268 | body:function (attrs, res) {res.write('1-open '+(attrs.x));
|
269 | this.def(attrs, res);
|
270 | res.write('1-close '+(attrs.x));
|
271 | } },
|
272 | "var:_context_":{ parent:"var:__context_",
|
273 | def:function (attrs, res) {var self = this;
|
274 | res._render(res.init(0, {parent: 'var:_context',def: function(_a, res) {res.write('2-open '+(attrs.x));
|
275 | self.def_1(attrs, res);
|
276 | res.write('2-close '+(attrs.x));
|
277 | },def_1: function(_a, res) {self.def_1(null, res)},}),{}, res);
|
278 | } },
|
279 | "var:context":{ parent:"var:_context_",
|
280 | def_1:function (attrs, res) {res.write('in '+(attrs.x));
|
281 | } } } |
\ | No newline at end of file |