UNPKG

14.6 kBJavaScriptView Raw
1var cache, coffee, coffeecup, coffeescript_helpers, compiler, elements, merge_elements, skeleton,
2 __slice = Array.prototype.slice,
3 __indexOf = Array.prototype.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 __hasProp = Object.prototype.hasOwnProperty,
5 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
6
7if (typeof window !== "undefined" && window !== null) {
8 coffeecup = window.coffeecup = {};
9 coffee = typeof CoffeeScript !== "undefined" && CoffeeScript !== null ? CoffeeScript : null;
10} else {
11 coffeecup = exports;
12 coffee = require('coffee-script');
13 compiler = require(__dirname + '/compiler');
14 compiler.setup(coffeecup);
15}
16
17coffeecup.version = '0.3.10';
18
19coffeecup.doctypes = {
20 'default': '<!DOCTYPE html>',
21 '5': '<!DOCTYPE html>',
22 'xml': '<?xml version="1.0" encoding="utf-8" ?>',
23 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
24 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
25 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
26 '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
27 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
28 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">',
29 'ce': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ce-html-1.0-transitional.dtd">'
30};
31
32coffeescript_helpers = "var __slice = Array.prototype.slice;\nvar __hasProp = Object.prototype.hasOwnProperty;\nvar __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\nvar __extends = function(child, parent) {\n for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }\n function ctor() { this.constructor = child; }\n ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype;\n return child; };\nvar __indexOf = Array.prototype.indexOf || function(item) {\n for (var i = 0, l = this.length; i < l; i++) {\n if (this[i] === item) return i;\n } return -1; };".replace(/\n/g, '');
33
34elements = {
35 regular: 'a abbr address article aside audio b bdi bdo blockquote body button\
36 canvas caption cite code colgroup datalist dd del details dfn div dl dt em\
37 fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup\
38 html i iframe ins kbd label legend li map mark menu meter nav noscript object\
39 ol optgroup option output p pre progress q rp rt ruby s samp script section\
40 select small span strong style sub summary sup table tbody td textarea tfoot\
41 th thead time title tr u ul video',
42 svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion\
43 animateTransform circle clipPath color-profile cursor defs desc ellipse\
44 feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix\
45 feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB\
46 feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology\
47 feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence\
48 filter font font-face font-face-format font-face-name font-face-src\
49 font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient\
50 marker mask metadata missing-glyph mpath path pattern polygon polyline\
51 radialGradient rect script set stop style svg symbol text textPath\
52 title tref tspan use view vkern',
53 "void": 'area base br col command embed hr img input keygen link meta param\
54 source track wbr',
55 obsolete: 'applet acronym bgsound dir frameset noframes isindex listing\
56 nextid noembed plaintext rb strike xmp big blink center font marquee multicol\
57 nobr spacer tt',
58 obsolete_void: 'basefont frame'
59};
60
61merge_elements = function() {
62 var a, args, element, result, _i, _j, _len, _len2, _ref;
63 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
64 result = [];
65 for (_i = 0, _len = args.length; _i < _len; _i++) {
66 a = args[_i];
67 _ref = elements[a].split(' ');
68 for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
69 element = _ref[_j];
70 if (__indexOf.call(result, element) < 0) result.push(element);
71 }
72 }
73 return result;
74};
75
76coffeecup.tags = merge_elements('regular', 'obsolete', 'void', 'obsolete_void', 'svg');
77
78coffeecup.self_closing = merge_elements('void', 'obsolete_void');
79
80skeleton = function(data) {
81 var coffeescript, comment, doctype, h, ie, stylus, tag, text, yield, __cc;
82 if (data == null) data = {};
83 if (data.format == null) data.format = false;
84 if (data.autoescape == null) data.autoescape = false;
85 __cc = {
86 buffer: [],
87 esc: function(txt) {
88 if (data.autoescape) {
89 return h(txt);
90 } else {
91 return txt.toString();
92 }
93 },
94 tabs: 0,
95 repeat: function(string, count) {
96 return Array(count + 1).join(string);
97 },
98 indent: function() {
99 if (data.format) return text(this.repeat(' ', this.tabs));
100 },
101 tag: function(name, args) {
102 var combo, i, _i, _len;
103 combo = [name];
104 for (_i = 0, _len = args.length; _i < _len; _i++) {
105 i = args[_i];
106 combo.push(i);
107 }
108 return tag.apply(data, combo);
109 },
110 render_idclass: function(str) {
111 var c, classes, i, id, _i, _j, _len, _len2, _ref;
112 classes = [];
113 _ref = str.split('.');
114 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
115 i = _ref[_i];
116 if (__indexOf.call(i, '#') >= 0) {
117 id = i.replace('#', '');
118 } else {
119 if (i !== '') classes.push(i);
120 }
121 }
122 if (id) text(" id=\"" + id + "\"");
123 if (classes.length > 0) {
124 text(" class=\"");
125 for (_j = 0, _len2 = classes.length; _j < _len2; _j++) {
126 c = classes[_j];
127 if (c !== classes[0]) text(' ');
128 text(c);
129 }
130 return text('"');
131 }
132 },
133 render_attrs: function(obj, prefix) {
134 var k, v, _results;
135 if (prefix == null) prefix = '';
136 _results = [];
137 for (k in obj) {
138 v = obj[k];
139 if (typeof v === 'boolean' && v) v = k;
140 if (typeof v === 'function') v = "(" + v + ").call(this);";
141 if (typeof v === 'object' && !(v instanceof Array)) {
142 _results.push(this.render_attrs(v, prefix + k + '-'));
143 } else if (v) {
144 _results.push(text(" " + (prefix + k) + "=\"" + (this.esc(v)) + "\""));
145 } else {
146 _results.push(void 0);
147 }
148 }
149 return _results;
150 },
151 render_contents: function(contents, safe) {
152 var result;
153 if (safe == null) safe = false;
154 switch (typeof contents) {
155 case 'string':
156 case 'number':
157 case 'boolean':
158 return text(safe ? contents : this.esc(contents));
159 case 'function':
160 if (data.format) text('\n');
161 this.tabs++;
162 result = contents.call(data);
163 if (typeof result === 'string') {
164 this.indent();
165 text(safe ? result : this.esc(result));
166 if (data.format) text('\n');
167 }
168 this.tabs--;
169 return this.indent();
170 }
171 },
172 render_tag: function(name, idclass, attrs, contents) {
173 this.indent();
174 text("<" + name);
175 if (idclass) this.render_idclass(idclass);
176 if (attrs) this.render_attrs(attrs);
177 if (__indexOf.call(this.self_closing, name) >= 0) {
178 text(' />');
179 if (data.format) text('\n');
180 } else {
181 text('>');
182 this.render_contents(contents);
183 text("</" + name + ">");
184 if (data.format) text('\n');
185 }
186 return null;
187 }
188 };
189 tag = function() {
190 var a, args, attrs, contents, idclass, name, _i, _len;
191 name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
192 for (_i = 0, _len = args.length; _i < _len; _i++) {
193 a = args[_i];
194 switch (typeof a) {
195 case 'function':
196 contents = a;
197 break;
198 case 'object':
199 attrs = a;
200 break;
201 case 'number':
202 case 'boolean':
203 contents = a;
204 break;
205 case 'string':
206 if (args.length === 1) {
207 contents = a;
208 } else {
209 if (a === args[0]) {
210 idclass = a;
211 } else {
212 contents = a;
213 }
214 }
215 }
216 }
217 return __cc.render_tag(name, idclass, attrs, contents);
218 };
219 yield = function(f) {
220 var old_buffer, temp_buffer;
221 temp_buffer = [];
222 old_buffer = __cc.buffer;
223 __cc.buffer = temp_buffer;
224 f();
225 __cc.buffer = old_buffer;
226 return temp_buffer.join('');
227 };
228 h = function(txt) {
229 return txt.toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
230 };
231 doctype = function(type) {
232 if (type == null) type = 'default';
233 text(__cc.doctypes[type]);
234 if (data.format) return text('\n');
235 };
236 text = function(txt) {
237 __cc.buffer.push(txt.toString());
238 return null;
239 };
240 comment = function(cmt) {
241 text("<!--" + cmt + "-->");
242 if (data.format) return text('\n');
243 };
244 coffeescript = function(param) {
245 switch (typeof param) {
246 case 'function':
247 return script("" + __cc.coffeescript_helpers + "(" + param + ").call(this);");
248 case 'string':
249 return script({
250 type: 'text/coffeescript'
251 }, function() {
252 return param;
253 });
254 case 'object':
255 param.type = 'text/coffeescript';
256 return script(param);
257 }
258 };
259 stylus = function(s) {
260 text('<style>');
261 if (data.format) text('\n');
262 data.stylus.render(s, {
263 compress: !data.format
264 }, function(err, css) {
265 if (err) throw err;
266 return text(css);
267 });
268 text('</style>');
269 if (data.format) return text('\n');
270 };
271 ie = function(condition, contents) {
272 __cc.indent();
273 text("<!--[if " + condition + "]>");
274 __cc.render_contents(contents);
275 text("<![endif]-->");
276 if (data.format) return text('\n');
277 };
278 return null;
279};
280
281skeleton = skeleton.toString().replace(/function\s*\(.*\)\s*\{/, '').replace(/return null;\s*\}$/, '');
282
283skeleton = coffeescript_helpers + skeleton;
284
285coffeecup.compile = function(template, options) {
286 var code, hardcoded_locals, k, t, tag_functions, tags_used, v, _i, _j, _len, _len2, _ref, _ref2;
287 if (options == null) options = {};
288 if (typeof template === 'function') {
289 template = template.toString();
290 } else if (typeof template === 'string' && (coffee != null)) {
291 template = coffee.compile(template, {
292 bare: true
293 });
294 template = "function(){" + template + "}";
295 }
296 hardcoded_locals = '';
297 if (options.hardcode) {
298 _ref = options.hardcode;
299 for (k in _ref) {
300 v = _ref[k];
301 if (typeof v === 'function') {
302 hardcoded_locals += "var " + k + " = function(){return (" + v + ").apply(data, arguments);};";
303 } else {
304 hardcoded_locals += "var " + k + " = " + (JSON.stringify(v)) + ";";
305 }
306 }
307 }
308 if (options.optimize && (compiler != null)) {
309 return compiler.compile(template, hardcoded_locals, options);
310 }
311 tag_functions = '';
312 tags_used = [];
313 _ref2 = coffeecup.tags;
314 for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
315 t = _ref2[_i];
316 if (template.indexOf(t) > -1 || hardcoded_locals.indexOf(t) > -1) {
317 tags_used.push(t);
318 }
319 }
320 tag_functions += "var " + (tags_used.join(',')) + ";";
321 for (_j = 0, _len2 = tags_used.length; _j < _len2; _j++) {
322 t = tags_used[_j];
323 tag_functions += "" + t + " = function(){return __cc.tag('" + t + "', arguments);};";
324 }
325 code = tag_functions + hardcoded_locals + skeleton;
326 code += "__cc.doctypes = " + (JSON.stringify(coffeecup.doctypes)) + ";";
327 code += "__cc.coffeescript_helpers = " + (JSON.stringify(coffeescript_helpers)) + ";";
328 code += "__cc.self_closing = " + (JSON.stringify(coffeecup.self_closing)) + ";";
329 if (options.locals) code += 'with(data.locals){';
330 code += "(" + template + ").call(data);";
331 if (options.locals) code += '}';
332 code += "return __cc.buffer.join('');";
333 return new Function('data', code);
334};
335
336cache = {};
337
338coffeecup.render = function(template, data, options) {
339 var k, tpl, v;
340 if (data == null) data = {};
341 if (options == null) options = {};
342 for (k in options) {
343 v = options[k];
344 data[k] = v;
345 }
346 if (data.cache == null) data.cache = false;
347 data.stylus = require('stylus');
348 if (data.optimize && !data.cache) data.optimize = false;
349 if (data.cache && (cache[template] != null)) {
350 tpl = cache[template];
351 } else if (data.cache) {
352 tpl = cache[template] = coffeecup.compile(template, data);
353 } else {
354 tpl = coffeecup.compile(template, data);
355 }
356 return tpl(data);
357};
358
359if (typeof window === "undefined" || window === null) {
360 coffeecup.adapters = {
361 simple: coffeecup.render,
362 meryl: coffeecup.render,
363 express: {
364 TemplateError: (function(_super) {
365
366 __extends(_Class, _super);
367
368 function _Class(message) {
369 this.message = message;
370 Error.call(this, this.message);
371 Error.captureStackTrace(this, arguments.callee);
372 }
373
374 _Class.prototype.name = 'TemplateError';
375
376 return _Class;
377
378 })(Error),
379 compile: function(template, data) {
380 var TemplateError, tpl;
381 if (data.hardcode == null) data.hardcode = {};
382 data.hardcode.partial = function() {
383 return text(this.partial.apply(this, arguments));
384 };
385 TemplateError = this.TemplateError;
386 try {
387 tpl = coffeecup.compile(template, data);
388 } catch (e) {
389 throw new TemplateError("Error compiling " + data.filename + ": " + e.message);
390 }
391 return function() {
392 try {
393 return tpl.apply(null, arguments);
394 } catch (e) {
395 throw new TemplateError("Error rendering " + data.filename + ": " + e.message);
396 }
397 };
398 }
399 }
400 };
401}