1 |
|
2 | (function webpackUniversalModuleDefinition(root, factory) {
|
3 | if(typeof exports === 'object' && typeof module === 'object')
|
4 | module.exports = factory();
|
5 | else if(typeof define === 'function' && define.amd)
|
6 | define([], factory);
|
7 | else if(typeof exports === 'object')
|
8 | exports["nunjucks"] = factory();
|
9 | else
|
10 | root["nunjucks"] = factory();
|
11 | })(this, function() {
|
12 | return (function(modules) {
|
13 |
|
14 | var installedModules = {};
|
15 |
|
16 |
|
17 | function __webpack_require__(moduleId) {
|
18 |
|
19 |
|
20 | if(installedModules[moduleId])
|
21 | return installedModules[moduleId].exports;
|
22 |
|
23 |
|
24 | var module = installedModules[moduleId] = {
|
25 | exports: {},
|
26 | id: moduleId,
|
27 | loaded: false
|
28 | };
|
29 |
|
30 |
|
31 | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
32 |
|
33 |
|
34 | module.loaded = true;
|
35 |
|
36 |
|
37 | return module.exports;
|
38 | }
|
39 |
|
40 |
|
41 |
|
42 | __webpack_require__.m = modules;
|
43 |
|
44 |
|
45 | __webpack_require__.c = installedModules;
|
46 |
|
47 |
|
48 | __webpack_require__.p = "";
|
49 |
|
50 |
|
51 | return __webpack_require__(0);
|
52 | })
|
53 |
|
54 | ([
|
55 |
|
56 | function(module, exports, __webpack_require__) {
|
57 |
|
58 | 'use strict';
|
59 |
|
60 | var lib = __webpack_require__(1);
|
61 | var env = __webpack_require__(2);
|
62 | var Loader = __webpack_require__(15);
|
63 | var loaders = __webpack_require__(14);
|
64 | var precompile = __webpack_require__(3);
|
65 |
|
66 | module.exports = {};
|
67 | module.exports.Environment = env.Environment;
|
68 | module.exports.Template = env.Template;
|
69 |
|
70 | module.exports.Loader = Loader;
|
71 | module.exports.FileSystemLoader = loaders.FileSystemLoader;
|
72 | module.exports.PrecompiledLoader = loaders.PrecompiledLoader;
|
73 | module.exports.WebLoader = loaders.WebLoader;
|
74 |
|
75 | module.exports.compiler = __webpack_require__(7);
|
76 | module.exports.parser = __webpack_require__(8);
|
77 | module.exports.lexer = __webpack_require__(9);
|
78 | module.exports.runtime = __webpack_require__(12);
|
79 | module.exports.lib = lib;
|
80 | module.exports.nodes = __webpack_require__(10);
|
81 |
|
82 | module.exports.installJinjaCompat = __webpack_require__(18);
|
83 |
|
84 |
|
85 |
|
86 | var e;
|
87 | module.exports.configure = function(templatesPath, opts) {
|
88 | opts = opts || {};
|
89 | if(lib.isObject(templatesPath)) {
|
90 | opts = templatesPath;
|
91 | templatesPath = null;
|
92 | }
|
93 |
|
94 | var TemplateLoader;
|
95 | if(loaders.FileSystemLoader) {
|
96 | TemplateLoader = new loaders.FileSystemLoader(templatesPath, {
|
97 | watch: opts.watch,
|
98 | noCache: opts.noCache
|
99 | });
|
100 | }
|
101 | else if(loaders.WebLoader) {
|
102 | TemplateLoader = new loaders.WebLoader(templatesPath, {
|
103 | useCache: opts.web && opts.web.useCache,
|
104 | async: opts.web && opts.web.async
|
105 | });
|
106 | }
|
107 |
|
108 | e = new env.Environment(TemplateLoader, opts);
|
109 |
|
110 | if(opts && opts.express) {
|
111 | e.express(opts.express);
|
112 | }
|
113 |
|
114 | return e;
|
115 | };
|
116 |
|
117 | module.exports.compile = function(src, env, path, eagerCompile) {
|
118 | if(!e) {
|
119 | module.exports.configure();
|
120 | }
|
121 | return new module.exports.Template(src, env, path, eagerCompile);
|
122 | };
|
123 |
|
124 | module.exports.render = function(name, ctx, cb) {
|
125 | if(!e) {
|
126 | module.exports.configure();
|
127 | }
|
128 |
|
129 | return e.render(name, ctx, cb);
|
130 | };
|
131 |
|
132 | module.exports.renderString = function(src, ctx, cb) {
|
133 | if(!e) {
|
134 | module.exports.configure();
|
135 | }
|
136 |
|
137 | return e.renderString(src, ctx, cb);
|
138 | };
|
139 |
|
140 | if(precompile) {
|
141 | module.exports.precompile = precompile.precompile;
|
142 | module.exports.precompileString = precompile.precompileString;
|
143 | }
|
144 |
|
145 |
|
146 | },
|
147 |
|
148 | function(module, exports) {
|
149 |
|
150 | 'use strict';
|
151 |
|
152 | var ArrayProto = Array.prototype;
|
153 | var ObjProto = Object.prototype;
|
154 |
|
155 | var escapeMap = {
|
156 | '&': '&',
|
157 | '"': '"',
|
158 | '\'': ''',
|
159 | '<': '<',
|
160 | '>': '>'
|
161 | };
|
162 |
|
163 | var escapeRegex = /[&"'<>]/g;
|
164 |
|
165 | var lookupEscape = function(ch) {
|
166 | return escapeMap[ch];
|
167 | };
|
168 |
|
169 | var exports = module.exports = {};
|
170 |
|
171 | exports.prettifyError = function(path, withInternals, err) {
|
172 |
|
173 |
|
174 | if (!err.Update) {
|
175 |
|
176 | err = new exports.TemplateError(err);
|
177 | }
|
178 | err.Update(path);
|
179 |
|
180 |
|
181 | if (!withInternals) {
|
182 | var old = err;
|
183 | err = new Error(old.message);
|
184 | err.name = old.name;
|
185 | }
|
186 |
|
187 | return err;
|
188 | };
|
189 |
|
190 | exports.TemplateError = function(message, lineno, colno) {
|
191 | var err = this;
|
192 |
|
193 | if (message instanceof Error) {
|
194 | err = message;
|
195 | message = message.name + ': ' + message.message;
|
196 |
|
197 | try {
|
198 | if(err.name = '') {}
|
199 | }
|
200 | catch(e) {
|
201 |
|
202 |
|
203 | err = this;
|
204 | }
|
205 | } else {
|
206 | if(Error.captureStackTrace) {
|
207 | Error.captureStackTrace(err);
|
208 | }
|
209 | }
|
210 |
|
211 | err.name = 'Template render error';
|
212 | err.message = message;
|
213 | err.lineno = lineno;
|
214 | err.colno = colno;
|
215 | err.firstUpdate = true;
|
216 |
|
217 | err.Update = function(path) {
|
218 | var message = '(' + (path || 'unknown path') + ')';
|
219 |
|
220 |
|
221 |
|
222 | if (this.firstUpdate) {
|
223 | if(this.lineno && this.colno) {
|
224 | message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']';
|
225 | }
|
226 | else if(this.lineno) {
|
227 | message += ' [Line ' + this.lineno + ']';
|
228 | }
|
229 | }
|
230 |
|
231 | message += '\n ';
|
232 | if (this.firstUpdate) {
|
233 | message += ' ';
|
234 | }
|
235 |
|
236 | this.message = message + (this.message || '');
|
237 | this.firstUpdate = false;
|
238 | return this;
|
239 | };
|
240 |
|
241 | return err;
|
242 | };
|
243 |
|
244 | exports.TemplateError.prototype = Error.prototype;
|
245 |
|
246 | exports.escape = function(val) {
|
247 | return val.replace(escapeRegex, lookupEscape);
|
248 | };
|
249 |
|
250 | exports.isFunction = function(obj) {
|
251 | return ObjProto.toString.call(obj) === '[object Function]';
|
252 | };
|
253 |
|
254 | exports.isArray = Array.isArray || function(obj) {
|
255 | return ObjProto.toString.call(obj) === '[object Array]';
|
256 | };
|
257 |
|
258 | exports.isString = function(obj) {
|
259 | return ObjProto.toString.call(obj) === '[object String]';
|
260 | };
|
261 |
|
262 | exports.isObject = function(obj) {
|
263 | return ObjProto.toString.call(obj) === '[object Object]';
|
264 | };
|
265 |
|
266 | exports.groupBy = function(obj, val) {
|
267 | var result = {};
|
268 | var iterator = exports.isFunction(val) ? val : function(obj) { return obj[val]; };
|
269 | for(var i=0; i<obj.length; i++) {
|
270 | var value = obj[i];
|
271 | var key = iterator(value, i);
|
272 | (result[key] || (result[key] = [])).push(value);
|
273 | }
|
274 | return result;
|
275 | };
|
276 |
|
277 | exports.toArray = function(obj) {
|
278 | return Array.prototype.slice.call(obj);
|
279 | };
|
280 |
|
281 | exports.without = function(array) {
|
282 | var result = [];
|
283 | if (!array) {
|
284 | return result;
|
285 | }
|
286 | var index = -1,
|
287 | length = array.length,
|
288 | contains = exports.toArray(arguments).slice(1);
|
289 |
|
290 | while(++index < length) {
|
291 | if(exports.indexOf(contains, array[index]) === -1) {
|
292 | result.push(array[index]);
|
293 | }
|
294 | }
|
295 | return result;
|
296 | };
|
297 |
|
298 | exports.extend = function(obj, obj2) {
|
299 | for(var k in obj2) {
|
300 | obj[k] = obj2[k];
|
301 | }
|
302 | return obj;
|
303 | };
|
304 |
|
305 | exports.repeat = function(char_, n) {
|
306 | var str = '';
|
307 | for(var i=0; i<n; i++) {
|
308 | str += char_;
|
309 | }
|
310 | return str;
|
311 | };
|
312 |
|
313 | exports.each = function(obj, func, context) {
|
314 | if(obj == null) {
|
315 | return;
|
316 | }
|
317 |
|
318 | if(ArrayProto.each && obj.each === ArrayProto.each) {
|
319 | obj.forEach(func, context);
|
320 | }
|
321 | else if(obj.length === +obj.length) {
|
322 | for(var i=0, l=obj.length; i<l; i++) {
|
323 | func.call(context, obj[i], i, obj);
|
324 | }
|
325 | }
|
326 | };
|
327 |
|
328 | exports.map = function(obj, func) {
|
329 | var results = [];
|
330 | if(obj == null) {
|
331 | return results;
|
332 | }
|
333 |
|
334 | if(ArrayProto.map && obj.map === ArrayProto.map) {
|
335 | return obj.map(func);
|
336 | }
|
337 |
|
338 | for(var i=0; i<obj.length; i++) {
|
339 | results[results.length] = func(obj[i], i);
|
340 | }
|
341 |
|
342 | if(obj.length === +obj.length) {
|
343 | results.length = obj.length;
|
344 | }
|
345 |
|
346 | return results;
|
347 | };
|
348 |
|
349 | exports.asyncIter = function(arr, iter, cb) {
|
350 | var i = -1;
|
351 |
|
352 | function next() {
|
353 | i++;
|
354 |
|
355 | if(i < arr.length) {
|
356 | iter(arr[i], i, next, cb);
|
357 | }
|
358 | else {
|
359 | cb();
|
360 | }
|
361 | }
|
362 |
|
363 | next();
|
364 | };
|
365 |
|
366 | exports.asyncFor = function(obj, iter, cb) {
|
367 | var keys = exports.keys(obj);
|
368 | var len = keys.length;
|
369 | var i = -1;
|
370 |
|
371 | function next() {
|
372 | i++;
|
373 | var k = keys[i];
|
374 |
|
375 | if(i < len) {
|
376 | iter(k, obj[k], i, len, next);
|
377 | }
|
378 | else {
|
379 | cb();
|
380 | }
|
381 | }
|
382 |
|
383 | next();
|
384 | };
|
385 |
|
386 |
|
387 | exports.indexOf = Array.prototype.indexOf ?
|
388 | function (arr, searchElement, fromIndex) {
|
389 | return Array.prototype.indexOf.call(arr, searchElement, fromIndex);
|
390 | } :
|
391 | function (arr, searchElement, fromIndex) {
|
392 | var length = this.length >>> 0;
|
393 |
|
394 | fromIndex = +fromIndex || 0;
|
395 |
|
396 | if(Math.abs(fromIndex) === Infinity) {
|
397 | fromIndex = 0;
|
398 | }
|
399 |
|
400 | if(fromIndex < 0) {
|
401 | fromIndex += length;
|
402 | if (fromIndex < 0) {
|
403 | fromIndex = 0;
|
404 | }
|
405 | }
|
406 |
|
407 | for(;fromIndex < length; fromIndex++) {
|
408 | if (arr[fromIndex] === searchElement) {
|
409 | return fromIndex;
|
410 | }
|
411 | }
|
412 |
|
413 | return -1;
|
414 | };
|
415 |
|
416 | if(!Array.prototype.map) {
|
417 | Array.prototype.map = function() {
|
418 | throw new Error('map is unimplemented for this js engine');
|
419 | };
|
420 | }
|
421 |
|
422 | exports.keys = function(obj) {
|
423 | if(Object.prototype.keys) {
|
424 | return obj.keys();
|
425 | }
|
426 | else {
|
427 | var keys = [];
|
428 | for(var k in obj) {
|
429 | if(obj.hasOwnProperty(k)) {
|
430 | keys.push(k);
|
431 | }
|
432 | }
|
433 | return keys;
|
434 | }
|
435 | };
|
436 |
|
437 | exports.inOperator = function (key, val) {
|
438 | if (exports.isArray(val)) {
|
439 | return exports.indexOf(val, key) !== -1;
|
440 | } else if (exports.isObject(val)) {
|
441 | return key in val;
|
442 | } else if (exports.isString(val)) {
|
443 | return val.indexOf(key) !== -1;
|
444 | } else {
|
445 | throw new Error('Cannot use "in" operator to search for "'
|
446 | + key + '" in unexpected types.');
|
447 | }
|
448 | };
|
449 |
|
450 |
|
451 | },
|
452 |
|
453 | function(module, exports, __webpack_require__) {
|
454 |
|
455 | 'use strict';
|
456 |
|
457 | var path = __webpack_require__(3);
|
458 | var asap = __webpack_require__(4);
|
459 | var lib = __webpack_require__(1);
|
460 | var Obj = __webpack_require__(6);
|
461 | var compiler = __webpack_require__(7);
|
462 | var builtin_filters = __webpack_require__(13);
|
463 | var builtin_loaders = __webpack_require__(14);
|
464 | var runtime = __webpack_require__(12);
|
465 | var globals = __webpack_require__(17);
|
466 | var Frame = runtime.Frame;
|
467 | var Template;
|
468 |
|
469 |
|
470 |
|
471 | builtin_loaders.PrecompiledLoader = __webpack_require__(16);
|
472 |
|
473 |
|
474 |
|
475 | function callbackAsap(cb, err, res) {
|
476 | asap(function() { cb(err, res); });
|
477 | }
|
478 |
|
479 | var Environment = Obj.extend({
|
480 | init: function(loaders, opts) {
|
481 |
|
482 |
|
483 |
|
484 |
|
485 |
|
486 |
|
487 | opts = this.opts = opts || {};
|
488 | this.opts.dev = !!opts.dev;
|
489 |
|
490 |
|
491 |
|
492 |
|
493 |
|
494 | this.opts.autoescape = opts.autoescape != null ? opts.autoescape : true;
|
495 |
|
496 |
|
497 |
|
498 | this.opts.throwOnUndefined = !!opts.throwOnUndefined;
|
499 | this.opts.trimBlocks = !!opts.trimBlocks;
|
500 | this.opts.lstripBlocks = !!opts.lstripBlocks;
|
501 |
|
502 | this.loaders = [];
|
503 |
|
504 | if(!loaders) {
|
505 |
|
506 | if(builtin_loaders.FileSystemLoader) {
|
507 | this.loaders = [new builtin_loaders.FileSystemLoader('views')];
|
508 | }
|
509 | else if(builtin_loaders.WebLoader) {
|
510 | this.loaders = [new builtin_loaders.WebLoader('/views')];
|
511 | }
|
512 | }
|
513 | else {
|
514 | this.loaders = lib.isArray(loaders) ? loaders : [loaders];
|
515 | }
|
516 |
|
517 |
|
518 |
|
519 |
|
520 | if((true) && window.nunjucksPrecompiled) {
|
521 | this.loaders.unshift(
|
522 | new builtin_loaders.PrecompiledLoader(window.nunjucksPrecompiled)
|
523 | );
|
524 | }
|
525 |
|
526 | this.initCache();
|
527 |
|
528 | this.globals = globals();
|
529 | this.filters = {};
|
530 | this.asyncFilters = [];
|
531 | this.extensions = {};
|
532 | this.extensionsList = [];
|
533 |
|
534 | for(var name in builtin_filters) {
|
535 | this.addFilter(name, builtin_filters[name]);
|
536 | }
|
537 | },
|
538 |
|
539 | initCache: function() {
|
540 |
|
541 | lib.each(this.loaders, function(loader) {
|
542 | loader.cache = {};
|
543 |
|
544 | if(typeof loader.on === 'function') {
|
545 | loader.on('update', function(template) {
|
546 | loader.cache[template] = null;
|
547 | });
|
548 | }
|
549 | });
|
550 | },
|
551 |
|
552 | addExtension: function(name, extension) {
|
553 | extension._name = name;
|
554 | this.extensions[name] = extension;
|
555 | this.extensionsList.push(extension);
|
556 | return this;
|
557 | },
|
558 |
|
559 | removeExtension: function(name) {
|
560 | var extension = this.getExtension(name);
|
561 | if (!extension) return;
|
562 |
|
563 | this.extensionsList = lib.without(this.extensionsList, extension);
|
564 | delete this.extensions[name];
|
565 | },
|
566 |
|
567 | getExtension: function(name) {
|
568 | return this.extensions[name];
|
569 | },
|
570 |
|
571 | hasExtension: function(name) {
|
572 | return !!this.extensions[name];
|
573 | },
|
574 |
|
575 | addGlobal: function(name, value) {
|
576 | this.globals[name] = value;
|
577 | return this;
|
578 | },
|
579 |
|
580 | getGlobal: function(name) {
|
581 | if(typeof this.globals[name] === 'undefined') {
|
582 | throw new Error('global not found: ' + name);
|
583 | }
|
584 | return this.globals[name];
|
585 | },
|
586 |
|
587 | addFilter: function(name, func, async) {
|
588 | var wrapped = func;
|
589 |
|
590 | if(async) {
|
591 | this.asyncFilters.push(name);
|
592 | }
|
593 | this.filters[name] = wrapped;
|
594 | return this;
|
595 | },
|
596 |
|
597 | getFilter: function(name) {
|
598 | if(!this.filters[name]) {
|
599 | throw new Error('filter not found: ' + name);
|
600 | }
|
601 | return this.filters[name];
|
602 | },
|
603 |
|
604 | resolveTemplate: function(loader, parentName, filename) {
|
605 | var isRelative = (loader.isRelative && parentName)? loader.isRelative(filename) : false;
|
606 | return (isRelative && loader.resolve)? loader.resolve(parentName, filename) : filename;
|
607 | },
|
608 |
|
609 | getTemplate: function(name, eagerCompile, parentName, ignoreMissing, cb) {
|
610 | var that = this;
|
611 | var tmpl = null;
|
612 | if(name && name.raw) {
|
613 |
|
614 | name = name.raw;
|
615 | }
|
616 |
|
617 | if(lib.isFunction(parentName)) {
|
618 | cb = parentName;
|
619 | parentName = null;
|
620 | eagerCompile = eagerCompile || false;
|
621 | }
|
622 |
|
623 | if(lib.isFunction(eagerCompile)) {
|
624 | cb = eagerCompile;
|
625 | eagerCompile = false;
|
626 | }
|
627 |
|
628 | if (name instanceof Template) {
|
629 | tmpl = name;
|
630 | }
|
631 | else if(typeof name !== 'string') {
|
632 | throw new Error('template names must be a string: ' + name);
|
633 | }
|
634 | else {
|
635 | for (var i = 0; i < this.loaders.length; i++) {
|
636 | var _name = this.resolveTemplate(this.loaders[i], parentName, name);
|
637 | tmpl = this.loaders[i].cache[_name];
|
638 | if (tmpl) break;
|
639 | }
|
640 | }
|
641 |
|
642 | if(tmpl) {
|
643 | if(eagerCompile) {
|
644 | tmpl.compile();
|
645 | }
|
646 |
|
647 | if(cb) {
|
648 | cb(null, tmpl);
|
649 | }
|
650 | else {
|
651 | return tmpl;
|
652 | }
|
653 | } else {
|
654 | var syncResult;
|
655 | var _this = this;
|
656 |
|
657 | var createTemplate = function(err, info) {
|
658 | if(!info && !err) {
|
659 | if(!ignoreMissing) {
|
660 | err = new Error('template not found: ' + name);
|
661 | }
|
662 | }
|
663 |
|
664 | if (err) {
|
665 | if(cb) {
|
666 | cb(err);
|
667 | }
|
668 | else {
|
669 | throw err;
|
670 | }
|
671 | }
|
672 | else {
|
673 | var tmpl;
|
674 | if(info) {
|
675 | tmpl = new Template(info.src, _this,
|
676 | info.path, eagerCompile);
|
677 |
|
678 | if(!info.noCache) {
|
679 | info.loader.cache[name] = tmpl;
|
680 | }
|
681 | }
|
682 | else {
|
683 | tmpl = new Template('', _this,
|
684 | '', eagerCompile);
|
685 | }
|
686 |
|
687 | if(cb) {
|
688 | cb(null, tmpl);
|
689 | }
|
690 | else {
|
691 | syncResult = tmpl;
|
692 | }
|
693 | }
|
694 | };
|
695 |
|
696 | lib.asyncIter(this.loaders, function(loader, i, next, done) {
|
697 | function handle(err, src) {
|
698 | if(err) {
|
699 | done(err);
|
700 | }
|
701 | else if(src) {
|
702 | src.loader = loader;
|
703 | done(null, src);
|
704 | }
|
705 | else {
|
706 | next();
|
707 | }
|
708 | }
|
709 |
|
710 |
|
711 | name = that.resolveTemplate(loader, parentName, name);
|
712 |
|
713 | if(loader.async) {
|
714 | loader.getSource(name, handle);
|
715 | }
|
716 | else {
|
717 | handle(null, loader.getSource(name));
|
718 | }
|
719 | }, createTemplate);
|
720 |
|
721 | return syncResult;
|
722 | }
|
723 | },
|
724 |
|
725 | express: function(app) {
|
726 | var env = this;
|
727 |
|
728 | function NunjucksView(name, opts) {
|
729 | this.name = name;
|
730 | this.path = name;
|
731 | this.defaultEngine = opts.defaultEngine;
|
732 | this.ext = path.extname(name);
|
733 | if (!this.ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
|
734 | if (!this.ext) this.name += (this.ext = ('.' !== this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
|
735 | }
|
736 |
|
737 | NunjucksView.prototype.render = function(opts, cb) {
|
738 | env.render(this.name, opts, cb);
|
739 | };
|
740 |
|
741 | app.set('view', NunjucksView);
|
742 | app.set('nunjucksEnv', this);
|
743 | return this;
|
744 | },
|
745 |
|
746 | render: function(name, ctx, cb) {
|
747 | if(lib.isFunction(ctx)) {
|
748 | cb = ctx;
|
749 | ctx = null;
|
750 | }
|
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 | var syncResult = null;
|
757 |
|
758 | this.getTemplate(name, function(err, tmpl) {
|
759 | if(err && cb) {
|
760 | callbackAsap(cb, err);
|
761 | }
|
762 | else if(err) {
|
763 | throw err;
|
764 | }
|
765 | else {
|
766 | syncResult = tmpl.render(ctx, cb);
|
767 | }
|
768 | });
|
769 |
|
770 | return syncResult;
|
771 | },
|
772 |
|
773 | renderString: function(src, ctx, opts, cb) {
|
774 | if(lib.isFunction(opts)) {
|
775 | cb = opts;
|
776 | opts = {};
|
777 | }
|
778 | opts = opts || {};
|
779 |
|
780 | var tmpl = new Template(src, this, opts.path);
|
781 | return tmpl.render(ctx, cb);
|
782 | }
|
783 | });
|
784 |
|
785 | var Context = Obj.extend({
|
786 | init: function(ctx, blocks, env) {
|
787 |
|
788 | this.env = env || new Environment();
|
789 |
|
790 |
|
791 | this.ctx = {};
|
792 | for(var k in ctx) {
|
793 | if(ctx.hasOwnProperty(k)) {
|
794 | this.ctx[k] = ctx[k];
|
795 | }
|
796 | }
|
797 |
|
798 | this.blocks = {};
|
799 | this.exported = [];
|
800 |
|
801 | for(var name in blocks) {
|
802 | this.addBlock(name, blocks[name]);
|
803 | }
|
804 | },
|
805 |
|
806 | lookup: function(name) {
|
807 |
|
808 |
|
809 | if(name in this.env.globals && !(name in this.ctx)) {
|
810 | return this.env.globals[name];
|
811 | }
|
812 | else {
|
813 | return this.ctx[name];
|
814 | }
|
815 | },
|
816 |
|
817 | setVariable: function(name, val) {
|
818 | this.ctx[name] = val;
|
819 | },
|
820 |
|
821 | getVariables: function() {
|
822 | return this.ctx;
|
823 | },
|
824 |
|
825 | addBlock: function(name, block) {
|
826 | this.blocks[name] = this.blocks[name] || [];
|
827 | this.blocks[name].push(block);
|
828 | return this;
|
829 | },
|
830 |
|
831 | getBlock: function(name) {
|
832 | if(!this.blocks[name]) {
|
833 | throw new Error('unknown block "' + name + '"');
|
834 | }
|
835 |
|
836 | return this.blocks[name][0];
|
837 | },
|
838 |
|
839 | getSuper: function(env, name, block, frame, runtime, cb) {
|
840 | var idx = lib.indexOf(this.blocks[name] || [], block);
|
841 | var blk = this.blocks[name][idx + 1];
|
842 | var context = this;
|
843 |
|
844 | if(idx === -1 || !blk) {
|
845 | throw new Error('no super block available for "' + name + '"');
|
846 | }
|
847 |
|
848 | blk(env, context, frame, runtime, cb);
|
849 | },
|
850 |
|
851 | addExport: function(name) {
|
852 | this.exported.push(name);
|
853 | },
|
854 |
|
855 | getExported: function() {
|
856 | var exported = {};
|
857 | for(var i=0; i<this.exported.length; i++) {
|
858 | var name = this.exported[i];
|
859 | exported[name] = this.ctx[name];
|
860 | }
|
861 | return exported;
|
862 | }
|
863 | });
|
864 |
|
865 | Template = Obj.extend({
|
866 | init: function (src, env, path, eagerCompile) {
|
867 | this.env = env || new Environment();
|
868 |
|
869 | if(lib.isObject(src)) {
|
870 | switch(src.type) {
|
871 | case 'code': this.tmplProps = src.obj; break;
|
872 | case 'string': this.tmplStr = src.obj; break;
|
873 | }
|
874 | }
|
875 | else if(lib.isString(src)) {
|
876 | this.tmplStr = src;
|
877 | }
|
878 | else {
|
879 | throw new Error('src must be a string or an object describing ' +
|
880 | 'the source');
|
881 | }
|
882 |
|
883 | this.path = path;
|
884 |
|
885 | if(eagerCompile) {
|
886 | var _this = this;
|
887 | try {
|
888 | _this._compile();
|
889 | }
|
890 | catch(err) {
|
891 | throw lib.prettifyError(this.path, this.env.opts.dev, err);
|
892 | }
|
893 | }
|
894 | else {
|
895 | this.compiled = false;
|
896 | }
|
897 | },
|
898 |
|
899 | render: function(ctx, parentFrame, cb) {
|
900 | if (typeof ctx === 'function') {
|
901 | cb = ctx;
|
902 | ctx = {};
|
903 | }
|
904 | else if (typeof parentFrame === 'function') {
|
905 | cb = parentFrame;
|
906 | parentFrame = null;
|
907 | }
|
908 |
|
909 | var forceAsync = true;
|
910 | if(parentFrame) {
|
911 |
|
912 |
|
913 |
|
914 |
|
915 | forceAsync = false;
|
916 | }
|
917 |
|
918 | var _this = this;
|
919 |
|
920 | try {
|
921 | _this.compile();
|
922 | } catch (_err) {
|
923 | var err = lib.prettifyError(this.path, this.env.opts.dev, _err);
|
924 | if (cb) return callbackAsap(cb, err);
|
925 | else throw err;
|
926 | }
|
927 |
|
928 | var context = new Context(ctx || {}, _this.blocks, _this.env);
|
929 | var frame = parentFrame ? parentFrame.push(true) : new Frame();
|
930 | frame.topLevel = true;
|
931 | var syncResult = null;
|
932 |
|
933 | _this.rootRenderFunc(
|
934 | _this.env,
|
935 | context,
|
936 | frame || new Frame(),
|
937 | runtime,
|
938 | function(err, res) {
|
939 | if(err) {
|
940 | err = lib.prettifyError(_this.path, _this.env.opts.dev, err);
|
941 | }
|
942 |
|
943 | if(cb) {
|
944 | if(forceAsync) {
|
945 | callbackAsap(cb, err, res);
|
946 | }
|
947 | else {
|
948 | cb(err, res);
|
949 | }
|
950 | }
|
951 | else {
|
952 | if(err) { throw err; }
|
953 | syncResult = res;
|
954 | }
|
955 | }
|
956 | );
|
957 |
|
958 | return syncResult;
|
959 | },
|
960 |
|
961 |
|
962 | getExported: function(ctx, parentFrame, cb) {
|
963 | if (typeof ctx === 'function') {
|
964 | cb = ctx;
|
965 | ctx = {};
|
966 | }
|
967 |
|
968 | if (typeof parentFrame === 'function') {
|
969 | cb = parentFrame;
|
970 | parentFrame = null;
|
971 | }
|
972 |
|
973 |
|
974 | try {
|
975 | this.compile();
|
976 | } catch (e) {
|
977 | if (cb) return cb(e);
|
978 | else throw e;
|
979 | }
|
980 |
|
981 | var frame = parentFrame ? parentFrame.push() : new Frame();
|
982 | frame.topLevel = true;
|
983 |
|
984 |
|
985 | var context = new Context(ctx || {}, this.blocks, this.env);
|
986 | this.rootRenderFunc(this.env,
|
987 | context,
|
988 | frame,
|
989 | runtime,
|
990 | function(err) {
|
991 | if ( err ) {
|
992 | cb(err, null);
|
993 | } else {
|
994 | cb(null, context.getExported());
|
995 | }
|
996 | });
|
997 | },
|
998 |
|
999 | compile: function() {
|
1000 | if(!this.compiled) {
|
1001 | this._compile();
|
1002 | }
|
1003 | },
|
1004 |
|
1005 | _compile: function() {
|
1006 | var props;
|
1007 |
|
1008 | if(this.tmplProps) {
|
1009 | props = this.tmplProps;
|
1010 | }
|
1011 | else {
|
1012 | var source = compiler.compile(this.tmplStr,
|
1013 | this.env.asyncFilters,
|
1014 | this.env.extensionsList,
|
1015 | this.path,
|
1016 | this.env.opts);
|
1017 |
|
1018 |
|
1019 | var func = new Function(source);
|
1020 | props = func();
|
1021 | }
|
1022 |
|
1023 | this.blocks = this._getBlocks(props);
|
1024 | this.rootRenderFunc = props.root;
|
1025 | this.compiled = true;
|
1026 | },
|
1027 |
|
1028 | _getBlocks: function(props) {
|
1029 | var blocks = {};
|
1030 |
|
1031 | for(var k in props) {
|
1032 | if(k.slice(0, 2) === 'b_') {
|
1033 | blocks[k.slice(2)] = props[k];
|
1034 | }
|
1035 | }
|
1036 |
|
1037 | return blocks;
|
1038 | }
|
1039 | });
|
1040 |
|
1041 | module.exports = {
|
1042 | Environment: Environment,
|
1043 | Template: Template
|
1044 | };
|
1045 |
|
1046 |
|
1047 | },
|
1048 |
|
1049 | function(module, exports) {
|
1050 |
|
1051 |
|
1052 |
|
1053 | },
|
1054 |
|
1055 | function(module, exports, __webpack_require__) {
|
1056 |
|
1057 | "use strict";
|
1058 |
|
1059 |
|
1060 | var rawAsap = __webpack_require__(5);
|
1061 |
|
1062 | var freeTasks = [];
|
1063 |
|
1064 |
|
1065 | var pendingErrors = [];
|
1066 | var requestErrorThrow = rawAsap.makeRequestCallFromTimer(throwFirstError);
|
1067 |
|
1068 | function throwFirstError() {
|
1069 | if (pendingErrors.length) {
|
1070 | throw pendingErrors.shift();
|
1071 | }
|
1072 | }
|
1073 |
|
1074 | |
1075 |
|
1076 |
|
1077 |
|
1078 |
|
1079 |
|
1080 |
|
1081 |
|
1082 | module.exports = asap;
|
1083 | function asap(task) {
|
1084 | var rawTask;
|
1085 | if (freeTasks.length) {
|
1086 | rawTask = freeTasks.pop();
|
1087 | } else {
|
1088 | rawTask = new RawTask();
|
1089 | }
|
1090 | rawTask.task = task;
|
1091 | rawAsap(rawTask);
|
1092 | }
|
1093 |
|
1094 |
|
1095 |
|
1096 | function RawTask() {
|
1097 | this.task = null;
|
1098 | }
|
1099 |
|
1100 |
|
1101 |
|
1102 | RawTask.prototype.call = function () {
|
1103 | try {
|
1104 | this.task.call();
|
1105 | } catch (error) {
|
1106 | if (asap.onerror) {
|
1107 |
|
1108 |
|
1109 |
|
1110 | asap.onerror(error);
|
1111 | } else {
|
1112 |
|
1113 |
|
1114 |
|
1115 | pendingErrors.push(error);
|
1116 | requestErrorThrow();
|
1117 | }
|
1118 | } finally {
|
1119 | this.task = null;
|
1120 | freeTasks[freeTasks.length] = this;
|
1121 | }
|
1122 | };
|
1123 |
|
1124 |
|
1125 | },
|
1126 |
|
1127 | function(module, exports) {
|
1128 |
|
1129 | (function(global) {"use strict";
|
1130 |
|
1131 |
|
1132 |
|
1133 |
|
1134 |
|
1135 |
|
1136 |
|
1137 |
|
1138 |
|
1139 |
|
1140 |
|
1141 | module.exports = rawAsap;
|
1142 | function rawAsap(task) {
|
1143 | if (!queue.length) {
|
1144 | requestFlush();
|
1145 | flushing = true;
|
1146 | }
|
1147 |
|
1148 | queue[queue.length] = task;
|
1149 | }
|
1150 |
|
1151 | var queue = [];
|
1152 |
|
1153 |
|
1154 | var flushing = false;
|
1155 |
|
1156 |
|
1157 |
|
1158 | var requestFlush;
|
1159 |
|
1160 |
|
1161 |
|
1162 | var index = 0;
|
1163 |
|
1164 |
|
1165 |
|
1166 | var capacity = 1024;
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 |
|
1172 |
|
1173 |
|
1174 | function flush() {
|
1175 | while (index < queue.length) {
|
1176 | var currentIndex = index;
|
1177 |
|
1178 |
|
1179 | index = index + 1;
|
1180 | queue[currentIndex].call();
|
1181 |
|
1182 |
|
1183 |
|
1184 |
|
1185 |
|
1186 | if (index > capacity) {
|
1187 |
|
1188 |
|
1189 | for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) {
|
1190 | queue[scan] = queue[scan + index];
|
1191 | }
|
1192 | queue.length -= index;
|
1193 | index = 0;
|
1194 | }
|
1195 | }
|
1196 | queue.length = 0;
|
1197 | index = 0;
|
1198 | flushing = false;
|
1199 | }
|
1200 |
|
1201 |
|
1202 |
|
1203 |
|
1204 |
|
1205 |
|
1206 |
|
1207 |
|
1208 |
|
1209 | var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver;
|
1210 |
|
1211 |
|
1212 |
|
1213 |
|
1214 |
|
1215 |
|
1216 |
|
1217 |
|
1218 |
|
1219 |
|
1220 |
|
1221 |
|
1222 | if (typeof BrowserMutationObserver === "function") {
|
1223 | requestFlush = makeRequestCallFromMutationObserver(flush);
|
1224 |
|
1225 |
|
1226 |
|
1227 |
|
1228 |
|
1229 |
|
1230 |
|
1231 |
|
1232 |
|
1233 |
|
1234 |
|
1235 |
|
1236 |
|
1237 |
|
1238 |
|
1239 |
|
1240 |
|
1241 |
|
1242 |
|
1243 |
|
1244 |
|
1245 |
|
1246 |
|
1247 |
|
1248 |
|
1249 |
|
1250 |
|
1251 |
|
1252 | } else {
|
1253 | requestFlush = makeRequestCallFromTimer(flush);
|
1254 | }
|
1255 |
|
1256 |
|
1257 |
|
1258 |
|
1259 |
|
1260 |
|
1261 | rawAsap.requestFlush = requestFlush;
|
1262 |
|
1263 |
|
1264 |
|
1265 | function makeRequestCallFromMutationObserver(callback) {
|
1266 | var toggle = 1;
|
1267 | var observer = new BrowserMutationObserver(callback);
|
1268 | var node = document.createTextNode("");
|
1269 | observer.observe(node, {characterData: true});
|
1270 | return function requestCall() {
|
1271 | toggle = -toggle;
|
1272 | node.data = toggle;
|
1273 | };
|
1274 | }
|
1275 |
|
1276 |
|
1277 |
|
1278 |
|
1279 |
|
1280 |
|
1281 |
|
1282 |
|
1283 |
|
1284 |
|
1285 |
|
1286 |
|
1287 |
|
1288 |
|
1289 |
|
1290 |
|
1291 |
|
1292 |
|
1293 |
|
1294 |
|
1295 |
|
1296 |
|
1297 |
|
1298 |
|
1299 |
|
1300 |
|
1301 |
|
1302 |
|
1303 |
|
1304 |
|
1305 |
|
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 |
|
1313 |
|
1314 |
|
1315 |
|
1316 | function makeRequestCallFromTimer(callback) {
|
1317 | return function requestCall() {
|
1318 |
|
1319 |
|
1320 |
|
1321 |
|
1322 | var timeoutHandle = setTimeout(handleTimer, 0);
|
1323 |
|
1324 |
|
1325 |
|
1326 | var intervalHandle = setInterval(handleTimer, 50);
|
1327 |
|
1328 | function handleTimer() {
|
1329 |
|
1330 |
|
1331 | clearTimeout(timeoutHandle);
|
1332 | clearInterval(intervalHandle);
|
1333 | callback();
|
1334 | }
|
1335 | };
|
1336 | }
|
1337 |
|
1338 |
|
1339 |
|
1340 |
|
1341 | rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;
|
1342 |
|
1343 |
|
1344 |
|
1345 |
|
1346 |
|
1347 |
|
1348 |
|
1349 |
|
1350 | }.call(exports, (function() { return this; }())))
|
1351 |
|
1352 | },
|
1353 |
|
1354 | function(module, exports) {
|
1355 |
|
1356 | 'use strict';
|
1357 |
|
1358 |
|
1359 |
|
1360 | function extend(cls, name, props) {
|
1361 |
|
1362 | var F = function() {};
|
1363 | F.prototype = cls.prototype;
|
1364 | var prototype = new F();
|
1365 |
|
1366 |
|
1367 | var fnTest = /xyz/.test(function(){ xyz; }) ? /\bparent\b/ : /.*/;
|
1368 | props = props || {};
|
1369 |
|
1370 | for(var k in props) {
|
1371 | var src = props[k];
|
1372 | var parent = prototype[k];
|
1373 |
|
1374 | if(typeof parent === 'function' &&
|
1375 | typeof src === 'function' &&
|
1376 | fnTest.test(src)) {
|
1377 |
|
1378 | prototype[k] = (function (src, parent) {
|
1379 | return function() {
|
1380 |
|
1381 | var tmp = this.parent;
|
1382 |
|
1383 |
|
1384 | this.parent = parent;
|
1385 | var res = src.apply(this, arguments);
|
1386 | this.parent = tmp;
|
1387 |
|
1388 | return res;
|
1389 | };
|
1390 | })(src, parent);
|
1391 | }
|
1392 | else {
|
1393 | prototype[k] = src;
|
1394 | }
|
1395 | }
|
1396 |
|
1397 | prototype.typename = name;
|
1398 |
|
1399 | var new_cls = function() {
|
1400 | if(prototype.init) {
|
1401 | prototype.init.apply(this, arguments);
|
1402 | }
|
1403 | };
|
1404 |
|
1405 | new_cls.prototype = prototype;
|
1406 | new_cls.prototype.constructor = new_cls;
|
1407 |
|
1408 | new_cls.extend = function(name, props) {
|
1409 | if(typeof name === 'object') {
|
1410 | props = name;
|
1411 | name = 'anonymous';
|
1412 | }
|
1413 | return extend(new_cls, name, props);
|
1414 | };
|
1415 |
|
1416 | return new_cls;
|
1417 | }
|
1418 |
|
1419 | module.exports = extend(Object, 'Object', {});
|
1420 |
|
1421 |
|
1422 | },
|
1423 |
|
1424 | function(module, exports, __webpack_require__) {
|
1425 |
|
1426 | 'use strict';
|
1427 |
|
1428 | var lib = __webpack_require__(1);
|
1429 | var parser = __webpack_require__(8);
|
1430 | var transformer = __webpack_require__(11);
|
1431 | var nodes = __webpack_require__(10);
|
1432 |
|
1433 | var Object = __webpack_require__(6);
|
1434 | var Frame = __webpack_require__(12).Frame;
|
1435 |
|
1436 |
|
1437 |
|
1438 | var compareOps = {
|
1439 | '==': '==',
|
1440 | '===': '===',
|
1441 | '!=': '!=',
|
1442 | '!==': '!==',
|
1443 | '<': '<',
|
1444 | '>': '>',
|
1445 | '<=': '<=',
|
1446 | '>=': '>='
|
1447 | };
|
1448 |
|
1449 |
|
1450 | function binOpEmitter(str) {
|
1451 | return function(node, frame) {
|
1452 | this.compile(node.left, frame);
|
1453 | this.emit(str);
|
1454 | this.compile(node.right, frame);
|
1455 | };
|
1456 | }
|
1457 |
|
1458 | var Compiler = Object.extend({
|
1459 | init: function(templateName, throwOnUndefined) {
|
1460 | this.templateName = templateName;
|
1461 | this.codebuf = [];
|
1462 | this.lastId = 0;
|
1463 | this.buffer = null;
|
1464 | this.bufferStack = [];
|
1465 | this.scopeClosers = '';
|
1466 | this.inBlock = false;
|
1467 | this.throwOnUndefined = throwOnUndefined;
|
1468 | },
|
1469 |
|
1470 | fail: function (msg, lineno, colno) {
|
1471 | if (lineno !== undefined) lineno += 1;
|
1472 | if (colno !== undefined) colno += 1;
|
1473 |
|
1474 | throw new lib.TemplateError(msg, lineno, colno);
|
1475 | },
|
1476 |
|
1477 | pushBufferId: function(id) {
|
1478 | this.bufferStack.push(this.buffer);
|
1479 | this.buffer = id;
|
1480 | this.emit('var ' + this.buffer + ' = "";');
|
1481 | },
|
1482 |
|
1483 | popBufferId: function() {
|
1484 | this.buffer = this.bufferStack.pop();
|
1485 | },
|
1486 |
|
1487 | emit: function(code) {
|
1488 | this.codebuf.push(code);
|
1489 | },
|
1490 |
|
1491 | emitLine: function(code) {
|
1492 | this.emit(code + '\n');
|
1493 | },
|
1494 |
|
1495 | emitLines: function() {
|
1496 | lib.each(lib.toArray(arguments), function(line) {
|
1497 | this.emitLine(line);
|
1498 | }, this);
|
1499 | },
|
1500 |
|
1501 | emitFuncBegin: function(name) {
|
1502 | this.buffer = 'output';
|
1503 | this.scopeClosers = '';
|
1504 | this.emitLine('function ' + name + '(env, context, frame, runtime, cb) {');
|
1505 | this.emitLine('var lineno = null;');
|
1506 | this.emitLine('var colno = null;');
|
1507 | this.emitLine('var ' + this.buffer + ' = "";');
|
1508 | this.emitLine('try {');
|
1509 | },
|
1510 |
|
1511 | emitFuncEnd: function(noReturn) {
|
1512 | if(!noReturn) {
|
1513 | this.emitLine('cb(null, ' + this.buffer +');');
|
1514 | }
|
1515 |
|
1516 | this.closeScopeLevels();
|
1517 | this.emitLine('} catch (e) {');
|
1518 | this.emitLine(' cb(runtime.handleError(e, lineno, colno));');
|
1519 | this.emitLine('}');
|
1520 | this.emitLine('}');
|
1521 | this.buffer = null;
|
1522 | },
|
1523 |
|
1524 | addScopeLevel: function() {
|
1525 | this.scopeClosers += '})';
|
1526 | },
|
1527 |
|
1528 | closeScopeLevels: function() {
|
1529 | this.emitLine(this.scopeClosers + ';');
|
1530 | this.scopeClosers = '';
|
1531 | },
|
1532 |
|
1533 | withScopedSyntax: function(func) {
|
1534 | var scopeClosers = this.scopeClosers;
|
1535 | this.scopeClosers = '';
|
1536 |
|
1537 | func.call(this);
|
1538 |
|
1539 | this.closeScopeLevels();
|
1540 | this.scopeClosers = scopeClosers;
|
1541 | },
|
1542 |
|
1543 | makeCallback: function(res) {
|
1544 | var err = this.tmpid();
|
1545 |
|
1546 | return 'function(' + err + (res ? ',' + res : '') + ') {\n' +
|
1547 | 'if(' + err + ') { cb(' + err + '); return; }';
|
1548 | },
|
1549 |
|
1550 | tmpid: function() {
|
1551 | this.lastId++;
|
1552 | return 't_' + this.lastId;
|
1553 | },
|
1554 |
|
1555 | _templateName: function() {
|
1556 | return this.templateName == null? 'undefined' : JSON.stringify(this.templateName);
|
1557 | },
|
1558 |
|
1559 | _compileChildren: function(node, frame) {
|
1560 | var children = node.children;
|
1561 | for(var i=0, l=children.length; i<l; i++) {
|
1562 | this.compile(children[i], frame);
|
1563 | }
|
1564 | },
|
1565 |
|
1566 | _compileAggregate: function(node, frame, startChar, endChar) {
|
1567 | if(startChar) {
|
1568 | this.emit(startChar);
|
1569 | }
|
1570 |
|
1571 | for(var i=0; i<node.children.length; i++) {
|
1572 | if(i > 0) {
|
1573 | this.emit(',');
|
1574 | }
|
1575 |
|
1576 | this.compile(node.children[i], frame);
|
1577 | }
|
1578 |
|
1579 | if(endChar) {
|
1580 | this.emit(endChar);
|
1581 | }
|
1582 | },
|
1583 |
|
1584 | _compileExpression: function(node, frame) {
|
1585 |
|
1586 |
|
1587 | this.assertType(
|
1588 | node,
|
1589 | nodes.Literal,
|
1590 | nodes.Symbol,
|
1591 | nodes.Group,
|
1592 | nodes.Array,
|
1593 | nodes.Dict,
|
1594 | nodes.FunCall,
|
1595 | nodes.Caller,
|
1596 | nodes.Filter,
|
1597 | nodes.LookupVal,
|
1598 | nodes.Compare,
|
1599 | nodes.InlineIf,
|
1600 | nodes.In,
|
1601 | nodes.And,
|
1602 | nodes.Or,
|
1603 | nodes.Not,
|
1604 | nodes.Add,
|
1605 | nodes.Concat,
|
1606 | nodes.Sub,
|
1607 | nodes.Mul,
|
1608 | nodes.Div,
|
1609 | nodes.FloorDiv,
|
1610 | nodes.Mod,
|
1611 | nodes.Pow,
|
1612 | nodes.Neg,
|
1613 | nodes.Pos,
|
1614 | nodes.Compare,
|
1615 | nodes.NodeList
|
1616 | );
|
1617 | this.compile(node, frame);
|
1618 | },
|
1619 |
|
1620 | assertType: function(node /*, types */) {
|
1621 | var types = lib.toArray(arguments).slice(1);
|
1622 | var success = false;
|
1623 |
|
1624 | for(var i=0; i<types.length; i++) {
|
1625 | if(node instanceof types[i]) {
|
1626 | success = true;
|
1627 | }
|
1628 | }
|
1629 |
|
1630 | if(!success) {
|
1631 | this.fail('assertType: invalid type: ' + node.typename,
|
1632 | node.lineno,
|
1633 | node.colno);
|
1634 | }
|
1635 | },
|
1636 |
|
1637 | compileCallExtension: function(node, frame, async) {
|
1638 | var args = node.args;
|
1639 | var contentArgs = node.contentArgs;
|
1640 | var autoescape = typeof node.autoescape === 'boolean' ? node.autoescape : true;
|
1641 |
|
1642 | if(!async) {
|
1643 | this.emit(this.buffer + ' += runtime.suppressValue(');
|
1644 | }
|
1645 |
|
1646 | this.emit('env.getExtension("' + node.extName + '")["' + node.prop + '"](');
|
1647 | this.emit('context');
|
1648 |
|
1649 | if(args || contentArgs) {
|
1650 | this.emit(',');
|
1651 | }
|
1652 |
|
1653 | if(args) {
|
1654 | if(!(args instanceof nodes.NodeList)) {
|
1655 | this.fail('compileCallExtension: arguments must be a NodeList, ' +
|
1656 | 'use `parser.parseSignature`');
|
1657 | }
|
1658 |
|
1659 | lib.each(args.children, function(arg, i) {
|
1660 |
|
1661 |
|
1662 |
|
1663 | this._compileExpression(arg, frame);
|
1664 |
|
1665 | if(i !== args.children.length - 1 || contentArgs.length) {
|
1666 | this.emit(',');
|
1667 | }
|
1668 | }, this);
|
1669 | }
|
1670 |
|
1671 | if(contentArgs.length) {
|
1672 | lib.each(contentArgs, function(arg, i) {
|
1673 | if(i > 0) {
|
1674 | this.emit(',');
|
1675 | }
|
1676 |
|
1677 | if(arg) {
|
1678 | var id = this.tmpid();
|
1679 |
|
1680 | this.emitLine('function(cb) {');
|
1681 | this.emitLine('if(!cb) { cb = function(err) { if(err) { throw err; }}}');
|
1682 | this.pushBufferId(id);
|
1683 |
|
1684 | this.withScopedSyntax(function() {
|
1685 | this.compile(arg, frame);
|
1686 | this.emitLine('cb(null, ' + id + ');');
|
1687 | });
|
1688 |
|
1689 | this.popBufferId();
|
1690 | this.emitLine('return ' + id + ';');
|
1691 | this.emitLine('}');
|
1692 | }
|
1693 | else {
|
1694 | this.emit('null');
|
1695 | }
|
1696 | }, this);
|
1697 | }
|
1698 |
|
1699 | if(async) {
|
1700 | var res = this.tmpid();
|
1701 | this.emitLine(', ' + this.makeCallback(res));
|
1702 | this.emitLine(this.buffer + ' += runtime.suppressValue(' + res + ', ' + autoescape + ' && env.opts.autoescape);');
|
1703 | this.addScopeLevel();
|
1704 | }
|
1705 | else {
|
1706 | this.emit(')');
|
1707 | this.emit(', ' + autoescape + ' && env.opts.autoescape);\n');
|
1708 | }
|
1709 | },
|
1710 |
|
1711 | compileCallExtensionAsync: function(node, frame) {
|
1712 | this.compileCallExtension(node, frame, true);
|
1713 | },
|
1714 |
|
1715 | compileNodeList: function(node, frame) {
|
1716 | this._compileChildren(node, frame);
|
1717 | },
|
1718 |
|
1719 | compileLiteral: function(node) {
|
1720 | if(typeof node.value === 'string') {
|
1721 | var val = node.value.replace(/\\/g, '\\\\');
|
1722 | val = val.replace(/"/g, '\\"');
|
1723 | val = val.replace(/\n/g, '\\n');
|
1724 | val = val.replace(/\r/g, '\\r');
|
1725 | val = val.replace(/\t/g, '\\t');
|
1726 | this.emit('"' + val + '"');
|
1727 | }
|
1728 | else if (node.value === null) {
|
1729 | this.emit('null');
|
1730 | }
|
1731 | else {
|
1732 | this.emit(node.value.toString());
|
1733 | }
|
1734 | },
|
1735 |
|
1736 | compileSymbol: function(node, frame) {
|
1737 | var name = node.value;
|
1738 | var v;
|
1739 |
|
1740 | if((v = frame.lookup(name))) {
|
1741 | this.emit(v);
|
1742 | }
|
1743 | else {
|
1744 | this.emit('runtime.contextOrFrameLookup(' +
|
1745 | 'context, frame, "' + name + '")');
|
1746 | }
|
1747 | },
|
1748 |
|
1749 | compileGroup: function(node, frame) {
|
1750 | this._compileAggregate(node, frame, '(', ')');
|
1751 | },
|
1752 |
|
1753 | compileArray: function(node, frame) {
|
1754 | this._compileAggregate(node, frame, '[', ']');
|
1755 | },
|
1756 |
|
1757 | compileDict: function(node, frame) {
|
1758 | this._compileAggregate(node, frame, '{', '}');
|
1759 | },
|
1760 |
|
1761 | compilePair: function(node, frame) {
|
1762 | var key = node.key;
|
1763 | var val = node.value;
|
1764 |
|
1765 | if(key instanceof nodes.Symbol) {
|
1766 | key = new nodes.Literal(key.lineno, key.colno, key.value);
|
1767 | }
|
1768 | else if(!(key instanceof nodes.Literal &&
|
1769 | typeof key.value === 'string')) {
|
1770 | this.fail('compilePair: Dict keys must be strings or names',
|
1771 | key.lineno,
|
1772 | key.colno);
|
1773 | }
|
1774 |
|
1775 | this.compile(key, frame);
|
1776 | this.emit(': ');
|
1777 | this._compileExpression(val, frame);
|
1778 | },
|
1779 |
|
1780 | compileInlineIf: function(node, frame) {
|
1781 | this.emit('(');
|
1782 | this.compile(node.cond, frame);
|
1783 | this.emit('?');
|
1784 | this.compile(node.body, frame);
|
1785 | this.emit(':');
|
1786 | if(node.else_ !== null)
|
1787 | this.compile(node.else_, frame);
|
1788 | else
|
1789 | this.emit('""');
|
1790 | this.emit(')');
|
1791 | },
|
1792 |
|
1793 | compileIn: function(node, frame) {
|
1794 | this.emit('runtime.inOperator(');
|
1795 | this.compile(node.left, frame);
|
1796 | this.emit(',');
|
1797 | this.compile(node.right, frame);
|
1798 | this.emit(')');
|
1799 | },
|
1800 |
|
1801 | compileOr: binOpEmitter(' || '),
|
1802 | compileAnd: binOpEmitter(' && '),
|
1803 | compileAdd: binOpEmitter(' + '),
|
1804 |
|
1805 |
|
1806 | compileConcat: binOpEmitter(' + "" + '),
|
1807 | compileSub: binOpEmitter(' - '),
|
1808 | compileMul: binOpEmitter(' * '),
|
1809 | compileDiv: binOpEmitter(' / '),
|
1810 | compileMod: binOpEmitter(' % '),
|
1811 |
|
1812 | compileNot: function(node, frame) {
|
1813 | this.emit('!');
|
1814 | this.compile(node.target, frame);
|
1815 | },
|
1816 |
|
1817 | compileFloorDiv: function(node, frame) {
|
1818 | this.emit('Math.floor(');
|
1819 | this.compile(node.left, frame);
|
1820 | this.emit(' / ');
|
1821 | this.compile(node.right, frame);
|
1822 | this.emit(')');
|
1823 | },
|
1824 |
|
1825 | compilePow: function(node, frame) {
|
1826 | this.emit('Math.pow(');
|
1827 | this.compile(node.left, frame);
|
1828 | this.emit(', ');
|
1829 | this.compile(node.right, frame);
|
1830 | this.emit(')');
|
1831 | },
|
1832 |
|
1833 | compileNeg: function(node, frame) {
|
1834 | this.emit('-');
|
1835 | this.compile(node.target, frame);
|
1836 | },
|
1837 |
|
1838 | compilePos: function(node, frame) {
|
1839 | this.emit('+');
|
1840 | this.compile(node.target, frame);
|
1841 | },
|
1842 |
|
1843 | compileCompare: function(node, frame) {
|
1844 | this.compile(node.expr, frame);
|
1845 |
|
1846 | for(var i=0; i<node.ops.length; i++) {
|
1847 | var n = node.ops[i];
|
1848 | this.emit(' ' + compareOps[n.type] + ' ');
|
1849 | this.compile(n.expr, frame);
|
1850 | }
|
1851 | },
|
1852 |
|
1853 | compileLookupVal: function(node, frame) {
|
1854 | this.emit('runtime.memberLookup((');
|
1855 | this._compileExpression(node.target, frame);
|
1856 | this.emit('),');
|
1857 | this._compileExpression(node.val, frame);
|
1858 | this.emit(')');
|
1859 | },
|
1860 |
|
1861 | _getNodeName: function(node) {
|
1862 | switch (node.typename) {
|
1863 | case 'Symbol':
|
1864 | return node.value;
|
1865 | case 'FunCall':
|
1866 | return 'the return value of (' + this._getNodeName(node.name) + ')';
|
1867 | case 'LookupVal':
|
1868 | return this._getNodeName(node.target) + '["' +
|
1869 | this._getNodeName(node.val) + '"]';
|
1870 | case 'Literal':
|
1871 | return node.value.toString();
|
1872 | default:
|
1873 | return '--expression--';
|
1874 | }
|
1875 | },
|
1876 |
|
1877 | compileFunCall: function(node, frame) {
|
1878 |
|
1879 |
|
1880 |
|
1881 |
|
1882 | this.emit('(lineno = ' + node.lineno +
|
1883 | ', colno = ' + node.colno + ', ');
|
1884 |
|
1885 | this.emit('runtime.callWrap(');
|
1886 |
|
1887 | this._compileExpression(node.name, frame);
|
1888 |
|
1889 |
|
1890 |
|
1891 | this.emit(', "' + this._getNodeName(node.name).replace(/"/g, '\\"') + '", context, ');
|
1892 |
|
1893 | this._compileAggregate(node.args, frame, '[', '])');
|
1894 |
|
1895 | this.emit(')');
|
1896 | },
|
1897 |
|
1898 | compileFilter: function(node, frame) {
|
1899 | var name = node.name;
|
1900 | this.assertType(name, nodes.Symbol);
|
1901 | this.emit('env.getFilter("' + name.value + '").call(context, ');
|
1902 | this._compileAggregate(node.args, frame);
|
1903 | this.emit(')');
|
1904 | },
|
1905 |
|
1906 | compileFilterAsync: function(node, frame) {
|
1907 | var name = node.name;
|
1908 | this.assertType(name, nodes.Symbol);
|
1909 |
|
1910 | var symbol = node.symbol.value;
|
1911 | frame.set(symbol, symbol);
|
1912 |
|
1913 | this.emit('env.getFilter("' + name.value + '").call(context, ');
|
1914 | this._compileAggregate(node.args, frame);
|
1915 | this.emitLine(', ' + this.makeCallback(symbol));
|
1916 |
|
1917 | this.addScopeLevel();
|
1918 | },
|
1919 |
|
1920 | compileKeywordArgs: function(node, frame) {
|
1921 | var names = [];
|
1922 |
|
1923 | lib.each(node.children, function(pair) {
|
1924 | names.push(pair.key.value);
|
1925 | });
|
1926 |
|
1927 | this.emit('runtime.makeKeywordArgs(');
|
1928 | this.compileDict(node, frame);
|
1929 | this.emit(')');
|
1930 | },
|
1931 |
|
1932 | compileSet: function(node, frame) {
|
1933 | var ids = [];
|
1934 |
|
1935 |
|
1936 |
|
1937 | lib.each(node.targets, function(target) {
|
1938 | var name = target.value;
|
1939 | var id = frame.lookup(name);
|
1940 |
|
1941 | if (id === null || id === undefined) {
|
1942 | id = this.tmpid();
|
1943 |
|
1944 |
|
1945 |
|
1946 | this.emitLine('var ' + id + ';');
|
1947 | }
|
1948 |
|
1949 | ids.push(id);
|
1950 | }, this);
|
1951 |
|
1952 | if (node.value) {
|
1953 | this.emit(ids.join(' = ') + ' = ');
|
1954 | this._compileExpression(node.value, frame);
|
1955 | this.emitLine(';');
|
1956 | }
|
1957 | else {
|
1958 | this.emit(ids.join(' = ') + ' = ');
|
1959 | this.compile(node.body, frame);
|
1960 | this.emitLine(';');
|
1961 | }
|
1962 |
|
1963 | lib.each(node.targets, function(target, i) {
|
1964 | var id = ids[i];
|
1965 | var name = target.value;
|
1966 |
|
1967 |
|
1968 |
|
1969 | this.emitLine('frame.set("' + name + '", ' + id + ', true);');
|
1970 |
|
1971 | this.emitLine('if(frame.topLevel) {');
|
1972 | this.emitLine('context.setVariable("' + name + '", ' + id + ');');
|
1973 | this.emitLine('}');
|
1974 |
|
1975 | if(name.charAt(0) !== '_') {
|
1976 | this.emitLine('if(frame.topLevel) {');
|
1977 | this.emitLine('context.addExport("' + name + '", ' + id + ');');
|
1978 | this.emitLine('}');
|
1979 | }
|
1980 | }, this);
|
1981 | },
|
1982 |
|
1983 | compileIf: function(node, frame, async) {
|
1984 | this.emit('if(');
|
1985 | this._compileExpression(node.cond, frame);
|
1986 | this.emitLine(') {');
|
1987 |
|
1988 | this.withScopedSyntax(function() {
|
1989 | this.compile(node.body, frame);
|
1990 |
|
1991 | if(async) {
|
1992 | this.emit('cb()');
|
1993 | }
|
1994 | });
|
1995 |
|
1996 | if(node.else_) {
|
1997 | this.emitLine('}\nelse {');
|
1998 |
|
1999 | this.withScopedSyntax(function() {
|
2000 | this.compile(node.else_, frame);
|
2001 |
|
2002 | if(async) {
|
2003 | this.emit('cb()');
|
2004 | }
|
2005 | });
|
2006 | } else if(async) {
|
2007 | this.emitLine('}\nelse {');
|
2008 | this.emit('cb()');
|
2009 | }
|
2010 |
|
2011 | this.emitLine('}');
|
2012 | },
|
2013 |
|
2014 | compileIfAsync: function(node, frame) {
|
2015 | this.emit('(function(cb) {');
|
2016 | this.compileIf(node, frame, true);
|
2017 | this.emit('})(' + this.makeCallback());
|
2018 | this.addScopeLevel();
|
2019 | },
|
2020 |
|
2021 | emitLoopBindings: function(node, arr, i, len) {
|
2022 | var bindings = {
|
2023 | index: i + ' + 1',
|
2024 | index0: i,
|
2025 | revindex: len + ' - ' + i,
|
2026 | revindex0: len + ' - ' + i + ' - 1',
|
2027 | first: i + ' === 0',
|
2028 | last: i + ' === ' + len + ' - 1',
|
2029 | length: len
|
2030 | };
|
2031 |
|
2032 | for (var name in bindings) {
|
2033 | this.emitLine('frame.set("loop.' + name + '", ' + bindings[name] + ');');
|
2034 | }
|
2035 | },
|
2036 |
|
2037 | compileFor: function(node, frame) {
|
2038 |
|
2039 |
|
2040 |
|
2041 |
|
2042 | var v;
|
2043 | var i = this.tmpid();
|
2044 | var len = this.tmpid();
|
2045 | var arr = this.tmpid();
|
2046 | frame = frame.push();
|
2047 |
|
2048 | this.emitLine('frame = frame.push();');
|
2049 |
|
2050 | this.emit('var ' + arr + ' = ');
|
2051 | this._compileExpression(node.arr, frame);
|
2052 | this.emitLine(';');
|
2053 |
|
2054 | this.emit('if(' + arr + ') {');
|
2055 |
|
2056 |
|
2057 |
|
2058 | if(node.name instanceof nodes.Array) {
|
2059 | this.emitLine('var ' + i + ';');
|
2060 |
|
2061 |
|
2062 |
|
2063 |
|
2064 | this.emitLine('if(runtime.isArray(' + arr + ')) {'); {
|
2065 | this.emitLine('var ' + len + ' = ' + arr + '.length;');
|
2066 | this.emitLine('for(' + i + '=0; ' + i + ' < ' + arr + '.length; '
|
2067 | + i + '++) {');
|
2068 |
|
2069 |
|
2070 | for (var u=0; u < node.name.children.length; u++) {
|
2071 | var tid = this.tmpid();
|
2072 | this.emitLine('var ' + tid + ' = ' + arr + '[' + i + '][' + u + ']');
|
2073 | this.emitLine('frame.set("' + node.name.children[u].value
|
2074 | + '", ' + arr + '[' + i + '][' + u + ']' + ');');
|
2075 | frame.set(node.name.children[u].value, tid);
|
2076 | }
|
2077 |
|
2078 | this.emitLoopBindings(node, arr, i, len);
|
2079 | this.withScopedSyntax(function() {
|
2080 | this.compile(node.body, frame);
|
2081 | });
|
2082 | this.emitLine('}');
|
2083 | }
|
2084 |
|
2085 | this.emitLine('} else {'); {
|
2086 |
|
2087 | var key = node.name.children[0];
|
2088 | var val = node.name.children[1];
|
2089 | var k = this.tmpid();
|
2090 | v = this.tmpid();
|
2091 | frame.set(key.value, k);
|
2092 | frame.set(val.value, v);
|
2093 |
|
2094 | this.emitLine(i + ' = -1;');
|
2095 | this.emitLine('var ' + len + ' = runtime.keys(' + arr + ').length;');
|
2096 | this.emitLine('for(var ' + k + ' in ' + arr + ') {');
|
2097 | this.emitLine(i + '++;');
|
2098 | this.emitLine('var ' + v + ' = ' + arr + '[' + k + '];');
|
2099 | this.emitLine('frame.set("' + key.value + '", ' + k + ');');
|
2100 | this.emitLine('frame.set("' + val.value + '", ' + v + ');');
|
2101 |
|
2102 | this.emitLoopBindings(node, arr, i, len);
|
2103 | this.withScopedSyntax(function() {
|
2104 | this.compile(node.body, frame);
|
2105 | });
|
2106 | this.emitLine('}');
|
2107 | }
|
2108 |
|
2109 | this.emitLine('}');
|
2110 | }
|
2111 | else {
|
2112 |
|
2113 | v = this.tmpid();
|
2114 | frame.set(node.name.value, v);
|
2115 |
|
2116 | this.emitLine('var ' + len + ' = ' + arr + '.length;');
|
2117 | this.emitLine('for(var ' + i + '=0; ' + i + ' < ' + arr + '.length; ' +
|
2118 | i + '++) {');
|
2119 | this.emitLine('var ' + v + ' = ' + arr + '[' + i + '];');
|
2120 | this.emitLine('frame.set("' + node.name.value + '", ' + v + ');');
|
2121 |
|
2122 | this.emitLoopBindings(node, arr, i, len);
|
2123 |
|
2124 | this.withScopedSyntax(function() {
|
2125 | this.compile(node.body, frame);
|
2126 | });
|
2127 |
|
2128 | this.emitLine('}');
|
2129 | }
|
2130 |
|
2131 | this.emitLine('}');
|
2132 | if (node.else_) {
|
2133 | this.emitLine('if (!' + len + ') {');
|
2134 | this.compile(node.else_, frame);
|
2135 | this.emitLine('}');
|
2136 | }
|
2137 |
|
2138 | this.emitLine('frame = frame.pop();');
|
2139 | },
|
2140 |
|
2141 | _compileAsyncLoop: function(node, frame, parallel) {
|
2142 |
|
2143 |
|
2144 |
|
2145 |
|
2146 | var i = this.tmpid();
|
2147 | var len = this.tmpid();
|
2148 | var arr = this.tmpid();
|
2149 | var asyncMethod = parallel ? 'asyncAll' : 'asyncEach';
|
2150 | frame = frame.push();
|
2151 |
|
2152 | this.emitLine('frame = frame.push();');
|
2153 |
|
2154 | this.emit('var ' + arr + ' = ');
|
2155 | this._compileExpression(node.arr, frame);
|
2156 | this.emitLine(';');
|
2157 |
|
2158 | if(node.name instanceof nodes.Array) {
|
2159 | this.emit('runtime.' + asyncMethod + '(' + arr + ', ' +
|
2160 | node.name.children.length + ', function(');
|
2161 |
|
2162 | lib.each(node.name.children, function(name) {
|
2163 | this.emit(name.value + ',');
|
2164 | }, this);
|
2165 |
|
2166 | this.emit(i + ',' + len + ',next) {');
|
2167 |
|
2168 | lib.each(node.name.children, function(name) {
|
2169 | var id = name.value;
|
2170 | frame.set(id, id);
|
2171 | this.emitLine('frame.set("' + id + '", ' + id + ');');
|
2172 | }, this);
|
2173 | }
|
2174 | else {
|
2175 | var id = node.name.value;
|
2176 | this.emitLine('runtime.' + asyncMethod + '(' + arr + ', 1, function(' + id + ', ' + i + ', ' + len + ',next) {');
|
2177 | this.emitLine('frame.set("' + id + '", ' + id + ');');
|
2178 | frame.set(id, id);
|
2179 | }
|
2180 |
|
2181 | this.emitLoopBindings(node, arr, i, len);
|
2182 |
|
2183 | this.withScopedSyntax(function() {
|
2184 | var buf;
|
2185 | if(parallel) {
|
2186 | buf = this.tmpid();
|
2187 | this.pushBufferId(buf);
|
2188 | }
|
2189 |
|
2190 | this.compile(node.body, frame);
|
2191 | this.emitLine('next(' + i + (buf ? ',' + buf : '') + ');');
|
2192 |
|
2193 | if(parallel) {
|
2194 | this.popBufferId();
|
2195 | }
|
2196 | });
|
2197 |
|
2198 | var output = this.tmpid();
|
2199 | this.emitLine('}, ' + this.makeCallback(output));
|
2200 | this.addScopeLevel();
|
2201 |
|
2202 | if(parallel) {
|
2203 | this.emitLine(this.buffer + ' += ' + output + ';');
|
2204 | }
|
2205 |
|
2206 | if (node.else_) {
|
2207 | this.emitLine('if (!' + arr + '.length) {');
|
2208 | this.compile(node.else_, frame);
|
2209 | this.emitLine('}');
|
2210 | }
|
2211 |
|
2212 | this.emitLine('frame = frame.pop();');
|
2213 | },
|
2214 |
|
2215 | compileAsyncEach: function(node, frame) {
|
2216 | this._compileAsyncLoop(node, frame);
|
2217 | },
|
2218 |
|
2219 | compileAsyncAll: function(node, frame) {
|
2220 | this._compileAsyncLoop(node, frame, true);
|
2221 | },
|
2222 |
|
2223 | _compileMacro: function(node, frame) {
|
2224 | var args = [];
|
2225 | var kwargs = null;
|
2226 | var funcId = 'macro_' + this.tmpid();
|
2227 |
|
2228 |
|
2229 | lib.each(node.args.children, function(arg, i) {
|
2230 | if(i === node.args.children.length - 1 &&
|
2231 | arg instanceof nodes.Dict) {
|
2232 | kwargs = arg;
|
2233 | }
|
2234 | else {
|
2235 | this.assertType(arg, nodes.Symbol);
|
2236 | args.push(arg);
|
2237 | }
|
2238 | }, this);
|
2239 |
|
2240 | var realNames = lib.map(args, function(n) { return 'l_' + n.value; });
|
2241 | realNames.push('kwargs');
|
2242 |
|
2243 |
|
2244 | var argNames = lib.map(args, function(n) { return '"' + n.value + '"'; });
|
2245 | var kwargNames = lib.map((kwargs && kwargs.children) || [],
|
2246 | function(n) { return '"' + n.key.value + '"'; });
|
2247 |
|
2248 |
|
2249 |
|
2250 |
|
2251 |
|
2252 | frame = frame.push();
|
2253 | this.emitLines(
|
2254 | 'var ' + funcId + ' = runtime.makeMacro(',
|
2255 | '[' + argNames.join(', ') + '], ',
|
2256 | '[' + kwargNames.join(', ') + '], ',
|
2257 | 'function (' + realNames.join(', ') + ') {',
|
2258 | 'frame = frame.push(true);',
|
2259 | 'kwargs = kwargs || {};',
|
2260 | 'if (kwargs.hasOwnProperty("caller")) {',
|
2261 | 'frame.set("caller", kwargs.caller); }'
|
2262 | );
|
2263 |
|
2264 |
|
2265 |
|
2266 |
|
2267 | lib.each(args, function(arg) {
|
2268 | this.emitLine('frame.set("' + arg.value + '", ' +
|
2269 | 'l_' + arg.value + ');');
|
2270 | frame.set(arg.value, 'l_' + arg.value);
|
2271 | }, this);
|
2272 |
|
2273 |
|
2274 | if(kwargs) {
|
2275 | lib.each(kwargs.children, function(pair) {
|
2276 | var name = pair.key.value;
|
2277 | this.emit('frame.set("' + name + '", ' +
|
2278 | 'kwargs.hasOwnProperty("' + name + '") ? ' +
|
2279 | 'kwargs["' + name + '"] : ');
|
2280 | this._compileExpression(pair.value, frame);
|
2281 | this.emitLine(');');
|
2282 | }, this);
|
2283 | }
|
2284 |
|
2285 | var bufferId = this.tmpid();
|
2286 | this.pushBufferId(bufferId);
|
2287 |
|
2288 | this.withScopedSyntax(function () {
|
2289 | this.compile(node.body, frame);
|
2290 | });
|
2291 |
|
2292 | frame = frame.pop();
|
2293 | this.emitLine('frame = frame.pop();');
|
2294 | this.emitLine('return new runtime.SafeString(' + bufferId + ');');
|
2295 | this.emitLine('});');
|
2296 | this.popBufferId();
|
2297 |
|
2298 | return funcId;
|
2299 | },
|
2300 |
|
2301 | compileMacro: function(node, frame) {
|
2302 | var funcId = this._compileMacro(node, frame);
|
2303 |
|
2304 |
|
2305 | var name = node.name.value;
|
2306 | frame.set(name, funcId);
|
2307 |
|
2308 | if(frame.parent) {
|
2309 | this.emitLine('frame.set("' + name + '", ' + funcId + ');');
|
2310 | }
|
2311 | else {
|
2312 | if(node.name.value.charAt(0) !== '_') {
|
2313 | this.emitLine('context.addExport("' + name + '");');
|
2314 | }
|
2315 | this.emitLine('context.setVariable("' + name + '", ' + funcId + ');');
|
2316 | }
|
2317 | },
|
2318 |
|
2319 | compileCaller: function(node, frame) {
|
2320 |
|
2321 | this.emit('(function (){');
|
2322 | var funcId = this._compileMacro(node, frame);
|
2323 | this.emit('return ' + funcId + ';})()');
|
2324 | },
|
2325 |
|
2326 | compileImport: function(node, frame) {
|
2327 | var id = this.tmpid();
|
2328 | var target = node.target.value;
|
2329 |
|
2330 | this.emit('env.getTemplate(');
|
2331 | this._compileExpression(node.template, frame);
|
2332 | this.emitLine(', false, '+this._templateName()+', false, ' + this.makeCallback(id));
|
2333 | this.addScopeLevel();
|
2334 |
|
2335 | this.emitLine(id + '.getExported(' +
|
2336 | (node.withContext ? 'context.getVariables(), frame, ' : '') +
|
2337 | this.makeCallback(id));
|
2338 | this.addScopeLevel();
|
2339 |
|
2340 | frame.set(target, id);
|
2341 |
|
2342 | if(frame.parent) {
|
2343 | this.emitLine('frame.set("' + target + '", ' + id + ');');
|
2344 | }
|
2345 | else {
|
2346 | this.emitLine('context.setVariable("' + target + '", ' + id + ');');
|
2347 | }
|
2348 | },
|
2349 |
|
2350 | compileFromImport: function(node, frame) {
|
2351 | var importedId = this.tmpid();
|
2352 |
|
2353 | this.emit('env.getTemplate(');
|
2354 | this._compileExpression(node.template, frame);
|
2355 | this.emitLine(', false, '+this._templateName()+', false, ' + this.makeCallback(importedId));
|
2356 | this.addScopeLevel();
|
2357 |
|
2358 | this.emitLine(importedId + '.getExported(' +
|
2359 | (node.withContext ? 'context.getVariables(), frame, ' : '') +
|
2360 | this.makeCallback(importedId));
|
2361 | this.addScopeLevel();
|
2362 |
|
2363 | lib.each(node.names.children, function(nameNode) {
|
2364 | var name;
|
2365 | var alias;
|
2366 | var id = this.tmpid();
|
2367 |
|
2368 | if(nameNode instanceof nodes.Pair) {
|
2369 | name = nameNode.key.value;
|
2370 | alias = nameNode.value.value;
|
2371 | }
|
2372 | else {
|
2373 | name = nameNode.value;
|
2374 | alias = name;
|
2375 | }
|
2376 |
|
2377 | this.emitLine('if(' + importedId + '.hasOwnProperty("' + name + '")) {');
|
2378 | this.emitLine('var ' + id + ' = ' + importedId + '.' + name + ';');
|
2379 | this.emitLine('} else {');
|
2380 | this.emitLine('cb(new Error("cannot import \'' + name + '\'")); return;');
|
2381 | this.emitLine('}');
|
2382 |
|
2383 | frame.set(alias, id);
|
2384 |
|
2385 | if(frame.parent) {
|
2386 | this.emitLine('frame.set("' + alias + '", ' + id + ');');
|
2387 | }
|
2388 | else {
|
2389 | this.emitLine('context.setVariable("' + alias + '", ' + id + ');');
|
2390 | }
|
2391 | }, this);
|
2392 | },
|
2393 |
|
2394 | compileBlock: function(node) {
|
2395 | var id = this.tmpid();
|
2396 |
|
2397 |
|
2398 |
|
2399 |
|
2400 |
|
2401 |
|
2402 |
|
2403 |
|
2404 |
|
2405 |
|
2406 |
|
2407 | if(!this.inBlock) {
|
2408 | this.emit('(parentTemplate ? function(e, c, f, r, cb) { cb(""); } : ');
|
2409 | }
|
2410 | this.emit('context.getBlock("' + node.name.value + '")');
|
2411 | if(!this.inBlock) {
|
2412 | this.emit(')');
|
2413 | }
|
2414 | this.emitLine('(env, context, frame, runtime, ' + this.makeCallback(id));
|
2415 | this.emitLine(this.buffer + ' += ' + id + ';');
|
2416 | this.addScopeLevel();
|
2417 | },
|
2418 |
|
2419 | compileSuper: function(node, frame) {
|
2420 | var name = node.blockName.value;
|
2421 | var id = node.symbol.value;
|
2422 |
|
2423 | this.emitLine('context.getSuper(env, ' +
|
2424 | '"' + name + '", ' +
|
2425 | 'b_' + name + ', ' +
|
2426 | 'frame, runtime, '+
|
2427 | this.makeCallback(id));
|
2428 | this.emitLine(id + ' = runtime.markSafe(' + id + ');');
|
2429 | this.addScopeLevel();
|
2430 | frame.set(id, id);
|
2431 | },
|
2432 |
|
2433 | compileExtends: function(node, frame) {
|
2434 | var k = this.tmpid();
|
2435 |
|
2436 | this.emit('env.getTemplate(');
|
2437 | this._compileExpression(node.template, frame);
|
2438 | this.emitLine(', true, '+this._templateName()+', false, ' + this.makeCallback('_parentTemplate'));
|
2439 |
|
2440 |
|
2441 |
|
2442 |
|
2443 | this.emitLine('parentTemplate = _parentTemplate');
|
2444 |
|
2445 | this.emitLine('for(var ' + k + ' in parentTemplate.blocks) {');
|
2446 | this.emitLine('context.addBlock(' + k +
|
2447 | ', parentTemplate.blocks[' + k + ']);');
|
2448 | this.emitLine('}');
|
2449 |
|
2450 | this.addScopeLevel();
|
2451 | },
|
2452 |
|
2453 | compileInclude: function(node, frame) {
|
2454 | var id = this.tmpid();
|
2455 | var id2 = this.tmpid();
|
2456 |
|
2457 | this.emit('env.getTemplate(');
|
2458 | this._compileExpression(node.template, frame);
|
2459 | this.emitLine(', false, '+this._templateName()+', ' + node.ignoreMissing + ', ' + this.makeCallback(id));
|
2460 | this.addScopeLevel();
|
2461 |
|
2462 | this.emitLine(id + '.render(' +
|
2463 | 'context.getVariables(), frame, ' + this.makeCallback(id2));
|
2464 | this.emitLine(this.buffer + ' += ' + id2);
|
2465 | this.addScopeLevel();
|
2466 | },
|
2467 |
|
2468 | compileTemplateData: function(node, frame) {
|
2469 | this.compileLiteral(node, frame);
|
2470 | },
|
2471 |
|
2472 | compileCapture: function(node, frame) {
|
2473 | this.emitLine('(function() {');
|
2474 | this.emitLine('var output = "";');
|
2475 | this.withScopedSyntax(function () {
|
2476 | this.compile(node.body, frame);
|
2477 | });
|
2478 | this.emitLine('return output;');
|
2479 | this.emitLine('})()');
|
2480 | },
|
2481 |
|
2482 | compileOutput: function(node, frame) {
|
2483 | var children = node.children;
|
2484 | for(var i=0, l=children.length; i<l; i++) {
|
2485 |
|
2486 |
|
2487 | if(children[i] instanceof nodes.TemplateData) {
|
2488 | if(children[i].value) {
|
2489 | this.emit(this.buffer + ' += ');
|
2490 | this.compileLiteral(children[i], frame);
|
2491 | this.emitLine(';');
|
2492 | }
|
2493 | }
|
2494 | else {
|
2495 | this.emit(this.buffer + ' += runtime.suppressValue(');
|
2496 | if(this.throwOnUndefined) {
|
2497 | this.emit('runtime.ensureDefined(');
|
2498 | }
|
2499 | this.compile(children[i], frame);
|
2500 | if(this.throwOnUndefined) {
|
2501 | this.emit(',' + node.lineno + ',' + node.colno + ')');
|
2502 | }
|
2503 | this.emit(', env.opts.autoescape);\n');
|
2504 | }
|
2505 | }
|
2506 | },
|
2507 |
|
2508 | compileRoot: function(node, frame) {
|
2509 | if(frame) {
|
2510 | this.fail('compileRoot: root node can\'t have frame');
|
2511 | }
|
2512 |
|
2513 | frame = new Frame();
|
2514 |
|
2515 | this.emitFuncBegin('root');
|
2516 | this.emitLine('var parentTemplate = null;');
|
2517 | this._compileChildren(node, frame);
|
2518 | this.emitLine('if(parentTemplate) {');
|
2519 | this.emitLine('parentTemplate.rootRenderFunc(env, context, frame, runtime, cb);');
|
2520 | this.emitLine('} else {');
|
2521 | this.emitLine('cb(null, ' + this.buffer +');');
|
2522 | this.emitLine('}');
|
2523 | this.emitFuncEnd(true);
|
2524 |
|
2525 | this.inBlock = true;
|
2526 |
|
2527 | var blockNames = [];
|
2528 |
|
2529 | var i, name, block, blocks = node.findAll(nodes.Block);
|
2530 | for (i = 0; i < blocks.length; i++) {
|
2531 | block = blocks[i];
|
2532 | name = block.name.value;
|
2533 |
|
2534 | if (blockNames.indexOf(name) !== -1) {
|
2535 | throw new Error('Block "' + name + '" defined more than once.');
|
2536 | }
|
2537 | blockNames.push(name);
|
2538 |
|
2539 | this.emitFuncBegin('b_' + name);
|
2540 |
|
2541 | var tmpFrame = new Frame();
|
2542 | this.compile(block.body, tmpFrame);
|
2543 | this.emitFuncEnd();
|
2544 | }
|
2545 |
|
2546 | this.emitLine('return {');
|
2547 | for (i = 0; i < blocks.length; i++) {
|
2548 | block = blocks[i];
|
2549 | name = 'b_' + block.name.value;
|
2550 | this.emitLine(name + ': ' + name + ',');
|
2551 | }
|
2552 | this.emitLine('root: root\n};');
|
2553 | },
|
2554 |
|
2555 | compile: function (node, frame) {
|
2556 | var _compile = this['compile' + node.typename];
|
2557 | if(_compile) {
|
2558 | _compile.call(this, node, frame);
|
2559 | }
|
2560 | else {
|
2561 | this.fail('compile: Cannot compile node: ' + node.typename,
|
2562 | node.lineno,
|
2563 | node.colno);
|
2564 | }
|
2565 | },
|
2566 |
|
2567 | getCode: function() {
|
2568 | return this.codebuf.join('');
|
2569 | }
|
2570 | });
|
2571 |
|
2572 |
|
2573 |
|
2574 |
|
2575 |
|
2576 |
|
2577 |
|
2578 |
|
2579 |
|
2580 |
|
2581 |
|
2582 | module.exports = {
|
2583 | compile: function(src, asyncFilters, extensions, name, opts) {
|
2584 | var c = new Compiler(name, opts.throwOnUndefined);
|
2585 |
|
2586 |
|
2587 | if(extensions && extensions.length) {
|
2588 | for(var i=0; i<extensions.length; i++) {
|
2589 | if('preprocess' in extensions[i]) {
|
2590 | src = extensions[i].preprocess(src, name);
|
2591 | }
|
2592 | }
|
2593 | }
|
2594 |
|
2595 | c.compile(transformer.transform(
|
2596 | parser.parse(src,
|
2597 | extensions,
|
2598 | opts),
|
2599 | asyncFilters,
|
2600 | name
|
2601 | ));
|
2602 | return c.getCode();
|
2603 | },
|
2604 |
|
2605 | Compiler: Compiler
|
2606 | };
|
2607 |
|
2608 |
|
2609 | },
|
2610 |
|
2611 | function(module, exports, __webpack_require__) {
|
2612 |
|
2613 | 'use strict';
|
2614 |
|
2615 | var lexer = __webpack_require__(9);
|
2616 | var nodes = __webpack_require__(10);
|
2617 |
|
2618 | var Object = __webpack_require__(6);
|
2619 | var lib = __webpack_require__(1);
|
2620 |
|
2621 | var Parser = Object.extend({
|
2622 | init: function (tokens) {
|
2623 | this.tokens = tokens;
|
2624 | this.peeked = null;
|
2625 | this.breakOnBlocks = null;
|
2626 | this.dropLeadingWhitespace = false;
|
2627 |
|
2628 | this.extensions = [];
|
2629 | },
|
2630 |
|
2631 | nextToken: function (withWhitespace) {
|
2632 | var tok;
|
2633 |
|
2634 | if(this.peeked) {
|
2635 | if(!withWhitespace && this.peeked.type === lexer.TOKEN_WHITESPACE) {
|
2636 | this.peeked = null;
|
2637 | }
|
2638 | else {
|
2639 | tok = this.peeked;
|
2640 | this.peeked = null;
|
2641 | return tok;
|
2642 | }
|
2643 | }
|
2644 |
|
2645 | tok = this.tokens.nextToken();
|
2646 |
|
2647 | if(!withWhitespace) {
|
2648 | while(tok && tok.type === lexer.TOKEN_WHITESPACE) {
|
2649 | tok = this.tokens.nextToken();
|
2650 | }
|
2651 | }
|
2652 |
|
2653 | return tok;
|
2654 | },
|
2655 |
|
2656 | peekToken: function () {
|
2657 | this.peeked = this.peeked || this.nextToken();
|
2658 | return this.peeked;
|
2659 | },
|
2660 |
|
2661 | pushToken: function(tok) {
|
2662 | if(this.peeked) {
|
2663 | throw new Error('pushToken: can only push one token on between reads');
|
2664 | }
|
2665 | this.peeked = tok;
|
2666 | },
|
2667 |
|
2668 | fail: function (msg, lineno, colno) {
|
2669 | if((lineno === undefined || colno === undefined) && this.peekToken()) {
|
2670 | var tok = this.peekToken();
|
2671 | lineno = tok.lineno;
|
2672 | colno = tok.colno;
|
2673 | }
|
2674 | if (lineno !== undefined) lineno += 1;
|
2675 | if (colno !== undefined) colno += 1;
|
2676 |
|
2677 | throw new lib.TemplateError(msg, lineno, colno);
|
2678 | },
|
2679 |
|
2680 | skip: function(type) {
|
2681 | var tok = this.nextToken();
|
2682 | if(!tok || tok.type !== type) {
|
2683 | this.pushToken(tok);
|
2684 | return false;
|
2685 | }
|
2686 | return true;
|
2687 | },
|
2688 |
|
2689 | expect: function(type) {
|
2690 | var tok = this.nextToken();
|
2691 | if(tok.type !== type) {
|
2692 | this.fail('expected ' + type + ', got ' + tok.type,
|
2693 | tok.lineno,
|
2694 | tok.colno);
|
2695 | }
|
2696 | return tok;
|
2697 | },
|
2698 |
|
2699 | skipValue: function(type, val) {
|
2700 | var tok = this.nextToken();
|
2701 | if(!tok || tok.type !== type || tok.value !== val) {
|
2702 | this.pushToken(tok);
|
2703 | return false;
|
2704 | }
|
2705 | return true;
|
2706 | },
|
2707 |
|
2708 | skipSymbol: function(val) {
|
2709 | return this.skipValue(lexer.TOKEN_SYMBOL, val);
|
2710 | },
|
2711 |
|
2712 | advanceAfterBlockEnd: function(name) {
|
2713 | var tok;
|
2714 | if(!name) {
|
2715 | tok = this.peekToken();
|
2716 |
|
2717 | if(!tok) {
|
2718 | this.fail('unexpected end of file');
|
2719 | }
|
2720 |
|
2721 | if(tok.type !== lexer.TOKEN_SYMBOL) {
|
2722 | this.fail('advanceAfterBlockEnd: expected symbol token or ' +
|
2723 | 'explicit name to be passed');
|
2724 | }
|
2725 |
|
2726 | name = this.nextToken().value;
|
2727 | }
|
2728 |
|
2729 | tok = this.nextToken();
|
2730 |
|
2731 | if(tok && tok.type === lexer.TOKEN_BLOCK_END) {
|
2732 | if(tok.value.charAt(0) === '-') {
|
2733 | this.dropLeadingWhitespace = true;
|
2734 | }
|
2735 | }
|
2736 | else {
|
2737 | this.fail('expected block end in ' + name + ' statement');
|
2738 | }
|
2739 |
|
2740 | return tok;
|
2741 | },
|
2742 |
|
2743 | advanceAfterVariableEnd: function() {
|
2744 | if(!this.skip(lexer.TOKEN_VARIABLE_END)) {
|
2745 | this.fail('expected variable end');
|
2746 | }
|
2747 | },
|
2748 |
|
2749 | parseFor: function() {
|
2750 | var forTok = this.peekToken();
|
2751 | var node;
|
2752 | var endBlock;
|
2753 |
|
2754 | if(this.skipSymbol('for')) {
|
2755 | node = new nodes.For(forTok.lineno, forTok.colno);
|
2756 | endBlock = 'endfor';
|
2757 | }
|
2758 | else if(this.skipSymbol('asyncEach')) {
|
2759 | node = new nodes.AsyncEach(forTok.lineno, forTok.colno);
|
2760 | endBlock = 'endeach';
|
2761 | }
|
2762 | else if(this.skipSymbol('asyncAll')) {
|
2763 | node = new nodes.AsyncAll(forTok.lineno, forTok.colno);
|
2764 | endBlock = 'endall';
|
2765 | }
|
2766 | else {
|
2767 | this.fail('parseFor: expected for{Async}', forTok.lineno, forTok.colno);
|
2768 | }
|
2769 |
|
2770 | node.name = this.parsePrimary();
|
2771 |
|
2772 | if(!(node.name instanceof nodes.Symbol)) {
|
2773 | this.fail('parseFor: variable name expected for loop');
|
2774 | }
|
2775 |
|
2776 | var type = this.peekToken().type;
|
2777 | if(type === lexer.TOKEN_COMMA) {
|
2778 |
|
2779 | var key = node.name;
|
2780 | node.name = new nodes.Array(key.lineno, key.colno);
|
2781 | node.name.addChild(key);
|
2782 |
|
2783 | while(this.skip(lexer.TOKEN_COMMA)) {
|
2784 | var prim = this.parsePrimary();
|
2785 | node.name.addChild(prim);
|
2786 | }
|
2787 | }
|
2788 |
|
2789 | if(!this.skipSymbol('in')) {
|
2790 | this.fail('parseFor: expected "in" keyword for loop',
|
2791 | forTok.lineno,
|
2792 | forTok.colno);
|
2793 | }
|
2794 |
|
2795 | node.arr = this.parseExpression();
|
2796 | this.advanceAfterBlockEnd(forTok.value);
|
2797 |
|
2798 | node.body = this.parseUntilBlocks(endBlock, 'else');
|
2799 |
|
2800 | if(this.skipSymbol('else')) {
|
2801 | this.advanceAfterBlockEnd('else');
|
2802 | node.else_ = this.parseUntilBlocks(endBlock);
|
2803 | }
|
2804 |
|
2805 | this.advanceAfterBlockEnd();
|
2806 |
|
2807 | return node;
|
2808 | },
|
2809 |
|
2810 | parseMacro: function() {
|
2811 | var macroTok = this.peekToken();
|
2812 | if(!this.skipSymbol('macro')) {
|
2813 | this.fail('expected macro');
|
2814 | }
|
2815 |
|
2816 | var name = this.parsePrimary(true);
|
2817 | var args = this.parseSignature();
|
2818 | var node = new nodes.Macro(macroTok.lineno,
|
2819 | macroTok.colno,
|
2820 | name,
|
2821 | args);
|
2822 |
|
2823 | this.advanceAfterBlockEnd(macroTok.value);
|
2824 | node.body = this.parseUntilBlocks('endmacro');
|
2825 | this.advanceAfterBlockEnd();
|
2826 |
|
2827 | return node;
|
2828 | },
|
2829 |
|
2830 | parseCall: function() {
|
2831 |
|
2832 |
|
2833 | var callTok = this.peekToken();
|
2834 | if(!this.skipSymbol('call')) {
|
2835 | this.fail('expected call');
|
2836 | }
|
2837 |
|
2838 | var callerArgs = this.parseSignature(true) || new nodes.NodeList();
|
2839 | var macroCall = this.parsePrimary();
|
2840 |
|
2841 | this.advanceAfterBlockEnd(callTok.value);
|
2842 | var body = this.parseUntilBlocks('endcall');
|
2843 | this.advanceAfterBlockEnd();
|
2844 |
|
2845 | var callerName = new nodes.Symbol(callTok.lineno,
|
2846 | callTok.colno,
|
2847 | 'caller');
|
2848 | var callerNode = new nodes.Caller(callTok.lineno,
|
2849 | callTok.colno,
|
2850 | callerName,
|
2851 | callerArgs,
|
2852 | body);
|
2853 |
|
2854 |
|
2855 | var args = macroCall.args.children;
|
2856 | if (!(args[args.length-1] instanceof nodes.KeywordArgs)) {
|
2857 | args.push(new nodes.KeywordArgs());
|
2858 | }
|
2859 | var kwargs = args[args.length - 1];
|
2860 | kwargs.addChild(new nodes.Pair(callTok.lineno,
|
2861 | callTok.colno,
|
2862 | callerName,
|
2863 | callerNode));
|
2864 |
|
2865 | return new nodes.Output(callTok.lineno,
|
2866 | callTok.colno,
|
2867 | [macroCall]);
|
2868 | },
|
2869 |
|
2870 | parseWithContext: function() {
|
2871 | var tok = this.peekToken();
|
2872 |
|
2873 | var withContext = null;
|
2874 |
|
2875 | if(this.skipSymbol('with')) {
|
2876 | withContext = true;
|
2877 | }
|
2878 | else if(this.skipSymbol('without')) {
|
2879 | withContext = false;
|
2880 | }
|
2881 |
|
2882 | if(withContext !== null) {
|
2883 | if(!this.skipSymbol('context')) {
|
2884 | this.fail('parseFrom: expected context after with/without',
|
2885 | tok.lineno,
|
2886 | tok.colno);
|
2887 | }
|
2888 | }
|
2889 |
|
2890 | return withContext;
|
2891 | },
|
2892 |
|
2893 | parseImport: function() {
|
2894 | var importTok = this.peekToken();
|
2895 | if(!this.skipSymbol('import')) {
|
2896 | this.fail('parseImport: expected import',
|
2897 | importTok.lineno,
|
2898 | importTok.colno);
|
2899 | }
|
2900 |
|
2901 | var template = this.parseExpression();
|
2902 |
|
2903 | if(!this.skipSymbol('as')) {
|
2904 | this.fail('parseImport: expected "as" keyword',
|
2905 | importTok.lineno,
|
2906 | importTok.colno);
|
2907 | }
|
2908 |
|
2909 | var target = this.parseExpression();
|
2910 |
|
2911 | var withContext = this.parseWithContext();
|
2912 |
|
2913 | var node = new nodes.Import(importTok.lineno,
|
2914 | importTok.colno,
|
2915 | template,
|
2916 | target,
|
2917 | withContext);
|
2918 |
|
2919 | this.advanceAfterBlockEnd(importTok.value);
|
2920 |
|
2921 | return node;
|
2922 | },
|
2923 |
|
2924 | parseFrom: function() {
|
2925 | var fromTok = this.peekToken();
|
2926 | if(!this.skipSymbol('from')) {
|
2927 | this.fail('parseFrom: expected from');
|
2928 | }
|
2929 |
|
2930 | var template = this.parseExpression();
|
2931 |
|
2932 | if(!this.skipSymbol('import')) {
|
2933 | this.fail('parseFrom: expected import',
|
2934 | fromTok.lineno,
|
2935 | fromTok.colno);
|
2936 | }
|
2937 |
|
2938 | var names = new nodes.NodeList(),
|
2939 | withContext;
|
2940 |
|
2941 | while(1) {
|
2942 | var nextTok = this.peekToken();
|
2943 | if(nextTok.type === lexer.TOKEN_BLOCK_END) {
|
2944 | if(!names.children.length) {
|
2945 | this.fail('parseFrom: Expected at least one import name',
|
2946 | fromTok.lineno,
|
2947 | fromTok.colno);
|
2948 | }
|
2949 |
|
2950 |
|
2951 |
|
2952 |
|
2953 | if(nextTok.value.charAt(0) === '-') {
|
2954 | this.dropLeadingWhitespace = true;
|
2955 | }
|
2956 |
|
2957 | this.nextToken();
|
2958 | break;
|
2959 | }
|
2960 |
|
2961 | if(names.children.length > 0 && !this.skip(lexer.TOKEN_COMMA)) {
|
2962 | this.fail('parseFrom: expected comma',
|
2963 | fromTok.lineno,
|
2964 | fromTok.colno);
|
2965 | }
|
2966 |
|
2967 | var name = this.parsePrimary();
|
2968 | if(name.value.charAt(0) === '_') {
|
2969 | this.fail('parseFrom: names starting with an underscore ' +
|
2970 | 'cannot be imported',
|
2971 | name.lineno,
|
2972 | name.colno);
|
2973 | }
|
2974 |
|
2975 | if(this.skipSymbol('as')) {
|
2976 | var alias = this.parsePrimary();
|
2977 | names.addChild(new nodes.Pair(name.lineno,
|
2978 | name.colno,
|
2979 | name,
|
2980 | alias));
|
2981 | }
|
2982 | else {
|
2983 | names.addChild(name);
|
2984 | }
|
2985 |
|
2986 | withContext = this.parseWithContext();
|
2987 | }
|
2988 |
|
2989 | return new nodes.FromImport(fromTok.lineno,
|
2990 | fromTok.colno,
|
2991 | template,
|
2992 | names,
|
2993 | withContext);
|
2994 | },
|
2995 |
|
2996 | parseBlock: function() {
|
2997 | var tag = this.peekToken();
|
2998 | if(!this.skipSymbol('block')) {
|
2999 | this.fail('parseBlock: expected block', tag.lineno, tag.colno);
|
3000 | }
|
3001 |
|
3002 | var node = new nodes.Block(tag.lineno, tag.colno);
|
3003 |
|
3004 | node.name = this.parsePrimary();
|
3005 | if(!(node.name instanceof nodes.Symbol)) {
|
3006 | this.fail('parseBlock: variable name expected',
|
3007 | tag.lineno,
|
3008 | tag.colno);
|
3009 | }
|
3010 |
|
3011 | this.advanceAfterBlockEnd(tag.value);
|
3012 |
|
3013 | node.body = this.parseUntilBlocks('endblock');
|
3014 | this.skipSymbol('endblock');
|
3015 | this.skipSymbol(node.name.value);
|
3016 |
|
3017 | var tok = this.peekToken();
|
3018 | if(!tok) {
|
3019 | this.fail('parseBlock: expected endblock, got end of file');
|
3020 | }
|
3021 |
|
3022 | this.advanceAfterBlockEnd(tok.value);
|
3023 |
|
3024 | return node;
|
3025 | },
|
3026 |
|
3027 | parseExtends: function() {
|
3028 | var tagName = 'extends';
|
3029 | var tag = this.peekToken();
|
3030 | if(!this.skipSymbol(tagName)) {
|
3031 | this.fail('parseTemplateRef: expected '+ tagName);
|
3032 | }
|
3033 |
|
3034 | var node = new nodes.Extends(tag.lineno, tag.colno);
|
3035 | node.template = this.parseExpression();
|
3036 |
|
3037 | this.advanceAfterBlockEnd(tag.value);
|
3038 | return node;
|
3039 | },
|
3040 |
|
3041 | parseInclude: function() {
|
3042 | var tagName = 'include';
|
3043 | var tag = this.peekToken();
|
3044 | if(!this.skipSymbol(tagName)) {
|
3045 | this.fail('parseInclude: expected '+ tagName);
|
3046 | }
|
3047 |
|
3048 | var node = new nodes.Include(tag.lineno, tag.colno);
|
3049 | node.template = this.parseExpression();
|
3050 |
|
3051 | if(this.skipSymbol('ignore') && this.skipSymbol('missing')) {
|
3052 | node.ignoreMissing = true;
|
3053 | }
|
3054 |
|
3055 | this.advanceAfterBlockEnd(tag.value);
|
3056 | return node;
|
3057 | },
|
3058 |
|
3059 | parseIf: function() {
|
3060 | var tag = this.peekToken();
|
3061 | var node;
|
3062 |
|
3063 | if(this.skipSymbol('if') || this.skipSymbol('elif') || this.skipSymbol('elseif')) {
|
3064 | node = new nodes.If(tag.lineno, tag.colno);
|
3065 | }
|
3066 | else if(this.skipSymbol('ifAsync')) {
|
3067 | node = new nodes.IfAsync(tag.lineno, tag.colno);
|
3068 | }
|
3069 | else {
|
3070 | this.fail('parseIf: expected if, elif, or elseif',
|
3071 | tag.lineno,
|
3072 | tag.colno);
|
3073 | }
|
3074 |
|
3075 | node.cond = this.parseExpression();
|
3076 | this.advanceAfterBlockEnd(tag.value);
|
3077 |
|
3078 | node.body = this.parseUntilBlocks('elif', 'elseif', 'else', 'endif');
|
3079 | var tok = this.peekToken();
|
3080 |
|
3081 | switch(tok && tok.value) {
|
3082 | case 'elseif':
|
3083 | case 'elif':
|
3084 | node.else_ = this.parseIf();
|
3085 | break;
|
3086 | case 'else':
|
3087 | this.advanceAfterBlockEnd();
|
3088 | node.else_ = this.parseUntilBlocks('endif');
|
3089 | this.advanceAfterBlockEnd();
|
3090 | break;
|
3091 | case 'endif':
|
3092 | node.else_ = null;
|
3093 | this.advanceAfterBlockEnd();
|
3094 | break;
|
3095 | default:
|
3096 | this.fail('parseIf: expected elif, else, or endif, ' +
|
3097 | 'got end of file');
|
3098 | }
|
3099 |
|
3100 | return node;
|
3101 | },
|
3102 |
|
3103 | parseSet: function() {
|
3104 | var tag = this.peekToken();
|
3105 | if(!this.skipSymbol('set')) {
|
3106 | this.fail('parseSet: expected set', tag.lineno, tag.colno);
|
3107 | }
|
3108 |
|
3109 | var node = new nodes.Set(tag.lineno, tag.colno, []);
|
3110 |
|
3111 | var target;
|
3112 | while((target = this.parsePrimary())) {
|
3113 | node.targets.push(target);
|
3114 |
|
3115 | if(!this.skip(lexer.TOKEN_COMMA)) {
|
3116 | break;
|
3117 | }
|
3118 | }
|
3119 |
|
3120 | if(!this.skipValue(lexer.TOKEN_OPERATOR, '=')) {
|
3121 | if (!this.skip(lexer.TOKEN_BLOCK_END)) {
|
3122 | this.fail('parseSet: expected = or block end in set tag',
|
3123 | tag.lineno,
|
3124 | tag.colno);
|
3125 | }
|
3126 | else {
|
3127 | node.body = new nodes.Capture(
|
3128 | tag.lineno,
|
3129 | tag.colno,
|
3130 | this.parseUntilBlocks('endset')
|
3131 | );
|
3132 | node.value = null;
|
3133 | this.advanceAfterBlockEnd();
|
3134 | }
|
3135 | }
|
3136 | else {
|
3137 | node.value = this.parseExpression();
|
3138 | this.advanceAfterBlockEnd(tag.value);
|
3139 | }
|
3140 |
|
3141 | return node;
|
3142 | },
|
3143 |
|
3144 | parseStatement: function () {
|
3145 | var tok = this.peekToken();
|
3146 | var node;
|
3147 |
|
3148 | if(tok.type !== lexer.TOKEN_SYMBOL) {
|
3149 | this.fail('tag name expected', tok.lineno, tok.colno);
|
3150 | }
|
3151 |
|
3152 | if(this.breakOnBlocks &&
|
3153 | lib.indexOf(this.breakOnBlocks, tok.value) !== -1) {
|
3154 | return null;
|
3155 | }
|
3156 |
|
3157 | switch(tok.value) {
|
3158 | case 'raw': return this.parseRaw();
|
3159 | case 'if':
|
3160 | case 'ifAsync':
|
3161 | return this.parseIf();
|
3162 | case 'for':
|
3163 | case 'asyncEach':
|
3164 | case 'asyncAll':
|
3165 | return this.parseFor();
|
3166 | case 'block': return this.parseBlock();
|
3167 | case 'extends': return this.parseExtends();
|
3168 | case 'include': return this.parseInclude();
|
3169 | case 'set': return this.parseSet();
|
3170 | case 'macro': return this.parseMacro();
|
3171 | case 'call': return this.parseCall();
|
3172 | case 'import': return this.parseImport();
|
3173 | case 'from': return this.parseFrom();
|
3174 | case 'filter': return this.parseFilterStatement();
|
3175 | default:
|
3176 | if (this.extensions.length) {
|
3177 | for (var i = 0; i < this.extensions.length; i++) {
|
3178 | var ext = this.extensions[i];
|
3179 | if (lib.indexOf(ext.tags || [], tok.value) !== -1) {
|
3180 | return ext.parse(this, nodes, lexer);
|
3181 | }
|
3182 | }
|
3183 | }
|
3184 | this.fail('unknown block tag: ' + tok.value, tok.lineno, tok.colno);
|
3185 | }
|
3186 |
|
3187 | return node;
|
3188 | },
|
3189 |
|
3190 | parseRaw: function() {
|
3191 |
|
3192 | var rawBlockRegex = /([\s\S]*?){%\s*(raw|endraw)\s*(?=%})%}/;
|
3193 | var rawLevel = 1;
|
3194 | var str = '';
|
3195 | var matches = null;
|
3196 |
|
3197 |
|
3198 |
|
3199 | var begun = this.advanceAfterBlockEnd();
|
3200 |
|
3201 |
|
3202 |
|
3203 | while((matches = this.tokens._extractRegex(rawBlockRegex)) && rawLevel > 0) {
|
3204 | var all = matches[0];
|
3205 | var pre = matches[1];
|
3206 | var blockName = matches[2];
|
3207 |
|
3208 |
|
3209 | if(blockName === 'raw') {
|
3210 | rawLevel += 1;
|
3211 | } else if(blockName === 'endraw') {
|
3212 | rawLevel -= 1;
|
3213 | }
|
3214 |
|
3215 |
|
3216 | if(rawLevel === 0) {
|
3217 |
|
3218 | str += pre;
|
3219 |
|
3220 | this.tokens.backN(all.length - pre.length);
|
3221 | } else {
|
3222 | str += all;
|
3223 | }
|
3224 | }
|
3225 |
|
3226 | return new nodes.Output(
|
3227 | begun.lineno,
|
3228 | begun.colno,
|
3229 | [new nodes.TemplateData(begun.lineno, begun.colno, str)]
|
3230 | );
|
3231 | },
|
3232 |
|
3233 | parsePostfix: function(node) {
|
3234 | var lookup, tok = this.peekToken();
|
3235 |
|
3236 | while(tok) {
|
3237 | if(tok.type === lexer.TOKEN_LEFT_PAREN) {
|
3238 |
|
3239 | node = new nodes.FunCall(tok.lineno,
|
3240 | tok.colno,
|
3241 | node,
|
3242 | this.parseSignature());
|
3243 | }
|
3244 | else if(tok.type === lexer.TOKEN_LEFT_BRACKET) {
|
3245 |
|
3246 | lookup = this.parseAggregate();
|
3247 | if(lookup.children.length > 1) {
|
3248 | this.fail('invalid index');
|
3249 | }
|
3250 |
|
3251 | node = new nodes.LookupVal(tok.lineno,
|
3252 | tok.colno,
|
3253 | node,
|
3254 | lookup.children[0]);
|
3255 | }
|
3256 | else if(tok.type === lexer.TOKEN_OPERATOR && tok.value === '.') {
|
3257 |
|
3258 | this.nextToken();
|
3259 | var val = this.nextToken();
|
3260 |
|
3261 | if(val.type !== lexer.TOKEN_SYMBOL) {
|
3262 | this.fail('expected name as lookup value, got ' + val.value,
|
3263 | val.lineno,
|
3264 | val.colno);
|
3265 | }
|
3266 |
|
3267 |
|
3268 |
|
3269 | lookup = new nodes.Literal(val.lineno,
|
3270 | val.colno,
|
3271 | val.value);
|
3272 |
|
3273 | node = new nodes.LookupVal(tok.lineno,
|
3274 | tok.colno,
|
3275 | node,
|
3276 | lookup);
|
3277 | }
|
3278 | else {
|
3279 | break;
|
3280 | }
|
3281 |
|
3282 | tok = this.peekToken();
|
3283 | }
|
3284 |
|
3285 | return node;
|
3286 | },
|
3287 |
|
3288 | parseExpression: function() {
|
3289 | var node = this.parseInlineIf();
|
3290 | return node;
|
3291 | },
|
3292 |
|
3293 | parseInlineIf: function() {
|
3294 | var node = this.parseOr();
|
3295 | if(this.skipSymbol('if')) {
|
3296 | var cond_node = this.parseOr();
|
3297 | var body_node = node;
|
3298 | node = new nodes.InlineIf(node.lineno, node.colno);
|
3299 | node.body = body_node;
|
3300 | node.cond = cond_node;
|
3301 | if(this.skipSymbol('else')) {
|
3302 | node.else_ = this.parseOr();
|
3303 | } else {
|
3304 | node.else_ = null;
|
3305 | }
|
3306 | }
|
3307 |
|
3308 | return node;
|
3309 | },
|
3310 |
|
3311 | parseOr: function() {
|
3312 | var node = this.parseAnd();
|
3313 | while(this.skipSymbol('or')) {
|
3314 | var node2 = this.parseAnd();
|
3315 | node = new nodes.Or(node.lineno,
|
3316 | node.colno,
|
3317 | node,
|
3318 | node2);
|
3319 | }
|
3320 | return node;
|
3321 | },
|
3322 |
|
3323 | parseAnd: function() {
|
3324 | var node = this.parseNot();
|
3325 | while(this.skipSymbol('and')) {
|
3326 | var node2 = this.parseNot();
|
3327 | node = new nodes.And(node.lineno,
|
3328 | node.colno,
|
3329 | node,
|
3330 | node2);
|
3331 | }
|
3332 | return node;
|
3333 | },
|
3334 |
|
3335 | parseNot: function() {
|
3336 | var tok = this.peekToken();
|
3337 | if(this.skipSymbol('not')) {
|
3338 | return new nodes.Not(tok.lineno,
|
3339 | tok.colno,
|
3340 | this.parseNot());
|
3341 | }
|
3342 | return this.parseIn();
|
3343 | },
|
3344 |
|
3345 | parseIn: function() {
|
3346 | var node = this.parseCompare();
|
3347 | while(1) {
|
3348 |
|
3349 | var tok = this.nextToken();
|
3350 | if (!tok) { break; }
|
3351 | var invert = tok.type === lexer.TOKEN_SYMBOL && tok.value === 'not';
|
3352 |
|
3353 | if (!invert) { this.pushToken(tok); }
|
3354 | if (this.skipSymbol('in')) {
|
3355 | var node2 = this.parseCompare();
|
3356 | node = new nodes.In(node.lineno,
|
3357 | node.colno,
|
3358 | node,
|
3359 | node2);
|
3360 | if (invert) {
|
3361 | node = new nodes.Not(node.lineno,
|
3362 | node.colno,
|
3363 | node);
|
3364 | }
|
3365 | }
|
3366 | else {
|
3367 |
|
3368 | if (invert) { this.pushToken(tok); }
|
3369 | break;
|
3370 | }
|
3371 | }
|
3372 | return node;
|
3373 | },
|
3374 |
|
3375 | parseCompare: function() {
|
3376 | var compareOps = ['==', '===', '!=', '!==', '<', '>', '<=', '>='];
|
3377 | var expr = this.parseConcat();
|
3378 | var ops = [];
|
3379 |
|
3380 | while(1) {
|
3381 | var tok = this.nextToken();
|
3382 |
|
3383 | if(!tok) {
|
3384 | break;
|
3385 | }
|
3386 | else if(lib.indexOf(compareOps, tok.value) !== -1) {
|
3387 | ops.push(new nodes.CompareOperand(tok.lineno,
|
3388 | tok.colno,
|
3389 | this.parseConcat(),
|
3390 | tok.value));
|
3391 | }
|
3392 | else {
|
3393 | this.pushToken(tok);
|
3394 | break;
|
3395 | }
|
3396 | }
|
3397 |
|
3398 | if(ops.length) {
|
3399 | return new nodes.Compare(ops[0].lineno,
|
3400 | ops[0].colno,
|
3401 | expr,
|
3402 | ops);
|
3403 | }
|
3404 | else {
|
3405 | return expr;
|
3406 | }
|
3407 | },
|
3408 |
|
3409 |
|
3410 | parseConcat: function(){
|
3411 | var node = this.parseAdd();
|
3412 | while(this.skipValue(lexer.TOKEN_TILDE, '~')) {
|
3413 | var node2 = this.parseAdd();
|
3414 | node = new nodes.Concat(node.lineno,
|
3415 | node.colno,
|
3416 | node,
|
3417 | node2);
|
3418 | }
|
3419 | return node;
|
3420 | },
|
3421 |
|
3422 | parseAdd: function() {
|
3423 | var node = this.parseSub();
|
3424 | while(this.skipValue(lexer.TOKEN_OPERATOR, '+')) {
|
3425 | var node2 = this.parseSub();
|
3426 | node = new nodes.Add(node.lineno,
|
3427 | node.colno,
|
3428 | node,
|
3429 | node2);
|
3430 | }
|
3431 | return node;
|
3432 | },
|
3433 |
|
3434 | parseSub: function() {
|
3435 | var node = this.parseMul();
|
3436 | while(this.skipValue(lexer.TOKEN_OPERATOR, '-')) {
|
3437 | var node2 = this.parseMul();
|
3438 | node = new nodes.Sub(node.lineno,
|
3439 | node.colno,
|
3440 | node,
|
3441 | node2);
|
3442 | }
|
3443 | return node;
|
3444 | },
|
3445 |
|
3446 | parseMul: function() {
|
3447 | var node = this.parseDiv();
|
3448 | while(this.skipValue(lexer.TOKEN_OPERATOR, '*')) {
|
3449 | var node2 = this.parseDiv();
|
3450 | node = new nodes.Mul(node.lineno,
|
3451 | node.colno,
|
3452 | node,
|
3453 | node2);
|
3454 | }
|
3455 | return node;
|
3456 | },
|
3457 |
|
3458 | parseDiv: function() {
|
3459 | var node = this.parseFloorDiv();
|
3460 | while(this.skipValue(lexer.TOKEN_OPERATOR, '/')) {
|
3461 | var node2 = this.parseFloorDiv();
|
3462 | node = new nodes.Div(node.lineno,
|
3463 | node.colno,
|
3464 | node,
|
3465 | node2);
|
3466 | }
|
3467 | return node;
|
3468 | },
|
3469 |
|
3470 | parseFloorDiv: function() {
|
3471 | var node = this.parseMod();
|
3472 | while(this.skipValue(lexer.TOKEN_OPERATOR, '//')) {
|
3473 | var node2 = this.parseMod();
|
3474 | node = new nodes.FloorDiv(node.lineno,
|
3475 | node.colno,
|
3476 | node,
|
3477 | node2);
|
3478 | }
|
3479 | return node;
|
3480 | },
|
3481 |
|
3482 | parseMod: function() {
|
3483 | var node = this.parsePow();
|
3484 | while(this.skipValue(lexer.TOKEN_OPERATOR, '%')) {
|
3485 | var node2 = this.parsePow();
|
3486 | node = new nodes.Mod(node.lineno,
|
3487 | node.colno,
|
3488 | node,
|
3489 | node2);
|
3490 | }
|
3491 | return node;
|
3492 | },
|
3493 |
|
3494 | parsePow: function() {
|
3495 | var node = this.parseUnary();
|
3496 | while(this.skipValue(lexer.TOKEN_OPERATOR, '**')) {
|
3497 | var node2 = this.parseUnary();
|
3498 | node = new nodes.Pow(node.lineno,
|
3499 | node.colno,
|
3500 | node,
|
3501 | node2);
|
3502 | }
|
3503 | return node;
|
3504 | },
|
3505 |
|
3506 | parseUnary: function(noFilters) {
|
3507 | var tok = this.peekToken();
|
3508 | var node;
|
3509 |
|
3510 | if(this.skipValue(lexer.TOKEN_OPERATOR, '-')) {
|
3511 | node = new nodes.Neg(tok.lineno,
|
3512 | tok.colno,
|
3513 | this.parseUnary(true));
|
3514 | }
|
3515 | else if(this.skipValue(lexer.TOKEN_OPERATOR, '+')) {
|
3516 | node = new nodes.Pos(tok.lineno,
|
3517 | tok.colno,
|
3518 | this.parseUnary(true));
|
3519 | }
|
3520 | else {
|
3521 | node = this.parsePrimary();
|
3522 | }
|
3523 |
|
3524 | if(!noFilters) {
|
3525 | node = this.parseFilter(node);
|
3526 | }
|
3527 |
|
3528 | return node;
|
3529 | },
|
3530 |
|
3531 | parsePrimary: function (noPostfix) {
|
3532 | var tok = this.nextToken();
|
3533 | var val;
|
3534 | var node = null;
|
3535 |
|
3536 | if(!tok) {
|
3537 | this.fail('expected expression, got end of file');
|
3538 | }
|
3539 | else if(tok.type === lexer.TOKEN_STRING) {
|
3540 | val = tok.value;
|
3541 | }
|
3542 | else if(tok.type === lexer.TOKEN_INT) {
|
3543 | val = parseInt(tok.value, 10);
|
3544 | }
|
3545 | else if(tok.type === lexer.TOKEN_FLOAT) {
|
3546 | val = parseFloat(tok.value);
|
3547 | }
|
3548 | else if(tok.type === lexer.TOKEN_BOOLEAN) {
|
3549 | if(tok.value === 'true') {
|
3550 | val = true;
|
3551 | }
|
3552 | else if(tok.value === 'false') {
|
3553 | val = false;
|
3554 | }
|
3555 | else {
|
3556 | this.fail('invalid boolean: ' + tok.value,
|
3557 | tok.lineno,
|
3558 | tok.colno);
|
3559 | }
|
3560 | }
|
3561 | else if(tok.type === lexer.TOKEN_NONE) {
|
3562 | val = null;
|
3563 | }
|
3564 | else if (tok.type === lexer.TOKEN_REGEX) {
|
3565 | val = new RegExp(tok.value.body, tok.value.flags);
|
3566 | }
|
3567 |
|
3568 | if(val !== undefined) {
|
3569 | node = new nodes.Literal(tok.lineno, tok.colno, val);
|
3570 | }
|
3571 | else if(tok.type === lexer.TOKEN_SYMBOL) {
|
3572 | node = new nodes.Symbol(tok.lineno, tok.colno, tok.value);
|
3573 |
|
3574 | if(!noPostfix) {
|
3575 | node = this.parsePostfix(node);
|
3576 | }
|
3577 | }
|
3578 | else {
|
3579 |
|
3580 |
|
3581 | this.pushToken(tok);
|
3582 | node = this.parseAggregate();
|
3583 | }
|
3584 |
|
3585 | if(node) {
|
3586 | return node;
|
3587 | }
|
3588 | else {
|
3589 | this.fail('unexpected token: ' + tok.value,
|
3590 | tok.lineno,
|
3591 | tok.colno);
|
3592 | }
|
3593 | },
|
3594 |
|
3595 | parseFilterName: function() {
|
3596 | var tok = this.expect(lexer.TOKEN_SYMBOL);
|
3597 | var name = tok.value;
|
3598 |
|
3599 | while(this.skipValue(lexer.TOKEN_OPERATOR, '.')) {
|
3600 | name += '.' + this.expect(lexer.TOKEN_SYMBOL).value;
|
3601 | }
|
3602 |
|
3603 | return new nodes.Symbol(tok.lineno, tok.colno, name);
|
3604 | },
|
3605 |
|
3606 | parseFilterArgs: function(node) {
|
3607 | if(this.peekToken().type === lexer.TOKEN_LEFT_PAREN) {
|
3608 |
|
3609 |
|
3610 | var call = this.parsePostfix(node);
|
3611 | return call.args.children;
|
3612 | }
|
3613 | return [];
|
3614 | },
|
3615 |
|
3616 | parseFilter: function(node) {
|
3617 | while(this.skip(lexer.TOKEN_PIPE)) {
|
3618 | var name = this.parseFilterName();
|
3619 |
|
3620 | node = new nodes.Filter(
|
3621 | name.lineno,
|
3622 | name.colno,
|
3623 | name,
|
3624 | new nodes.NodeList(
|
3625 | name.lineno,
|
3626 | name.colno,
|
3627 | [node].concat(this.parseFilterArgs(node))
|
3628 | )
|
3629 | );
|
3630 | }
|
3631 |
|
3632 | return node;
|
3633 | },
|
3634 |
|
3635 | parseFilterStatement: function() {
|
3636 | var filterTok = this.peekToken();
|
3637 | if(!this.skipSymbol('filter')) {
|
3638 | this.fail('parseFilterStatement: expected filter');
|
3639 | }
|
3640 |
|
3641 | var name = this.parseFilterName();
|
3642 | var args = this.parseFilterArgs(name);
|
3643 |
|
3644 | this.advanceAfterBlockEnd(filterTok.value);
|
3645 | var body = new nodes.Capture(
|
3646 | name.lineno,
|
3647 | name.colno,
|
3648 | this.parseUntilBlocks('endfilter')
|
3649 | );
|
3650 | this.advanceAfterBlockEnd();
|
3651 |
|
3652 | var node = new nodes.Filter(
|
3653 | name.lineno,
|
3654 | name.colno,
|
3655 | name,
|
3656 | new nodes.NodeList(
|
3657 | name.lineno,
|
3658 | name.colno,
|
3659 | [body].concat(args)
|
3660 | )
|
3661 | );
|
3662 |
|
3663 | return new nodes.Output(
|
3664 | name.lineno,
|
3665 | name.colno,
|
3666 | [node]
|
3667 | );
|
3668 | },
|
3669 |
|
3670 | parseAggregate: function() {
|
3671 | var tok = this.nextToken();
|
3672 | var node;
|
3673 |
|
3674 | switch(tok.type) {
|
3675 | case lexer.TOKEN_LEFT_PAREN:
|
3676 | node = new nodes.Group(tok.lineno, tok.colno); break;
|
3677 | case lexer.TOKEN_LEFT_BRACKET:
|
3678 | node = new nodes.Array(tok.lineno, tok.colno); break;
|
3679 | case lexer.TOKEN_LEFT_CURLY:
|
3680 | node = new nodes.Dict(tok.lineno, tok.colno); break;
|
3681 | default:
|
3682 | return null;
|
3683 | }
|
3684 |
|
3685 | while(1) {
|
3686 | var type = this.peekToken().type;
|
3687 | if(type === lexer.TOKEN_RIGHT_PAREN ||
|
3688 | type === lexer.TOKEN_RIGHT_BRACKET ||
|
3689 | type === lexer.TOKEN_RIGHT_CURLY) {
|
3690 | this.nextToken();
|
3691 | break;
|
3692 | }
|
3693 |
|
3694 | if(node.children.length > 0) {
|
3695 | if(!this.skip(lexer.TOKEN_COMMA)) {
|
3696 | this.fail('parseAggregate: expected comma after expression',
|
3697 | tok.lineno,
|
3698 | tok.colno);
|
3699 | }
|
3700 | }
|
3701 |
|
3702 | if(node instanceof nodes.Dict) {
|
3703 |
|
3704 | var key = this.parsePrimary();
|
3705 |
|
3706 |
|
3707 |
|
3708 | if(!this.skip(lexer.TOKEN_COLON)) {
|
3709 | this.fail('parseAggregate: expected colon after dict key',
|
3710 | tok.lineno,
|
3711 | tok.colno);
|
3712 | }
|
3713 |
|
3714 |
|
3715 | var value = this.parseExpression();
|
3716 | node.addChild(new nodes.Pair(key.lineno,
|
3717 | key.colno,
|
3718 | key,
|
3719 | value));
|
3720 | }
|
3721 | else {
|
3722 |
|
3723 | var expr = this.parseExpression();
|
3724 | node.addChild(expr);
|
3725 | }
|
3726 | }
|
3727 |
|
3728 | return node;
|
3729 | },
|
3730 |
|
3731 | parseSignature: function(tolerant, noParens) {
|
3732 | var tok = this.peekToken();
|
3733 | if(!noParens && tok.type !== lexer.TOKEN_LEFT_PAREN) {
|
3734 | if(tolerant) {
|
3735 | return null;
|
3736 | }
|
3737 | else {
|
3738 | this.fail('expected arguments', tok.lineno, tok.colno);
|
3739 | }
|
3740 | }
|
3741 |
|
3742 | if(tok.type === lexer.TOKEN_LEFT_PAREN) {
|
3743 | tok = this.nextToken();
|
3744 | }
|
3745 |
|
3746 | var args = new nodes.NodeList(tok.lineno, tok.colno);
|
3747 | var kwargs = new nodes.KeywordArgs(tok.lineno, tok.colno);
|
3748 | var checkComma = false;
|
3749 |
|
3750 | while(1) {
|
3751 | tok = this.peekToken();
|
3752 | if(!noParens && tok.type === lexer.TOKEN_RIGHT_PAREN) {
|
3753 | this.nextToken();
|
3754 | break;
|
3755 | }
|
3756 | else if(noParens && tok.type === lexer.TOKEN_BLOCK_END) {
|
3757 | break;
|
3758 | }
|
3759 |
|
3760 | if(checkComma && !this.skip(lexer.TOKEN_COMMA)) {
|
3761 | this.fail('parseSignature: expected comma after expression',
|
3762 | tok.lineno,
|
3763 | tok.colno);
|
3764 | }
|
3765 | else {
|
3766 | var arg = this.parseExpression();
|
3767 |
|
3768 | if(this.skipValue(lexer.TOKEN_OPERATOR, '=')) {
|
3769 | kwargs.addChild(
|
3770 | new nodes.Pair(arg.lineno,
|
3771 | arg.colno,
|
3772 | arg,
|
3773 | this.parseExpression())
|
3774 | );
|
3775 | }
|
3776 | else {
|
3777 | args.addChild(arg);
|
3778 | }
|
3779 | }
|
3780 |
|
3781 | checkComma = true;
|
3782 | }
|
3783 |
|
3784 | if(kwargs.children.length) {
|
3785 | args.addChild(kwargs);
|
3786 | }
|
3787 |
|
3788 | return args;
|
3789 | },
|
3790 |
|
3791 | parseUntilBlocks: function(/* blockNames */) {
|
3792 | var prev = this.breakOnBlocks;
|
3793 | this.breakOnBlocks = lib.toArray(arguments);
|
3794 |
|
3795 | var ret = this.parse();
|
3796 |
|
3797 | this.breakOnBlocks = prev;
|
3798 | return ret;
|
3799 | },
|
3800 |
|
3801 | parseNodes: function () {
|
3802 | var tok;
|
3803 | var buf = [];
|
3804 |
|
3805 | while((tok = this.nextToken())) {
|
3806 | if(tok.type === lexer.TOKEN_DATA) {
|
3807 | var data = tok.value;
|
3808 | var nextToken = this.peekToken();
|
3809 | var nextVal = nextToken && nextToken.value;
|
3810 |
|
3811 |
|
3812 |
|
3813 |
|
3814 | if(this.dropLeadingWhitespace) {
|
3815 |
|
3816 | data = data.replace(/^\s*/, '');
|
3817 | this.dropLeadingWhitespace = false;
|
3818 | }
|
3819 |
|
3820 |
|
3821 | if(nextToken &&
|
3822 | ((nextToken.type === lexer.TOKEN_BLOCK_START &&
|
3823 | nextVal.charAt(nextVal.length - 1) === '-') ||
|
3824 | (nextToken.type === lexer.TOKEN_COMMENT &&
|
3825 | nextVal.charAt(this.tokens.tags.COMMENT_START.length)
|
3826 | === '-'))) {
|
3827 |
|
3828 | data = data.replace(/\s*$/, '');
|
3829 | }
|
3830 |
|
3831 | buf.push(new nodes.Output(tok.lineno,
|
3832 | tok.colno,
|
3833 | [new nodes.TemplateData(tok.lineno,
|
3834 | tok.colno,
|
3835 | data)]));
|
3836 | }
|
3837 | else if(tok.type === lexer.TOKEN_BLOCK_START) {
|
3838 | this.dropLeadingWhitespace = false;
|
3839 | var n = this.parseStatement();
|
3840 | if(!n) {
|
3841 | break;
|
3842 | }
|
3843 | buf.push(n);
|
3844 | }
|
3845 | else if(tok.type === lexer.TOKEN_VARIABLE_START) {
|
3846 | var e = this.parseExpression();
|
3847 | this.advanceAfterVariableEnd();
|
3848 | this.dropLeadingWhitespace = false;
|
3849 | buf.push(new nodes.Output(tok.lineno, tok.colno, [e]));
|
3850 | }
|
3851 | else if(tok.type === lexer.TOKEN_COMMENT) {
|
3852 | this.dropLeadingWhitespace = tok.value.charAt(
|
3853 | tok.value.length - this.tokens.tags.COMMENT_END.length - 1
|
3854 | ) === '-';
|
3855 | } else {
|
3856 |
|
3857 | this.fail('Unexpected token at top-level: ' +
|
3858 | tok.type, tok.lineno, tok.colno);
|
3859 |
|
3860 | }
|
3861 | }
|
3862 |
|
3863 | return buf;
|
3864 | },
|
3865 |
|
3866 | parse: function() {
|
3867 | return new nodes.NodeList(0, 0, this.parseNodes());
|
3868 | },
|
3869 |
|
3870 | parseAsRoot: function() {
|
3871 | return new nodes.Root(0, 0, this.parseNodes());
|
3872 | }
|
3873 | });
|
3874 |
|
3875 |
|
3876 |
|
3877 |
|
3878 |
|
3879 |
|
3880 |
|
3881 |
|
3882 |
|
3883 |
|
3884 |
|
3885 |
|
3886 |
|
3887 |
|
3888 |
|
3889 | module.exports = {
|
3890 | parse: function(src, extensions, opts) {
|
3891 | var p = new Parser(lexer.lex(src, opts));
|
3892 | if (extensions !== undefined) {
|
3893 | p.extensions = extensions;
|
3894 | }
|
3895 | return p.parseAsRoot();
|
3896 | }
|
3897 | };
|
3898 |
|
3899 |
|
3900 | },
|
3901 |
|
3902 | function(module, exports, __webpack_require__) {
|
3903 |
|
3904 | 'use strict';
|
3905 |
|
3906 | var lib = __webpack_require__(1);
|
3907 |
|
3908 | var whitespaceChars = ' \n\t\r\u00A0';
|
3909 | var delimChars = '()[]{}%*-+~/#,:|.<>=!';
|
3910 | var intChars = '0123456789';
|
3911 |
|
3912 | var BLOCK_START = '{%';
|
3913 | var BLOCK_END = '%}';
|
3914 | var VARIABLE_START = '{{';
|
3915 | var VARIABLE_END = '}}';
|
3916 | var COMMENT_START = '{#';
|
3917 | var COMMENT_END = '#}';
|
3918 |
|
3919 | var TOKEN_STRING = 'string';
|
3920 | var TOKEN_WHITESPACE = 'whitespace';
|
3921 | var TOKEN_DATA = 'data';
|
3922 | var TOKEN_BLOCK_START = 'block-start';
|
3923 | var TOKEN_BLOCK_END = 'block-end';
|
3924 | var TOKEN_VARIABLE_START = 'variable-start';
|
3925 | var TOKEN_VARIABLE_END = 'variable-end';
|
3926 | var TOKEN_COMMENT = 'comment';
|
3927 | var TOKEN_LEFT_PAREN = 'left-paren';
|
3928 | var TOKEN_RIGHT_PAREN = 'right-paren';
|
3929 | var TOKEN_LEFT_BRACKET = 'left-bracket';
|
3930 | var TOKEN_RIGHT_BRACKET = 'right-bracket';
|
3931 | var TOKEN_LEFT_CURLY = 'left-curly';
|
3932 | var TOKEN_RIGHT_CURLY = 'right-curly';
|
3933 | var TOKEN_OPERATOR = 'operator';
|
3934 | var TOKEN_COMMA = 'comma';
|
3935 | var TOKEN_COLON = 'colon';
|
3936 | var TOKEN_TILDE = 'tilde';
|
3937 | var TOKEN_PIPE = 'pipe';
|
3938 | var TOKEN_INT = 'int';
|
3939 | var TOKEN_FLOAT = 'float';
|
3940 | var TOKEN_BOOLEAN = 'boolean';
|
3941 | var TOKEN_NONE = 'none';
|
3942 | var TOKEN_SYMBOL = 'symbol';
|
3943 | var TOKEN_SPECIAL = 'special';
|
3944 | var TOKEN_REGEX = 'regex';
|
3945 |
|
3946 | function token(type, value, lineno, colno) {
|
3947 | return {
|
3948 | type: type,
|
3949 | value: value,
|
3950 | lineno: lineno,
|
3951 | colno: colno
|
3952 | };
|
3953 | }
|
3954 |
|
3955 | function Tokenizer(str, opts) {
|
3956 | this.str = str;
|
3957 | this.index = 0;
|
3958 | this.len = str.length;
|
3959 | this.lineno = 0;
|
3960 | this.colno = 0;
|
3961 |
|
3962 | this.in_code = false;
|
3963 |
|
3964 | opts = opts || {};
|
3965 |
|
3966 | var tags = opts.tags || {};
|
3967 | this.tags = {
|
3968 | BLOCK_START: tags.blockStart || BLOCK_START,
|
3969 | BLOCK_END: tags.blockEnd || BLOCK_END,
|
3970 | VARIABLE_START: tags.variableStart || VARIABLE_START,
|
3971 | VARIABLE_END: tags.variableEnd || VARIABLE_END,
|
3972 | COMMENT_START: tags.commentStart || COMMENT_START,
|
3973 | COMMENT_END: tags.commentEnd || COMMENT_END
|
3974 | };
|
3975 |
|
3976 | this.trimBlocks = !!opts.trimBlocks;
|
3977 | this.lstripBlocks = !!opts.lstripBlocks;
|
3978 | }
|
3979 |
|
3980 | Tokenizer.prototype.nextToken = function() {
|
3981 | var lineno = this.lineno;
|
3982 | var colno = this.colno;
|
3983 | var tok;
|
3984 |
|
3985 | if(this.in_code) {
|
3986 |
|
3987 | var cur = this.current();
|
3988 |
|
3989 | if(this.is_finished()) {
|
3990 |
|
3991 | return null;
|
3992 | }
|
3993 | else if(cur === '"' || cur === '\'') {
|
3994 |
|
3995 | return token(TOKEN_STRING, this.parseString(cur), lineno, colno);
|
3996 | }
|
3997 | else if((tok = this._extract(whitespaceChars))) {
|
3998 |
|
3999 | return token(TOKEN_WHITESPACE, tok, lineno, colno);
|
4000 | }
|
4001 | else if((tok = this._extractString(this.tags.BLOCK_END)) ||
|
4002 | (tok = this._extractString('-' + this.tags.BLOCK_END))) {
|
4003 |
|
4004 |
|
4005 |
|
4006 |
|
4007 |
|
4008 |
|
4009 | this.in_code = false;
|
4010 | if(this.trimBlocks) {
|
4011 | cur = this.current();
|
4012 | if(cur === '\n') {
|
4013 |
|
4014 | this.forward();
|
4015 | }else if(cur === '\r'){
|
4016 |
|
4017 | this.forward();
|
4018 | cur = this.current();
|
4019 | if(cur === '\n'){
|
4020 | this.forward();
|
4021 | }else{
|
4022 |
|
4023 | this.back();
|
4024 | }
|
4025 | }
|
4026 | }
|
4027 | return token(TOKEN_BLOCK_END, tok, lineno, colno);
|
4028 | }
|
4029 | else if((tok = this._extractString(this.tags.VARIABLE_END))) {
|
4030 |
|
4031 | this.in_code = false;
|
4032 | return token(TOKEN_VARIABLE_END, tok, lineno, colno);
|
4033 | }
|
4034 | else if (cur === 'r' && this.str.charAt(this.index + 1) === '/') {
|
4035 |
|
4036 | this.forwardN(2);
|
4037 |
|
4038 |
|
4039 | var regexBody = '';
|
4040 | while (!this.is_finished()) {
|
4041 | if (this.current() === '/' && this.previous() !== '\\') {
|
4042 | this.forward();
|
4043 | break;
|
4044 | } else {
|
4045 | regexBody += this.current();
|
4046 | this.forward();
|
4047 | }
|
4048 | }
|
4049 |
|
4050 |
|
4051 |
|
4052 | var POSSIBLE_FLAGS = ['g', 'i', 'm', 'y'];
|
4053 | var regexFlags = '';
|
4054 | while (!this.is_finished()) {
|
4055 | var isCurrentAFlag = POSSIBLE_FLAGS.indexOf(this.current()) !== -1;
|
4056 | if (isCurrentAFlag) {
|
4057 | regexFlags += this.current();
|
4058 | this.forward();
|
4059 | } else {
|
4060 | break;
|
4061 | }
|
4062 | }
|
4063 |
|
4064 | return token(TOKEN_REGEX, {body: regexBody, flags: regexFlags}, lineno, colno);
|
4065 | }
|
4066 | else if(delimChars.indexOf(cur) !== -1) {
|
4067 |
|
4068 | this.forward();
|
4069 | var complexOps = ['==', '===', '!=', '!==', '<=', '>=', '//', '**'];
|
4070 | var curComplex = cur + this.current();
|
4071 | var type;
|
4072 |
|
4073 | if(lib.indexOf(complexOps, curComplex) !== -1) {
|
4074 | this.forward();
|
4075 | cur = curComplex;
|
4076 |
|
4077 |
|
4078 | if(lib.indexOf(complexOps, curComplex + this.current()) !== -1) {
|
4079 | cur = curComplex + this.current();
|
4080 | this.forward();
|
4081 | }
|
4082 | }
|
4083 |
|
4084 | switch(cur) {
|
4085 | case '(': type = TOKEN_LEFT_PAREN; break;
|
4086 | case ')': type = TOKEN_RIGHT_PAREN; break;
|
4087 | case '[': type = TOKEN_LEFT_BRACKET; break;
|
4088 | case ']': type = TOKEN_RIGHT_BRACKET; break;
|
4089 | case '{': type = TOKEN_LEFT_CURLY; break;
|
4090 | case '}': type = TOKEN_RIGHT_CURLY; break;
|
4091 | case ',': type = TOKEN_COMMA; break;
|
4092 | case ':': type = TOKEN_COLON; break;
|
4093 | case '~': type = TOKEN_TILDE; break;
|
4094 | case '|': type = TOKEN_PIPE; break;
|
4095 | default: type = TOKEN_OPERATOR;
|
4096 | }
|
4097 |
|
4098 | return token(type, cur, lineno, colno);
|
4099 | }
|
4100 | else {
|
4101 |
|
4102 |
|
4103 | tok = this._extractUntil(whitespaceChars + delimChars);
|
4104 |
|
4105 | if(tok.match(/^[-+]?[0-9]+$/)) {
|
4106 | if(this.current() === '.') {
|
4107 | this.forward();
|
4108 | var dec = this._extract(intChars);
|
4109 | return token(TOKEN_FLOAT, tok + '.' + dec, lineno, colno);
|
4110 | }
|
4111 | else {
|
4112 | return token(TOKEN_INT, tok, lineno, colno);
|
4113 | }
|
4114 | }
|
4115 | else if(tok.match(/^(true|false)$/)) {
|
4116 | return token(TOKEN_BOOLEAN, tok, lineno, colno);
|
4117 | }
|
4118 | else if(tok === 'none') {
|
4119 | return token(TOKEN_NONE, tok, lineno, colno);
|
4120 | }
|
4121 | else if(tok) {
|
4122 | return token(TOKEN_SYMBOL, tok, lineno, colno);
|
4123 | }
|
4124 | else {
|
4125 | throw new Error('Unexpected value while parsing: ' + tok);
|
4126 | }
|
4127 | }
|
4128 | }
|
4129 | else {
|
4130 |
|
4131 |
|
4132 |
|
4133 | var beginChars = (this.tags.BLOCK_START.charAt(0) +
|
4134 | this.tags.VARIABLE_START.charAt(0) +
|
4135 | this.tags.COMMENT_START.charAt(0) +
|
4136 | this.tags.COMMENT_END.charAt(0));
|
4137 |
|
4138 | if(this.is_finished()) {
|
4139 | return null;
|
4140 | }
|
4141 | else if((tok = this._extractString(this.tags.BLOCK_START + '-')) ||
|
4142 | (tok = this._extractString(this.tags.BLOCK_START))) {
|
4143 | this.in_code = true;
|
4144 | return token(TOKEN_BLOCK_START, tok, lineno, colno);
|
4145 | }
|
4146 | else if((tok = this._extractString(this.tags.VARIABLE_START))) {
|
4147 | this.in_code = true;
|
4148 | return token(TOKEN_VARIABLE_START, tok, lineno, colno);
|
4149 | }
|
4150 | else {
|
4151 | tok = '';
|
4152 | var data;
|
4153 | var in_comment = false;
|
4154 |
|
4155 | if(this._matches(this.tags.COMMENT_START)) {
|
4156 | in_comment = true;
|
4157 | tok = this._extractString(this.tags.COMMENT_START);
|
4158 | }
|
4159 |
|
4160 |
|
4161 |
|
4162 |
|
4163 |
|
4164 |
|
4165 |
|
4166 | while((data = this._extractUntil(beginChars)) !== null) {
|
4167 | tok += data;
|
4168 |
|
4169 | if((this._matches(this.tags.BLOCK_START) ||
|
4170 | this._matches(this.tags.VARIABLE_START) ||
|
4171 | this._matches(this.tags.COMMENT_START)) &&
|
4172 | !in_comment) {
|
4173 | if(this.lstripBlocks &&
|
4174 | this._matches(this.tags.BLOCK_START) &&
|
4175 | this.colno > 0 &&
|
4176 | this.colno <= tok.length) {
|
4177 | var lastLine = tok.slice(-this.colno);
|
4178 | if(/^\s+$/.test(lastLine)) {
|
4179 |
|
4180 | tok = tok.slice(0, -this.colno);
|
4181 | if(!tok.length) {
|
4182 |
|
4183 |
|
4184 | return this.nextToken();
|
4185 | }
|
4186 | }
|
4187 | }
|
4188 |
|
4189 | break;
|
4190 | }
|
4191 | else if(this._matches(this.tags.COMMENT_END)) {
|
4192 | if(!in_comment) {
|
4193 | throw new Error('unexpected end of comment');
|
4194 | }
|
4195 | tok += this._extractString(this.tags.COMMENT_END);
|
4196 | break;
|
4197 | }
|
4198 | else {
|
4199 |
|
4200 |
|
4201 | tok += this.current();
|
4202 | this.forward();
|
4203 | }
|
4204 | }
|
4205 |
|
4206 | if(data === null && in_comment) {
|
4207 | throw new Error('expected end of comment, got end of file');
|
4208 | }
|
4209 |
|
4210 | return token(in_comment ? TOKEN_COMMENT : TOKEN_DATA,
|
4211 | tok,
|
4212 | lineno,
|
4213 | colno);
|
4214 | }
|
4215 | }
|
4216 |
|
4217 | throw new Error('Could not parse text');
|
4218 | };
|
4219 |
|
4220 | Tokenizer.prototype.parseString = function(delimiter) {
|
4221 | this.forward();
|
4222 |
|
4223 | var str = '';
|
4224 |
|
4225 | while(!this.is_finished() && this.current() !== delimiter) {
|
4226 | var cur = this.current();
|
4227 |
|
4228 | if(cur === '\\') {
|
4229 | this.forward();
|
4230 | switch(this.current()) {
|
4231 | case 'n': str += '\n'; break;
|
4232 | case 't': str += '\t'; break;
|
4233 | case 'r': str += '\r'; break;
|
4234 | default:
|
4235 | str += this.current();
|
4236 | }
|
4237 | this.forward();
|
4238 | }
|
4239 | else {
|
4240 | str += cur;
|
4241 | this.forward();
|
4242 | }
|
4243 | }
|
4244 |
|
4245 | this.forward();
|
4246 | return str;
|
4247 | };
|
4248 |
|
4249 | Tokenizer.prototype._matches = function(str) {
|
4250 | if(this.index + str.length > this.len) {
|
4251 | return null;
|
4252 | }
|
4253 |
|
4254 | var m = this.str.slice(this.index, this.index + str.length);
|
4255 | return m === str;
|
4256 | };
|
4257 |
|
4258 | Tokenizer.prototype._extractString = function(str) {
|
4259 | if(this._matches(str)) {
|
4260 | this.index += str.length;
|
4261 | return str;
|
4262 | }
|
4263 | return null;
|
4264 | };
|
4265 |
|
4266 | Tokenizer.prototype._extractUntil = function(charString) {
|
4267 |
|
4268 |
|
4269 | return this._extractMatching(true, charString || '');
|
4270 | };
|
4271 |
|
4272 | Tokenizer.prototype._extract = function(charString) {
|
4273 |
|
4274 |
|
4275 | return this._extractMatching(false, charString);
|
4276 | };
|
4277 |
|
4278 | Tokenizer.prototype._extractMatching = function (breakOnMatch, charString) {
|
4279 |
|
4280 |
|
4281 |
|
4282 |
|
4283 | if(this.is_finished()) {
|
4284 | return null;
|
4285 | }
|
4286 |
|
4287 | var first = charString.indexOf(this.current());
|
4288 |
|
4289 |
|
4290 | if((breakOnMatch && first === -1) ||
|
4291 | (!breakOnMatch && first !== -1)) {
|
4292 | var t = this.current();
|
4293 | this.forward();
|
4294 |
|
4295 |
|
4296 |
|
4297 | var idx = charString.indexOf(this.current());
|
4298 |
|
4299 | while(((breakOnMatch && idx === -1) ||
|
4300 | (!breakOnMatch && idx !== -1)) && !this.is_finished()) {
|
4301 | t += this.current();
|
4302 | this.forward();
|
4303 |
|
4304 | idx = charString.indexOf(this.current());
|
4305 | }
|
4306 |
|
4307 | return t;
|
4308 | }
|
4309 |
|
4310 | return '';
|
4311 | };
|
4312 |
|
4313 | Tokenizer.prototype._extractRegex = function(regex) {
|
4314 | var matches = this.currentStr().match(regex);
|
4315 | if(!matches) {
|
4316 | return null;
|
4317 | }
|
4318 |
|
4319 |
|
4320 | this.forwardN(matches[0].length);
|
4321 |
|
4322 | return matches;
|
4323 | };
|
4324 |
|
4325 | Tokenizer.prototype.is_finished = function() {
|
4326 | return this.index >= this.len;
|
4327 | };
|
4328 |
|
4329 | Tokenizer.prototype.forwardN = function(n) {
|
4330 | for(var i=0; i<n; i++) {
|
4331 | this.forward();
|
4332 | }
|
4333 | };
|
4334 |
|
4335 | Tokenizer.prototype.forward = function() {
|
4336 | this.index++;
|
4337 |
|
4338 | if(this.previous() === '\n') {
|
4339 | this.lineno++;
|
4340 | this.colno = 0;
|
4341 | }
|
4342 | else {
|
4343 | this.colno++;
|
4344 | }
|
4345 | };
|
4346 |
|
4347 | Tokenizer.prototype.backN = function(n) {
|
4348 | for(var i=0; i<n; i++) {
|
4349 | this.back();
|
4350 | }
|
4351 | };
|
4352 |
|
4353 | Tokenizer.prototype.back = function() {
|
4354 | this.index--;
|
4355 |
|
4356 | if(this.current() === '\n') {
|
4357 | this.lineno--;
|
4358 |
|
4359 | var idx = this.src.lastIndexOf('\n', this.index-1);
|
4360 | if(idx === -1) {
|
4361 | this.colno = this.index;
|
4362 | }
|
4363 | else {
|
4364 | this.colno = this.index - idx;
|
4365 | }
|
4366 | }
|
4367 | else {
|
4368 | this.colno--;
|
4369 | }
|
4370 | };
|
4371 |
|
4372 |
|
4373 | Tokenizer.prototype.current = function() {
|
4374 | if(!this.is_finished()) {
|
4375 | return this.str.charAt(this.index);
|
4376 | }
|
4377 | return '';
|
4378 | };
|
4379 |
|
4380 |
|
4381 | Tokenizer.prototype.currentStr = function() {
|
4382 | if(!this.is_finished()) {
|
4383 | return this.str.substr(this.index);
|
4384 | }
|
4385 | return '';
|
4386 | };
|
4387 |
|
4388 | Tokenizer.prototype.previous = function() {
|
4389 | return this.str.charAt(this.index-1);
|
4390 | };
|
4391 |
|
4392 | module.exports = {
|
4393 | lex: function(src, opts) {
|
4394 | return new Tokenizer(src, opts);
|
4395 | },
|
4396 |
|
4397 | TOKEN_STRING: TOKEN_STRING,
|
4398 | TOKEN_WHITESPACE: TOKEN_WHITESPACE,
|
4399 | TOKEN_DATA: TOKEN_DATA,
|
4400 | TOKEN_BLOCK_START: TOKEN_BLOCK_START,
|
4401 | TOKEN_BLOCK_END: TOKEN_BLOCK_END,
|
4402 | TOKEN_VARIABLE_START: TOKEN_VARIABLE_START,
|
4403 | TOKEN_VARIABLE_END: TOKEN_VARIABLE_END,
|
4404 | TOKEN_COMMENT: TOKEN_COMMENT,
|
4405 | TOKEN_LEFT_PAREN: TOKEN_LEFT_PAREN,
|
4406 | TOKEN_RIGHT_PAREN: TOKEN_RIGHT_PAREN,
|
4407 | TOKEN_LEFT_BRACKET: TOKEN_LEFT_BRACKET,
|
4408 | TOKEN_RIGHT_BRACKET: TOKEN_RIGHT_BRACKET,
|
4409 | TOKEN_LEFT_CURLY: TOKEN_LEFT_CURLY,
|
4410 | TOKEN_RIGHT_CURLY: TOKEN_RIGHT_CURLY,
|
4411 | TOKEN_OPERATOR: TOKEN_OPERATOR,
|
4412 | TOKEN_COMMA: TOKEN_COMMA,
|
4413 | TOKEN_COLON: TOKEN_COLON,
|
4414 | TOKEN_TILDE: TOKEN_TILDE,
|
4415 | TOKEN_PIPE: TOKEN_PIPE,
|
4416 | TOKEN_INT: TOKEN_INT,
|
4417 | TOKEN_FLOAT: TOKEN_FLOAT,
|
4418 | TOKEN_BOOLEAN: TOKEN_BOOLEAN,
|
4419 | TOKEN_NONE: TOKEN_NONE,
|
4420 | TOKEN_SYMBOL: TOKEN_SYMBOL,
|
4421 | TOKEN_SPECIAL: TOKEN_SPECIAL,
|
4422 | TOKEN_REGEX: TOKEN_REGEX
|
4423 | };
|
4424 |
|
4425 |
|
4426 | },
|
4427 |
|
4428 | function(module, exports, __webpack_require__) {
|
4429 |
|
4430 | (function(process) {'use strict';
|
4431 |
|
4432 | var lib = __webpack_require__(1);
|
4433 |
|
4434 | var Object = __webpack_require__(6);
|
4435 |
|
4436 | function traverseAndCheck(obj, type, results) {
|
4437 | if(obj instanceof type) {
|
4438 | results.push(obj);
|
4439 | }
|
4440 |
|
4441 | if(obj instanceof Node) {
|
4442 | obj.findAll(type, results);
|
4443 | }
|
4444 | }
|
4445 |
|
4446 | var Node = Object.extend('Node', {
|
4447 | init: function(lineno, colno) {
|
4448 | this.lineno = lineno;
|
4449 | this.colno = colno;
|
4450 |
|
4451 | var fields = this.fields;
|
4452 | for(var i = 0, l = fields.length; i < l; i++) {
|
4453 | var field = fields[i];
|
4454 |
|
4455 |
|
4456 | var val = arguments[i + 2];
|
4457 |
|
4458 |
|
4459 |
|
4460 | if(val === undefined) {
|
4461 | val = null;
|
4462 | }
|
4463 |
|
4464 | this[field] = val;
|
4465 | }
|
4466 | },
|
4467 |
|
4468 | findAll: function(type, results) {
|
4469 | results = results || [];
|
4470 |
|
4471 | var i, l;
|
4472 | if(this instanceof NodeList) {
|
4473 | var children = this.children;
|
4474 |
|
4475 | for(i = 0, l = children.length; i < l; i++) {
|
4476 | traverseAndCheck(children[i], type, results);
|
4477 | }
|
4478 | }
|
4479 | else {
|
4480 | var fields = this.fields;
|
4481 |
|
4482 | for(i = 0, l = fields.length; i < l; i++) {
|
4483 | traverseAndCheck(this[fields[i]], type, results);
|
4484 | }
|
4485 | }
|
4486 |
|
4487 | return results;
|
4488 | },
|
4489 |
|
4490 | iterFields: function(func) {
|
4491 | lib.each(this.fields, function(field) {
|
4492 | func(this[field], field);
|
4493 | }, this);
|
4494 | }
|
4495 | });
|
4496 |
|
4497 |
|
4498 | var Value = Node.extend('Value', { fields: ['value'] });
|
4499 |
|
4500 |
|
4501 | var NodeList = Node.extend('NodeList', {
|
4502 | fields: ['children'],
|
4503 |
|
4504 | init: function(lineno, colno, nodes) {
|
4505 | this.parent(lineno, colno, nodes || []);
|
4506 | },
|
4507 |
|
4508 | addChild: function(node) {
|
4509 | this.children.push(node);
|
4510 | }
|
4511 | });
|
4512 |
|
4513 | var Root = NodeList.extend('Root');
|
4514 | var Literal = Value.extend('Literal');
|
4515 | var Symbol = Value.extend('Symbol');
|
4516 | var Group = NodeList.extend('Group');
|
4517 | var Array = NodeList.extend('Array');
|
4518 | var Pair = Node.extend('Pair', { fields: ['key', 'value'] });
|
4519 | var Dict = NodeList.extend('Dict');
|
4520 | var LookupVal = Node.extend('LookupVal', { fields: ['target', 'val'] });
|
4521 | var If = Node.extend('If', { fields: ['cond', 'body', 'else_'] });
|
4522 | var IfAsync = If.extend('IfAsync');
|
4523 | var InlineIf = Node.extend('InlineIf', { fields: ['cond', 'body', 'else_'] });
|
4524 | var For = Node.extend('For', { fields: ['arr', 'name', 'body', 'else_'] });
|
4525 | var AsyncEach = For.extend('AsyncEach');
|
4526 | var AsyncAll = For.extend('AsyncAll');
|
4527 | var Macro = Node.extend('Macro', { fields: ['name', 'args', 'body'] });
|
4528 | var Caller = Macro.extend('Caller');
|
4529 | var Import = Node.extend('Import', { fields: ['template', 'target', 'withContext'] });
|
4530 | var FromImport = Node.extend('FromImport', {
|
4531 | fields: ['template', 'names', 'withContext'],
|
4532 |
|
4533 | init: function(lineno, colno, template, names, withContext) {
|
4534 | this.parent(lineno, colno,
|
4535 | template,
|
4536 | names || new NodeList(), withContext);
|
4537 | }
|
4538 | });
|
4539 | var FunCall = Node.extend('FunCall', { fields: ['name', 'args'] });
|
4540 | var Filter = FunCall.extend('Filter');
|
4541 | var FilterAsync = Filter.extend('FilterAsync', {
|
4542 | fields: ['name', 'args', 'symbol']
|
4543 | });
|
4544 | var KeywordArgs = Dict.extend('KeywordArgs');
|
4545 | var Block = Node.extend('Block', { fields: ['name', 'body'] });
|
4546 | var Super = Node.extend('Super', { fields: ['blockName', 'symbol'] });
|
4547 | var TemplateRef = Node.extend('TemplateRef', { fields: ['template'] });
|
4548 | var Extends = TemplateRef.extend('Extends');
|
4549 | var Include = Node.extend('Include', { fields: ['template', 'ignoreMissing'] });
|
4550 | var Set = Node.extend('Set', { fields: ['targets', 'value'] });
|
4551 | var Output = NodeList.extend('Output');
|
4552 | var Capture = Node.extend('Capture', { fields: ['body'] });
|
4553 | var TemplateData = Literal.extend('TemplateData');
|
4554 | var UnaryOp = Node.extend('UnaryOp', { fields: ['target'] });
|
4555 | var BinOp = Node.extend('BinOp', { fields: ['left', 'right'] });
|
4556 | var In = BinOp.extend('In');
|
4557 | var Or = BinOp.extend('Or');
|
4558 | var And = BinOp.extend('And');
|
4559 | var Not = UnaryOp.extend('Not');
|
4560 | var Add = BinOp.extend('Add');
|
4561 | var Concat = BinOp.extend('Concat');
|
4562 | var Sub = BinOp.extend('Sub');
|
4563 | var Mul = BinOp.extend('Mul');
|
4564 | var Div = BinOp.extend('Div');
|
4565 | var FloorDiv = BinOp.extend('FloorDiv');
|
4566 | var Mod = BinOp.extend('Mod');
|
4567 | var Pow = BinOp.extend('Pow');
|
4568 | var Neg = UnaryOp.extend('Neg');
|
4569 | var Pos = UnaryOp.extend('Pos');
|
4570 | var Compare = Node.extend('Compare', { fields: ['expr', 'ops'] });
|
4571 | var CompareOperand = Node.extend('CompareOperand', {
|
4572 | fields: ['expr', 'type']
|
4573 | });
|
4574 |
|
4575 | var CallExtension = Node.extend('CallExtension', {
|
4576 | fields: ['extName', 'prop', 'args', 'contentArgs'],
|
4577 |
|
4578 | init: function(ext, prop, args, contentArgs) {
|
4579 | this.extName = ext._name || ext;
|
4580 | this.prop = prop;
|
4581 | this.args = args || new NodeList();
|
4582 | this.contentArgs = contentArgs || [];
|
4583 | this.autoescape = ext.autoescape;
|
4584 | }
|
4585 | });
|
4586 |
|
4587 | var CallExtensionAsync = CallExtension.extend('CallExtensionAsync');
|
4588 |
|
4589 |
|
4590 | function printNodes(node, indent) {
|
4591 | indent = indent || 0;
|
4592 |
|
4593 |
|
4594 | function print(str, indent, inline) {
|
4595 | var lines = str.split('\n');
|
4596 |
|
4597 | for(var i=0; i<lines.length; i++) {
|
4598 | if(lines[i]) {
|
4599 | if((inline && i > 0) || !inline) {
|
4600 | for(var j=0; j<indent; j++) {
|
4601 | process.stdout.write(' ');
|
4602 | }
|
4603 | }
|
4604 | }
|
4605 |
|
4606 | if(i === lines.length-1) {
|
4607 | process.stdout.write(lines[i]);
|
4608 | }
|
4609 | else {
|
4610 | process.stdout.write(lines[i] + '\n');
|
4611 | }
|
4612 | }
|
4613 | }
|
4614 |
|
4615 | print(node.typename + ': ', indent);
|
4616 |
|
4617 | if(node instanceof NodeList) {
|
4618 | print('\n');
|
4619 | lib.each(node.children, function(n) {
|
4620 | printNodes(n, indent + 2);
|
4621 | });
|
4622 | }
|
4623 | else if(node instanceof CallExtension) {
|
4624 | print(node.extName + '.' + node.prop);
|
4625 | print('\n');
|
4626 |
|
4627 | if(node.args) {
|
4628 | printNodes(node.args, indent + 2);
|
4629 | }
|
4630 |
|
4631 | if(node.contentArgs) {
|
4632 | lib.each(node.contentArgs, function(n) {
|
4633 | printNodes(n, indent + 2);
|
4634 | });
|
4635 | }
|
4636 | }
|
4637 | else {
|
4638 | var nodes = null;
|
4639 | var props = null;
|
4640 |
|
4641 | node.iterFields(function(val, field) {
|
4642 | if(val instanceof Node) {
|
4643 | nodes = nodes || {};
|
4644 | nodes[field] = val;
|
4645 | }
|
4646 | else {
|
4647 | props = props || {};
|
4648 | props[field] = val;
|
4649 | }
|
4650 | });
|
4651 |
|
4652 | if(props) {
|
4653 | print(JSON.stringify(props, null, 2) + '\n', null, true);
|
4654 | }
|
4655 | else {
|
4656 | print('\n');
|
4657 | }
|
4658 |
|
4659 | if(nodes) {
|
4660 | for(var k in nodes) {
|
4661 | printNodes(nodes[k], indent + 2);
|
4662 | }
|
4663 | }
|
4664 |
|
4665 | }
|
4666 | }
|
4667 |
|
4668 |
|
4669 |
|
4670 |
|
4671 |
|
4672 |
|
4673 |
|
4674 |
|
4675 |
|
4676 | module.exports = {
|
4677 | Node: Node,
|
4678 | Root: Root,
|
4679 | NodeList: NodeList,
|
4680 | Value: Value,
|
4681 | Literal: Literal,
|
4682 | Symbol: Symbol,
|
4683 | Group: Group,
|
4684 | Array: Array,
|
4685 | Pair: Pair,
|
4686 | Dict: Dict,
|
4687 | Output: Output,
|
4688 | Capture: Capture,
|
4689 | TemplateData: TemplateData,
|
4690 | If: If,
|
4691 | IfAsync: IfAsync,
|
4692 | InlineIf: InlineIf,
|
4693 | For: For,
|
4694 | AsyncEach: AsyncEach,
|
4695 | AsyncAll: AsyncAll,
|
4696 | Macro: Macro,
|
4697 | Caller: Caller,
|
4698 | Import: Import,
|
4699 | FromImport: FromImport,
|
4700 | FunCall: FunCall,
|
4701 | Filter: Filter,
|
4702 | FilterAsync: FilterAsync,
|
4703 | KeywordArgs: KeywordArgs,
|
4704 | Block: Block,
|
4705 | Super: Super,
|
4706 | Extends: Extends,
|
4707 | Include: Include,
|
4708 | Set: Set,
|
4709 | LookupVal: LookupVal,
|
4710 | BinOp: BinOp,
|
4711 | In: In,
|
4712 | Or: Or,
|
4713 | And: And,
|
4714 | Not: Not,
|
4715 | Add: Add,
|
4716 | Concat: Concat,
|
4717 | Sub: Sub,
|
4718 | Mul: Mul,
|
4719 | Div: Div,
|
4720 | FloorDiv: FloorDiv,
|
4721 | Mod: Mod,
|
4722 | Pow: Pow,
|
4723 | Neg: Neg,
|
4724 | Pos: Pos,
|
4725 | Compare: Compare,
|
4726 | CompareOperand: CompareOperand,
|
4727 |
|
4728 | CallExtension: CallExtension,
|
4729 | CallExtensionAsync: CallExtensionAsync,
|
4730 |
|
4731 | printNodes: printNodes
|
4732 | };
|
4733 |
|
4734 | }.call(exports, __webpack_require__(3)))
|
4735 |
|
4736 | },
|
4737 |
|
4738 | function(module, exports, __webpack_require__) {
|
4739 |
|
4740 | 'use strict';
|
4741 |
|
4742 | var nodes = __webpack_require__(10);
|
4743 | var lib = __webpack_require__(1);
|
4744 |
|
4745 | var sym = 0;
|
4746 | function gensym() {
|
4747 | return 'hole_' + sym++;
|
4748 | }
|
4749 |
|
4750 |
|
4751 | function mapCOW(arr, func) {
|
4752 | var res = null;
|
4753 |
|
4754 | for(var i=0; i<arr.length; i++) {
|
4755 | var item = func(arr[i]);
|
4756 |
|
4757 | if(item !== arr[i]) {
|
4758 | if(!res) {
|
4759 | res = arr.slice();
|
4760 | }
|
4761 |
|
4762 | res[i] = item;
|
4763 | }
|
4764 | }
|
4765 |
|
4766 | return res || arr;
|
4767 | }
|
4768 |
|
4769 | function walk(ast, func, depthFirst) {
|
4770 | if(!(ast instanceof nodes.Node)) {
|
4771 | return ast;
|
4772 | }
|
4773 |
|
4774 | if(!depthFirst) {
|
4775 | var astT = func(ast);
|
4776 |
|
4777 | if(astT && astT !== ast) {
|
4778 | return astT;
|
4779 | }
|
4780 | }
|
4781 |
|
4782 | if(ast instanceof nodes.NodeList) {
|
4783 | var children = mapCOW(ast.children, function(node) {
|
4784 | return walk(node, func, depthFirst);
|
4785 | });
|
4786 |
|
4787 | if(children !== ast.children) {
|
4788 | ast = new nodes[ast.typename](ast.lineno, ast.colno, children);
|
4789 | }
|
4790 | }
|
4791 | else if(ast instanceof nodes.CallExtension) {
|
4792 | var args = walk(ast.args, func, depthFirst);
|
4793 |
|
4794 | var contentArgs = mapCOW(ast.contentArgs, function(node) {
|
4795 | return walk(node, func, depthFirst);
|
4796 | });
|
4797 |
|
4798 | if(args !== ast.args || contentArgs !== ast.contentArgs) {
|
4799 | ast = new nodes[ast.typename](ast.extName,
|
4800 | ast.prop,
|
4801 | args,
|
4802 | contentArgs);
|
4803 | }
|
4804 | }
|
4805 | else {
|
4806 | var props = ast.fields.map(function(field) {
|
4807 | return ast[field];
|
4808 | });
|
4809 |
|
4810 | var propsT = mapCOW(props, function(prop) {
|
4811 | return walk(prop, func, depthFirst);
|
4812 | });
|
4813 |
|
4814 | if(propsT !== props) {
|
4815 | ast = new nodes[ast.typename](ast.lineno, ast.colno);
|
4816 |
|
4817 | propsT.forEach(function(prop, i) {
|
4818 | ast[ast.fields[i]] = prop;
|
4819 | });
|
4820 | }
|
4821 | }
|
4822 |
|
4823 | return depthFirst ? (func(ast) || ast) : ast;
|
4824 | }
|
4825 |
|
4826 | function depthWalk(ast, func) {
|
4827 | return walk(ast, func, true);
|
4828 | }
|
4829 |
|
4830 | function _liftFilters(node, asyncFilters, prop) {
|
4831 | var children = [];
|
4832 |
|
4833 | var walked = depthWalk(prop ? node[prop] : node, function(node) {
|
4834 | if(node instanceof nodes.Block) {
|
4835 | return node;
|
4836 | }
|
4837 | else if((node instanceof nodes.Filter &&
|
4838 | lib.indexOf(asyncFilters, node.name.value) !== -1) ||
|
4839 | node instanceof nodes.CallExtensionAsync) {
|
4840 | var symbol = new nodes.Symbol(node.lineno,
|
4841 | node.colno,
|
4842 | gensym());
|
4843 |
|
4844 | children.push(new nodes.FilterAsync(node.lineno,
|
4845 | node.colno,
|
4846 | node.name,
|
4847 | node.args,
|
4848 | symbol));
|
4849 | return symbol;
|
4850 | }
|
4851 | });
|
4852 |
|
4853 | if(prop) {
|
4854 | node[prop] = walked;
|
4855 | }
|
4856 | else {
|
4857 | node = walked;
|
4858 | }
|
4859 |
|
4860 | if(children.length) {
|
4861 | children.push(node);
|
4862 |
|
4863 | return new nodes.NodeList(
|
4864 | node.lineno,
|
4865 | node.colno,
|
4866 | children
|
4867 | );
|
4868 | }
|
4869 | else {
|
4870 | return node;
|
4871 | }
|
4872 | }
|
4873 |
|
4874 | function liftFilters(ast, asyncFilters) {
|
4875 | return depthWalk(ast, function(node) {
|
4876 | if(node instanceof nodes.Output) {
|
4877 | return _liftFilters(node, asyncFilters);
|
4878 | }
|
4879 | else if(node instanceof nodes.Set) {
|
4880 | return _liftFilters(node, asyncFilters, 'value');
|
4881 | }
|
4882 | else if(node instanceof nodes.For) {
|
4883 | return _liftFilters(node, asyncFilters, 'arr');
|
4884 | }
|
4885 | else if(node instanceof nodes.If) {
|
4886 | return _liftFilters(node, asyncFilters, 'cond');
|
4887 | }
|
4888 | else if(node instanceof nodes.CallExtension) {
|
4889 | return _liftFilters(node, asyncFilters, 'args');
|
4890 | }
|
4891 | });
|
4892 | }
|
4893 |
|
4894 | function liftSuper(ast) {
|
4895 | return walk(ast, function(blockNode) {
|
4896 | if(!(blockNode instanceof nodes.Block)) {
|
4897 | return;
|
4898 | }
|
4899 |
|
4900 | var hasSuper = false;
|
4901 | var symbol = gensym();
|
4902 |
|
4903 | blockNode.body = walk(blockNode.body, function(node) {
|
4904 | if(node instanceof nodes.FunCall &&
|
4905 | node.name.value === 'super') {
|
4906 | hasSuper = true;
|
4907 | return new nodes.Symbol(node.lineno, node.colno, symbol);
|
4908 | }
|
4909 | });
|
4910 |
|
4911 | if(hasSuper) {
|
4912 | blockNode.body.children.unshift(new nodes.Super(
|
4913 | 0, 0, blockNode.name, new nodes.Symbol(0, 0, symbol)
|
4914 | ));
|
4915 | }
|
4916 | });
|
4917 | }
|
4918 |
|
4919 | function convertStatements(ast) {
|
4920 | return depthWalk(ast, function(node) {
|
4921 | if(!(node instanceof nodes.If) &&
|
4922 | !(node instanceof nodes.For)) {
|
4923 | return;
|
4924 | }
|
4925 |
|
4926 | var async = false;
|
4927 | walk(node, function(node) {
|
4928 | if(node instanceof nodes.FilterAsync ||
|
4929 | node instanceof nodes.IfAsync ||
|
4930 | node instanceof nodes.AsyncEach ||
|
4931 | node instanceof nodes.AsyncAll ||
|
4932 | node instanceof nodes.CallExtensionAsync) {
|
4933 | async = true;
|
4934 |
|
4935 | return node;
|
4936 | }
|
4937 | });
|
4938 |
|
4939 | if(async) {
|
4940 | if(node instanceof nodes.If) {
|
4941 | return new nodes.IfAsync(
|
4942 | node.lineno,
|
4943 | node.colno,
|
4944 | node.cond,
|
4945 | node.body,
|
4946 | node.else_
|
4947 | );
|
4948 | }
|
4949 | else if(node instanceof nodes.For) {
|
4950 | return new nodes.AsyncEach(
|
4951 | node.lineno,
|
4952 | node.colno,
|
4953 | node.arr,
|
4954 | node.name,
|
4955 | node.body,
|
4956 | node.else_
|
4957 | );
|
4958 | }
|
4959 | }
|
4960 | });
|
4961 | }
|
4962 |
|
4963 | function cps(ast, asyncFilters) {
|
4964 | return convertStatements(liftSuper(liftFilters(ast, asyncFilters)));
|
4965 | }
|
4966 |
|
4967 | function transform(ast, asyncFilters) {
|
4968 | return cps(ast, asyncFilters || []);
|
4969 | }
|
4970 |
|
4971 |
|
4972 |
|
4973 |
|
4974 |
|
4975 |
|
4976 | module.exports = {
|
4977 | transform: transform
|
4978 | };
|
4979 |
|
4980 |
|
4981 | },
|
4982 |
|
4983 | function(module, exports, __webpack_require__) {
|
4984 |
|
4985 | 'use strict';
|
4986 |
|
4987 | var lib = __webpack_require__(1);
|
4988 | var Obj = __webpack_require__(6);
|
4989 |
|
4990 |
|
4991 |
|
4992 |
|
4993 | var Frame = Obj.extend({
|
4994 | init: function(parent, isolateWrites) {
|
4995 | this.variables = {};
|
4996 | this.parent = parent;
|
4997 | this.topLevel = false;
|
4998 |
|
4999 |
|
5000 | this.isolateWrites = isolateWrites;
|
5001 | },
|
5002 |
|
5003 | set: function(name, val, resolveUp) {
|
5004 |
|
5005 |
|
5006 | var parts = name.split('.');
|
5007 | var obj = this.variables;
|
5008 | var frame = this;
|
5009 |
|
5010 | if(resolveUp) {
|
5011 | if((frame = this.resolve(parts[0], true))) {
|
5012 | frame.set(name, val);
|
5013 | return;
|
5014 | }
|
5015 | }
|
5016 |
|
5017 | for(var i=0; i<parts.length - 1; i++) {
|
5018 | var id = parts[i];
|
5019 |
|
5020 | if(!obj[id]) {
|
5021 | obj[id] = {};
|
5022 | }
|
5023 | obj = obj[id];
|
5024 | }
|
5025 |
|
5026 | obj[parts[parts.length - 1]] = val;
|
5027 | },
|
5028 |
|
5029 | get: function(name) {
|
5030 | var val = this.variables[name];
|
5031 | if(val !== undefined && val !== null) {
|
5032 | return val;
|
5033 | }
|
5034 | return null;
|
5035 | },
|
5036 |
|
5037 | lookup: function(name) {
|
5038 | var p = this.parent;
|
5039 | var val = this.variables[name];
|
5040 | if(val !== undefined && val !== null) {
|
5041 | return val;
|
5042 | }
|
5043 | return p && p.lookup(name);
|
5044 | },
|
5045 |
|
5046 | resolve: function(name, forWrite) {
|
5047 | var p = (forWrite && this.isolateWrites) ? undefined : this.parent;
|
5048 | var val = this.variables[name];
|
5049 | if(val !== undefined && val !== null) {
|
5050 | return this;
|
5051 | }
|
5052 | return p && p.resolve(name);
|
5053 | },
|
5054 |
|
5055 | push: function(isolateWrites) {
|
5056 | return new Frame(this, isolateWrites);
|
5057 | },
|
5058 |
|
5059 | pop: function() {
|
5060 | return this.parent;
|
5061 | }
|
5062 | });
|
5063 |
|
5064 | function makeMacro(argNames, kwargNames, func) {
|
5065 | return function() {
|
5066 | var argCount = numArgs(arguments);
|
5067 | var args;
|
5068 | var kwargs = getKeywordArgs(arguments);
|
5069 | var i;
|
5070 |
|
5071 | if(argCount > argNames.length) {
|
5072 | args = Array.prototype.slice.call(arguments, 0, argNames.length);
|
5073 |
|
5074 |
|
5075 |
|
5076 | var vals = Array.prototype.slice.call(arguments, args.length, argCount);
|
5077 | for(i = 0; i < vals.length; i++) {
|
5078 | if(i < kwargNames.length) {
|
5079 | kwargs[kwargNames[i]] = vals[i];
|
5080 | }
|
5081 | }
|
5082 |
|
5083 | args.push(kwargs);
|
5084 | }
|
5085 | else if(argCount < argNames.length) {
|
5086 | args = Array.prototype.slice.call(arguments, 0, argCount);
|
5087 |
|
5088 | for(i = argCount; i < argNames.length; i++) {
|
5089 | var arg = argNames[i];
|
5090 |
|
5091 |
|
5092 |
|
5093 |
|
5094 | args.push(kwargs[arg]);
|
5095 | delete kwargs[arg];
|
5096 | }
|
5097 |
|
5098 | args.push(kwargs);
|
5099 | }
|
5100 | else {
|
5101 | args = arguments;
|
5102 | }
|
5103 |
|
5104 | return func.apply(this, args);
|
5105 | };
|
5106 | }
|
5107 |
|
5108 | function makeKeywordArgs(obj) {
|
5109 | obj.__keywords = true;
|
5110 | return obj;
|
5111 | }
|
5112 |
|
5113 | function getKeywordArgs(args) {
|
5114 | var len = args.length;
|
5115 | if(len) {
|
5116 | var lastArg = args[len - 1];
|
5117 | if(lastArg && lastArg.hasOwnProperty('__keywords')) {
|
5118 | return lastArg;
|
5119 | }
|
5120 | }
|
5121 | return {};
|
5122 | }
|
5123 |
|
5124 | function numArgs(args) {
|
5125 | var len = args.length;
|
5126 | if(len === 0) {
|
5127 | return 0;
|
5128 | }
|
5129 |
|
5130 | var lastArg = args[len - 1];
|
5131 | if(lastArg && lastArg.hasOwnProperty('__keywords')) {
|
5132 | return len - 1;
|
5133 | }
|
5134 | else {
|
5135 | return len;
|
5136 | }
|
5137 | }
|
5138 |
|
5139 |
|
5140 |
|
5141 |
|
5142 | function SafeString(val) {
|
5143 | if(typeof val !== 'string') {
|
5144 | return val;
|
5145 | }
|
5146 |
|
5147 | this.val = val;
|
5148 | this.length = val.length;
|
5149 | }
|
5150 |
|
5151 | SafeString.prototype = Object.create(String.prototype, {
|
5152 | length: { writable: true, configurable: true, value: 0 }
|
5153 | });
|
5154 | SafeString.prototype.valueOf = function() {
|
5155 | return this.val;
|
5156 | };
|
5157 | SafeString.prototype.toString = function() {
|
5158 | return this.val;
|
5159 | };
|
5160 |
|
5161 | function copySafeness(dest, target) {
|
5162 | if(dest instanceof SafeString) {
|
5163 | return new SafeString(target);
|
5164 | }
|
5165 | return target.toString();
|
5166 | }
|
5167 |
|
5168 | function markSafe(val) {
|
5169 | var type = typeof val;
|
5170 |
|
5171 | if(type === 'string') {
|
5172 | return new SafeString(val);
|
5173 | }
|
5174 | else if(type !== 'function') {
|
5175 | return val;
|
5176 | }
|
5177 | else {
|
5178 | return function() {
|
5179 | var ret = val.apply(this, arguments);
|
5180 |
|
5181 | if(typeof ret === 'string') {
|
5182 | return new SafeString(ret);
|
5183 | }
|
5184 |
|
5185 | return ret;
|
5186 | };
|
5187 | }
|
5188 | }
|
5189 |
|
5190 | function suppressValue(val, autoescape) {
|
5191 | val = (val !== undefined && val !== null) ? val : '';
|
5192 |
|
5193 | if(autoescape && !(val instanceof SafeString)) {
|
5194 | val = lib.escape(val.toString());
|
5195 | }
|
5196 |
|
5197 | return val;
|
5198 | }
|
5199 |
|
5200 | function ensureDefined(val, lineno, colno) {
|
5201 | if(val === null || val === undefined) {
|
5202 | throw new lib.TemplateError(
|
5203 | 'attempted to output null or undefined value',
|
5204 | lineno + 1,
|
5205 | colno + 1
|
5206 | );
|
5207 | }
|
5208 | return val;
|
5209 | }
|
5210 |
|
5211 | function memberLookup(obj, val) {
|
5212 | obj = obj || {};
|
5213 |
|
5214 | if(typeof obj[val] === 'function') {
|
5215 | return function() {
|
5216 | return obj[val].apply(obj, arguments);
|
5217 | };
|
5218 | }
|
5219 |
|
5220 | return obj[val];
|
5221 | }
|
5222 |
|
5223 | function callWrap(obj, name, context, args) {
|
5224 | if(!obj) {
|
5225 | throw new Error('Unable to call `' + name + '`, which is undefined or falsey');
|
5226 | }
|
5227 | else if(typeof obj !== 'function') {
|
5228 | throw new Error('Unable to call `' + name + '`, which is not a function');
|
5229 | }
|
5230 |
|
5231 |
|
5232 | return obj.apply(context, args);
|
5233 | }
|
5234 |
|
5235 | function contextOrFrameLookup(context, frame, name) {
|
5236 | var val = frame.lookup(name);
|
5237 | return (val !== undefined && val !== null) ?
|
5238 | val :
|
5239 | context.lookup(name);
|
5240 | }
|
5241 |
|
5242 | function handleError(error, lineno, colno) {
|
5243 | if(error.lineno) {
|
5244 | return error;
|
5245 | }
|
5246 | else {
|
5247 | return new lib.TemplateError(error, lineno, colno);
|
5248 | }
|
5249 | }
|
5250 |
|
5251 | function asyncEach(arr, dimen, iter, cb) {
|
5252 | if(lib.isArray(arr)) {
|
5253 | var len = arr.length;
|
5254 |
|
5255 | lib.asyncIter(arr, function(item, i, next) {
|
5256 | switch(dimen) {
|
5257 | case 1: iter(item, i, len, next); break;
|
5258 | case 2: iter(item[0], item[1], i, len, next); break;
|
5259 | case 3: iter(item[0], item[1], item[2], i, len, next); break;
|
5260 | default:
|
5261 | item.push(i, next);
|
5262 | iter.apply(this, item);
|
5263 | }
|
5264 | }, cb);
|
5265 | }
|
5266 | else {
|
5267 | lib.asyncFor(arr, function(key, val, i, len, next) {
|
5268 | iter(key, val, i, len, next);
|
5269 | }, cb);
|
5270 | }
|
5271 | }
|
5272 |
|
5273 | function asyncAll(arr, dimen, func, cb) {
|
5274 | var finished = 0;
|
5275 | var len, i;
|
5276 | var outputArr;
|
5277 |
|
5278 | function done(i, output) {
|
5279 | finished++;
|
5280 | outputArr[i] = output;
|
5281 |
|
5282 | if(finished === len) {
|
5283 | cb(null, outputArr.join(''));
|
5284 | }
|
5285 | }
|
5286 |
|
5287 | if(lib.isArray(arr)) {
|
5288 | len = arr.length;
|
5289 | outputArr = new Array(len);
|
5290 |
|
5291 | if(len === 0) {
|
5292 | cb(null, '');
|
5293 | }
|
5294 | else {
|
5295 | for(i = 0; i < arr.length; i++) {
|
5296 | var item = arr[i];
|
5297 |
|
5298 | switch(dimen) {
|
5299 | case 1: func(item, i, len, done); break;
|
5300 | case 2: func(item[0], item[1], i, len, done); break;
|
5301 | case 3: func(item[0], item[1], item[2], i, len, done); break;
|
5302 | default:
|
5303 | item.push(i, done);
|
5304 |
|
5305 | func.apply(this, item);
|
5306 | }
|
5307 | }
|
5308 | }
|
5309 | }
|
5310 | else {
|
5311 | var keys = lib.keys(arr);
|
5312 | len = keys.length;
|
5313 | outputArr = new Array(len);
|
5314 |
|
5315 | if(len === 0) {
|
5316 | cb(null, '');
|
5317 | }
|
5318 | else {
|
5319 | for(i = 0; i < keys.length; i++) {
|
5320 | var k = keys[i];
|
5321 | func(k, arr[k], i, len, done);
|
5322 | }
|
5323 | }
|
5324 | }
|
5325 | }
|
5326 |
|
5327 | module.exports = {
|
5328 | Frame: Frame,
|
5329 | makeMacro: makeMacro,
|
5330 | makeKeywordArgs: makeKeywordArgs,
|
5331 | numArgs: numArgs,
|
5332 | suppressValue: suppressValue,
|
5333 | ensureDefined: ensureDefined,
|
5334 | memberLookup: memberLookup,
|
5335 | contextOrFrameLookup: contextOrFrameLookup,
|
5336 | callWrap: callWrap,
|
5337 | handleError: handleError,
|
5338 | isArray: lib.isArray,
|
5339 | keys: lib.keys,
|
5340 | SafeString: SafeString,
|
5341 | copySafeness: copySafeness,
|
5342 | markSafe: markSafe,
|
5343 | asyncEach: asyncEach,
|
5344 | asyncAll: asyncAll,
|
5345 | inOperator: lib.inOperator
|
5346 | };
|
5347 |
|
5348 |
|
5349 | },
|
5350 |
|
5351 | function(module, exports, __webpack_require__) {
|
5352 |
|
5353 | 'use strict';
|
5354 |
|
5355 | var lib = __webpack_require__(1);
|
5356 | var r = __webpack_require__(12);
|
5357 |
|
5358 | function normalize(value, defaultValue) {
|
5359 | if(value === null || value === undefined || value === false) {
|
5360 | return defaultValue;
|
5361 | }
|
5362 | return value;
|
5363 | }
|
5364 |
|
5365 | var filters = {
|
5366 | abs: function(n) {
|
5367 | return Math.abs(n);
|
5368 | },
|
5369 |
|
5370 | batch: function(arr, linecount, fill_with) {
|
5371 | var i;
|
5372 | var res = [];
|
5373 | var tmp = [];
|
5374 |
|
5375 | for(i = 0; i < arr.length; i++) {
|
5376 | if(i % linecount === 0 && tmp.length) {
|
5377 | res.push(tmp);
|
5378 | tmp = [];
|
5379 | }
|
5380 |
|
5381 | tmp.push(arr[i]);
|
5382 | }
|
5383 |
|
5384 | if(tmp.length) {
|
5385 | if(fill_with) {
|
5386 | for(i = tmp.length; i < linecount; i++) {
|
5387 | tmp.push(fill_with);
|
5388 | }
|
5389 | }
|
5390 |
|
5391 | res.push(tmp);
|
5392 | }
|
5393 |
|
5394 | return res;
|
5395 | },
|
5396 |
|
5397 | capitalize: function(str) {
|
5398 | str = normalize(str, '');
|
5399 | var ret = str.toLowerCase();
|
5400 | return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
|
5401 | },
|
5402 |
|
5403 | center: function(str, width) {
|
5404 | str = normalize(str, '');
|
5405 | width = width || 80;
|
5406 |
|
5407 | if(str.length >= width) {
|
5408 | return str;
|
5409 | }
|
5410 |
|
5411 | var spaces = width - str.length;
|
5412 | var pre = lib.repeat(' ', spaces/2 - spaces % 2);
|
5413 | var post = lib.repeat(' ', spaces/2);
|
5414 | return r.copySafeness(str, pre + str + post);
|
5415 | },
|
5416 |
|
5417 | 'default': function(val, def, bool) {
|
5418 | if(bool) {
|
5419 | return val ? val : def;
|
5420 | }
|
5421 | else {
|
5422 | return (val !== undefined) ? val : def;
|
5423 | }
|
5424 | },
|
5425 |
|
5426 | dictsort: function(val, case_sensitive, by) {
|
5427 | if (!lib.isObject(val)) {
|
5428 | throw new lib.TemplateError('dictsort filter: val must be an object');
|
5429 | }
|
5430 |
|
5431 | var array = [];
|
5432 | for (var k in val) {
|
5433 |
|
5434 | array.push([k,val[k]]);
|
5435 | }
|
5436 |
|
5437 | var si;
|
5438 | if (by === undefined || by === 'key') {
|
5439 | si = 0;
|
5440 | } else if (by === 'value') {
|
5441 | si = 1;
|
5442 | } else {
|
5443 | throw new lib.TemplateError(
|
5444 | 'dictsort filter: You can only sort by either key or value');
|
5445 | }
|
5446 |
|
5447 | array.sort(function(t1, t2) {
|
5448 | var a = t1[si];
|
5449 | var b = t2[si];
|
5450 |
|
5451 | if (!case_sensitive) {
|
5452 | if (lib.isString(a)) {
|
5453 | a = a.toUpperCase();
|
5454 | }
|
5455 | if (lib.isString(b)) {
|
5456 | b = b.toUpperCase();
|
5457 | }
|
5458 | }
|
5459 |
|
5460 | return a > b ? 1 : (a === b ? 0 : -1);
|
5461 | });
|
5462 |
|
5463 | return array;
|
5464 | },
|
5465 |
|
5466 | dump: function(obj) {
|
5467 | return JSON.stringify(obj);
|
5468 | },
|
5469 |
|
5470 | escape: function(str) {
|
5471 | if(str instanceof r.SafeString) {
|
5472 | return str;
|
5473 | }
|
5474 | str = (str === null || str === undefined) ? '' : str;
|
5475 | return r.markSafe(lib.escape(str.toString()));
|
5476 | },
|
5477 |
|
5478 | safe: function(str) {
|
5479 | if (str instanceof r.SafeString) {
|
5480 | return str;
|
5481 | }
|
5482 | str = (str === null || str === undefined) ? '' : str;
|
5483 | return r.markSafe(str.toString());
|
5484 | },
|
5485 |
|
5486 | first: function(arr) {
|
5487 | return arr[0];
|
5488 | },
|
5489 |
|
5490 | groupby: function(arr, attr) {
|
5491 | return lib.groupBy(arr, attr);
|
5492 | },
|
5493 |
|
5494 | indent: function(str, width, indentfirst) {
|
5495 | str = normalize(str, '');
|
5496 |
|
5497 | if (str === '') return '';
|
5498 |
|
5499 | width = width || 4;
|
5500 | var res = '';
|
5501 | var lines = str.split('\n');
|
5502 | var sp = lib.repeat(' ', width);
|
5503 |
|
5504 | for(var i=0; i<lines.length; i++) {
|
5505 | if(i === 0 && !indentfirst) {
|
5506 | res += lines[i] + '\n';
|
5507 | }
|
5508 | else {
|
5509 | res += sp + lines[i] + '\n';
|
5510 | }
|
5511 | }
|
5512 |
|
5513 | return r.copySafeness(str, res);
|
5514 | },
|
5515 |
|
5516 | join: function(arr, del, attr) {
|
5517 | del = del || '';
|
5518 |
|
5519 | if(attr) {
|
5520 | arr = lib.map(arr, function(v) {
|
5521 | return v[attr];
|
5522 | });
|
5523 | }
|
5524 |
|
5525 | return arr.join(del);
|
5526 | },
|
5527 |
|
5528 | last: function(arr) {
|
5529 | return arr[arr.length-1];
|
5530 | },
|
5531 |
|
5532 | length: function(val) {
|
5533 | var value = normalize(val, '');
|
5534 |
|
5535 | if(value !== undefined) {
|
5536 | if(
|
5537 | (typeof Map === 'function' && value instanceof Map) ||
|
5538 | (typeof Set === 'function' && value instanceof Set)
|
5539 | ) {
|
5540 |
|
5541 | return value.size;
|
5542 | }
|
5543 | if(lib.isObject(value) && !(value instanceof r.SafeString)) {
|
5544 |
|
5545 | return Object.keys(value).length;
|
5546 | }
|
5547 | return value.length;
|
5548 | }
|
5549 | return 0;
|
5550 | },
|
5551 |
|
5552 | list: function(val) {
|
5553 | if(lib.isString(val)) {
|
5554 | return val.split('');
|
5555 | }
|
5556 | else if(lib.isObject(val)) {
|
5557 | var keys = [];
|
5558 |
|
5559 | if(Object.keys) {
|
5560 | keys = Object.keys(val);
|
5561 | }
|
5562 | else {
|
5563 | for(var k in val) {
|
5564 | keys.push(k);
|
5565 | }
|
5566 | }
|
5567 |
|
5568 | return lib.map(keys, function(k) {
|
5569 | return { key: k,
|
5570 | value: val[k] };
|
5571 | });
|
5572 | }
|
5573 | else if(lib.isArray(val)) {
|
5574 | return val;
|
5575 | }
|
5576 | else {
|
5577 | throw new lib.TemplateError('list filter: type not iterable');
|
5578 | }
|
5579 | },
|
5580 |
|
5581 | lower: function(str) {
|
5582 | str = normalize(str, '');
|
5583 | return str.toLowerCase();
|
5584 | },
|
5585 |
|
5586 | random: function(arr) {
|
5587 | return arr[Math.floor(Math.random() * arr.length)];
|
5588 | },
|
5589 |
|
5590 | rejectattr: function(arr, attr) {
|
5591 | return arr.filter(function (item) {
|
5592 | return !item[attr];
|
5593 | });
|
5594 | },
|
5595 |
|
5596 | selectattr: function(arr, attr) {
|
5597 | return arr.filter(function (item) {
|
5598 | return !!item[attr];
|
5599 | });
|
5600 | },
|
5601 |
|
5602 | replace: function(str, old, new_, maxCount) {
|
5603 | var originalStr = str;
|
5604 |
|
5605 | if (old instanceof RegExp) {
|
5606 | return str.replace(old, new_);
|
5607 | }
|
5608 |
|
5609 | if(typeof maxCount === 'undefined'){
|
5610 | maxCount = -1;
|
5611 | }
|
5612 |
|
5613 | var res = '';
|
5614 |
|
5615 |
|
5616 | if(typeof old === 'number'){
|
5617 | old = old + '';
|
5618 | }
|
5619 | else if(typeof old !== 'string') {
|
5620 |
|
5621 |
|
5622 | return str;
|
5623 | }
|
5624 |
|
5625 |
|
5626 | if(typeof str === 'number'){
|
5627 | str = str + '';
|
5628 | }
|
5629 |
|
5630 |
|
5631 | if(typeof str !== 'string' && !(str instanceof r.SafeString)){
|
5632 | return str;
|
5633 | }
|
5634 |
|
5635 |
|
5636 | if(old === ''){
|
5637 |
|
5638 |
|
5639 | res = new_ + str.split('').join(new_) + new_;
|
5640 | return r.copySafeness(str, res);
|
5641 | }
|
5642 |
|
5643 | var nextIndex = str.indexOf(old);
|
5644 |
|
5645 |
|
5646 | if(maxCount === 0 || nextIndex === -1){
|
5647 | return str;
|
5648 | }
|
5649 |
|
5650 | var pos = 0;
|
5651 | var count = 0;
|
5652 |
|
5653 | while(nextIndex > -1 && (maxCount === -1 || count < maxCount)){
|
5654 |
|
5655 |
|
5656 | res += str.substring(pos, nextIndex) + new_;
|
5657 |
|
5658 | pos = nextIndex + old.length;
|
5659 | count++;
|
5660 |
|
5661 | nextIndex = str.indexOf(old, pos);
|
5662 | }
|
5663 |
|
5664 |
|
5665 |
|
5666 | if(pos < str.length) {
|
5667 | res += str.substring(pos);
|
5668 | }
|
5669 |
|
5670 | return r.copySafeness(originalStr, res);
|
5671 | },
|
5672 |
|
5673 | reverse: function(val) {
|
5674 | var arr;
|
5675 | if(lib.isString(val)) {
|
5676 | arr = filters.list(val);
|
5677 | }
|
5678 | else {
|
5679 |
|
5680 | arr = lib.map(val, function(v) { return v; });
|
5681 | }
|
5682 |
|
5683 | arr.reverse();
|
5684 |
|
5685 | if(lib.isString(val)) {
|
5686 | return r.copySafeness(val, arr.join(''));
|
5687 | }
|
5688 | return arr;
|
5689 | },
|
5690 |
|
5691 | round: function(val, precision, method) {
|
5692 | precision = precision || 0;
|
5693 | var factor = Math.pow(10, precision);
|
5694 | var rounder;
|
5695 |
|
5696 | if(method === 'ceil') {
|
5697 | rounder = Math.ceil;
|
5698 | }
|
5699 | else if(method === 'floor') {
|
5700 | rounder = Math.floor;
|
5701 | }
|
5702 | else {
|
5703 | rounder = Math.round;
|
5704 | }
|
5705 |
|
5706 | return rounder(val * factor) / factor;
|
5707 | },
|
5708 |
|
5709 | slice: function(arr, slices, fillWith) {
|
5710 | var sliceLength = Math.floor(arr.length / slices);
|
5711 | var extra = arr.length % slices;
|
5712 | var offset = 0;
|
5713 | var res = [];
|
5714 |
|
5715 | for(var i=0; i<slices; i++) {
|
5716 | var start = offset + i * sliceLength;
|
5717 | if(i < extra) {
|
5718 | offset++;
|
5719 | }
|
5720 | var end = offset + (i + 1) * sliceLength;
|
5721 |
|
5722 | var slice = arr.slice(start, end);
|
5723 | if(fillWith && i >= extra) {
|
5724 | slice.push(fillWith);
|
5725 | }
|
5726 | res.push(slice);
|
5727 | }
|
5728 |
|
5729 | return res;
|
5730 | },
|
5731 |
|
5732 | sum: function(arr, attr, start) {
|
5733 | var sum = 0;
|
5734 |
|
5735 | if(typeof start === 'number'){
|
5736 | sum += start;
|
5737 | }
|
5738 |
|
5739 | if(attr) {
|
5740 | arr = lib.map(arr, function(v) {
|
5741 | return v[attr];
|
5742 | });
|
5743 | }
|
5744 |
|
5745 | for(var i = 0; i < arr.length; i++) {
|
5746 | sum += arr[i];
|
5747 | }
|
5748 |
|
5749 | return sum;
|
5750 | },
|
5751 |
|
5752 | sort: r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function(arr, reverse, caseSens, attr) {
|
5753 |
|
5754 | arr = lib.map(arr, function(v) { return v; });
|
5755 |
|
5756 | arr.sort(function(a, b) {
|
5757 | var x, y;
|
5758 |
|
5759 | if(attr) {
|
5760 | x = a[attr];
|
5761 | y = b[attr];
|
5762 | }
|
5763 | else {
|
5764 | x = a;
|
5765 | y = b;
|
5766 | }
|
5767 |
|
5768 | if(!caseSens && lib.isString(x) && lib.isString(y)) {
|
5769 | x = x.toLowerCase();
|
5770 | y = y.toLowerCase();
|
5771 | }
|
5772 |
|
5773 | if(x < y) {
|
5774 | return reverse ? 1 : -1;
|
5775 | }
|
5776 | else if(x > y) {
|
5777 | return reverse ? -1: 1;
|
5778 | }
|
5779 | else {
|
5780 | return 0;
|
5781 | }
|
5782 | });
|
5783 |
|
5784 | return arr;
|
5785 | }),
|
5786 |
|
5787 | string: function(obj) {
|
5788 | return r.copySafeness(obj, obj);
|
5789 | },
|
5790 |
|
5791 | striptags: function(input, preserve_linebreaks) {
|
5792 | input = normalize(input, '');
|
5793 | preserve_linebreaks = preserve_linebreaks || false;
|
5794 | var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|<!--[\s\S]*?-->/gi;
|
5795 | var trimmedInput = filters.trim(input.replace(tags, ''));
|
5796 | var res = '';
|
5797 | if (preserve_linebreaks) {
|
5798 | res = trimmedInput
|
5799 | .replace(/^ +| +$/gm, '')
|
5800 | .replace(/ +/g, ' ')
|
5801 | .replace(/(\r\n)/g, '\n')
|
5802 | .replace(/\n\n\n+/g, '\n\n');
|
5803 | } else {
|
5804 | res = trimmedInput.replace(/\s+/gi, ' ');
|
5805 | }
|
5806 | return r.copySafeness(input, res);
|
5807 | },
|
5808 |
|
5809 | title: function(str) {
|
5810 | str = normalize(str, '');
|
5811 | var words = str.split(' ');
|
5812 | for(var i = 0; i < words.length; i++) {
|
5813 | words[i] = filters.capitalize(words[i]);
|
5814 | }
|
5815 | return r.copySafeness(str, words.join(' '));
|
5816 | },
|
5817 |
|
5818 | trim: function(str) {
|
5819 | return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
|
5820 | },
|
5821 |
|
5822 | truncate: function(input, length, killwords, end) {
|
5823 | var orig = input;
|
5824 | input = normalize(input, '');
|
5825 | length = length || 255;
|
5826 |
|
5827 | if (input.length <= length)
|
5828 | return input;
|
5829 |
|
5830 | if (killwords) {
|
5831 | input = input.substring(0, length);
|
5832 | } else {
|
5833 | var idx = input.lastIndexOf(' ', length);
|
5834 | if(idx === -1) {
|
5835 | idx = length;
|
5836 | }
|
5837 |
|
5838 | input = input.substring(0, idx);
|
5839 | }
|
5840 |
|
5841 | input += (end !== undefined && end !== null) ? end : '...';
|
5842 | return r.copySafeness(orig, input);
|
5843 | },
|
5844 |
|
5845 | upper: function(str) {
|
5846 | str = normalize(str, '');
|
5847 | return str.toUpperCase();
|
5848 | },
|
5849 |
|
5850 | urlencode: function(obj) {
|
5851 | var enc = encodeURIComponent;
|
5852 | if (lib.isString(obj)) {
|
5853 | return enc(obj);
|
5854 | } else {
|
5855 | var parts;
|
5856 | if (lib.isArray(obj)) {
|
5857 | parts = obj.map(function(item) {
|
5858 | return enc(item[0]) + '=' + enc(item[1]);
|
5859 | });
|
5860 | } else {
|
5861 | parts = [];
|
5862 | for (var k in obj) {
|
5863 | if (obj.hasOwnProperty(k)) {
|
5864 | parts.push(enc(k) + '=' + enc(obj[k]));
|
5865 | }
|
5866 | }
|
5867 | }
|
5868 | return parts.join('&');
|
5869 | }
|
5870 | },
|
5871 |
|
5872 | urlize: function(str, length, nofollow) {
|
5873 | if (isNaN(length)) length = Infinity;
|
5874 |
|
5875 | var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : '');
|
5876 |
|
5877 |
|
5878 |
|
5879 | var puncRE = /^(?:\(|<|<)?(.*?)(?:\.|,|\)|\n|>)?$/;
|
5880 |
|
5881 | var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
|
5882 | var httpHttpsRE = /^https?:\/\/.*$/;
|
5883 | var wwwRE = /^www\./;
|
5884 | var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/;
|
5885 |
|
5886 | var words = str.split(/(\s+)/).filter(function(word) {
|
5887 |
|
5888 |
|
5889 | return word && word.length;
|
5890 | }).map(function(word) {
|
5891 | var matches = word.match(puncRE);
|
5892 | var possibleUrl = matches && matches[1] || word;
|
5893 |
|
5894 |
|
5895 | if (httpHttpsRE.test(possibleUrl))
|
5896 | return '<a href="' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
5897 |
|
5898 |
|
5899 | if (wwwRE.test(possibleUrl))
|
5900 | return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
5901 |
|
5902 |
|
5903 | if (emailRE.test(possibleUrl))
|
5904 | return '<a href="mailto:' + possibleUrl + '">' + possibleUrl + '</a>';
|
5905 |
|
5906 |
|
5907 | if (tldRE.test(possibleUrl))
|
5908 | return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
|
5909 |
|
5910 | return word;
|
5911 |
|
5912 | });
|
5913 |
|
5914 | return words.join('');
|
5915 | },
|
5916 |
|
5917 | wordcount: function(str) {
|
5918 | str = normalize(str, '');
|
5919 | var words = (str) ? str.match(/\w+/g) : null;
|
5920 | return (words) ? words.length : null;
|
5921 | },
|
5922 |
|
5923 | 'float': function(val, def) {
|
5924 | var res = parseFloat(val);
|
5925 | return isNaN(res) ? def : res;
|
5926 | },
|
5927 |
|
5928 | 'int': function(val, def) {
|
5929 | var res = parseInt(val, 10);
|
5930 | return isNaN(res) ? def : res;
|
5931 | }
|
5932 | };
|
5933 |
|
5934 |
|
5935 | filters.d = filters['default'];
|
5936 | filters.e = filters.escape;
|
5937 |
|
5938 | module.exports = filters;
|
5939 |
|
5940 |
|
5941 | },
|
5942 |
|
5943 | function(module, exports, __webpack_require__) {
|
5944 |
|
5945 | 'use strict';
|
5946 |
|
5947 | var Loader = __webpack_require__(15);
|
5948 | var PrecompiledLoader = __webpack_require__(16);
|
5949 |
|
5950 | var WebLoader = Loader.extend({
|
5951 | init: function(baseURL, opts) {
|
5952 | this.baseURL = baseURL || '.';
|
5953 | opts = opts || {};
|
5954 |
|
5955 |
|
5956 |
|
5957 |
|
5958 |
|
5959 | this.useCache = !!opts.useCache;
|
5960 |
|
5961 |
|
5962 |
|
5963 |
|
5964 |
|
5965 |
|
5966 | this.async = !!opts.async;
|
5967 | },
|
5968 |
|
5969 | resolve: function(from, to) {
|
5970 | throw new Error('relative templates not support in the browser yet');
|
5971 | },
|
5972 |
|
5973 | getSource: function(name, cb) {
|
5974 | var useCache = this.useCache;
|
5975 | var result;
|
5976 | this.fetch(this.baseURL + '/' + name, function(err, src) {
|
5977 | if(err) {
|
5978 | if(cb) {
|
5979 | cb(err.content);
|
5980 | } else {
|
5981 | if (err.status === 404) {
|
5982 | result = null;
|
5983 | } else {
|
5984 | throw err.content;
|
5985 | }
|
5986 | }
|
5987 | }
|
5988 | else {
|
5989 | result = { src: src,
|
5990 | path: name,
|
5991 | noCache: !useCache };
|
5992 | if(cb) {
|
5993 | cb(null, result);
|
5994 | }
|
5995 | }
|
5996 | });
|
5997 |
|
5998 |
|
5999 |
|
6000 |
|
6001 | return result;
|
6002 | },
|
6003 |
|
6004 | fetch: function(url, cb) {
|
6005 |
|
6006 | var ajax;
|
6007 | var loading = true;
|
6008 |
|
6009 | if(window.XMLHttpRequest) {
|
6010 | ajax = new XMLHttpRequest();
|
6011 | }
|
6012 | else if(window.ActiveXObject) {
|
6013 |
|
6014 | ajax = new ActiveXObject('Microsoft.XMLHTTP');
|
6015 | }
|
6016 |
|
6017 | ajax.onreadystatechange = function() {
|
6018 | if(ajax.readyState === 4 && loading) {
|
6019 | loading = false;
|
6020 | if(ajax.status === 0 || ajax.status === 200) {
|
6021 | cb(null, ajax.responseText);
|
6022 | }
|
6023 | else {
|
6024 | cb({ status: ajax.status, content: ajax.responseText });
|
6025 | }
|
6026 | }
|
6027 | };
|
6028 |
|
6029 | url += (url.indexOf('?') === -1 ? '?' : '&') + 's=' +
|
6030 | (new Date().getTime());
|
6031 |
|
6032 | ajax.open('GET', url, this.async);
|
6033 | ajax.send();
|
6034 | }
|
6035 | });
|
6036 |
|
6037 | module.exports = {
|
6038 | WebLoader: WebLoader,
|
6039 | PrecompiledLoader: PrecompiledLoader
|
6040 | };
|
6041 |
|
6042 |
|
6043 | },
|
6044 |
|
6045 | function(module, exports, __webpack_require__) {
|
6046 |
|
6047 | 'use strict';
|
6048 |
|
6049 | var path = __webpack_require__(3);
|
6050 | var Obj = __webpack_require__(6);
|
6051 | var lib = __webpack_require__(1);
|
6052 |
|
6053 | var Loader = Obj.extend({
|
6054 | on: function(name, func) {
|
6055 | this.listeners = this.listeners || {};
|
6056 | this.listeners[name] = this.listeners[name] || [];
|
6057 | this.listeners[name].push(func);
|
6058 | },
|
6059 |
|
6060 | emit: function(name /*, arg1, arg2, ...*/) {
|
6061 | var args = Array.prototype.slice.call(arguments, 1);
|
6062 |
|
6063 | if(this.listeners && this.listeners[name]) {
|
6064 | lib.each(this.listeners[name], function(listener) {
|
6065 | listener.apply(null, args);
|
6066 | });
|
6067 | }
|
6068 | },
|
6069 |
|
6070 | resolve: function(from, to) {
|
6071 | return path.resolve(path.dirname(from), to);
|
6072 | },
|
6073 |
|
6074 | isRelative: function(filename) {
|
6075 | return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
|
6076 | }
|
6077 | });
|
6078 |
|
6079 | module.exports = Loader;
|
6080 |
|
6081 |
|
6082 | },
|
6083 |
|
6084 | function(module, exports, __webpack_require__) {
|
6085 |
|
6086 | 'use strict';
|
6087 |
|
6088 | var Loader = __webpack_require__(15);
|
6089 |
|
6090 | var PrecompiledLoader = Loader.extend({
|
6091 | init: function(compiledTemplates) {
|
6092 | this.precompiled = compiledTemplates || {};
|
6093 | },
|
6094 |
|
6095 | getSource: function(name) {
|
6096 | if (this.precompiled[name]) {
|
6097 | return {
|
6098 | src: { type: 'code',
|
6099 | obj: this.precompiled[name] },
|
6100 | path: name
|
6101 | };
|
6102 | }
|
6103 | return null;
|
6104 | }
|
6105 | });
|
6106 |
|
6107 | module.exports = PrecompiledLoader;
|
6108 |
|
6109 |
|
6110 | },
|
6111 |
|
6112 | function(module, exports) {
|
6113 |
|
6114 | 'use strict';
|
6115 |
|
6116 | function cycler(items) {
|
6117 | var index = -1;
|
6118 |
|
6119 | return {
|
6120 | current: null,
|
6121 | reset: function() {
|
6122 | index = -1;
|
6123 | this.current = null;
|
6124 | },
|
6125 |
|
6126 | next: function() {
|
6127 | index++;
|
6128 | if(index >= items.length) {
|
6129 | index = 0;
|
6130 | }
|
6131 |
|
6132 | this.current = items[index];
|
6133 | return this.current;
|
6134 | },
|
6135 | };
|
6136 |
|
6137 | }
|
6138 |
|
6139 | function joiner(sep) {
|
6140 | sep = sep || ',';
|
6141 | var first = true;
|
6142 |
|
6143 | return function() {
|
6144 | var val = first ? '' : sep;
|
6145 | first = false;
|
6146 | return val;
|
6147 | };
|
6148 | }
|
6149 |
|
6150 |
|
6151 |
|
6152 |
|
6153 | function globals() {
|
6154 | return {
|
6155 | range: function(start, stop, step) {
|
6156 | if(typeof stop === 'undefined') {
|
6157 | stop = start;
|
6158 | start = 0;
|
6159 | step = 1;
|
6160 | }
|
6161 | else if(!step) {
|
6162 | step = 1;
|
6163 | }
|
6164 |
|
6165 | var arr = [];
|
6166 | var i;
|
6167 | if (step > 0) {
|
6168 | for (i=start; i<stop; i+=step) {
|
6169 | arr.push(i);
|
6170 | }
|
6171 | } else {
|
6172 | for (i=start; i>stop; i+=step) {
|
6173 | arr.push(i);
|
6174 | }
|
6175 | }
|
6176 | return arr;
|
6177 | },
|
6178 |
|
6179 |
|
6180 |
|
6181 |
|
6182 | cycler: function() {
|
6183 | return cycler(Array.prototype.slice.call(arguments));
|
6184 | },
|
6185 |
|
6186 | joiner: function(sep) {
|
6187 | return joiner(sep);
|
6188 | }
|
6189 | };
|
6190 | }
|
6191 |
|
6192 | module.exports = globals;
|
6193 |
|
6194 |
|
6195 | },
|
6196 |
|
6197 | function(module, exports) {
|
6198 |
|
6199 | function installCompat() {
|
6200 | 'use strict';
|
6201 |
|
6202 |
|
6203 |
|
6204 | var runtime = this.runtime;
|
6205 | var lib = this.lib;
|
6206 |
|
6207 | var orig_contextOrFrameLookup = runtime.contextOrFrameLookup;
|
6208 | runtime.contextOrFrameLookup = function(context, frame, key) {
|
6209 | var val = orig_contextOrFrameLookup.apply(this, arguments);
|
6210 | if (val === undefined) {
|
6211 | switch (key) {
|
6212 | case 'True':
|
6213 | return true;
|
6214 | case 'False':
|
6215 | return false;
|
6216 | case 'None':
|
6217 | return null;
|
6218 | }
|
6219 | }
|
6220 |
|
6221 | return val;
|
6222 | };
|
6223 |
|
6224 | var orig_memberLookup = runtime.memberLookup;
|
6225 | var ARRAY_MEMBERS = {
|
6226 | pop: function(index) {
|
6227 | if (index === undefined) {
|
6228 | return this.pop();
|
6229 | }
|
6230 | if (index >= this.length || index < 0) {
|
6231 | throw new Error('KeyError');
|
6232 | }
|
6233 | return this.splice(index, 1);
|
6234 | },
|
6235 | remove: function(element) {
|
6236 | for (var i = 0; i < this.length; i++) {
|
6237 | if (this[i] === element) {
|
6238 | return this.splice(i, 1);
|
6239 | }
|
6240 | }
|
6241 | throw new Error('ValueError');
|
6242 | },
|
6243 | count: function(element) {
|
6244 | var count = 0;
|
6245 | for (var i = 0; i < this.length; i++) {
|
6246 | if (this[i] === element) {
|
6247 | count++;
|
6248 | }
|
6249 | }
|
6250 | return count;
|
6251 | },
|
6252 | index: function(element) {
|
6253 | var i;
|
6254 | if ((i = this.indexOf(element)) === -1) {
|
6255 | throw new Error('ValueError');
|
6256 | }
|
6257 | return i;
|
6258 | },
|
6259 | find: function(element) {
|
6260 | return this.indexOf(element);
|
6261 | },
|
6262 | insert: function(index, elem) {
|
6263 | return this.splice(index, 0, elem);
|
6264 | }
|
6265 | };
|
6266 | var OBJECT_MEMBERS = {
|
6267 | items: function() {
|
6268 | var ret = [];
|
6269 | for(var k in this) {
|
6270 | ret.push([k, this[k]]);
|
6271 | }
|
6272 | return ret;
|
6273 | },
|
6274 | values: function() {
|
6275 | var ret = [];
|
6276 | for(var k in this) {
|
6277 | ret.push(this[k]);
|
6278 | }
|
6279 | return ret;
|
6280 | },
|
6281 | keys: function() {
|
6282 | var ret = [];
|
6283 | for(var k in this) {
|
6284 | ret.push(k);
|
6285 | }
|
6286 | return ret;
|
6287 | },
|
6288 | get: function(key, def) {
|
6289 | var output = this[key];
|
6290 | if (output === undefined) {
|
6291 | output = def;
|
6292 | }
|
6293 | return output;
|
6294 | },
|
6295 | has_key: function(key) {
|
6296 | return this.hasOwnProperty(key);
|
6297 | },
|
6298 | pop: function(key, def) {
|
6299 | var output = this[key];
|
6300 | if (output === undefined && def !== undefined) {
|
6301 | output = def;
|
6302 | } else if (output === undefined) {
|
6303 | throw new Error('KeyError');
|
6304 | } else {
|
6305 | delete this[key];
|
6306 | }
|
6307 | return output;
|
6308 | },
|
6309 | popitem: function() {
|
6310 | for (var k in this) {
|
6311 |
|
6312 | var val = this[k];
|
6313 | delete this[k];
|
6314 | return [k, val];
|
6315 | }
|
6316 | throw new Error('KeyError');
|
6317 | },
|
6318 | setdefault: function(key, def) {
|
6319 | if (key in this) {
|
6320 | return this[key];
|
6321 | }
|
6322 | if (def === undefined) {
|
6323 | def = null;
|
6324 | }
|
6325 | return this[key] = def;
|
6326 | },
|
6327 | update: function(kwargs) {
|
6328 | for (var k in kwargs) {
|
6329 | this[k] = kwargs[k];
|
6330 | }
|
6331 | return null;
|
6332 | }
|
6333 | };
|
6334 | OBJECT_MEMBERS.iteritems = OBJECT_MEMBERS.items;
|
6335 | OBJECT_MEMBERS.itervalues = OBJECT_MEMBERS.values;
|
6336 | OBJECT_MEMBERS.iterkeys = OBJECT_MEMBERS.keys;
|
6337 | runtime.memberLookup = function(obj, val, autoescape) {
|
6338 | obj = obj || {};
|
6339 |
|
6340 |
|
6341 |
|
6342 | if (lib.isArray(obj) && ARRAY_MEMBERS.hasOwnProperty(val)) {
|
6343 | return function() {return ARRAY_MEMBERS[val].apply(obj, arguments);};
|
6344 | }
|
6345 |
|
6346 | if (lib.isObject(obj) && OBJECT_MEMBERS.hasOwnProperty(val)) {
|
6347 | return function() {return OBJECT_MEMBERS[val].apply(obj, arguments);};
|
6348 | }
|
6349 |
|
6350 | return orig_memberLookup.apply(this, arguments);
|
6351 | };
|
6352 | }
|
6353 |
|
6354 | module.exports = installCompat;
|
6355 |
|
6356 |
|
6357 | }
|
6358 | ])
|
6359 | });
|
6360 | ; |
\ | No newline at end of file |