UNPKG

76.7 kBJavaScriptView Raw
1/*! Browser bundle of nunjucks 2.5.2 (slim, only works with precompiled templates) */
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() {
12return /******/ (function(modules) { // webpackBootstrap
13/******/ // The module cache
14/******/ var installedModules = {};
15
16/******/ // The require function
17/******/ function __webpack_require__(moduleId) {
18
19/******/ // Check if module is in cache
20/******/ if(installedModules[moduleId])
21/******/ return installedModules[moduleId].exports;
22
23/******/ // Create a new module (and put it into the cache)
24/******/ var module = installedModules[moduleId] = {
25/******/ exports: {},
26/******/ id: moduleId,
27/******/ loaded: false
28/******/ };
29
30/******/ // Execute the module function
31/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
32
33/******/ // Flag the module as loaded
34/******/ module.loaded = true;
35
36/******/ // Return the exports of the module
37/******/ return module.exports;
38/******/ }
39
40
41/******/ // expose the modules object (__webpack_modules__)
42/******/ __webpack_require__.m = modules;
43
44/******/ // expose the module cache
45/******/ __webpack_require__.c = installedModules;
46
47/******/ // __webpack_public_path__
48/******/ __webpack_require__.p = "";
49
50/******/ // Load entry module and return exports
51/******/ return __webpack_require__(0);
52/******/ })
53/************************************************************************/
54/******/ ([
55/* 0 */
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__(11);
63 var loaders = __webpack_require__(3);
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__(3);
76 module.exports.parser = __webpack_require__(3);
77 module.exports.lexer = __webpack_require__(3);
78 module.exports.runtime = __webpack_require__(8);
79 module.exports.lib = lib;
80 module.exports.nodes = __webpack_require__(3);
81
82 module.exports.installJinjaCompat = __webpack_require__(12);
83
84 // A single instance of an environment, since this is so commonly used
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/* 1 */
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 '<': '&lt;',
160 '>': '&gt;'
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 // jshint -W022
173 // http://jslinterrors.com/do-not-assign-to-the-exception-parameter
174 if (!err.Update) {
175 // not one of ours, cast it
176 err = new exports.TemplateError(err);
177 }
178 err.Update(path);
179
180 // Unless they marked the dev flag, show them a trace from here
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) { // for casting regular js errors
194 err = message;
195 message = message.name + ': ' + message.message;
196
197 try {
198 if(err.name = '') {}
199 }
200 catch(e) {
201 // If we can't set the name of the error object in this
202 // environment, don't use it
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 // only show lineno + colno next to path of template
221 // where error occurred
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 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
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; // Hack to convert object.length to a UInt32
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/* 2 */
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__(3);
462 var builtin_filters = __webpack_require__(7);
463 var builtin_loaders = __webpack_require__(3);
464 var runtime = __webpack_require__(8);
465 var globals = __webpack_require__(9);
466 var Frame = runtime.Frame;
467 var Template;
468
469 // Unconditionally load in this loader, even if no other ones are
470 // included (possible in the slim browser build)
471 builtin_loaders.PrecompiledLoader = __webpack_require__(10);
472
473 // If the user is using the async API, *always* call it
474 // asynchronously even if the template was synchronous.
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 // The dev flag determines the trace that'll be shown on errors.
482 // If set to true, returns the full trace from the error point,
483 // otherwise will return trace starting from Template.render
484 // (the full trace from within nunjucks may confuse developers using
485 // the library)
486 // defaults to false
487 opts = this.opts = opts || {};
488 this.opts.dev = !!opts.dev;
489
490 // The autoescape flag sets global autoescaping. If true,
491 // every string variable will be escaped by default.
492 // If false, strings can be manually escaped using the `escape` filter.
493 // defaults to true
494 this.opts.autoescape = opts.autoescape != null ? opts.autoescape : true;
495
496 // If true, this will make the system throw errors if trying
497 // to output a null or undefined value
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 // The filesystem loader is only available server-side
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 // It's easy to use precompiled templates: just include them
518 // before you configure nunjucks and this will automatically
519 // pick it up and use it
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 // Caching and cache busting
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 // this fixes autoescape for templates referenced in symbols
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 // Resolve name relative to parentName
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 // We support a synchronous API to make it easier to migrate
753 // existing code to async. This works because if you don't do
754 // anything async work, the whole thing is actually run
755 // synchronously.
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 // Has to be tied to an environment so we can tap into its globals.
788 this.env = env || new Environment();
789
790 // Make a duplicate of ctx
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 // This is one of the most called functions, so optimize for
808 // the typical case where the name isn't in the globals
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 // If there is a frame, we are being called from internal
912 // code of another template, and the internal system
913 // depends on the sync/async nature of the parent template
914 // to be inherited, so force an async callback
915 forceAsync = false;
916 }
917
918 var _this = this;
919 // Catch compile errors for async rendering
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 // Catch compile errors for async rendering
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 // Run the rootRenderFunc to populate the context with exported vars
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 /* jslint evil: true */
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/* 3 */
1049/***/ function(module, exports) {
1050
1051
1052
1053/***/ },
1054/* 4 */
1055/***/ function(module, exports, __webpack_require__) {
1056
1057 "use strict";
1058
1059 // rawAsap provides everything we need except exception management.
1060 var rawAsap = __webpack_require__(5);
1061 // RawTasks are recycled to reduce GC churn.
1062 var freeTasks = [];
1063 // We queue errors to ensure they are thrown in right order (FIFO).
1064 // Array-as-queue is good enough here, since we are just dealing with exceptions.
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 * Calls a task as soon as possible after returning, in its own event, with priority
1076 * over other events like animation, reflow, and repaint. An error thrown from an
1077 * event will not interrupt, nor even substantially slow down the processing of
1078 * other events, but will be rather postponed to a lower priority event.
1079 * @param {{call}} task A callable object, typically a function that takes no
1080 * arguments.
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 // We wrap tasks with recyclable task objects. A task object implements
1095 // `call`, just like a function.
1096 function RawTask() {
1097 this.task = null;
1098 }
1099
1100 // The sole purpose of wrapping the task is to catch the exception and recycle
1101 // the task object after its single use.
1102 RawTask.prototype.call = function () {
1103 try {
1104 this.task.call();
1105 } catch (error) {
1106 if (asap.onerror) {
1107 // This hook exists purely for testing purposes.
1108 // Its name will be periodically randomized to break any code that
1109 // depends on its existence.
1110 asap.onerror(error);
1111 } else {
1112 // In a web browser, exceptions are not fatal. However, to avoid
1113 // slowing down the queue of pending tasks, we rethrow the error in a
1114 // lower priority turn.
1115 pendingErrors.push(error);
1116 requestErrorThrow();
1117 }
1118 } finally {
1119 this.task = null;
1120 freeTasks[freeTasks.length] = this;
1121 }
1122 };
1123
1124
1125/***/ },
1126/* 5 */
1127/***/ function(module, exports) {
1128
1129 /* WEBPACK VAR INJECTION */(function(global) {"use strict";
1130
1131 // Use the fastest means possible to execute a task in its own turn, with
1132 // priority over other events including IO, animation, reflow, and redraw
1133 // events in browsers.
1134 //
1135 // An exception thrown by a task will permanently interrupt the processing of
1136 // subsequent tasks. The higher level `asap` function ensures that if an
1137 // exception is thrown by a task, that the task queue will continue flushing as
1138 // soon as possible, but if you use `rawAsap` directly, you are responsible to
1139 // either ensure that no exceptions are thrown from your task, or to manually
1140 // call `rawAsap.requestFlush` if an exception is thrown.
1141 module.exports = rawAsap;
1142 function rawAsap(task) {
1143 if (!queue.length) {
1144 requestFlush();
1145 flushing = true;
1146 }
1147 // Equivalent to push, but avoids a function call.
1148 queue[queue.length] = task;
1149 }
1150
1151 var queue = [];
1152 // Once a flush has been requested, no further calls to `requestFlush` are
1153 // necessary until the next `flush` completes.
1154 var flushing = false;
1155 // `requestFlush` is an implementation-specific method that attempts to kick
1156 // off a `flush` event as quickly as possible. `flush` will attempt to exhaust
1157 // the event queue before yielding to the browser's own event loop.
1158 var requestFlush;
1159 // The position of the next task to execute in the task queue. This is
1160 // preserved between calls to `flush` so that it can be resumed if
1161 // a task throws an exception.
1162 var index = 0;
1163 // If a task schedules additional tasks recursively, the task queue can grow
1164 // unbounded. To prevent memory exhaustion, the task queue will periodically
1165 // truncate already-completed tasks.
1166 var capacity = 1024;
1167
1168 // The flush function processes all tasks that have been scheduled with
1169 // `rawAsap` unless and until one of those tasks throws an exception.
1170 // If a task throws an exception, `flush` ensures that its state will remain
1171 // consistent and will resume where it left off when called again.
1172 // However, `flush` does not make any arrangements to be called again if an
1173 // exception is thrown.
1174 function flush() {
1175 while (index < queue.length) {
1176 var currentIndex = index;
1177 // Advance the index before calling the task. This ensures that we will
1178 // begin flushing on the next task the task throws an error.
1179 index = index + 1;
1180 queue[currentIndex].call();
1181 // Prevent leaking memory for long chains of recursive calls to `asap`.
1182 // If we call `asap` within tasks scheduled by `asap`, the queue will
1183 // grow, but to avoid an O(n) walk for every task we execute, we don't
1184 // shift tasks off the queue after they have been executed.
1185 // Instead, we periodically shift 1024 tasks off the queue.
1186 if (index > capacity) {
1187 // Manually shift all values starting at the index back to the
1188 // beginning of the queue.
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 // `requestFlush` is implemented using a strategy based on data collected from
1202 // every available SauceLabs Selenium web driver worker at time of writing.
1203 // https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593
1204
1205 // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
1206 // have WebKitMutationObserver but not un-prefixed MutationObserver.
1207 // Must use `global` instead of `window` to work in both frames and web
1208 // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
1209 var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver;
1210
1211 // MutationObservers are desirable because they have high priority and work
1212 // reliably everywhere they are implemented.
1213 // They are implemented in all modern browsers.
1214 //
1215 // - Android 4-4.3
1216 // - Chrome 26-34
1217 // - Firefox 14-29
1218 // - Internet Explorer 11
1219 // - iPad Safari 6-7.1
1220 // - iPhone Safari 7-7.1
1221 // - Safari 6-7
1222 if (typeof BrowserMutationObserver === "function") {
1223 requestFlush = makeRequestCallFromMutationObserver(flush);
1224
1225 // MessageChannels are desirable because they give direct access to the HTML
1226 // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera
1227 // 11-12, and in web workers in many engines.
1228 // Although message channels yield to any queued rendering and IO tasks, they
1229 // would be better than imposing the 4ms delay of timers.
1230 // However, they do not work reliably in Internet Explorer or Safari.
1231
1232 // Internet Explorer 10 is the only browser that has setImmediate but does
1233 // not have MutationObservers.
1234 // Although setImmediate yields to the browser's renderer, it would be
1235 // preferrable to falling back to setTimeout since it does not have
1236 // the minimum 4ms penalty.
1237 // Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and
1238 // Desktop to a lesser extent) that renders both setImmediate and
1239 // MessageChannel useless for the purposes of ASAP.
1240 // https://github.com/kriskowal/q/issues/396
1241
1242 // Timers are implemented universally.
1243 // We fall back to timers in workers in most engines, and in foreground
1244 // contexts in the following browsers.
1245 // However, note that even this simple case requires nuances to operate in a
1246 // broad spectrum of browsers.
1247 //
1248 // - Firefox 3-13
1249 // - Internet Explorer 6-9
1250 // - iPad Safari 4.3
1251 // - Lynx 2.8.7
1252 } else {
1253 requestFlush = makeRequestCallFromTimer(flush);
1254 }
1255
1256 // `requestFlush` requests that the high priority event queue be flushed as
1257 // soon as possible.
1258 // This is useful to prevent an error thrown in a task from stalling the event
1259 // queue if the exception handled by Node.js’s
1260 // `process.on("uncaughtException")` or by a domain.
1261 rawAsap.requestFlush = requestFlush;
1262
1263 // To request a high priority event, we induce a mutation observer by toggling
1264 // the text of a text node between "1" and "-1".
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 // The message channel technique was discovered by Malte Ubl and was the
1277 // original foundation for this library.
1278 // http://www.nonblocking.io/2011/06/windownexttick.html
1279
1280 // Safari 6.0.5 (at least) intermittently fails to create message ports on a
1281 // page's first load. Thankfully, this version of Safari supports
1282 // MutationObservers, so we don't need to fall back in that case.
1283
1284 // function makeRequestCallFromMessageChannel(callback) {
1285 // var channel = new MessageChannel();
1286 // channel.port1.onmessage = callback;
1287 // return function requestCall() {
1288 // channel.port2.postMessage(0);
1289 // };
1290 // }
1291
1292 // For reasons explained above, we are also unable to use `setImmediate`
1293 // under any circumstances.
1294 // Even if we were, there is another bug in Internet Explorer 10.
1295 // It is not sufficient to assign `setImmediate` to `requestFlush` because
1296 // `setImmediate` must be called *by name* and therefore must be wrapped in a
1297 // closure.
1298 // Never forget.
1299
1300 // function makeRequestCallFromSetImmediate(callback) {
1301 // return function requestCall() {
1302 // setImmediate(callback);
1303 // };
1304 // }
1305
1306 // Safari 6.0 has a problem where timers will get lost while the user is
1307 // scrolling. This problem does not impact ASAP because Safari 6.0 supports
1308 // mutation observers, so that implementation is used instead.
1309 // However, if we ever elect to use timers in Safari, the prevalent work-around
1310 // is to add a scroll event listener that calls for a flush.
1311
1312 // `setTimeout` does not call the passed callback if the delay is less than
1313 // approximately 7 in web workers in Firefox 8 through 18, and sometimes not
1314 // even then.
1315
1316 function makeRequestCallFromTimer(callback) {
1317 return function requestCall() {
1318 // We dispatch a timeout with a specified delay of 0 for engines that
1319 // can reliably accommodate that request. This will usually be snapped
1320 // to a 4 milisecond delay, but once we're flushing, there's no delay
1321 // between events.
1322 var timeoutHandle = setTimeout(handleTimer, 0);
1323 // However, since this timer gets frequently dropped in Firefox
1324 // workers, we enlist an interval handle that will try to fire
1325 // an event 20 times per second until it succeeds.
1326 var intervalHandle = setInterval(handleTimer, 50);
1327
1328 function handleTimer() {
1329 // Whichever timer succeeds will cancel both timers and
1330 // execute the callback.
1331 clearTimeout(timeoutHandle);
1332 clearInterval(intervalHandle);
1333 callback();
1334 }
1335 };
1336 }
1337
1338 // This is for `asap.js` only.
1339 // Its name will be periodically randomized to break any code that depends on
1340 // its existence.
1341 rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;
1342
1343 // ASAP was originally a nextTick shim included in Q. This was factored out
1344 // into this ASAP package. It was later adapted to RSVP which made further
1345 // amendments. These decisions, particularly to marginalize MessageChannel and
1346 // to capture the MutationObserver implementation in a closure, were integrated
1347 // back into ASAP proper.
1348 // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js
1349
1350 /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
1351
1352/***/ },
1353/* 6 */
1354/***/ function(module, exports) {
1355
1356 'use strict';
1357
1358 // A simple class system, more documentation to come
1359
1360 function extend(cls, name, props) {
1361 // This does that same thing as Object.create, but with support for IE8
1362 var F = function() {};
1363 F.prototype = cls.prototype;
1364 var prototype = new F();
1365
1366 // jshint undef: false
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 /*jshint -W083 */
1378 prototype[k] = (function (src, parent) {
1379 return function() {
1380 // Save the current parent method
1381 var tmp = this.parent;
1382
1383 // Set parent to the previous method, call, and restore
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/* 7 */
1424/***/ function(module, exports, __webpack_require__) {
1425
1426 'use strict';
1427
1428 var lib = __webpack_require__(1);
1429 var r = __webpack_require__(8);
1430
1431 function normalize(value, defaultValue) {
1432 if(value === null || value === undefined || value === false) {
1433 return defaultValue;
1434 }
1435 return value;
1436 }
1437
1438 var filters = {
1439 abs: function(n) {
1440 return Math.abs(n);
1441 },
1442
1443 batch: function(arr, linecount, fill_with) {
1444 var i;
1445 var res = [];
1446 var tmp = [];
1447
1448 for(i = 0; i < arr.length; i++) {
1449 if(i % linecount === 0 && tmp.length) {
1450 res.push(tmp);
1451 tmp = [];
1452 }
1453
1454 tmp.push(arr[i]);
1455 }
1456
1457 if(tmp.length) {
1458 if(fill_with) {
1459 for(i = tmp.length; i < linecount; i++) {
1460 tmp.push(fill_with);
1461 }
1462 }
1463
1464 res.push(tmp);
1465 }
1466
1467 return res;
1468 },
1469
1470 capitalize: function(str) {
1471 str = normalize(str, '');
1472 var ret = str.toLowerCase();
1473 return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
1474 },
1475
1476 center: function(str, width) {
1477 str = normalize(str, '');
1478 width = width || 80;
1479
1480 if(str.length >= width) {
1481 return str;
1482 }
1483
1484 var spaces = width - str.length;
1485 var pre = lib.repeat(' ', spaces/2 - spaces % 2);
1486 var post = lib.repeat(' ', spaces/2);
1487 return r.copySafeness(str, pre + str + post);
1488 },
1489
1490 'default': function(val, def, bool) {
1491 if(bool) {
1492 return val ? val : def;
1493 }
1494 else {
1495 return (val !== undefined) ? val : def;
1496 }
1497 },
1498
1499 dictsort: function(val, case_sensitive, by) {
1500 if (!lib.isObject(val)) {
1501 throw new lib.TemplateError('dictsort filter: val must be an object');
1502 }
1503
1504 var array = [];
1505 for (var k in val) {
1506 // deliberately include properties from the object's prototype
1507 array.push([k,val[k]]);
1508 }
1509
1510 var si;
1511 if (by === undefined || by === 'key') {
1512 si = 0;
1513 } else if (by === 'value') {
1514 si = 1;
1515 } else {
1516 throw new lib.TemplateError(
1517 'dictsort filter: You can only sort by either key or value');
1518 }
1519
1520 array.sort(function(t1, t2) {
1521 var a = t1[si];
1522 var b = t2[si];
1523
1524 if (!case_sensitive) {
1525 if (lib.isString(a)) {
1526 a = a.toUpperCase();
1527 }
1528 if (lib.isString(b)) {
1529 b = b.toUpperCase();
1530 }
1531 }
1532
1533 return a > b ? 1 : (a === b ? 0 : -1);
1534 });
1535
1536 return array;
1537 },
1538
1539 dump: function(obj) {
1540 return JSON.stringify(obj);
1541 },
1542
1543 escape: function(str) {
1544 if(str instanceof r.SafeString) {
1545 return str;
1546 }
1547 str = (str === null || str === undefined) ? '' : str;
1548 return r.markSafe(lib.escape(str.toString()));
1549 },
1550
1551 safe: function(str) {
1552 if (str instanceof r.SafeString) {
1553 return str;
1554 }
1555 str = (str === null || str === undefined) ? '' : str;
1556 return r.markSafe(str.toString());
1557 },
1558
1559 first: function(arr) {
1560 return arr[0];
1561 },
1562
1563 groupby: function(arr, attr) {
1564 return lib.groupBy(arr, attr);
1565 },
1566
1567 indent: function(str, width, indentfirst) {
1568 str = normalize(str, '');
1569
1570 if (str === '') return '';
1571
1572 width = width || 4;
1573 var res = '';
1574 var lines = str.split('\n');
1575 var sp = lib.repeat(' ', width);
1576
1577 for(var i=0; i<lines.length; i++) {
1578 if(i === 0 && !indentfirst) {
1579 res += lines[i] + '\n';
1580 }
1581 else {
1582 res += sp + lines[i] + '\n';
1583 }
1584 }
1585
1586 return r.copySafeness(str, res);
1587 },
1588
1589 join: function(arr, del, attr) {
1590 del = del || '';
1591
1592 if(attr) {
1593 arr = lib.map(arr, function(v) {
1594 return v[attr];
1595 });
1596 }
1597
1598 return arr.join(del);
1599 },
1600
1601 last: function(arr) {
1602 return arr[arr.length-1];
1603 },
1604
1605 length: function(val) {
1606 var value = normalize(val, '');
1607
1608 if(value !== undefined) {
1609 if(
1610 (typeof Map === 'function' && value instanceof Map) ||
1611 (typeof Set === 'function' && value instanceof Set)
1612 ) {
1613 // ECMAScript 2015 Maps and Sets
1614 return value.size;
1615 }
1616 if(lib.isObject(value) && !(value instanceof r.SafeString)) {
1617 // Objects (besides SafeStrings), non-primative Arrays
1618 return Object.keys(value).length;
1619 }
1620 return value.length;
1621 }
1622 return 0;
1623 },
1624
1625 list: function(val) {
1626 if(lib.isString(val)) {
1627 return val.split('');
1628 }
1629 else if(lib.isObject(val)) {
1630 var keys = [];
1631
1632 if(Object.keys) {
1633 keys = Object.keys(val);
1634 }
1635 else {
1636 for(var k in val) {
1637 keys.push(k);
1638 }
1639 }
1640
1641 return lib.map(keys, function(k) {
1642 return { key: k,
1643 value: val[k] };
1644 });
1645 }
1646 else if(lib.isArray(val)) {
1647 return val;
1648 }
1649 else {
1650 throw new lib.TemplateError('list filter: type not iterable');
1651 }
1652 },
1653
1654 lower: function(str) {
1655 str = normalize(str, '');
1656 return str.toLowerCase();
1657 },
1658
1659 random: function(arr) {
1660 return arr[Math.floor(Math.random() * arr.length)];
1661 },
1662
1663 rejectattr: function(arr, attr) {
1664 return arr.filter(function (item) {
1665 return !item[attr];
1666 });
1667 },
1668
1669 selectattr: function(arr, attr) {
1670 return arr.filter(function (item) {
1671 return !!item[attr];
1672 });
1673 },
1674
1675 replace: function(str, old, new_, maxCount) {
1676 var originalStr = str;
1677
1678 if (old instanceof RegExp) {
1679 return str.replace(old, new_);
1680 }
1681
1682 if(typeof maxCount === 'undefined'){
1683 maxCount = -1;
1684 }
1685
1686 var res = ''; // Output
1687
1688 // Cast Numbers in the search term to string
1689 if(typeof old === 'number'){
1690 old = old + '';
1691 }
1692 else if(typeof old !== 'string') {
1693 // If it is something other than number or string,
1694 // return the original string
1695 return str;
1696 }
1697
1698 // Cast numbers in the replacement to string
1699 if(typeof str === 'number'){
1700 str = str + '';
1701 }
1702
1703 // If by now, we don't have a string, throw it back
1704 if(typeof str !== 'string' && !(str instanceof r.SafeString)){
1705 return str;
1706 }
1707
1708 // ShortCircuits
1709 if(old === ''){
1710 // Mimic the python behaviour: empty string is replaced
1711 // by replacement e.g. "abc"|replace("", ".") -> .a.b.c.
1712 res = new_ + str.split('').join(new_) + new_;
1713 return r.copySafeness(str, res);
1714 }
1715
1716 var nextIndex = str.indexOf(old);
1717 // if # of replacements to perform is 0, or the string to does
1718 // not contain the old value, return the string
1719 if(maxCount === 0 || nextIndex === -1){
1720 return str;
1721 }
1722
1723 var pos = 0;
1724 var count = 0; // # of replacements made
1725
1726 while(nextIndex > -1 && (maxCount === -1 || count < maxCount)){
1727 // Grab the next chunk of src string and add it with the
1728 // replacement, to the result
1729 res += str.substring(pos, nextIndex) + new_;
1730 // Increment our pointer in the src string
1731 pos = nextIndex + old.length;
1732 count++;
1733 // See if there are any more replacements to be made
1734 nextIndex = str.indexOf(old, pos);
1735 }
1736
1737 // We've either reached the end, or done the max # of
1738 // replacements, tack on any remaining string
1739 if(pos < str.length) {
1740 res += str.substring(pos);
1741 }
1742
1743 return r.copySafeness(originalStr, res);
1744 },
1745
1746 reverse: function(val) {
1747 var arr;
1748 if(lib.isString(val)) {
1749 arr = filters.list(val);
1750 }
1751 else {
1752 // Copy it
1753 arr = lib.map(val, function(v) { return v; });
1754 }
1755
1756 arr.reverse();
1757
1758 if(lib.isString(val)) {
1759 return r.copySafeness(val, arr.join(''));
1760 }
1761 return arr;
1762 },
1763
1764 round: function(val, precision, method) {
1765 precision = precision || 0;
1766 var factor = Math.pow(10, precision);
1767 var rounder;
1768
1769 if(method === 'ceil') {
1770 rounder = Math.ceil;
1771 }
1772 else if(method === 'floor') {
1773 rounder = Math.floor;
1774 }
1775 else {
1776 rounder = Math.round;
1777 }
1778
1779 return rounder(val * factor) / factor;
1780 },
1781
1782 slice: function(arr, slices, fillWith) {
1783 var sliceLength = Math.floor(arr.length / slices);
1784 var extra = arr.length % slices;
1785 var offset = 0;
1786 var res = [];
1787
1788 for(var i=0; i<slices; i++) {
1789 var start = offset + i * sliceLength;
1790 if(i < extra) {
1791 offset++;
1792 }
1793 var end = offset + (i + 1) * sliceLength;
1794
1795 var slice = arr.slice(start, end);
1796 if(fillWith && i >= extra) {
1797 slice.push(fillWith);
1798 }
1799 res.push(slice);
1800 }
1801
1802 return res;
1803 },
1804
1805 sum: function(arr, attr, start) {
1806 var sum = 0;
1807
1808 if(typeof start === 'number'){
1809 sum += start;
1810 }
1811
1812 if(attr) {
1813 arr = lib.map(arr, function(v) {
1814 return v[attr];
1815 });
1816 }
1817
1818 for(var i = 0; i < arr.length; i++) {
1819 sum += arr[i];
1820 }
1821
1822 return sum;
1823 },
1824
1825 sort: r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function(arr, reverse, caseSens, attr) {
1826 // Copy it
1827 arr = lib.map(arr, function(v) { return v; });
1828
1829 arr.sort(function(a, b) {
1830 var x, y;
1831
1832 if(attr) {
1833 x = a[attr];
1834 y = b[attr];
1835 }
1836 else {
1837 x = a;
1838 y = b;
1839 }
1840
1841 if(!caseSens && lib.isString(x) && lib.isString(y)) {
1842 x = x.toLowerCase();
1843 y = y.toLowerCase();
1844 }
1845
1846 if(x < y) {
1847 return reverse ? 1 : -1;
1848 }
1849 else if(x > y) {
1850 return reverse ? -1: 1;
1851 }
1852 else {
1853 return 0;
1854 }
1855 });
1856
1857 return arr;
1858 }),
1859
1860 string: function(obj) {
1861 return r.copySafeness(obj, obj);
1862 },
1863
1864 striptags: function(input, preserve_linebreaks) {
1865 input = normalize(input, '');
1866 preserve_linebreaks = preserve_linebreaks || false;
1867 var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|<!--[\s\S]*?-->/gi;
1868 var trimmedInput = filters.trim(input.replace(tags, ''));
1869 var res = '';
1870 if (preserve_linebreaks) {
1871 res = trimmedInput
1872 .replace(/^ +| +$/gm, '') // remove leading and trailing spaces
1873 .replace(/ +/g, ' ') // squash adjacent spaces
1874 .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF)
1875 .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks
1876 } else {
1877 res = trimmedInput.replace(/\s+/gi, ' ');
1878 }
1879 return r.copySafeness(input, res);
1880 },
1881
1882 title: function(str) {
1883 str = normalize(str, '');
1884 var words = str.split(' ');
1885 for(var i = 0; i < words.length; i++) {
1886 words[i] = filters.capitalize(words[i]);
1887 }
1888 return r.copySafeness(str, words.join(' '));
1889 },
1890
1891 trim: function(str) {
1892 return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
1893 },
1894
1895 truncate: function(input, length, killwords, end) {
1896 var orig = input;
1897 input = normalize(input, '');
1898 length = length || 255;
1899
1900 if (input.length <= length)
1901 return input;
1902
1903 if (killwords) {
1904 input = input.substring(0, length);
1905 } else {
1906 var idx = input.lastIndexOf(' ', length);
1907 if(idx === -1) {
1908 idx = length;
1909 }
1910
1911 input = input.substring(0, idx);
1912 }
1913
1914 input += (end !== undefined && end !== null) ? end : '...';
1915 return r.copySafeness(orig, input);
1916 },
1917
1918 upper: function(str) {
1919 str = normalize(str, '');
1920 return str.toUpperCase();
1921 },
1922
1923 urlencode: function(obj) {
1924 var enc = encodeURIComponent;
1925 if (lib.isString(obj)) {
1926 return enc(obj);
1927 } else {
1928 var parts;
1929 if (lib.isArray(obj)) {
1930 parts = obj.map(function(item) {
1931 return enc(item[0]) + '=' + enc(item[1]);
1932 });
1933 } else {
1934 parts = [];
1935 for (var k in obj) {
1936 if (obj.hasOwnProperty(k)) {
1937 parts.push(enc(k) + '=' + enc(obj[k]));
1938 }
1939 }
1940 }
1941 return parts.join('&');
1942 }
1943 },
1944
1945 urlize: function(str, length, nofollow) {
1946 if (isNaN(length)) length = Infinity;
1947
1948 var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : '');
1949
1950 // For the jinja regexp, see
1951 // https://github.com/mitsuhiko/jinja2/blob/f15b814dcba6aa12bc74d1f7d0c881d55f7126be/jinja2/utils.py#L20-L23
1952 var puncRE = /^(?:\(|<|&lt;)?(.*?)(?:\.|,|\)|\n|&gt;)?$/;
1953 // from http://blog.gerv.net/2011/05/html5_email_address_regexp/
1954 var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
1955 var httpHttpsRE = /^https?:\/\/.*$/;
1956 var wwwRE = /^www\./;
1957 var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/;
1958
1959 var words = str.split(/(\s+)/).filter(function(word) {
1960 // If the word has no length, bail. This can happen for str with
1961 // trailing whitespace.
1962 return word && word.length;
1963 }).map(function(word) {
1964 var matches = word.match(puncRE);
1965 var possibleUrl = matches && matches[1] || word;
1966
1967 // url that starts with http or https
1968 if (httpHttpsRE.test(possibleUrl))
1969 return '<a href="' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
1970
1971 // url that starts with www.
1972 if (wwwRE.test(possibleUrl))
1973 return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
1974
1975 // an email address of the form username@domain.tld
1976 if (emailRE.test(possibleUrl))
1977 return '<a href="mailto:' + possibleUrl + '">' + possibleUrl + '</a>';
1978
1979 // url that ends in .com, .org or .net that is not an email address
1980 if (tldRE.test(possibleUrl))
1981 return '<a href="http://' + possibleUrl + '"' + noFollowAttr + '>' + possibleUrl.substr(0, length) + '</a>';
1982
1983 return word;
1984
1985 });
1986
1987 return words.join('');
1988 },
1989
1990 wordcount: function(str) {
1991 str = normalize(str, '');
1992 var words = (str) ? str.match(/\w+/g) : null;
1993 return (words) ? words.length : null;
1994 },
1995
1996 'float': function(val, def) {
1997 var res = parseFloat(val);
1998 return isNaN(res) ? def : res;
1999 },
2000
2001 'int': function(val, def) {
2002 var res = parseInt(val, 10);
2003 return isNaN(res) ? def : res;
2004 }
2005 };
2006
2007 // Aliases
2008 filters.d = filters['default'];
2009 filters.e = filters.escape;
2010
2011 module.exports = filters;
2012
2013
2014/***/ },
2015/* 8 */
2016/***/ function(module, exports, __webpack_require__) {
2017
2018 'use strict';
2019
2020 var lib = __webpack_require__(1);
2021 var Obj = __webpack_require__(6);
2022
2023 // Frames keep track of scoping both at compile-time and run-time so
2024 // we know how to access variables. Block tags can introduce special
2025 // variables, for example.
2026 var Frame = Obj.extend({
2027 init: function(parent, isolateWrites) {
2028 this.variables = {};
2029 this.parent = parent;
2030 this.topLevel = false;
2031 // if this is true, writes (set) should never propagate upwards past
2032 // this frame to its parent (though reads may).
2033 this.isolateWrites = isolateWrites;
2034 },
2035
2036 set: function(name, val, resolveUp) {
2037 // Allow variables with dots by automatically creating the
2038 // nested structure
2039 var parts = name.split('.');
2040 var obj = this.variables;
2041 var frame = this;
2042
2043 if(resolveUp) {
2044 if((frame = this.resolve(parts[0], true))) {
2045 frame.set(name, val);
2046 return;
2047 }
2048 }
2049
2050 for(var i=0; i<parts.length - 1; i++) {
2051 var id = parts[i];
2052
2053 if(!obj[id]) {
2054 obj[id] = {};
2055 }
2056 obj = obj[id];
2057 }
2058
2059 obj[parts[parts.length - 1]] = val;
2060 },
2061
2062 get: function(name) {
2063 var val = this.variables[name];
2064 if(val !== undefined && val !== null) {
2065 return val;
2066 }
2067 return null;
2068 },
2069
2070 lookup: function(name) {
2071 var p = this.parent;
2072 var val = this.variables[name];
2073 if(val !== undefined && val !== null) {
2074 return val;
2075 }
2076 return p && p.lookup(name);
2077 },
2078
2079 resolve: function(name, forWrite) {
2080 var p = (forWrite && this.isolateWrites) ? undefined : this.parent;
2081 var val = this.variables[name];
2082 if(val !== undefined && val !== null) {
2083 return this;
2084 }
2085 return p && p.resolve(name);
2086 },
2087
2088 push: function(isolateWrites) {
2089 return new Frame(this, isolateWrites);
2090 },
2091
2092 pop: function() {
2093 return this.parent;
2094 }
2095 });
2096
2097 function makeMacro(argNames, kwargNames, func) {
2098 return function() {
2099 var argCount = numArgs(arguments);
2100 var args;
2101 var kwargs = getKeywordArgs(arguments);
2102 var i;
2103
2104 if(argCount > argNames.length) {
2105 args = Array.prototype.slice.call(arguments, 0, argNames.length);
2106
2107 // Positional arguments that should be passed in as
2108 // keyword arguments (essentially default values)
2109 var vals = Array.prototype.slice.call(arguments, args.length, argCount);
2110 for(i = 0; i < vals.length; i++) {
2111 if(i < kwargNames.length) {
2112 kwargs[kwargNames[i]] = vals[i];
2113 }
2114 }
2115
2116 args.push(kwargs);
2117 }
2118 else if(argCount < argNames.length) {
2119 args = Array.prototype.slice.call(arguments, 0, argCount);
2120
2121 for(i = argCount; i < argNames.length; i++) {
2122 var arg = argNames[i];
2123
2124 // Keyword arguments that should be passed as
2125 // positional arguments, i.e. the caller explicitly
2126 // used the name of a positional arg
2127 args.push(kwargs[arg]);
2128 delete kwargs[arg];
2129 }
2130
2131 args.push(kwargs);
2132 }
2133 else {
2134 args = arguments;
2135 }
2136
2137 return func.apply(this, args);
2138 };
2139 }
2140
2141 function makeKeywordArgs(obj) {
2142 obj.__keywords = true;
2143 return obj;
2144 }
2145
2146 function getKeywordArgs(args) {
2147 var len = args.length;
2148 if(len) {
2149 var lastArg = args[len - 1];
2150 if(lastArg && lastArg.hasOwnProperty('__keywords')) {
2151 return lastArg;
2152 }
2153 }
2154 return {};
2155 }
2156
2157 function numArgs(args) {
2158 var len = args.length;
2159 if(len === 0) {
2160 return 0;
2161 }
2162
2163 var lastArg = args[len - 1];
2164 if(lastArg && lastArg.hasOwnProperty('__keywords')) {
2165 return len - 1;
2166 }
2167 else {
2168 return len;
2169 }
2170 }
2171
2172 // A SafeString object indicates that the string should not be
2173 // autoescaped. This happens magically because autoescaping only
2174 // occurs on primitive string objects.
2175 function SafeString(val) {
2176 if(typeof val !== 'string') {
2177 return val;
2178 }
2179
2180 this.val = val;
2181 this.length = val.length;
2182 }
2183
2184 SafeString.prototype = Object.create(String.prototype, {
2185 length: { writable: true, configurable: true, value: 0 }
2186 });
2187 SafeString.prototype.valueOf = function() {
2188 return this.val;
2189 };
2190 SafeString.prototype.toString = function() {
2191 return this.val;
2192 };
2193
2194 function copySafeness(dest, target) {
2195 if(dest instanceof SafeString) {
2196 return new SafeString(target);
2197 }
2198 return target.toString();
2199 }
2200
2201 function markSafe(val) {
2202 var type = typeof val;
2203
2204 if(type === 'string') {
2205 return new SafeString(val);
2206 }
2207 else if(type !== 'function') {
2208 return val;
2209 }
2210 else {
2211 return function() {
2212 var ret = val.apply(this, arguments);
2213
2214 if(typeof ret === 'string') {
2215 return new SafeString(ret);
2216 }
2217
2218 return ret;
2219 };
2220 }
2221 }
2222
2223 function suppressValue(val, autoescape) {
2224 val = (val !== undefined && val !== null) ? val : '';
2225
2226 if(autoescape && !(val instanceof SafeString)) {
2227 val = lib.escape(val.toString());
2228 }
2229
2230 return val;
2231 }
2232
2233 function ensureDefined(val, lineno, colno) {
2234 if(val === null || val === undefined) {
2235 throw new lib.TemplateError(
2236 'attempted to output null or undefined value',
2237 lineno + 1,
2238 colno + 1
2239 );
2240 }
2241 return val;
2242 }
2243
2244 function memberLookup(obj, val) {
2245 obj = obj || {};
2246
2247 if(typeof obj[val] === 'function') {
2248 return function() {
2249 return obj[val].apply(obj, arguments);
2250 };
2251 }
2252
2253 return obj[val];
2254 }
2255
2256 function callWrap(obj, name, context, args) {
2257 if(!obj) {
2258 throw new Error('Unable to call `' + name + '`, which is undefined or falsey');
2259 }
2260 else if(typeof obj !== 'function') {
2261 throw new Error('Unable to call `' + name + '`, which is not a function');
2262 }
2263
2264 // jshint validthis: true
2265 return obj.apply(context, args);
2266 }
2267
2268 function contextOrFrameLookup(context, frame, name) {
2269 var val = frame.lookup(name);
2270 return (val !== undefined && val !== null) ?
2271 val :
2272 context.lookup(name);
2273 }
2274
2275 function handleError(error, lineno, colno) {
2276 if(error.lineno) {
2277 return error;
2278 }
2279 else {
2280 return new lib.TemplateError(error, lineno, colno);
2281 }
2282 }
2283
2284 function asyncEach(arr, dimen, iter, cb) {
2285 if(lib.isArray(arr)) {
2286 var len = arr.length;
2287
2288 lib.asyncIter(arr, function(item, i, next) {
2289 switch(dimen) {
2290 case 1: iter(item, i, len, next); break;
2291 case 2: iter(item[0], item[1], i, len, next); break;
2292 case 3: iter(item[0], item[1], item[2], i, len, next); break;
2293 default:
2294 item.push(i, next);
2295 iter.apply(this, item);
2296 }
2297 }, cb);
2298 }
2299 else {
2300 lib.asyncFor(arr, function(key, val, i, len, next) {
2301 iter(key, val, i, len, next);
2302 }, cb);
2303 }
2304 }
2305
2306 function asyncAll(arr, dimen, func, cb) {
2307 var finished = 0;
2308 var len, i;
2309 var outputArr;
2310
2311 function done(i, output) {
2312 finished++;
2313 outputArr[i] = output;
2314
2315 if(finished === len) {
2316 cb(null, outputArr.join(''));
2317 }
2318 }
2319
2320 if(lib.isArray(arr)) {
2321 len = arr.length;
2322 outputArr = new Array(len);
2323
2324 if(len === 0) {
2325 cb(null, '');
2326 }
2327 else {
2328 for(i = 0; i < arr.length; i++) {
2329 var item = arr[i];
2330
2331 switch(dimen) {
2332 case 1: func(item, i, len, done); break;
2333 case 2: func(item[0], item[1], i, len, done); break;
2334 case 3: func(item[0], item[1], item[2], i, len, done); break;
2335 default:
2336 item.push(i, done);
2337 // jshint validthis: true
2338 func.apply(this, item);
2339 }
2340 }
2341 }
2342 }
2343 else {
2344 var keys = lib.keys(arr);
2345 len = keys.length;
2346 outputArr = new Array(len);
2347
2348 if(len === 0) {
2349 cb(null, '');
2350 }
2351 else {
2352 for(i = 0; i < keys.length; i++) {
2353 var k = keys[i];
2354 func(k, arr[k], i, len, done);
2355 }
2356 }
2357 }
2358 }
2359
2360 module.exports = {
2361 Frame: Frame,
2362 makeMacro: makeMacro,
2363 makeKeywordArgs: makeKeywordArgs,
2364 numArgs: numArgs,
2365 suppressValue: suppressValue,
2366 ensureDefined: ensureDefined,
2367 memberLookup: memberLookup,
2368 contextOrFrameLookup: contextOrFrameLookup,
2369 callWrap: callWrap,
2370 handleError: handleError,
2371 isArray: lib.isArray,
2372 keys: lib.keys,
2373 SafeString: SafeString,
2374 copySafeness: copySafeness,
2375 markSafe: markSafe,
2376 asyncEach: asyncEach,
2377 asyncAll: asyncAll,
2378 inOperator: lib.inOperator
2379 };
2380
2381
2382/***/ },
2383/* 9 */
2384/***/ function(module, exports) {
2385
2386 'use strict';
2387
2388 function cycler(items) {
2389 var index = -1;
2390
2391 return {
2392 current: null,
2393 reset: function() {
2394 index = -1;
2395 this.current = null;
2396 },
2397
2398 next: function() {
2399 index++;
2400 if(index >= items.length) {
2401 index = 0;
2402 }
2403
2404 this.current = items[index];
2405 return this.current;
2406 },
2407 };
2408
2409 }
2410
2411 function joiner(sep) {
2412 sep = sep || ',';
2413 var first = true;
2414
2415 return function() {
2416 var val = first ? '' : sep;
2417 first = false;
2418 return val;
2419 };
2420 }
2421
2422 // Making this a function instead so it returns a new object
2423 // each time it's called. That way, if something like an environment
2424 // uses it, they will each have their own copy.
2425 function globals() {
2426 return {
2427 range: function(start, stop, step) {
2428 if(typeof stop === 'undefined') {
2429 stop = start;
2430 start = 0;
2431 step = 1;
2432 }
2433 else if(!step) {
2434 step = 1;
2435 }
2436
2437 var arr = [];
2438 var i;
2439 if (step > 0) {
2440 for (i=start; i<stop; i+=step) {
2441 arr.push(i);
2442 }
2443 } else {
2444 for (i=start; i>stop; i+=step) {
2445 arr.push(i);
2446 }
2447 }
2448 return arr;
2449 },
2450
2451 // lipsum: function(n, html, min, max) {
2452 // },
2453
2454 cycler: function() {
2455 return cycler(Array.prototype.slice.call(arguments));
2456 },
2457
2458 joiner: function(sep) {
2459 return joiner(sep);
2460 }
2461 };
2462 }
2463
2464 module.exports = globals;
2465
2466
2467/***/ },
2468/* 10 */
2469/***/ function(module, exports, __webpack_require__) {
2470
2471 'use strict';
2472
2473 var Loader = __webpack_require__(11);
2474
2475 var PrecompiledLoader = Loader.extend({
2476 init: function(compiledTemplates) {
2477 this.precompiled = compiledTemplates || {};
2478 },
2479
2480 getSource: function(name) {
2481 if (this.precompiled[name]) {
2482 return {
2483 src: { type: 'code',
2484 obj: this.precompiled[name] },
2485 path: name
2486 };
2487 }
2488 return null;
2489 }
2490 });
2491
2492 module.exports = PrecompiledLoader;
2493
2494
2495/***/ },
2496/* 11 */
2497/***/ function(module, exports, __webpack_require__) {
2498
2499 'use strict';
2500
2501 var path = __webpack_require__(3);
2502 var Obj = __webpack_require__(6);
2503 var lib = __webpack_require__(1);
2504
2505 var Loader = Obj.extend({
2506 on: function(name, func) {
2507 this.listeners = this.listeners || {};
2508 this.listeners[name] = this.listeners[name] || [];
2509 this.listeners[name].push(func);
2510 },
2511
2512 emit: function(name /*, arg1, arg2, ...*/) {
2513 var args = Array.prototype.slice.call(arguments, 1);
2514
2515 if(this.listeners && this.listeners[name]) {
2516 lib.each(this.listeners[name], function(listener) {
2517 listener.apply(null, args);
2518 });
2519 }
2520 },
2521
2522 resolve: function(from, to) {
2523 return path.resolve(path.dirname(from), to);
2524 },
2525
2526 isRelative: function(filename) {
2527 return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
2528 }
2529 });
2530
2531 module.exports = Loader;
2532
2533
2534/***/ },
2535/* 12 */
2536/***/ function(module, exports) {
2537
2538 function installCompat() {
2539 'use strict';
2540
2541 // This must be called like `nunjucks.installCompat` so that `this`
2542 // references the nunjucks instance
2543 var runtime = this.runtime; // jshint ignore:line
2544 var lib = this.lib; // jshint ignore:line
2545
2546 var orig_contextOrFrameLookup = runtime.contextOrFrameLookup;
2547 runtime.contextOrFrameLookup = function(context, frame, key) {
2548 var val = orig_contextOrFrameLookup.apply(this, arguments);
2549 if (val === undefined) {
2550 switch (key) {
2551 case 'True':
2552 return true;
2553 case 'False':
2554 return false;
2555 case 'None':
2556 return null;
2557 }
2558 }
2559
2560 return val;
2561 };
2562
2563 var orig_memberLookup = runtime.memberLookup;
2564 var ARRAY_MEMBERS = {
2565 pop: function(index) {
2566 if (index === undefined) {
2567 return this.pop();
2568 }
2569 if (index >= this.length || index < 0) {
2570 throw new Error('KeyError');
2571 }
2572 return this.splice(index, 1);
2573 },
2574 remove: function(element) {
2575 for (var i = 0; i < this.length; i++) {
2576 if (this[i] === element) {
2577 return this.splice(i, 1);
2578 }
2579 }
2580 throw new Error('ValueError');
2581 },
2582 count: function(element) {
2583 var count = 0;
2584 for (var i = 0; i < this.length; i++) {
2585 if (this[i] === element) {
2586 count++;
2587 }
2588 }
2589 return count;
2590 },
2591 index: function(element) {
2592 var i;
2593 if ((i = this.indexOf(element)) === -1) {
2594 throw new Error('ValueError');
2595 }
2596 return i;
2597 },
2598 find: function(element) {
2599 return this.indexOf(element);
2600 },
2601 insert: function(index, elem) {
2602 return this.splice(index, 0, elem);
2603 }
2604 };
2605 var OBJECT_MEMBERS = {
2606 items: function() {
2607 var ret = [];
2608 for(var k in this) {
2609 ret.push([k, this[k]]);
2610 }
2611 return ret;
2612 },
2613 values: function() {
2614 var ret = [];
2615 for(var k in this) {
2616 ret.push(this[k]);
2617 }
2618 return ret;
2619 },
2620 keys: function() {
2621 var ret = [];
2622 for(var k in this) {
2623 ret.push(k);
2624 }
2625 return ret;
2626 },
2627 get: function(key, def) {
2628 var output = this[key];
2629 if (output === undefined) {
2630 output = def;
2631 }
2632 return output;
2633 },
2634 has_key: function(key) {
2635 return this.hasOwnProperty(key);
2636 },
2637 pop: function(key, def) {
2638 var output = this[key];
2639 if (output === undefined && def !== undefined) {
2640 output = def;
2641 } else if (output === undefined) {
2642 throw new Error('KeyError');
2643 } else {
2644 delete this[key];
2645 }
2646 return output;
2647 },
2648 popitem: function() {
2649 for (var k in this) {
2650 // Return the first object pair.
2651 var val = this[k];
2652 delete this[k];
2653 return [k, val];
2654 }
2655 throw new Error('KeyError');
2656 },
2657 setdefault: function(key, def) {
2658 if (key in this) {
2659 return this[key];
2660 }
2661 if (def === undefined) {
2662 def = null;
2663 }
2664 return this[key] = def;
2665 },
2666 update: function(kwargs) {
2667 for (var k in kwargs) {
2668 this[k] = kwargs[k];
2669 }
2670 return null; // Always returns None
2671 }
2672 };
2673 OBJECT_MEMBERS.iteritems = OBJECT_MEMBERS.items;
2674 OBJECT_MEMBERS.itervalues = OBJECT_MEMBERS.values;
2675 OBJECT_MEMBERS.iterkeys = OBJECT_MEMBERS.keys;
2676 runtime.memberLookup = function(obj, val, autoescape) { // jshint ignore:line
2677 obj = obj || {};
2678
2679 // If the object is an object, return any of the methods that Python would
2680 // otherwise provide.
2681 if (lib.isArray(obj) && ARRAY_MEMBERS.hasOwnProperty(val)) {
2682 return function() {return ARRAY_MEMBERS[val].apply(obj, arguments);};
2683 }
2684
2685 if (lib.isObject(obj) && OBJECT_MEMBERS.hasOwnProperty(val)) {
2686 return function() {return OBJECT_MEMBERS[val].apply(obj, arguments);};
2687 }
2688
2689 return orig_memberLookup.apply(this, arguments);
2690 };
2691 }
2692
2693 module.exports = installCompat;
2694
2695
2696/***/ }
2697/******/ ])
2698});
2699;
\No newline at end of file