1 |
|
2 |
|
3 | (function() {
|
4 | var modules = {};
|
5 | (function() {
|
6 |
|
7 |
|
8 |
|
9 | function extend(cls, name, props) {
|
10 |
|
11 | var F = function() {};
|
12 | F.prototype = cls.prototype;
|
13 | var prototype = new F();
|
14 |
|
15 | var fnTest = /xyz/.test(function(){ xyz; }) ? /\bparent\b/ : /.*/;
|
16 | props = props || {};
|
17 |
|
18 | for(var k in props) {
|
19 | var src = props[k];
|
20 | var parent = prototype[k];
|
21 |
|
22 | if(typeof parent == "function" &&
|
23 | typeof src == "function" &&
|
24 | fnTest.test(src)) {
|
25 | prototype[k] = (function (src, parent) {
|
26 | return function() {
|
27 |
|
28 | var tmp = this.parent;
|
29 |
|
30 |
|
31 | this.parent = parent;
|
32 | var res = src.apply(this, arguments);
|
33 | this.parent = tmp;
|
34 |
|
35 | return res;
|
36 | };
|
37 | })(src, parent);
|
38 | }
|
39 | else {
|
40 | prototype[k] = src;
|
41 | }
|
42 | }
|
43 |
|
44 | prototype.typename = name;
|
45 |
|
46 | var new_cls = function() {
|
47 | if(prototype.init) {
|
48 | prototype.init.apply(this, arguments);
|
49 | }
|
50 | };
|
51 |
|
52 | new_cls.prototype = prototype;
|
53 | new_cls.prototype.constructor = new_cls;
|
54 |
|
55 | new_cls.extend = function(name, props) {
|
56 | if(typeof name == "object") {
|
57 | props = name;
|
58 | name = "anonymous";
|
59 | }
|
60 | return extend(new_cls, name, props);
|
61 | };
|
62 |
|
63 | return new_cls;
|
64 | }
|
65 |
|
66 | modules['object'] = extend(Object, "Object", {});
|
67 | })();
|
68 | (function() {
|
69 | var ArrayProto = Array.prototype;
|
70 | var ObjProto = Object.prototype;
|
71 |
|
72 | var escapeMap = {
|
73 | '&': '&',
|
74 | '"': '"',
|
75 | "'": ''',
|
76 | "<": '<',
|
77 | ">": '>'
|
78 | };
|
79 |
|
80 | var escapeRegex = /[&"'<>]/g;
|
81 |
|
82 | var lookupEscape = function(ch) {
|
83 | return escapeMap[ch];
|
84 | };
|
85 |
|
86 | var exports = modules['lib'] = {};
|
87 |
|
88 | exports.withPrettyErrors = function(path, withInternals, func) {
|
89 | try {
|
90 | return func();
|
91 | } catch (e) {
|
92 | if (!e.Update) {
|
93 |
|
94 | e = new exports.TemplateError(e);
|
95 | }
|
96 | e.Update(path);
|
97 |
|
98 |
|
99 | if (!withInternals) {
|
100 | var old = e;
|
101 | e = new Error(old.message);
|
102 | e.name = old.name;
|
103 | }
|
104 |
|
105 | throw e;
|
106 | }
|
107 | };
|
108 |
|
109 | exports.TemplateError = function(message, lineno, colno) {
|
110 | var err = this;
|
111 |
|
112 | if (message instanceof Error) {
|
113 | err = message;
|
114 | message = message.name + ": " + message.message;
|
115 | } else {
|
116 | if(Error.captureStackTrace) {
|
117 | Error.captureStackTrace(err);
|
118 | }
|
119 | }
|
120 |
|
121 | err.name = 'Template render error';
|
122 | err.message = message;
|
123 | err.lineno = lineno;
|
124 | err.colno = colno;
|
125 | err.firstUpdate = true;
|
126 |
|
127 | err.Update = function(path) {
|
128 | var message = "(" + (path || "unknown path") + ")";
|
129 |
|
130 |
|
131 |
|
132 | if (this.firstUpdate) {
|
133 | if(this.lineno && this.colno) {
|
134 | message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']';
|
135 | }
|
136 | else if(this.lineno) {
|
137 | message += ' [Line ' + this.lineno + ']';
|
138 | }
|
139 | }
|
140 |
|
141 | message += '\n ';
|
142 | if (this.firstUpdate) {
|
143 | message += ' ';
|
144 | }
|
145 |
|
146 | this.message = message + (this.message || '');
|
147 | this.firstUpdate = false;
|
148 | return this;
|
149 | };
|
150 |
|
151 | return err;
|
152 | };
|
153 |
|
154 | exports.TemplateError.prototype = Error.prototype;
|
155 |
|
156 | exports.escape = function(val) {
|
157 | return val.replace(escapeRegex, lookupEscape);
|
158 | };
|
159 |
|
160 | exports.isFunction = function(obj) {
|
161 | return ObjProto.toString.call(obj) == '[object Function]';
|
162 | };
|
163 |
|
164 | exports.isArray = Array.isArray || function(obj) {
|
165 | return ObjProto.toString.call(obj) == '[object Array]';
|
166 | };
|
167 |
|
168 | exports.isString = function(obj) {
|
169 | return ObjProto.toString.call(obj) == '[object String]';
|
170 | };
|
171 |
|
172 | exports.isObject = function(obj) {
|
173 | return ObjProto.toString.call(obj) == '[object Object]';
|
174 | };
|
175 |
|
176 | exports.groupBy = function(obj, val) {
|
177 | var result = {};
|
178 | var iterator = exports.isFunction(val) ? val : function(obj) { return obj[val]; };
|
179 | for(var i=0; i<obj.length; i++) {
|
180 | var value = obj[i];
|
181 | var key = iterator(value, i);
|
182 | (result[key] || (result[key] = [])).push(value);
|
183 | }
|
184 | return result;
|
185 | };
|
186 |
|
187 | exports.toArray = function(obj) {
|
188 | return Array.prototype.slice.call(obj);
|
189 | };
|
190 |
|
191 | exports.without = function(array) {
|
192 | var result = [];
|
193 | if (!array) {
|
194 | return result;
|
195 | }
|
196 | var index = -1,
|
197 | length = array.length,
|
198 | contains = exports.toArray(arguments).slice(1);
|
199 |
|
200 | while(++index < length) {
|
201 | if(contains.indexOf(array[index]) === -1) {
|
202 | result.push(array[index]);
|
203 | }
|
204 | }
|
205 | return result;
|
206 | };
|
207 |
|
208 | exports.extend = function(obj, obj2) {
|
209 | for(var k in obj2) {
|
210 | obj[k] = obj2[k];
|
211 | }
|
212 | return obj;
|
213 | };
|
214 |
|
215 | exports.repeat = function(char_, n) {
|
216 | var str = '';
|
217 | for(var i=0; i<n; i++) {
|
218 | str += char_;
|
219 | }
|
220 | return str;
|
221 | };
|
222 |
|
223 | exports.each = function(obj, func, context) {
|
224 | if(obj == null) {
|
225 | return;
|
226 | }
|
227 |
|
228 | if(ArrayProto.each && obj.each == ArrayProto.each) {
|
229 | obj.forEach(func, context);
|
230 | }
|
231 | else if(obj.length === +obj.length) {
|
232 | for(var i=0, l=obj.length; i<l; i++) {
|
233 | func.call(context, obj[i], i, obj);
|
234 | }
|
235 | }
|
236 | };
|
237 |
|
238 | exports.map = function(obj, func) {
|
239 | var results = [];
|
240 | if(obj == null) {
|
241 | return results;
|
242 | }
|
243 |
|
244 | if(ArrayProto.map && obj.map === ArrayProto.map) {
|
245 | return obj.map(func);
|
246 | }
|
247 |
|
248 | for(var i=0; i<obj.length; i++) {
|
249 | results[results.length] = func(obj[i], i);
|
250 | }
|
251 |
|
252 | if(obj.length === +obj.length) {
|
253 | results.length = obj.length;
|
254 | }
|
255 |
|
256 | return results;
|
257 | };
|
258 |
|
259 | exports.asyncIter = function(arr, iter, cb) {
|
260 | var i = -1;
|
261 |
|
262 | function next() {
|
263 | i++;
|
264 |
|
265 | if(i < arr.length) {
|
266 | iter(arr[i], i, next, cb);
|
267 | }
|
268 | else {
|
269 | cb();
|
270 | }
|
271 | }
|
272 |
|
273 | next();
|
274 | };
|
275 |
|
276 | exports.asyncFor = function(obj, iter, cb) {
|
277 | var keys = exports.keys(obj);
|
278 | var len = keys.length;
|
279 | var i = -1;
|
280 |
|
281 | function next() {
|
282 | i++;
|
283 | var k = keys[i];
|
284 |
|
285 | if(i < len) {
|
286 | iter(k, obj[k], i, len, next);
|
287 | }
|
288 | else {
|
289 | cb();
|
290 | }
|
291 | }
|
292 |
|
293 | next();
|
294 | };
|
295 |
|
296 | if(!Array.prototype.indexOf) {
|
297 | Array.prototype.indexOf = function(array, searchElement /*, fromIndex */) {
|
298 | if (array == null) {
|
299 | throw new TypeError();
|
300 | }
|
301 | var t = Object(array);
|
302 | var len = t.length >>> 0;
|
303 | if (len === 0) {
|
304 | return -1;
|
305 | }
|
306 | var n = 0;
|
307 | if (arguments.length > 2) {
|
308 | n = Number(arguments[2]);
|
309 | if (n != n) {
|
310 | n = 0;
|
311 | } else if (n != 0 && n != Infinity && n != -Infinity) {
|
312 | n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
313 | }
|
314 | }
|
315 | if (n >= len) {
|
316 | return -1;
|
317 | }
|
318 | var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
319 | for (; k < len; k++) {
|
320 | if (k in t && t[k] === searchElement) {
|
321 | return k;
|
322 | }
|
323 | }
|
324 | return -1;
|
325 | };
|
326 | }
|
327 |
|
328 | if(!Array.prototype.map) {
|
329 | Array.prototype.map = function() {
|
330 | throw new Error("map is unimplemented for this js engine");
|
331 | };
|
332 | }
|
333 |
|
334 | exports.keys = function(obj) {
|
335 | if(Object.prototype.keys) {
|
336 | return obj.keys();
|
337 | }
|
338 | else {
|
339 | var keys = [];
|
340 | for(var k in obj) {
|
341 | if(obj.hasOwnProperty(k)) {
|
342 | keys.push(k);
|
343 | }
|
344 | }
|
345 | return keys;
|
346 | }
|
347 | }
|
348 | })();
|
349 | (function() {
|
350 | var lib = modules["lib"];
|
351 | var Obj = modules["object"];
|
352 |
|
353 |
|
354 |
|
355 |
|
356 | var Frame = Obj.extend({
|
357 | init: function(parent) {
|
358 | this.variables = {};
|
359 | this.parent = parent;
|
360 | },
|
361 |
|
362 | set: function(name, val, resolveUp) {
|
363 |
|
364 |
|
365 | var parts = name.split('.');
|
366 | var obj = this.variables;
|
367 | var frame = this;
|
368 |
|
369 | if(resolveUp) {
|
370 | if((frame = this.resolve(parts[0]))) {
|
371 | frame.set(name, val);
|
372 | return;
|
373 | }
|
374 | frame = this;
|
375 | }
|
376 |
|
377 | for(var i=0; i<parts.length - 1; i++) {
|
378 | var id = parts[i];
|
379 |
|
380 | if(!obj[id]) {
|
381 | obj[id] = {};
|
382 | }
|
383 | obj = obj[id];
|
384 | }
|
385 |
|
386 | obj[parts[parts.length - 1]] = val;
|
387 | },
|
388 |
|
389 | get: function(name) {
|
390 | var val = this.variables[name];
|
391 | if(val !== undefined && val !== null) {
|
392 | return val;
|
393 | }
|
394 | return null;
|
395 | },
|
396 |
|
397 | lookup: function(name) {
|
398 | var p = this.parent;
|
399 | var val = this.variables[name];
|
400 | if(val !== undefined && val !== null) {
|
401 | return val;
|
402 | }
|
403 | return p && p.lookup(name);
|
404 | },
|
405 |
|
406 | resolve: function(name) {
|
407 | var p = this.parent;
|
408 | var val = this.variables[name];
|
409 | if(val != null) {
|
410 | return this;
|
411 | }
|
412 | return p && p.resolve(name);
|
413 | },
|
414 |
|
415 | push: function() {
|
416 | return new Frame(this);
|
417 | },
|
418 |
|
419 | pop: function() {
|
420 | return this.parent;
|
421 | }
|
422 | });
|
423 |
|
424 | function makeMacro(argNames, kwargNames, func) {
|
425 | return function() {
|
426 | var argCount = numArgs(arguments);
|
427 | var args;
|
428 | var kwargs = getKeywordArgs(arguments);
|
429 |
|
430 | if(argCount > argNames.length) {
|
431 | args = Array.prototype.slice.call(arguments, 0, argNames.length);
|
432 |
|
433 |
|
434 |
|
435 | var vals = Array.prototype.slice.call(arguments, args.length, argCount);
|
436 | for(var i=0; i<vals.length; i++) {
|
437 | if(i < kwargNames.length) {
|
438 | kwargs[kwargNames[i]] = vals[i];
|
439 | }
|
440 | }
|
441 |
|
442 | args.push(kwargs);
|
443 | }
|
444 | else if(argCount < argNames.length) {
|
445 | args = Array.prototype.slice.call(arguments, 0, argCount);
|
446 |
|
447 | for(var i=argCount; i<argNames.length; i++) {
|
448 | var arg = argNames[i];
|
449 |
|
450 |
|
451 |
|
452 |
|
453 | args.push(kwargs[arg]);
|
454 | delete kwargs[arg];
|
455 | }
|
456 |
|
457 | args.push(kwargs);
|
458 | }
|
459 | else {
|
460 | args = arguments;
|
461 | }
|
462 |
|
463 | return func.apply(this, args);
|
464 | };
|
465 | }
|
466 |
|
467 | function makeKeywordArgs(obj) {
|
468 | obj.__keywords = true;
|
469 | return obj;
|
470 | }
|
471 |
|
472 | function getKeywordArgs(args) {
|
473 | var len = args.length;
|
474 | if(len) {
|
475 | var lastArg = args[len - 1];
|
476 | if(lastArg && lastArg.hasOwnProperty('__keywords')) {
|
477 | return lastArg;
|
478 | }
|
479 | }
|
480 | return {};
|
481 | }
|
482 |
|
483 | function numArgs(args) {
|
484 | var len = args.length;
|
485 | if(len === 0) {
|
486 | return 0;
|
487 | }
|
488 |
|
489 | var lastArg = args[len - 1];
|
490 | if(lastArg && lastArg.hasOwnProperty('__keywords')) {
|
491 | return len - 1;
|
492 | }
|
493 | else {
|
494 | return len;
|
495 | }
|
496 | }
|
497 |
|
498 |
|
499 |
|
500 |
|
501 | function SafeString(val) {
|
502 | if(typeof val != 'string') {
|
503 | return val;
|
504 | }
|
505 |
|
506 | this.val = val;
|
507 | }
|
508 |
|
509 | SafeString.prototype = Object.create(String.prototype);
|
510 | SafeString.prototype.valueOf = function() {
|
511 | return this.val;
|
512 | };
|
513 | SafeString.prototype.toString = function() {
|
514 | return this.val;
|
515 | };
|
516 |
|
517 | function copySafeness(dest, target) {
|
518 | if(dest instanceof SafeString) {
|
519 | return new SafeString(target);
|
520 | }
|
521 | return target.toString();
|
522 | }
|
523 |
|
524 | function markSafe(val) {
|
525 | var type = typeof val;
|
526 |
|
527 | if(type === 'string') {
|
528 | return new SafeString(val);
|
529 | }
|
530 | else if(type !== 'function') {
|
531 | return val;
|
532 | }
|
533 | else {
|
534 | return function() {
|
535 | var ret = val.apply(this, arguments);
|
536 |
|
537 | if(typeof ret === 'string') {
|
538 | return new SafeString(ret);
|
539 | }
|
540 |
|
541 | return ret;
|
542 | };
|
543 | }
|
544 | }
|
545 |
|
546 | function suppressValue(val, autoescape) {
|
547 | val = (val !== undefined && val !== null) ? val : "";
|
548 |
|
549 | if(autoescape && typeof val === "string") {
|
550 | val = lib.escape(val);
|
551 | }
|
552 |
|
553 | return val;
|
554 | }
|
555 |
|
556 | function memberLookup(obj, val) {
|
557 | obj = obj || {};
|
558 |
|
559 | if(typeof obj[val] === 'function') {
|
560 | return function() {
|
561 | return obj[val].apply(obj, arguments);
|
562 | };
|
563 | }
|
564 |
|
565 | return obj[val];
|
566 | }
|
567 |
|
568 | function callWrap(obj, name, args) {
|
569 | if(!obj) {
|
570 | throw new Error('Unable to call `' + name + '`, which is undefined or falsey');
|
571 | }
|
572 | else if(typeof obj !== 'function') {
|
573 | throw new Error('Unable to call `' + name + '`, which is not a function');
|
574 | }
|
575 |
|
576 | return obj.apply(this, args);
|
577 | }
|
578 |
|
579 | function contextOrFrameLookup(context, frame, name) {
|
580 | var val = frame.lookup(name);
|
581 | return (val !== undefined && val !== null) ?
|
582 | val :
|
583 | context.lookup(name);
|
584 | }
|
585 |
|
586 | function handleError(error, lineno, colno) {
|
587 | if(error.lineno) {
|
588 | return error;
|
589 | }
|
590 | else {
|
591 | return new lib.TemplateError(error, lineno, colno);
|
592 | }
|
593 | }
|
594 |
|
595 | function asyncEach(arr, dimen, iter, cb) {
|
596 | if(lib.isArray(arr)) {
|
597 | var len = arr.length;
|
598 |
|
599 | lib.asyncIter(arr, function(item, i, next) {
|
600 | switch(dimen) {
|
601 | case 1: iter(item, i, len, next); break;
|
602 | case 2: iter(item[0], item[1], i, len, next); break;
|
603 | case 3: iter(item[0], item[1], item[2], i, len, next); break;
|
604 | default:
|
605 | item.push(i, next);
|
606 | iter.apply(this, item);
|
607 | }
|
608 | }, cb);
|
609 | }
|
610 | else {
|
611 | lib.asyncFor(arr, function(key, val, i, len, next) {
|
612 | iter(key, val, i, len, next);
|
613 | }, cb);
|
614 | }
|
615 | }
|
616 |
|
617 | function asyncAll(arr, dimen, func, cb) {
|
618 | var finished = 0;
|
619 | var len;
|
620 | var outputArr;
|
621 |
|
622 | function done(i, output) {
|
623 | finished++;
|
624 | outputArr[i] = output;
|
625 |
|
626 | if(finished == len) {
|
627 | cb(null, outputArr.join(''));
|
628 | }
|
629 | }
|
630 |
|
631 | if(lib.isArray(arr)) {
|
632 | len = arr.length;
|
633 | outputArr = new Array(len);
|
634 |
|
635 | if(len == 0) {
|
636 | cb(null, '');
|
637 | }
|
638 | else {
|
639 | for(var i=0; i<arr.length; i++) {
|
640 | var item = arr[i];
|
641 |
|
642 | switch(dimen) {
|
643 | case 1: func(item, i, len, done); break;
|
644 | case 2: func(item[0], item[1], i, len, done); break;
|
645 | case 3: func(item[0], item[1], item[2], i, len, done); break;
|
646 | default:
|
647 | item.push(i, done);
|
648 | func.apply(this, item);
|
649 | }
|
650 | }
|
651 | }
|
652 | }
|
653 | else {
|
654 | var keys = lib.keys(arr);
|
655 | len = keys.length;
|
656 | outputArr = new Array(len);
|
657 |
|
658 | if(len == 0) {
|
659 | cb(null, '');
|
660 | }
|
661 | else {
|
662 | for(var i=0; i<keys.length; i++) {
|
663 | var k = keys[i];
|
664 | func(k, arr[k], i, len, done);
|
665 | }
|
666 | }
|
667 | }
|
668 | }
|
669 |
|
670 | modules['runtime'] = {
|
671 | Frame: Frame,
|
672 | makeMacro: makeMacro,
|
673 | makeKeywordArgs: makeKeywordArgs,
|
674 | numArgs: numArgs,
|
675 | suppressValue: suppressValue,
|
676 | memberLookup: memberLookup,
|
677 | contextOrFrameLookup: contextOrFrameLookup,
|
678 | callWrap: callWrap,
|
679 | handleError: handleError,
|
680 | isArray: lib.isArray,
|
681 | keys: lib.keys,
|
682 | SafeString: SafeString,
|
683 | copySafeness: copySafeness,
|
684 | markSafe: markSafe,
|
685 | asyncEach: asyncEach,
|
686 | asyncAll: asyncAll
|
687 | };
|
688 | })();
|
689 | (function() {
|
690 | var Obj = modules["object"];
|
691 | var lib = modules["lib"];
|
692 |
|
693 | var Loader = Obj.extend({
|
694 | on: function(name, func) {
|
695 | this.listeners = this.listeners || {};
|
696 | this.listeners[name] = this.listeners[name] || [];
|
697 | this.listeners[name].push(func);
|
698 | },
|
699 |
|
700 | emit: function(name /*, arg1, arg2, ...*/) {
|
701 | var args = Array.prototype.slice.call(arguments, 1);
|
702 |
|
703 | if(this.listeners && this.listeners[name]) {
|
704 | lib.each(this.listeners[name], function(listener) {
|
705 | listener.apply(null, args);
|
706 | });
|
707 | }
|
708 | }
|
709 | });
|
710 |
|
711 | modules['loader'] = Loader;
|
712 | })();
|
713 | (function() {
|
714 | var Loader = modules["loader"];
|
715 |
|
716 | var WebLoader = Loader.extend({
|
717 | init: function(baseURL, neverUpdate) {
|
718 |
|
719 |
|
720 |
|
721 | this.precompiled = window.nunjucksPrecompiled || {};
|
722 |
|
723 | this.baseURL = baseURL || '';
|
724 | this.neverUpdate = neverUpdate;
|
725 | },
|
726 |
|
727 | getSource: function(name) {
|
728 | if(this.precompiled[name]) {
|
729 | return {
|
730 | src: { type: "code",
|
731 | obj: this.precompiled[name] },
|
732 | path: name
|
733 | };
|
734 | }
|
735 | else {
|
736 | var src = this.fetch(this.baseURL + '/' + name);
|
737 | if(!src) {
|
738 | return null;
|
739 | }
|
740 |
|
741 | return { src: src,
|
742 | path: name,
|
743 | noCache: !this.neverUpdate };
|
744 | }
|
745 | },
|
746 |
|
747 | fetch: function(url, callback) {
|
748 |
|
749 | var ajax;
|
750 | var loading = true;
|
751 | var src;
|
752 |
|
753 | if(window.XMLHttpRequest) {
|
754 | ajax = new XMLHttpRequest();
|
755 | }
|
756 | else if(window.ActiveXObject) {
|
757 | ajax = new ActiveXObject("Microsoft.XMLHTTP");
|
758 | }
|
759 |
|
760 | ajax.onreadystatechange = function() {
|
761 | if(ajax.readyState === 4 && (ajax.status === 0 || ajax.status === 200) && loading) {
|
762 | loading = false;
|
763 | src = ajax.responseText;
|
764 | }
|
765 | };
|
766 |
|
767 | url += (url.indexOf('?') === -1 ? '?' : '&') + 's=' +
|
768 | (new Date().getTime());
|
769 |
|
770 |
|
771 |
|
772 | ajax.open('GET', url, false);
|
773 | ajax.send();
|
774 |
|
775 | return src;
|
776 | }
|
777 | });
|
778 |
|
779 | modules['web-loaders'] = {
|
780 | WebLoader: WebLoader
|
781 | };
|
782 | })();
|
783 | (function() {
|
784 | if(typeof window === 'undefined' || window !== this) {
|
785 | modules['loaders'] = modules["node-loaders"];
|
786 | }
|
787 | else {
|
788 | modules['loaders'] = modules["web-loaders"];
|
789 | }
|
790 | })();
|
791 | (function() {
|
792 | var lib = modules["lib"];
|
793 | var r = modules["runtime"];
|
794 |
|
795 | var filters = {
|
796 | abs: function(n) {
|
797 | return Math.abs(n);
|
798 | },
|
799 |
|
800 | batch: function(arr, linecount, fill_with) {
|
801 | var res = [];
|
802 | var tmp = [];
|
803 |
|
804 | for(var i=0; i<arr.length; i++) {
|
805 | if(i % linecount === 0 && tmp.length) {
|
806 | res.push(tmp);
|
807 | tmp = [];
|
808 | }
|
809 |
|
810 | tmp.push(arr[i]);
|
811 | }
|
812 |
|
813 | if(tmp.length) {
|
814 | if(fill_with) {
|
815 | for(var i=tmp.length; i<linecount; i++) {
|
816 | tmp.push(fill_with);
|
817 | }
|
818 | }
|
819 |
|
820 | res.push(tmp);
|
821 | }
|
822 |
|
823 | return res;
|
824 | },
|
825 |
|
826 | capitalize: function(str) {
|
827 | var ret = str.toLowerCase();
|
828 | return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
|
829 | },
|
830 |
|
831 | center: function(str, width) {
|
832 | width = width || 80;
|
833 |
|
834 | if(str.length >= width) {
|
835 | return str;
|
836 | }
|
837 |
|
838 | var spaces = width - str.length;
|
839 | var pre = lib.repeat(" ", spaces/2 - spaces % 2);
|
840 | var post = lib.repeat(" ", spaces/2);
|
841 | return r.copySafeness(str, pre + str + post);
|
842 | },
|
843 |
|
844 | 'default': function(val, def) {
|
845 | return val ? val : def;
|
846 | },
|
847 |
|
848 | dictsort: function(val, case_sensitive, by) {
|
849 | if (!lib.isObject(val)) {
|
850 | throw new lib.TemplateError("dictsort filter: val must be an object");
|
851 | }
|
852 |
|
853 | var array = [];
|
854 | for (var k in val) {
|
855 |
|
856 | array.push([k,val[k]]);
|
857 | }
|
858 |
|
859 | var si;
|
860 | if (by === undefined || by === "key") {
|
861 | si = 0;
|
862 | } else if (by === "value") {
|
863 | si = 1;
|
864 | } else {
|
865 | throw new lib.TemplateError(
|
866 | "dictsort filter: You can only sort by either key or value");
|
867 | }
|
868 |
|
869 | array.sort(function(t1, t2) {
|
870 | var a = t1[si];
|
871 | var b = t2[si];
|
872 |
|
873 | if (!case_sensitive) {
|
874 | if (lib.isString(a)) {
|
875 | a = a.toUpperCase();
|
876 | }
|
877 | if (lib.isString(b)) {
|
878 | b = b.toUpperCase();
|
879 | }
|
880 | }
|
881 |
|
882 | return a > b ? 1 : (a == b ? 0 : -1);
|
883 | });
|
884 |
|
885 | return array;
|
886 | },
|
887 |
|
888 | escape: function(str) {
|
889 | if(typeof str == 'string' ||
|
890 | str instanceof r.SafeString) {
|
891 | return lib.escape(str);
|
892 | }
|
893 | return str;
|
894 | },
|
895 |
|
896 | safe: function(str) {
|
897 | return r.markSafe(str);
|
898 | },
|
899 |
|
900 | first: function(arr) {
|
901 | return arr[0];
|
902 | },
|
903 |
|
904 | groupby: function(arr, attr) {
|
905 | return lib.groupBy(arr, attr);
|
906 | },
|
907 |
|
908 | indent: function(str, width, indentfirst) {
|
909 | width = width || 4;
|
910 | var res = '';
|
911 | var lines = str.split('\n');
|
912 | var sp = lib.repeat(' ', width);
|
913 |
|
914 | for(var i=0; i<lines.length; i++) {
|
915 | if(i == 0 && !indentfirst) {
|
916 | res += lines[i] + '\n';
|
917 | }
|
918 | else {
|
919 | res += sp + lines[i] + '\n';
|
920 | }
|
921 | }
|
922 |
|
923 | return r.copySafeness(str, res);
|
924 | },
|
925 |
|
926 | join: function(arr, del, attr) {
|
927 | del = del || '';
|
928 |
|
929 | if(attr) {
|
930 | arr = lib.map(arr, function(v) {
|
931 | return v[attr];
|
932 | });
|
933 | }
|
934 |
|
935 | return arr.join(del);
|
936 | },
|
937 |
|
938 | last: function(arr) {
|
939 | return arr[arr.length-1];
|
940 | },
|
941 |
|
942 | length: function(arr) {
|
943 | return arr !== undefined ? arr.length : 0;
|
944 | },
|
945 |
|
946 | list: function(val) {
|
947 | if(lib.isString(val)) {
|
948 | return val.split('');
|
949 | }
|
950 | else if(lib.isObject(val)) {
|
951 | var keys = [];
|
952 |
|
953 | if(Object.keys) {
|
954 | keys = Object.keys(val);
|
955 | }
|
956 | else {
|
957 | for(var k in val) {
|
958 | keys.push(k);
|
959 | }
|
960 | }
|
961 |
|
962 | return lib.map(keys, function(k) {
|
963 | return { key: k,
|
964 | value: val[k] };
|
965 | });
|
966 | }
|
967 | else {
|
968 | throw new lib.TemplateError("list filter: type not iterable");
|
969 | }
|
970 | },
|
971 |
|
972 | lower: function(str) {
|
973 | return str.toLowerCase();
|
974 | },
|
975 |
|
976 | random: function(arr) {
|
977 | return arr[Math.floor(Math.random() * arr.length)];
|
978 | },
|
979 |
|
980 | replace: function(str, old, new_, maxCount) {
|
981 | var res = str;
|
982 | var last = res;
|
983 | var count = 1;
|
984 | res = res.replace(old, new_);
|
985 |
|
986 | while(last != res) {
|
987 | if(count >= maxCount) {
|
988 | break;
|
989 | }
|
990 |
|
991 | last = res;
|
992 | res = res.replace(old, new_);
|
993 | count++;
|
994 | }
|
995 |
|
996 | return r.copySafeness(str, res);
|
997 | },
|
998 |
|
999 | reverse: function(val) {
|
1000 | var arr;
|
1001 | if(lib.isString(val)) {
|
1002 | arr = filters.list(val);
|
1003 | }
|
1004 | else {
|
1005 |
|
1006 | arr = lib.map(val, function(v) { return v; });
|
1007 | }
|
1008 |
|
1009 | arr.reverse();
|
1010 |
|
1011 | if(lib.isString(val)) {
|
1012 | return r.copySafeness(val, arr.join(''));
|
1013 | }
|
1014 | return arr;
|
1015 | },
|
1016 |
|
1017 | round: function(val, precision, method) {
|
1018 | precision = precision || 0;
|
1019 | var factor = Math.pow(10, precision);
|
1020 | var rounder;
|
1021 |
|
1022 | if(method == 'ceil') {
|
1023 | rounder = Math.ceil;
|
1024 | }
|
1025 | else if(method == 'floor') {
|
1026 | rounder = Math.floor;
|
1027 | }
|
1028 | else {
|
1029 | rounder = Math.round;
|
1030 | }
|
1031 |
|
1032 | return rounder(val * factor) / factor;
|
1033 | },
|
1034 |
|
1035 | slice: function(arr, slices, fillWith) {
|
1036 | var sliceLength = Math.floor(arr.length / slices);
|
1037 | var extra = arr.length % slices;
|
1038 | var offset = 0;
|
1039 | var res = [];
|
1040 |
|
1041 | for(var i=0; i<slices; i++) {
|
1042 | var start = offset + i * sliceLength;
|
1043 | if(i < extra) {
|
1044 | offset++;
|
1045 | }
|
1046 | var end = offset + (i + 1) * sliceLength;
|
1047 |
|
1048 | var slice = arr.slice(start, end);
|
1049 | if(fillWith && i >= extra) {
|
1050 | slice.push(fillWith);
|
1051 | }
|
1052 | res.push(slice);
|
1053 | }
|
1054 |
|
1055 | return res;
|
1056 | },
|
1057 |
|
1058 | sort: function(arr, reverse, caseSens, attr) {
|
1059 |
|
1060 | arr = lib.map(arr, function(v) { return v; });
|
1061 |
|
1062 | arr.sort(function(a, b) {
|
1063 | var x, y;
|
1064 |
|
1065 | if(attr) {
|
1066 | x = a[attr];
|
1067 | y = b[attr];
|
1068 | }
|
1069 | else {
|
1070 | x = a;
|
1071 | y = b;
|
1072 | }
|
1073 |
|
1074 | if(!caseSens && lib.isString(x) && lib.isString(y)) {
|
1075 | x = x.toLowerCase();
|
1076 | y = y.toLowerCase();
|
1077 | }
|
1078 |
|
1079 | if(x < y) {
|
1080 | return reverse ? 1 : -1;
|
1081 | }
|
1082 | else if(x > y) {
|
1083 | return reverse ? -1: 1;
|
1084 | }
|
1085 | else {
|
1086 | return 0;
|
1087 | }
|
1088 | });
|
1089 |
|
1090 | return arr;
|
1091 | },
|
1092 |
|
1093 | string: function(obj) {
|
1094 | return r.copySafeness(obj, obj);
|
1095 | },
|
1096 |
|
1097 | title: function(str) {
|
1098 | var words = str.split(' ');
|
1099 | for(var i = 0; i < words.length; i++) {
|
1100 | words[i] = filters.capitalize(words[i]);
|
1101 | }
|
1102 | return r.copySafeness(str, words.join(' '));
|
1103 | },
|
1104 |
|
1105 | trim: function(str) {
|
1106 | return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
|
1107 | },
|
1108 |
|
1109 | truncate: function(input, length, killwords, end) {
|
1110 | var orig = input;
|
1111 | length = length || 255;
|
1112 |
|
1113 | if (input.length <= length)
|
1114 | return input;
|
1115 |
|
1116 | if (killwords) {
|
1117 | input = input.substring(0, length);
|
1118 | } else {
|
1119 | var idx = input.lastIndexOf(' ', length);
|
1120 | if(idx === -1) {
|
1121 | idx = length;
|
1122 | }
|
1123 |
|
1124 | input = input.substring(0, idx);
|
1125 | }
|
1126 |
|
1127 | input += (end !== undefined && end !== null) ? end : '...';
|
1128 | return r.copySafeness(orig, input);
|
1129 | },
|
1130 |
|
1131 | upper: function(str) {
|
1132 | return str.toUpperCase();
|
1133 | },
|
1134 |
|
1135 | urlencode: function(obj) {
|
1136 | var enc = encodeURIComponent;
|
1137 | if (lib.isString(obj)) {
|
1138 | return enc(obj);
|
1139 | } else {
|
1140 | var parts;
|
1141 | if (lib.isArray(obj)) {
|
1142 | parts = obj.map(function(item) {
|
1143 | return enc(item[0]) + '=' + enc(item[1]);
|
1144 | })
|
1145 | } else {
|
1146 | parts = [];
|
1147 | for (var k in obj) {
|
1148 | if (obj.hasOwnProperty(k)) {
|
1149 | parts.push(enc(k) + '=' + enc(obj[k]));
|
1150 | }
|
1151 | }
|
1152 | }
|
1153 | return parts.join('&');
|
1154 | }
|
1155 | },
|
1156 |
|
1157 | urlize: function(str, length, nofollow) {
|
1158 | if (isNaN(length)) length = Infinity;
|
1159 |
|
1160 | var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : '');
|
1161 |
|
1162 |
|
1163 |
|
1164 | var puncRE = /^(?:\(|<|<)?(.*?)(?:\.|,|\)|\n|>)?$/;
|
1165 |
|
1166 | var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
|
1167 | var httpHttpsRE = /^https?:\/\/.*$/;
|
1168 | var wwwRE = /^www\./;
|
1169 | var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/;
|
1170 |
|
1171 | var words = str.split(/\s+/).filter(function(word) {
|
1172 |
|
1173 |
|
1174 | return word && word.length;
|
1175 | }).map(function(word) {
|
1176 | var matches = word.match(puncRE);
|
1177 |
|
1178 | var possibleUrl = matches && matches[1] || word;
|
1179 |
|
1180 |
|
1181 | if (httpHttpsRE.test(possibleUrl))
|
1182 | return '<a href="' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
1183 |
|
1184 |
|
1185 | if (wwwRE.test(possibleUrl))
|
1186 | return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
1187 |
|
1188 |
|
1189 | if (emailRE.test(possibleUrl))
|
1190 | return '<a href="mailto:' + possibleUrl + '">' + possibleUrl + '</a>';
|
1191 |
|
1192 |
|
1193 | if (tldRE.test(possibleUrl))
|
1194 | return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
1195 |
|
1196 | return possibleUrl;
|
1197 |
|
1198 | });
|
1199 |
|
1200 | return words.join(' ');
|
1201 | },
|
1202 |
|
1203 | wordcount: function(str) {
|
1204 | var words = (str) ? str.match(/\w+/g) : null;
|
1205 | return (words) ? words.length : null;
|
1206 | },
|
1207 |
|
1208 | 'float': function(val, def) {
|
1209 | var res = parseFloat(val);
|
1210 | return isNaN(res) ? def : res;
|
1211 | },
|
1212 |
|
1213 | 'int': function(val, def) {
|
1214 | var res = parseInt(val, 10);
|
1215 | return isNaN(res) ? def : res;
|
1216 | }
|
1217 | };
|
1218 |
|
1219 |
|
1220 | filters.d = filters['default'];
|
1221 | filters.e = filters.escape;
|
1222 |
|
1223 | modules['filters'] = filters;
|
1224 | })();
|
1225 | (function() {
|
1226 |
|
1227 | function cycler(items) {
|
1228 | var index = -1;
|
1229 | var current = null;
|
1230 |
|
1231 | return {
|
1232 | reset: function() {
|
1233 | index = -1;
|
1234 | current = null;
|
1235 | },
|
1236 |
|
1237 | next: function() {
|
1238 | index++;
|
1239 | if(index >= items.length) {
|
1240 | index = 0;
|
1241 | }
|
1242 |
|
1243 | current = items[index];
|
1244 | return current;
|
1245 | }
|
1246 | };
|
1247 |
|
1248 | }
|
1249 |
|
1250 | function joiner(sep) {
|
1251 | sep = sep || ',';
|
1252 | var first = true;
|
1253 |
|
1254 | return function() {
|
1255 | var val = first ? '' : sep;
|
1256 | first = false;
|
1257 | return val;
|
1258 | };
|
1259 | }
|
1260 |
|
1261 | var globals = {
|
1262 | range: function(start, stop, step) {
|
1263 | if(!stop) {
|
1264 | stop = start;
|
1265 | start = 0;
|
1266 | step = 1;
|
1267 | }
|
1268 | else if(!step) {
|
1269 | step = 1;
|
1270 | }
|
1271 |
|
1272 | var arr = [];
|
1273 | for(var i=start; i<stop; i+=step) {
|
1274 | arr.push(i);
|
1275 | }
|
1276 | return arr;
|
1277 | },
|
1278 |
|
1279 |
|
1280 |
|
1281 |
|
1282 | cycler: function() {
|
1283 | return cycler(Array.prototype.slice.call(arguments));
|
1284 | },
|
1285 |
|
1286 | joiner: function(sep) {
|
1287 | return joiner(sep);
|
1288 | }
|
1289 | }
|
1290 |
|
1291 | modules['globals'] = globals;
|
1292 | })();
|
1293 | (function() {
|
1294 | var path = modules["path"];
|
1295 | var lib = modules["lib"];
|
1296 | var Obj = modules["object"];
|
1297 | var lexer = modules["lexer"];
|
1298 | var compiler = modules["compiler"];
|
1299 | var builtin_filters = modules["filters"];
|
1300 | var builtin_loaders = modules["loaders"];
|
1301 | var runtime = modules["runtime"];
|
1302 | var globals = modules["globals"];
|
1303 | var Frame = runtime.Frame;
|
1304 |
|
1305 | var Environment = Obj.extend({
|
1306 | init: function(loaders, opts) {
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 |
|
1313 | opts = opts || {};
|
1314 | this.dev = !!opts.dev;
|
1315 |
|
1316 |
|
1317 |
|
1318 |
|
1319 |
|
1320 | this.autoesc = !!opts.autoescape;
|
1321 |
|
1322 | if(!loaders) {
|
1323 |
|
1324 | if(builtin_loaders.FileSystemLoader) {
|
1325 | this.loaders = [new builtin_loaders.FileSystemLoader('views')];
|
1326 | }
|
1327 | else {
|
1328 | this.loaders = [new builtin_loaders.WebLoader('/views')];
|
1329 | }
|
1330 | }
|
1331 | else {
|
1332 | this.loaders = lib.isArray(loaders) ? loaders : [loaders];
|
1333 | }
|
1334 |
|
1335 | this.initCache();
|
1336 | this.filters = {};
|
1337 | this.asyncFilters = [];
|
1338 | this.extensions = {};
|
1339 | this.extensionsList = [];
|
1340 |
|
1341 | if(opts.tags) {
|
1342 | lexer.setTags(opts.tags);
|
1343 | }
|
1344 |
|
1345 | for(var name in builtin_filters) {
|
1346 | this.addFilter(name, builtin_filters[name]);
|
1347 | }
|
1348 | },
|
1349 |
|
1350 | initCache: function() {
|
1351 |
|
1352 | var cache = {};
|
1353 |
|
1354 | lib.each(this.loaders, function(loader) {
|
1355 | if(typeof loader.on === 'function'){
|
1356 | loader.on('update', function(template) {
|
1357 | cache[template] = null;
|
1358 | });
|
1359 | }
|
1360 | });
|
1361 |
|
1362 | this.cache = cache;
|
1363 | },
|
1364 |
|
1365 | addExtension: function(name, extension) {
|
1366 | extension._name = name;
|
1367 | this.extensions[name] = extension;
|
1368 | this.extensionsList.push(extension);
|
1369 | },
|
1370 |
|
1371 | getExtension: function(name) {
|
1372 | return this.extensions[name];
|
1373 | },
|
1374 |
|
1375 | addGlobal: function(name, value) {
|
1376 | globals[name] = value;
|
1377 | },
|
1378 |
|
1379 | addFilter: function(name, func, async) {
|
1380 | var wrapped = func;
|
1381 |
|
1382 | if(async) {
|
1383 | this.asyncFilters.push(name);
|
1384 | }
|
1385 | this.filters[name] = wrapped;
|
1386 | },
|
1387 |
|
1388 | getFilter: function(name) {
|
1389 | if(!this.filters[name]) {
|
1390 | throw new Error('filter not found: ' + name);
|
1391 | }
|
1392 | return this.filters[name];
|
1393 | },
|
1394 |
|
1395 | getTemplate: function(name, eagerCompile, cb) {
|
1396 | if(name && name.raw) {
|
1397 |
|
1398 | name = name.raw;
|
1399 | }
|
1400 |
|
1401 | if(lib.isFunction(eagerCompile)) {
|
1402 | cb = eagerCompile;
|
1403 | eagerCompile = false;
|
1404 | }
|
1405 |
|
1406 | if(typeof name !== 'string') {
|
1407 | throw new Error('template names must be a string: ' + name);
|
1408 | }
|
1409 |
|
1410 | var tmpl = this.cache[name];
|
1411 |
|
1412 | if(tmpl) {
|
1413 | if(eagerCompile) {
|
1414 | tmpl.compile();
|
1415 | }
|
1416 |
|
1417 | if(cb) {
|
1418 | cb(null, tmpl);
|
1419 | }
|
1420 | else {
|
1421 | return tmpl;
|
1422 | }
|
1423 | } else {
|
1424 | var syncResult;
|
1425 |
|
1426 | lib.asyncIter(this.loaders, function(loader, i, next, done) {
|
1427 | function handle(src) {
|
1428 | if(src) {
|
1429 | done(src);
|
1430 | }
|
1431 | else {
|
1432 | next();
|
1433 | }
|
1434 | }
|
1435 |
|
1436 | if(loader.async) {
|
1437 | loader.getSource(name, function(err, src) {
|
1438 | if(err) { throw err; }
|
1439 | handle(src);
|
1440 | });
|
1441 | }
|
1442 | else {
|
1443 | handle(loader.getSource(name));
|
1444 | }
|
1445 | }, function(info) {
|
1446 | if(!info) {
|
1447 | var err = new Error('template not found: ' + name);
|
1448 | if(cb) {
|
1449 | cb(err);
|
1450 | }
|
1451 | else {
|
1452 | throw err;
|
1453 | }
|
1454 | }
|
1455 | else {
|
1456 | var tmpl = new Template(info.src, this,
|
1457 | info.path, eagerCompile);
|
1458 |
|
1459 | if(!info.noCache) {
|
1460 | this.cache[name] = tmpl;
|
1461 | }
|
1462 |
|
1463 | if(cb) {
|
1464 | cb(null, tmpl);
|
1465 | }
|
1466 | else {
|
1467 | syncResult = tmpl;
|
1468 | }
|
1469 | }
|
1470 | }.bind(this));
|
1471 |
|
1472 | return syncResult;
|
1473 | }
|
1474 | },
|
1475 |
|
1476 | express: function(app) {
|
1477 | var env = this;
|
1478 |
|
1479 | function NunjucksView(name, opts) {
|
1480 | this.name = name;
|
1481 | this.path = name;
|
1482 | this.defaultEngine = opts.defaultEngine;
|
1483 | this.ext = path.extname(name);
|
1484 | if (!this.ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
|
1485 | if (!this.ext) this.name += (this.ext = ('.' !== this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
|
1486 | }
|
1487 |
|
1488 | NunjucksView.prototype.render = function(opts, cb) {
|
1489 | env.render(this.name, opts, cb);
|
1490 | };
|
1491 |
|
1492 | app.set('view', NunjucksView);
|
1493 | },
|
1494 |
|
1495 | render: function(name, ctx, cb) {
|
1496 | if(lib.isFunction(ctx)) {
|
1497 | cb = ctx;
|
1498 | ctx = null;
|
1499 | }
|
1500 |
|
1501 |
|
1502 |
|
1503 |
|
1504 |
|
1505 | var syncResult = null;
|
1506 |
|
1507 | this.getTemplate(name, function(err, tmpl) {
|
1508 | if(err && cb) {
|
1509 | cb(err);
|
1510 | }
|
1511 | else if(err) {
|
1512 | throw err;
|
1513 | }
|
1514 | else {
|
1515 | tmpl.render(ctx, cb || function(err, res) {
|
1516 | if(err) { throw err; }
|
1517 | syncResult = res;
|
1518 | });
|
1519 | }
|
1520 | });
|
1521 |
|
1522 | return syncResult;
|
1523 | },
|
1524 |
|
1525 | renderString: function(src, ctx, cb) {
|
1526 | var tmpl = new Template(src, this);
|
1527 | return tmpl.render(ctx, cb);
|
1528 | }
|
1529 | });
|
1530 |
|
1531 | var Context = Obj.extend({
|
1532 | init: function(ctx, blocks) {
|
1533 | this.ctx = ctx;
|
1534 | this.blocks = {};
|
1535 | this.exported = [];
|
1536 |
|
1537 | for(var name in blocks) {
|
1538 | this.addBlock(name, blocks[name]);
|
1539 | }
|
1540 | },
|
1541 |
|
1542 | lookup: function(name) {
|
1543 |
|
1544 |
|
1545 | if(name in globals && !(name in this.ctx)) {
|
1546 | return globals[name];
|
1547 | }
|
1548 | else {
|
1549 | return this.ctx[name];
|
1550 | }
|
1551 | },
|
1552 |
|
1553 | setVariable: function(name, val) {
|
1554 | this.ctx[name] = val;
|
1555 | },
|
1556 |
|
1557 | getVariables: function() {
|
1558 | return this.ctx;
|
1559 | },
|
1560 |
|
1561 | addBlock: function(name, block) {
|
1562 | this.blocks[name] = this.blocks[name] || [];
|
1563 | this.blocks[name].push(block);
|
1564 | },
|
1565 |
|
1566 | getBlock: function(name) {
|
1567 | if(!this.blocks[name]) {
|
1568 | throw new Error('unknown block "' + name + '"');
|
1569 | }
|
1570 |
|
1571 | return this.blocks[name][0];
|
1572 | },
|
1573 |
|
1574 | getSuper: function(env, name, block, frame, runtime, cb) {
|
1575 | var idx = (this.blocks[name] || []).indexOf(block);
|
1576 | var blk = this.blocks[name][idx + 1];
|
1577 | var context = this;
|
1578 |
|
1579 | if(idx == -1 || !blk) {
|
1580 | throw new Error('no super block available for "' + name + '"');
|
1581 | }
|
1582 |
|
1583 | blk(env, context, frame, runtime, cb);
|
1584 | },
|
1585 |
|
1586 | addExport: function(name) {
|
1587 | this.exported.push(name);
|
1588 | },
|
1589 |
|
1590 | getExported: function() {
|
1591 | var exported = {};
|
1592 | for(var i=0; i<this.exported.length; i++) {
|
1593 | var name = this.exported[i];
|
1594 | exported[name] = this.ctx[name];
|
1595 | }
|
1596 | return exported;
|
1597 | }
|
1598 | });
|
1599 |
|
1600 | var Template = Obj.extend({
|
1601 | init: function (src, env, path, eagerCompile) {
|
1602 | this.env = env || new Environment();
|
1603 |
|
1604 | if(lib.isObject(src)) {
|
1605 | switch(src.type) {
|
1606 | case 'code': this.tmplProps = src.obj; break;
|
1607 | case 'string': this.tmplStr = src.obj; break;
|
1608 | }
|
1609 | }
|
1610 | else if(lib.isString(src)) {
|
1611 | this.tmplStr = src;
|
1612 | }
|
1613 | else {
|
1614 | throw new Error("src must be a string or an object describing " +
|
1615 | "the source");
|
1616 | }
|
1617 |
|
1618 | this.path = path;
|
1619 |
|
1620 | if(eagerCompile) {
|
1621 | lib.withPrettyErrors(this.path,
|
1622 | this.env.dev,
|
1623 | this._compile.bind(this));
|
1624 | }
|
1625 | else {
|
1626 | this.compiled = false;
|
1627 | }
|
1628 | },
|
1629 |
|
1630 | render: function(ctx, frame, cb) {
|
1631 | if (typeof ctx === 'function') {
|
1632 | cb = ctx;
|
1633 | ctx = {};
|
1634 | }
|
1635 | else if (typeof frame === 'function') {
|
1636 | cb = frame;
|
1637 | frame = null;
|
1638 | }
|
1639 |
|
1640 | return lib.withPrettyErrors(this.path, this.env.dev, function() {
|
1641 | this.compile();
|
1642 |
|
1643 | var context = new Context(ctx || {}, this.blocks);
|
1644 | var syncResult = null;
|
1645 |
|
1646 | this.rootRenderFunc(this.env,
|
1647 | context,
|
1648 | frame || new Frame(),
|
1649 | runtime,
|
1650 | cb || function(err, res) {
|
1651 | if(err) { throw err; }
|
1652 | syncResult = res;
|
1653 | });
|
1654 |
|
1655 | return syncResult;
|
1656 | }.bind(this));
|
1657 | },
|
1658 |
|
1659 | getExported: function(cb) {
|
1660 | this.compile();
|
1661 |
|
1662 |
|
1663 | var context = new Context({}, this.blocks);
|
1664 | this.rootRenderFunc(this.env,
|
1665 | context,
|
1666 | new Frame(),
|
1667 | runtime,
|
1668 | function() {
|
1669 | cb(null, context.getExported());
|
1670 | });
|
1671 | },
|
1672 |
|
1673 | compile: function() {
|
1674 | if(!this.compiled) {
|
1675 | this._compile();
|
1676 | }
|
1677 | },
|
1678 |
|
1679 | _compile: function() {
|
1680 | var props;
|
1681 |
|
1682 | if(this.tmplProps) {
|
1683 | props = this.tmplProps;
|
1684 | }
|
1685 | else {
|
1686 | var source = compiler.compile(this.tmplStr,
|
1687 | this.env.asyncFilters,
|
1688 | this.env.extensionsList,
|
1689 | this.path);
|
1690 | var func = new Function(source);
|
1691 | props = func();
|
1692 | }
|
1693 |
|
1694 | this.blocks = this._getBlocks(props);
|
1695 | this.rootRenderFunc = props.root;
|
1696 | this.compiled = true;
|
1697 | },
|
1698 |
|
1699 | _getBlocks: function(props) {
|
1700 | var blocks = {};
|
1701 |
|
1702 | for(var k in props) {
|
1703 | if(k.slice(0, 2) == 'b_') {
|
1704 | blocks[k.slice(2)] = props[k];
|
1705 | }
|
1706 | }
|
1707 |
|
1708 | return blocks;
|
1709 | }
|
1710 | });
|
1711 |
|
1712 |
|
1713 |
|
1714 |
|
1715 |
|
1716 |
|
1717 | modules['environment'] = {
|
1718 | Environment: Environment,
|
1719 | Template: Template
|
1720 | };
|
1721 | })();
|
1722 | var nunjucks;
|
1723 |
|
1724 | var lib = modules["lib"];
|
1725 | var env = modules["environment"];
|
1726 | var compiler = modules["compiler"];
|
1727 | var parser = modules["parser"];
|
1728 | var lexer = modules["lexer"];
|
1729 | var runtime = modules["runtime"];
|
1730 | var Loader = modules["loader"];
|
1731 | var loaders = modules["loaders"];
|
1732 | var precompile = modules["precompile"];
|
1733 |
|
1734 | nunjucks = {};
|
1735 | nunjucks.Environment = env.Environment;
|
1736 | nunjucks.Template = env.Template;
|
1737 |
|
1738 | nunjucks.Loader = Loader;
|
1739 | nunjucks.FileSystemLoader = loaders.FileSystemLoader;
|
1740 | nunjucks.WebLoader = loaders.WebLoader;
|
1741 |
|
1742 | nunjucks.compiler = compiler;
|
1743 | nunjucks.parser = parser;
|
1744 | nunjucks.lexer = lexer;
|
1745 | nunjucks.runtime = runtime;
|
1746 |
|
1747 |
|
1748 |
|
1749 | var e;
|
1750 | nunjucks.configure = function(templatesPath, opts) {
|
1751 | opts = opts || {};
|
1752 | if(lib.isObject(templatesPath)) {
|
1753 | opts = templatesPath;
|
1754 | templatesPath = null;
|
1755 | }
|
1756 |
|
1757 | var noWatch = 'watch' in opts ? !opts.watch : false;
|
1758 | var loader = loaders.FileSystemLoader || loaders.WebLoader;
|
1759 | e = new env.Environment(new loader(templatesPath, noWatch), opts);
|
1760 |
|
1761 | if(opts && opts.express) {
|
1762 | e.express(opts.express);
|
1763 | }
|
1764 |
|
1765 | return e;
|
1766 | };
|
1767 |
|
1768 | nunjucks.compile = function(src, env, path, eagerCompile) {
|
1769 | if(!e) {
|
1770 | nunjucks.configure();
|
1771 | }
|
1772 | return new nunjucks.Template(src, env, path, eagerCompile);
|
1773 | };
|
1774 |
|
1775 | nunjucks.render = function(name, ctx, cb) {
|
1776 | if(!e) {
|
1777 | nunjucks.configure();
|
1778 | }
|
1779 |
|
1780 | return e.render(name, ctx, cb);
|
1781 | };
|
1782 |
|
1783 | nunjucks.renderString = function(src, ctx, cb) {
|
1784 | if(!e) {
|
1785 | nunjucks.configure();
|
1786 | }
|
1787 |
|
1788 | return e.renderString(src, ctx, cb);
|
1789 | };
|
1790 |
|
1791 | if(precompile) {
|
1792 | nunjucks.precompile = precompile.precompile;
|
1793 | nunjucks.precompileString = precompile.precompileString;
|
1794 | }
|
1795 |
|
1796 | nunjucks.require = function(name) { return modules[name]; };
|
1797 |
|
1798 | if(typeof define === 'function' && define.amd) {
|
1799 | define(function() { return nunjucks; });
|
1800 | }
|
1801 | else {
|
1802 | window.nunjucks = nunjucks;
|
1803 | if(typeof module !== 'undefined') module.exports = nunjucks;
|
1804 | }
|
1805 |
|
1806 | })();
|