UNPKG

11.8 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.3.3
2var Code, call_bound_func, coffee, coffeecup, parser, skeleton, uglify, _ref,
3 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4
5coffee = require('coffee-script');
6
7_ref = require('uglify-js'), uglify = _ref.uglify, parser = _ref.parser;
8
9coffeecup = null;
10
11exports.setup = function(cc) {
12 return coffeecup = cc;
13};
14
15skeleton = 'var __cc = {\n buffer: \'\'\n};\nvar text = function(txt) {\n if (typeof txt === \'string\' || txt instanceof String) {\n __cc.buffer += txt;\n } else if (typeof txt === \'number\' || txt instanceof Number) {\n __cc.buffer += txt.toString();\n }\n};\nvar h = function(txt) {\n var escaped;\n if (typeof txt === \'string\' || txt instanceof String) {\n escaped = txt.replace(/&/g, \'&amp;\')\n .replace(/</g, \'&lt;\')\n .replace(/>/g, \'&gt;\')\n .replace(/"/g, \'&quot;\');\n } else {\n escaped = txt;\n }\n return escaped;\n};\nvar cede = function(f) {\n var temp_buffer = \'\';\n var old_buffer = __cc.buffer;\n __cc.buffer = temp_buffer;\n f();\n temp_buffer = __cc.buffer;\n __cc.buffer = old_buffer;\n return temp_buffer;\n};\n';
16
17call_bound_func = function(func) {
18 return ['call', ['dot', func, 'call'], [['name', 'data']]];
19};
20
21Code = (function() {
22
23 function Code(parent) {
24 this.parent = parent;
25 this.nodes = [];
26 this.line = '';
27 }
28
29 Code.prototype.call = function(arg) {
30 return ['stat', ['call', ['name', 'text'], [arg]]];
31 };
32
33 Code.prototype.append = function(str) {
34 if (this.block != null) {
35 return this.block.append(str);
36 } else {
37 return this.line += str;
38 }
39 };
40
41 Code.prototype.flush = function() {
42 if (this.block != null) {
43 return this.block.flush();
44 } else {
45 this.merge_text(['string', this.line]);
46 return this.line = '';
47 }
48 };
49
50 Code.prototype.open_if = function(condition) {
51 this.flush();
52 if (this.block != null) {
53 return this.block.open_if(condition);
54 } else {
55 this.block = new Code();
56 return this.block.condition = condition;
57 }
58 };
59
60 Code.prototype.close_if = function() {
61 this.flush();
62 if (this.block.block != null) {
63 return this.block.close_if();
64 } else {
65 this.nodes.push(['if', this.block.condition, ['block', this.block.nodes]]);
66 return delete this.block;
67 }
68 };
69
70 Code.prototype.push = function(node) {
71 this.flush();
72 if (this.block != null) {
73 return this.block.push(node);
74 } else {
75 return this.merge_text(node);
76 }
77 };
78
79 Code.prototype.merge_text = function(arg) {
80 var l, ok, oldArg, prev, _ref1, _ref2;
81 if (arg[0] === 'binary' && arg[1] === '+') {
82 this.merge_text(arg[2]);
83 arg = arg[3];
84 }
85 if (l = this.nodes.length) {
86 prev = this.nodes[l - 1];
87 if (prev[0] === 'stat' && prev[1][0] === 'call' && prev[1][1][0] === 'name' && prev[1][1][1] === 'text') {
88 oldArg = prev[1][2][0];
89 ok = ['string', 'num'];
90 if ((_ref1 = oldArg[0], __indexOf.call(ok, _ref1) >= 0) && (_ref2 = arg[0], __indexOf.call(ok, _ref2) >= 0)) {
91 prev[1][2][0] = ['string', oldArg[1] + arg[1]];
92 return;
93 }
94 }
95 }
96 return this.nodes.push(this.call(arg));
97 };
98
99 Code.prototype.get_nodes = function() {
100 this.flush();
101 if (this.parent[0] === 'stat') {
102 return ['splice', this.nodes];
103 }
104 return call_bound_func(['function', null, [], this.nodes]);
105 };
106
107 return Code;
108
109})();
110
111exports.compile = function(source, hardcoded_locals, options) {
112 var ast, code, compiled, escape, w;
113 escape = function(node) {
114 if (options.autoescape) {
115 return ['call', ['name', 'h'], [node]];
116 }
117 return node;
118 };
119 ast = parser.parse(hardcoded_locals + ("(" + source + ").call(data);"));
120 w = uglify.ast_walker();
121 ast = w.with_walkers({
122 call: function(expr, args) {
123 var arg, classes, code, comment, condition, contents, doctype, escape_all, func, i, id, idx, name, node, render_attrs, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3;
124 name = expr[1];
125 if (name === 'doctype') {
126 code = new Code(w.parent());
127 if (args.length > 0) {
128 doctype = args[0][1].toString();
129 if (doctype in coffeecup.doctypes) {
130 code.append(coffeecup.doctypes[doctype]);
131 } else {
132 throw new Error('Invalid doctype');
133 }
134 } else {
135 code.append(coffeecup.doctypes["default"]);
136 }
137 return code.get_nodes();
138 } else if (name === 'comment') {
139 comment = args[0];
140 code = new Code(w.parent());
141 if (comment[0] === 'string') {
142 code.append("<!--" + comment[1] + "-->");
143 } else {
144 code.append('<!--');
145 code.push(escape(comment));
146 code.append('-->');
147 }
148 return code.get_nodes();
149 } else if (name === 'ie') {
150 condition = args[0], contents = args[1];
151 code = new Code(w.parent());
152 if (condition[0] === 'string') {
153 code.append("<!--[if " + condition[1] + "]>");
154 } else {
155 code.append('<!--[if ');
156 code.push(escape(condition));
157 code.append(']>');
158 }
159 code.push(call_bound_func(w.walk(contents)));
160 code.append('<![endif]-->');
161 return code.get_nodes();
162 } else if (__indexOf.call(coffeecup.tags, name) >= 0 || (name === 'tag' || name === 'coffeescript')) {
163 if (name === 'tag') {
164 name = args.shift()[1];
165 }
166 if (name === 'coffeescript') {
167 name = 'script';
168 for (_i = 0, _len = args.length; _i < _len; _i++) {
169 arg = args[_i];
170 if ((_ref1 = arg[0]) !== 'string' && _ref1 !== 'object' && _ref1 !== 'function') {
171 throw new Error('Invalid argument to coffeescript function');
172 }
173 if (arg[0] === 'string' && (args.length === 1 || arg !== args[0])) {
174 arg[1] = coffee.compile(arg[1], {
175 bare: true
176 });
177 }
178 }
179 }
180 code = new Code(w.parent());
181 code.append("<" + name);
182 for (_j = 0, _len1 = args.length; _j < _len1; _j++) {
183 arg = args[_j];
184 switch (arg[0]) {
185 case 'function':
186 if (name === 'script') {
187 func = uglify.gen_code(arg, {
188 beautify: true,
189 indent_level: 2
190 });
191 contents = ['string', "" + func + ".call(this);"];
192 } else {
193 func = w.walk(arg);
194 _ref2 = func[3];
195 for (idx = _k = 0, _len2 = _ref2.length; _k < _len2; idx = ++_k) {
196 node = _ref2[idx];
197 if (node[0] === 'return' && (node[1] != null) && node[1][0] !== 'string') {
198 func[3][idx][1] = escape(node[1]);
199 }
200 }
201 contents = call_bound_func(func);
202 }
203 break;
204 case 'object':
205 render_attrs = function(obj, prefix) {
206 var attr, key, value, varname, _l, _len3, _ref3, _ref4, _results;
207 if (prefix == null) {
208 prefix = '';
209 }
210 _results = [];
211 for (_l = 0, _len3 = obj.length; _l < _len3; _l++) {
212 attr = obj[_l];
213 key = attr[0];
214 value = attr[1];
215 if (value[0] === 'name' && value[1] === 'true') {
216 _results.push(code.append(" " + key + "=\"" + key + "\""));
217 } else if (value[0] === 'name' && ((_ref3 = value[1]) === 'undefined' || _ref3 === 'null' || _ref3 === 'false')) {
218 continue;
219 } else if ((_ref4 = value[0]) === 'name' || _ref4 === 'dot') {
220 varname = uglify.gen_code(value);
221 condition = "typeof " + varname + " !== 'undefined' && " + varname + " !== null && " + varname + " !== false";
222 code.open_if(parser.parse(condition)[1][0][1]);
223 code.append(" " + (prefix + key) + "=\"");
224 code.push(escape(value));
225 code.append('"');
226 _results.push(code.close_if());
227 } else if (value[0] === 'string') {
228 _results.push(code.append(" " + (prefix + key) + "=\"" + value[1] + "\""));
229 } else if (value[0] === 'function') {
230 func = uglify.gen_code(value).replace(/"/g, '&quot;');
231 _results.push(code.append(" " + (prefix + key) + "=\"" + func + ".call(this);\""));
232 } else if (value[0] === 'object') {
233 _results.push(render_attrs(value[1], prefix + key + '-'));
234 } else {
235 code.append(" " + (prefix + key) + "=\"");
236 code.push(escape(value));
237 _results.push(code.append('"'));
238 }
239 }
240 return _results;
241 };
242 render_attrs(arg[1]);
243 break;
244 case 'string':
245 if (args.length > 1 && arg === args[0]) {
246 classes = [];
247 _ref3 = arg[1].split('.');
248 for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
249 i = _ref3[_l];
250 if (__indexOf.call(i, '#') >= 0) {
251 id = i.replace('#', '');
252 } else {
253 if (i !== '') {
254 classes.push(i);
255 }
256 }
257 }
258 if (id) {
259 code.append(" id=\"" + id + "\"");
260 }
261 if (classes.length > 0) {
262 code.append(" class=\"" + (classes.join(' ')) + "\"");
263 }
264 } else {
265 arg[1] = arg[1].replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
266 contents = arg;
267 }
268 break;
269 case 'binary':
270 escape_all = function(node) {
271 switch (node[0]) {
272 case 'binary':
273 node[2] = escape_all(node[2]);
274 node[3] = escape_all(node[3]);
275 return node;
276 case 'string':
277 return node;
278 case 'call':
279 if (node[1][0] === 'name' && node[1][1] === 'cede') {
280 return node;
281 }
282 return escape(node);
283 default:
284 return escape(node);
285 }
286 };
287 contents = escape_all(w.walk(arg));
288 break;
289 default:
290 contents = escape(w.walk(arg));
291 }
292 }
293 if (__indexOf.call(coffeecup.self_closing, name) >= 0) {
294 code.append(' />');
295 } else {
296 code.append('>');
297 }
298 if (contents != null) {
299 code.push(contents);
300 }
301 if (!(__indexOf.call(coffeecup.self_closing, name) >= 0)) {
302 code.append("</" + name + ">");
303 }
304 return code.get_nodes();
305 }
306 return null;
307 }
308 }, function() {
309 return w.walk(ast);
310 });
311 compiled = uglify.gen_code(ast, {
312 beautify: true,
313 indent_level: 2
314 });
315 if (options.locals) {
316 compiled = "with(data.locals){" + compiled + "}";
317 }
318 code = skeleton + compiled + "return __cc.buffer;";
319 return new Function('data', code);
320};