From 550e2f03ad0b60b3c9db3d68dbf014dcb740a2ff Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Tue, 17 Jan 2017 15:37:25 +0530 Subject: Initial Commit --- src/libs/nunjucks.js | 6692 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6692 insertions(+) create mode 100644 src/libs/nunjucks.js (limited to 'src/libs/nunjucks.js') diff --git a/src/libs/nunjucks.js b/src/libs/nunjucks.js new file mode 100644 index 0000000..fa4db0a --- /dev/null +++ b/src/libs/nunjucks.js @@ -0,0 +1,6692 @@ +/*! Browser bundle of nunjucks 3.0.0 */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["nunjucks"] = factory(); + else + root["nunjucks"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lib = __webpack_require__(1); + var env = __webpack_require__(2); + var Loader = __webpack_require__(15); + var loaders = __webpack_require__(14); + var precompile = __webpack_require__(3); + + module.exports = {}; + module.exports.Environment = env.Environment; + module.exports.Template = env.Template; + + module.exports.Loader = Loader; + module.exports.FileSystemLoader = loaders.FileSystemLoader; + module.exports.PrecompiledLoader = loaders.PrecompiledLoader; + module.exports.WebLoader = loaders.WebLoader; + + module.exports.compiler = __webpack_require__(7); + module.exports.parser = __webpack_require__(8); + module.exports.lexer = __webpack_require__(9); + module.exports.runtime = __webpack_require__(12); + module.exports.lib = lib; + module.exports.nodes = __webpack_require__(10); + + module.exports.installJinjaCompat = __webpack_require__(21); + + // A single instance of an environment, since this is so commonly used + + var e; + module.exports.configure = function(templatesPath, opts) { + opts = opts || {}; + if(lib.isObject(templatesPath)) { + opts = templatesPath; + templatesPath = null; + } + + var TemplateLoader; + if(loaders.FileSystemLoader) { + TemplateLoader = new loaders.FileSystemLoader(templatesPath, { + watch: opts.watch, + noCache: opts.noCache + }); + } + else if(loaders.WebLoader) { + TemplateLoader = new loaders.WebLoader(templatesPath, { + useCache: opts.web && opts.web.useCache, + async: opts.web && opts.web.async + }); + } + + e = new env.Environment(TemplateLoader, opts); + + if(opts && opts.express) { + e.express(opts.express); + } + + return e; + }; + + module.exports.compile = function(src, env, path, eagerCompile) { + if(!e) { + module.exports.configure(); + } + return new module.exports.Template(src, env, path, eagerCompile); + }; + + module.exports.render = function(name, ctx, cb) { + if(!e) { + module.exports.configure(); + } + + return e.render(name, ctx, cb); + }; + + module.exports.renderString = function(src, ctx, cb) { + if(!e) { + module.exports.configure(); + } + + return e.renderString(src, ctx, cb); + }; + + if(precompile) { + module.exports.precompile = precompile.precompile; + module.exports.precompileString = precompile.precompileString; + } + + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + 'use strict'; + + var ArrayProto = Array.prototype; + var ObjProto = Object.prototype; + + var escapeMap = { + '&': '&', + '"': '"', + '\'': ''', + '<': '<', + '>': '>' + }; + + var escapeRegex = /[&"'<>]/g; + + var lookupEscape = function(ch) { + return escapeMap[ch]; + }; + + var exports = module.exports = {}; + + exports.prettifyError = function(path, withInternals, err) { + // jshint -W022 + // http://jslinterrors.com/do-not-assign-to-the-exception-parameter + if (!err.Update) { + // not one of ours, cast it + err = new exports.TemplateError(err); + } + err.Update(path); + + // Unless they marked the dev flag, show them a trace from here + if (!withInternals) { + var old = err; + err = new Error(old.message); + err.name = old.name; + } + + return err; + }; + + exports.TemplateError = function(message, lineno, colno) { + var err = this; + + if (message instanceof Error) { // for casting regular js errors + err = message; + message = message.name + ': ' + message.message; + + try { + if(err.name = '') {} + } + catch(e) { + // If we can't set the name of the error object in this + // environment, don't use it + err = this; + } + } else { + if(Error.captureStackTrace) { + Error.captureStackTrace(err); + } + } + + err.name = 'Template render error'; + err.message = message; + err.lineno = lineno; + err.colno = colno; + err.firstUpdate = true; + + err.Update = function(path) { + var message = '(' + (path || 'unknown path') + ')'; + + // only show lineno + colno next to path of template + // where error occurred + if (this.firstUpdate) { + if(this.lineno && this.colno) { + message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']'; + } + else if(this.lineno) { + message += ' [Line ' + this.lineno + ']'; + } + } + + message += '\n '; + if (this.firstUpdate) { + message += ' '; + } + + this.message = message + (this.message || ''); + this.firstUpdate = false; + return this; + }; + + return err; + }; + + exports.TemplateError.prototype = Error.prototype; + + exports.escape = function(val) { + return val.replace(escapeRegex, lookupEscape); + }; + + exports.isFunction = function(obj) { + return ObjProto.toString.call(obj) === '[object Function]'; + }; + + exports.isArray = Array.isArray || function(obj) { + return ObjProto.toString.call(obj) === '[object Array]'; + }; + + exports.isString = function(obj) { + return ObjProto.toString.call(obj) === '[object String]'; + }; + + exports.isObject = function(obj) { + return ObjProto.toString.call(obj) === '[object Object]'; + }; + + exports.groupBy = function(obj, val) { + var result = {}; + var iterator = exports.isFunction(val) ? val : function(obj) { return obj[val]; }; + for(var i=0; i>> 0; // Hack to convert object.length to a UInt32 + + fromIndex = +fromIndex || 0; + + if(Math.abs(fromIndex) === Infinity) { + fromIndex = 0; + } + + if(fromIndex < 0) { + fromIndex += length; + if (fromIndex < 0) { + fromIndex = 0; + } + } + + for(;fromIndex < length; fromIndex++) { + if (arr[fromIndex] === searchElement) { + return fromIndex; + } + } + + return -1; + }; + + if(!Array.prototype.map) { + Array.prototype.map = function() { + throw new Error('map is unimplemented for this js engine'); + }; + } + + exports.keys = function(obj) { + if(Object.prototype.keys) { + return obj.keys(); + } + else { + var keys = []; + for(var k in obj) { + if(obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + } + }; + + exports.inOperator = function (key, val) { + if (exports.isArray(val)) { + return exports.indexOf(val, key) !== -1; + } else if (exports.isObject(val)) { + return key in val; + } else if (exports.isString(val)) { + return val.indexOf(key) !== -1; + } else { + throw new Error('Cannot use "in" operator to search for "' + + key + '" in unexpected types.'); + } + }; + + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var path = __webpack_require__(3); + var asap = __webpack_require__(4); + var lib = __webpack_require__(1); + var Obj = __webpack_require__(6); + var compiler = __webpack_require__(7); + var builtin_filters = __webpack_require__(13); + var builtin_loaders = __webpack_require__(14); + var runtime = __webpack_require__(12); + var globals = __webpack_require__(17); + var waterfall = __webpack_require__(18); + var Frame = runtime.Frame; + var Template; + + // Unconditionally load in this loader, even if no other ones are + // included (possible in the slim browser build) + builtin_loaders.PrecompiledLoader = __webpack_require__(16); + + // If the user is using the async API, *always* call it + // asynchronously even if the template was synchronous. + function callbackAsap(cb, err, res) { + asap(function() { cb(err, res); }); + } + + var Environment = Obj.extend({ + init: function(loaders, opts) { + // The dev flag determines the trace that'll be shown on errors. + // If set to true, returns the full trace from the error point, + // otherwise will return trace starting from Template.render + // (the full trace from within nunjucks may confuse developers using + // the library) + // defaults to false + opts = this.opts = opts || {}; + this.opts.dev = !!opts.dev; + + // The autoescape flag sets global autoescaping. If true, + // every string variable will be escaped by default. + // If false, strings can be manually escaped using the `escape` filter. + // defaults to true + this.opts.autoescape = opts.autoescape != null ? opts.autoescape : true; + + // If true, this will make the system throw errors if trying + // to output a null or undefined value + this.opts.throwOnUndefined = !!opts.throwOnUndefined; + this.opts.trimBlocks = !!opts.trimBlocks; + this.opts.lstripBlocks = !!opts.lstripBlocks; + + this.loaders = []; + + if(!loaders) { + // The filesystem loader is only available server-side + if(builtin_loaders.FileSystemLoader) { + this.loaders = [new builtin_loaders.FileSystemLoader('views')]; + } + else if(builtin_loaders.WebLoader) { + this.loaders = [new builtin_loaders.WebLoader('/views')]; + } + } + else { + this.loaders = lib.isArray(loaders) ? loaders : [loaders]; + } + + // It's easy to use precompiled templates: just include them + // before you configure nunjucks and this will automatically + // pick it up and use it + if((true) && window.nunjucksPrecompiled) { + this.loaders.unshift( + new builtin_loaders.PrecompiledLoader(window.nunjucksPrecompiled) + ); + } + + this.initCache(); + + this.globals = globals(); + this.filters = {}; + this.asyncFilters = []; + this.extensions = {}; + this.extensionsList = []; + + for(var name in builtin_filters) { + this.addFilter(name, builtin_filters[name]); + } + }, + + initCache: function() { + // Caching and cache busting + lib.each(this.loaders, function(loader) { + loader.cache = {}; + + if(typeof loader.on === 'function') { + loader.on('update', function(template) { + loader.cache[template] = null; + }); + } + }); + }, + + addExtension: function(name, extension) { + extension._name = name; + this.extensions[name] = extension; + this.extensionsList.push(extension); + return this; + }, + + removeExtension: function(name) { + var extension = this.getExtension(name); + if (!extension) return; + + this.extensionsList = lib.without(this.extensionsList, extension); + delete this.extensions[name]; + }, + + getExtension: function(name) { + return this.extensions[name]; + }, + + hasExtension: function(name) { + return !!this.extensions[name]; + }, + + addGlobal: function(name, value) { + this.globals[name] = value; + return this; + }, + + getGlobal: function(name) { + if(typeof this.globals[name] === 'undefined') { + throw new Error('global not found: ' + name); + } + return this.globals[name]; + }, + + addFilter: function(name, func, async) { + var wrapped = func; + + if(async) { + this.asyncFilters.push(name); + } + this.filters[name] = wrapped; + return this; + }, + + getFilter: function(name) { + if(!this.filters[name]) { + throw new Error('filter not found: ' + name); + } + return this.filters[name]; + }, + + resolveTemplate: function(loader, parentName, filename) { + var isRelative = (loader.isRelative && parentName)? loader.isRelative(filename) : false; + return (isRelative && loader.resolve)? loader.resolve(parentName, filename) : filename; + }, + + getTemplate: function(name, eagerCompile, parentName, ignoreMissing, cb) { + var that = this; + var tmpl = null; + if(name && name.raw) { + // this fixes autoescape for templates referenced in symbols + name = name.raw; + } + + if(lib.isFunction(parentName)) { + cb = parentName; + parentName = null; + eagerCompile = eagerCompile || false; + } + + if(lib.isFunction(eagerCompile)) { + cb = eagerCompile; + eagerCompile = false; + } + + if (name instanceof Template) { + tmpl = name; + } + else if(typeof name !== 'string') { + throw new Error('template names must be a string: ' + name); + } + else { + for (var i = 0; i < this.loaders.length; i++) { + var _name = this.resolveTemplate(this.loaders[i], parentName, name); + tmpl = this.loaders[i].cache[_name]; + if (tmpl) break; + } + } + + if(tmpl) { + if(eagerCompile) { + tmpl.compile(); + } + + if(cb) { + cb(null, tmpl); + } + else { + return tmpl; + } + } else { + var syncResult; + var _this = this; + + var createTemplate = function(err, info) { + if(!info && !err) { + if(!ignoreMissing) { + err = new Error('template not found: ' + name); + } + } + + if (err) { + if(cb) { + cb(err); + } + else { + throw err; + } + } + else { + var tmpl; + if(info) { + tmpl = new Template(info.src, _this, + info.path, eagerCompile); + + if(!info.noCache) { + info.loader.cache[name] = tmpl; + } + } + else { + tmpl = new Template('', _this, + '', eagerCompile); + } + + if(cb) { + cb(null, tmpl); + } + else { + syncResult = tmpl; + } + } + }; + + lib.asyncIter(this.loaders, function(loader, i, next, done) { + function handle(err, src) { + if(err) { + done(err); + } + else if(src) { + src.loader = loader; + done(null, src); + } + else { + next(); + } + } + + // Resolve name relative to parentName + name = that.resolveTemplate(loader, parentName, name); + + if(loader.async) { + loader.getSource(name, handle); + } + else { + handle(null, loader.getSource(name)); + } + }, createTemplate); + + return syncResult; + } + }, + + express: function(app) { + var env = this; + + function NunjucksView(name, opts) { + this.name = name; + this.path = name; + this.defaultEngine = opts.defaultEngine; + this.ext = path.extname(name); + if (!this.ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); + if (!this.ext) this.name += (this.ext = ('.' !== this.defaultEngine[0] ? '.' : '') + this.defaultEngine); + } + + NunjucksView.prototype.render = function(opts, cb) { + env.render(this.name, opts, cb); + }; + + app.set('view', NunjucksView); + app.set('nunjucksEnv', this); + return this; + }, + + render: function(name, ctx, cb) { + if(lib.isFunction(ctx)) { + cb = ctx; + ctx = null; + } + + // We support a synchronous API to make it easier to migrate + // existing code to async. This works because if you don't do + // anything async work, the whole thing is actually run + // synchronously. + var syncResult = null; + + this.getTemplate(name, function(err, tmpl) { + if(err && cb) { + callbackAsap(cb, err); + } + else if(err) { + throw err; + } + else { + syncResult = tmpl.render(ctx, cb); + } + }); + + return syncResult; + }, + + renderString: function(src, ctx, opts, cb) { + if(lib.isFunction(opts)) { + cb = opts; + opts = {}; + } + opts = opts || {}; + + var tmpl = new Template(src, this, opts.path); + return tmpl.render(ctx, cb); + }, + + waterfall: waterfall + }); + + var Context = Obj.extend({ + init: function(ctx, blocks, env) { + // Has to be tied to an environment so we can tap into its globals. + this.env = env || new Environment(); + + // Make a duplicate of ctx + this.ctx = {}; + for(var k in ctx) { + if(ctx.hasOwnProperty(k)) { + this.ctx[k] = ctx[k]; + } + } + + this.blocks = {}; + this.exported = []; + + for(var name in blocks) { + this.addBlock(name, blocks[name]); + } + }, + + lookup: function(name) { + // This is one of the most called functions, so optimize for + // the typical case where the name isn't in the globals + if(name in this.env.globals && !(name in this.ctx)) { + return this.env.globals[name]; + } + else { + return this.ctx[name]; + } + }, + + setVariable: function(name, val) { + this.ctx[name] = val; + }, + + getVariables: function() { + return this.ctx; + }, + + addBlock: function(name, block) { + this.blocks[name] = this.blocks[name] || []; + this.blocks[name].push(block); + return this; + }, + + getBlock: function(name) { + if(!this.blocks[name]) { + throw new Error('unknown block "' + name + '"'); + } + + return this.blocks[name][0]; + }, + + getSuper: function(env, name, block, frame, runtime, cb) { + var idx = lib.indexOf(this.blocks[name] || [], block); + var blk = this.blocks[name][idx + 1]; + var context = this; + + if(idx === -1 || !blk) { + throw new Error('no super block available for "' + name + '"'); + } + + blk(env, context, frame, runtime, cb); + }, + + addExport: function(name) { + this.exported.push(name); + }, + + getExported: function() { + var exported = {}; + for(var i=0; i capacity) { + // Manually shift all values starting at the index back to the + // beginning of the queue. + for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) { + queue[scan] = queue[scan + index]; + } + queue.length -= index; + index = 0; + } + } + queue.length = 0; + index = 0; + flushing = false; + } + + // `requestFlush` is implemented using a strategy based on data collected from + // every available SauceLabs Selenium web driver worker at time of writing. + // https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593 + + // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that + // have WebKitMutationObserver but not un-prefixed MutationObserver. + // Must use `global` instead of `window` to work in both frames and web + // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop. + var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver; + + // MutationObservers are desirable because they have high priority and work + // reliably everywhere they are implemented. + // They are implemented in all modern browsers. + // + // - Android 4-4.3 + // - Chrome 26-34 + // - Firefox 14-29 + // - Internet Explorer 11 + // - iPad Safari 6-7.1 + // - iPhone Safari 7-7.1 + // - Safari 6-7 + if (typeof BrowserMutationObserver === "function") { + requestFlush = makeRequestCallFromMutationObserver(flush); + + // MessageChannels are desirable because they give direct access to the HTML + // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera + // 11-12, and in web workers in many engines. + // Although message channels yield to any queued rendering and IO tasks, they + // would be better than imposing the 4ms delay of timers. + // However, they do not work reliably in Internet Explorer or Safari. + + // Internet Explorer 10 is the only browser that has setImmediate but does + // not have MutationObservers. + // Although setImmediate yields to the browser's renderer, it would be + // preferrable to falling back to setTimeout since it does not have + // the minimum 4ms penalty. + // Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and + // Desktop to a lesser extent) that renders both setImmediate and + // MessageChannel useless for the purposes of ASAP. + // https://github.com/kriskowal/q/issues/396 + + // Timers are implemented universally. + // We fall back to timers in workers in most engines, and in foreground + // contexts in the following browsers. + // However, note that even this simple case requires nuances to operate in a + // broad spectrum of browsers. + // + // - Firefox 3-13 + // - Internet Explorer 6-9 + // - iPad Safari 4.3 + // - Lynx 2.8.7 + } else { + requestFlush = makeRequestCallFromTimer(flush); + } + + // `requestFlush` requests that the high priority event queue be flushed as + // soon as possible. + // This is useful to prevent an error thrown in a task from stalling the event + // queue if the exception handled by Node.js’s + // `process.on("uncaughtException")` or by a domain. + rawAsap.requestFlush = requestFlush; + + // To request a high priority event, we induce a mutation observer by toggling + // the text of a text node between "1" and "-1". + function makeRequestCallFromMutationObserver(callback) { + var toggle = 1; + var observer = new BrowserMutationObserver(callback); + var node = document.createTextNode(""); + observer.observe(node, {characterData: true}); + return function requestCall() { + toggle = -toggle; + node.data = toggle; + }; + } + + // The message channel technique was discovered by Malte Ubl and was the + // original foundation for this library. + // http://www.nonblocking.io/2011/06/windownexttick.html + + // Safari 6.0.5 (at least) intermittently fails to create message ports on a + // page's first load. Thankfully, this version of Safari supports + // MutationObservers, so we don't need to fall back in that case. + + // function makeRequestCallFromMessageChannel(callback) { + // var channel = new MessageChannel(); + // channel.port1.onmessage = callback; + // return function requestCall() { + // channel.port2.postMessage(0); + // }; + // } + + // For reasons explained above, we are also unable to use `setImmediate` + // under any circumstances. + // Even if we were, there is another bug in Internet Explorer 10. + // It is not sufficient to assign `setImmediate` to `requestFlush` because + // `setImmediate` must be called *by name* and therefore must be wrapped in a + // closure. + // Never forget. + + // function makeRequestCallFromSetImmediate(callback) { + // return function requestCall() { + // setImmediate(callback); + // }; + // } + + // Safari 6.0 has a problem where timers will get lost while the user is + // scrolling. This problem does not impact ASAP because Safari 6.0 supports + // mutation observers, so that implementation is used instead. + // However, if we ever elect to use timers in Safari, the prevalent work-around + // is to add a scroll event listener that calls for a flush. + + // `setTimeout` does not call the passed callback if the delay is less than + // approximately 7 in web workers in Firefox 8 through 18, and sometimes not + // even then. + + function makeRequestCallFromTimer(callback) { + return function requestCall() { + // We dispatch a timeout with a specified delay of 0 for engines that + // can reliably accommodate that request. This will usually be snapped + // to a 4 milisecond delay, but once we're flushing, there's no delay + // between events. + var timeoutHandle = setTimeout(handleTimer, 0); + // However, since this timer gets frequently dropped in Firefox + // workers, we enlist an interval handle that will try to fire + // an event 20 times per second until it succeeds. + var intervalHandle = setInterval(handleTimer, 50); + + function handleTimer() { + // Whichever timer succeeds will cancel both timers and + // execute the callback. + clearTimeout(timeoutHandle); + clearInterval(intervalHandle); + callback(); + } + }; + } + + // This is for `asap.js` only. + // Its name will be periodically randomized to break any code that depends on + // its existence. + rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer; + + // ASAP was originally a nextTick shim included in Q. This was factored out + // into this ASAP package. It was later adapted to RSVP which made further + // amendments. These decisions, particularly to marginalize MessageChannel and + // to capture the MutationObserver implementation in a closure, were integrated + // back into ASAP proper. + // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + 'use strict'; + + // A simple class system, more documentation to come + + function extend(cls, name, props) { + // This does that same thing as Object.create, but with support for IE8 + var F = function() {}; + F.prototype = cls.prototype; + var prototype = new F(); + + // jshint undef: false + var fnTest = /xyz/.test(function(){ xyz; }) ? /\bparent\b/ : /.*/; + props = props || {}; + + for(var k in props) { + var src = props[k]; + var parent = prototype[k]; + + if(typeof parent === 'function' && + typeof src === 'function' && + fnTest.test(src)) { + /*jshint -W083 */ + prototype[k] = (function (src, parent) { + return function() { + // Save the current parent method + var tmp = this.parent; + + // Set parent to the previous method, call, and restore + this.parent = parent; + var res = src.apply(this, arguments); + this.parent = tmp; + + return res; + }; + })(src, parent); + } + else { + prototype[k] = src; + } + } + + prototype.typename = name; + + var new_cls = function() { + if(prototype.init) { + prototype.init.apply(this, arguments); + } + }; + + new_cls.prototype = prototype; + new_cls.prototype.constructor = new_cls; + + new_cls.extend = function(name, props) { + if(typeof name === 'object') { + props = name; + name = 'anonymous'; + } + return extend(new_cls, name, props); + }; + + return new_cls; + } + + module.exports = extend(Object, 'Object', {}); + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lib = __webpack_require__(1); + var parser = __webpack_require__(8); + var transformer = __webpack_require__(11); + var nodes = __webpack_require__(10); + // jshint -W079 + var Object = __webpack_require__(6); + var Frame = __webpack_require__(12).Frame; + + // These are all the same for now, but shouldn't be passed straight + // through + var compareOps = { + '==': '==', + '===': '===', + '!=': '!=', + '!==': '!==', + '<': '<', + '>': '>', + '<=': '<=', + '>=': '>=' + }; + + // A common pattern is to emit binary operators + function binOpEmitter(str) { + return function(node, frame) { + this.compile(node.left, frame); + this.emit(str); + this.compile(node.right, frame); + }; + } + + var Compiler = Object.extend({ + init: function(templateName, throwOnUndefined) { + this.templateName = templateName; + this.codebuf = []; + this.lastId = 0; + this.buffer = null; + this.bufferStack = []; + this.scopeClosers = ''; + this.inBlock = false; + this.throwOnUndefined = throwOnUndefined; + }, + + fail: function (msg, lineno, colno) { + if (lineno !== undefined) lineno += 1; + if (colno !== undefined) colno += 1; + + throw new lib.TemplateError(msg, lineno, colno); + }, + + pushBufferId: function(id) { + this.bufferStack.push(this.buffer); + this.buffer = id; + this.emit('var ' + this.buffer + ' = "";'); + }, + + popBufferId: function() { + this.buffer = this.bufferStack.pop(); + }, + + emit: function(code) { + this.codebuf.push(code); + }, + + emitLine: function(code) { + this.emit(code + '\n'); + }, + + emitLines: function() { + lib.each(lib.toArray(arguments), function(line) { + this.emitLine(line); + }, this); + }, + + emitFuncBegin: function(name) { + this.buffer = 'output'; + this.scopeClosers = ''; + this.emitLine('function ' + name + '(env, context, frame, runtime, cb) {'); + this.emitLine('var lineno = null;'); + this.emitLine('var colno = null;'); + this.emitLine('var ' + this.buffer + ' = "";'); + this.emitLine('try {'); + }, + + emitFuncEnd: function(noReturn) { + if(!noReturn) { + this.emitLine('cb(null, ' + this.buffer +');'); + } + + this.closeScopeLevels(); + this.emitLine('} catch (e) {'); + this.emitLine(' cb(runtime.handleError(e, lineno, colno));'); + this.emitLine('}'); + this.emitLine('}'); + this.buffer = null; + }, + + addScopeLevel: function() { + this.scopeClosers += '})'; + }, + + closeScopeLevels: function() { + this.emitLine(this.scopeClosers + ';'); + this.scopeClosers = ''; + }, + + withScopedSyntax: function(func) { + var scopeClosers = this.scopeClosers; + this.scopeClosers = ''; + + func.call(this); + + this.closeScopeLevels(); + this.scopeClosers = scopeClosers; + }, + + makeCallback: function(res) { + var err = this.tmpid(); + + return 'function(' + err + (res ? ',' + res : '') + ') {\n' + + 'if(' + err + ') { cb(' + err + '); return; }'; + }, + + tmpid: function() { + this.lastId++; + return 't_' + this.lastId; + }, + + _templateName: function() { + return this.templateName == null? 'undefined' : JSON.stringify(this.templateName); + }, + + _compileChildren: function(node, frame) { + var children = node.children; + for(var i=0, l=children.length; i 0) { + this.emit(','); + } + + this.compile(node.children[i], frame); + } + + if(endChar) { + this.emit(endChar); + } + }, + + _compileExpression: function(node, frame) { + // TODO: I'm not really sure if this type check is worth it or + // not. + this.assertType( + node, + nodes.Literal, + nodes.Symbol, + nodes.Group, + nodes.Array, + nodes.Dict, + nodes.FunCall, + nodes.Caller, + nodes.Filter, + nodes.LookupVal, + nodes.Compare, + nodes.InlineIf, + nodes.In, + nodes.And, + nodes.Or, + nodes.Not, + nodes.Add, + nodes.Concat, + nodes.Sub, + nodes.Mul, + nodes.Div, + nodes.FloorDiv, + nodes.Mod, + nodes.Pow, + nodes.Neg, + nodes.Pos, + nodes.Compare, + nodes.NodeList + ); + this.compile(node, frame); + }, + + assertType: function(node /*, types */) { + var types = lib.toArray(arguments).slice(1); + var success = false; + + for(var i=0; i 0) { + this.emit(','); + } + + if(arg) { + var id = this.tmpid(); + + this.emitLine('function(cb) {'); + this.emitLine('if(!cb) { cb = function(err) { if(err) { throw err; }}}'); + this.pushBufferId(id); + + this.withScopedSyntax(function() { + this.compile(arg, frame); + this.emitLine('cb(null, ' + id + ');'); + }); + + this.popBufferId(); + this.emitLine('return ' + id + ';'); + this.emitLine('}'); + } + else { + this.emit('null'); + } + }, this); + } + + if(async) { + var res = this.tmpid(); + this.emitLine(', ' + this.makeCallback(res)); + this.emitLine(this.buffer + ' += runtime.suppressValue(' + res + ', ' + autoescape + ' && env.opts.autoescape);'); + this.addScopeLevel(); + } + else { + this.emit(')'); + this.emit(', ' + autoescape + ' && env.opts.autoescape);\n'); + } + }, + + compileCallExtensionAsync: function(node, frame) { + this.compileCallExtension(node, frame, true); + }, + + compileNodeList: function(node, frame) { + this._compileChildren(node, frame); + }, + + compileLiteral: function(node) { + if(typeof node.value === 'string') { + var val = node.value.replace(/\\/g, '\\\\'); + val = val.replace(/"/g, '\\"'); + val = val.replace(/\n/g, '\\n'); + val = val.replace(/\r/g, '\\r'); + val = val.replace(/\t/g, '\\t'); + this.emit('"' + val + '"'); + } + else if (node.value === null) { + this.emit('null'); + } + else { + this.emit(node.value.toString()); + } + }, + + compileSymbol: function(node, frame) { + var name = node.value; + var v; + + if((v = frame.lookup(name))) { + this.emit(v); + } + else { + this.emit('runtime.contextOrFrameLookup(' + + 'context, frame, "' + name + '")'); + } + }, + + compileGroup: function(node, frame) { + this._compileAggregate(node, frame, '(', ')'); + }, + + compileArray: function(node, frame) { + this._compileAggregate(node, frame, '[', ']'); + }, + + compileDict: function(node, frame) { + this._compileAggregate(node, frame, '{', '}'); + }, + + compilePair: function(node, frame) { + var key = node.key; + var val = node.value; + + if(key instanceof nodes.Symbol) { + key = new nodes.Literal(key.lineno, key.colno, key.value); + } + else if(!(key instanceof nodes.Literal && + typeof key.value === 'string')) { + this.fail('compilePair: Dict keys must be strings or names', + key.lineno, + key.colno); + } + + this.compile(key, frame); + this.emit(': '); + this._compileExpression(val, frame); + }, + + compileInlineIf: function(node, frame) { + this.emit('('); + this.compile(node.cond, frame); + this.emit('?'); + this.compile(node.body, frame); + this.emit(':'); + if(node.else_ !== null) + this.compile(node.else_, frame); + else + this.emit('""'); + this.emit(')'); + }, + + compileIn: function(node, frame) { + this.emit('runtime.inOperator('); + this.compile(node.left, frame); + this.emit(','); + this.compile(node.right, frame); + this.emit(')'); + }, + + compileOr: binOpEmitter(' || '), + compileAnd: binOpEmitter(' && '), + compileAdd: binOpEmitter(' + '), + // ensure concatenation instead of addition + // by adding empty string in between + compileConcat: binOpEmitter(' + "" + '), + compileSub: binOpEmitter(' - '), + compileMul: binOpEmitter(' * '), + compileDiv: binOpEmitter(' / '), + compileMod: binOpEmitter(' % '), + + compileNot: function(node, frame) { + this.emit('!'); + this.compile(node.target, frame); + }, + + compileFloorDiv: function(node, frame) { + this.emit('Math.floor('); + this.compile(node.left, frame); + this.emit(' / '); + this.compile(node.right, frame); + this.emit(')'); + }, + + compilePow: function(node, frame) { + this.emit('Math.pow('); + this.compile(node.left, frame); + this.emit(', '); + this.compile(node.right, frame); + this.emit(')'); + }, + + compileNeg: function(node, frame) { + this.emit('-'); + this.compile(node.target, frame); + }, + + compilePos: function(node, frame) { + this.emit('+'); + this.compile(node.target, frame); + }, + + compileCompare: function(node, frame) { + this.compile(node.expr, frame); + + for(var i=0; i 0 && !this.skip(lexer.TOKEN_COMMA)) { + this.fail('parseFrom: expected comma', + fromTok.lineno, + fromTok.colno); + } + + var name = this.parsePrimary(); + if(name.value.charAt(0) === '_') { + this.fail('parseFrom: names starting with an underscore ' + + 'cannot be imported', + name.lineno, + name.colno); + } + + if(this.skipSymbol('as')) { + var alias = this.parsePrimary(); + names.addChild(new nodes.Pair(name.lineno, + name.colno, + name, + alias)); + } + else { + names.addChild(name); + } + + withContext = this.parseWithContext(); + } + + return new nodes.FromImport(fromTok.lineno, + fromTok.colno, + template, + names, + withContext); + }, + + parseBlock: function() { + var tag = this.peekToken(); + if(!this.skipSymbol('block')) { + this.fail('parseBlock: expected block', tag.lineno, tag.colno); + } + + var node = new nodes.Block(tag.lineno, tag.colno); + + node.name = this.parsePrimary(); + if(!(node.name instanceof nodes.Symbol)) { + this.fail('parseBlock: variable name expected', + tag.lineno, + tag.colno); + } + + this.advanceAfterBlockEnd(tag.value); + + node.body = this.parseUntilBlocks('endblock'); + this.skipSymbol('endblock'); + this.skipSymbol(node.name.value); + + var tok = this.peekToken(); + if(!tok) { + this.fail('parseBlock: expected endblock, got end of file'); + } + + this.advanceAfterBlockEnd(tok.value); + + return node; + }, + + parseExtends: function() { + var tagName = 'extends'; + var tag = this.peekToken(); + if(!this.skipSymbol(tagName)) { + this.fail('parseTemplateRef: expected '+ tagName); + } + + var node = new nodes.Extends(tag.lineno, tag.colno); + node.template = this.parseExpression(); + + this.advanceAfterBlockEnd(tag.value); + return node; + }, + + parseInclude: function() { + var tagName = 'include'; + var tag = this.peekToken(); + if(!this.skipSymbol(tagName)) { + this.fail('parseInclude: expected '+ tagName); + } + + var node = new nodes.Include(tag.lineno, tag.colno); + node.template = this.parseExpression(); + + if(this.skipSymbol('ignore') && this.skipSymbol('missing')) { + node.ignoreMissing = true; + } + + this.advanceAfterBlockEnd(tag.value); + return node; + }, + + parseIf: function() { + var tag = this.peekToken(); + var node; + + if(this.skipSymbol('if') || this.skipSymbol('elif') || this.skipSymbol('elseif')) { + node = new nodes.If(tag.lineno, tag.colno); + } + else if(this.skipSymbol('ifAsync')) { + node = new nodes.IfAsync(tag.lineno, tag.colno); + } + else { + this.fail('parseIf: expected if, elif, or elseif', + tag.lineno, + tag.colno); + } + + node.cond = this.parseExpression(); + this.advanceAfterBlockEnd(tag.value); + + node.body = this.parseUntilBlocks('elif', 'elseif', 'else', 'endif'); + var tok = this.peekToken(); + + switch(tok && tok.value) { + case 'elseif': + case 'elif': + node.else_ = this.parseIf(); + break; + case 'else': + this.advanceAfterBlockEnd(); + node.else_ = this.parseUntilBlocks('endif'); + this.advanceAfterBlockEnd(); + break; + case 'endif': + node.else_ = null; + this.advanceAfterBlockEnd(); + break; + default: + this.fail('parseIf: expected elif, else, or endif, ' + + 'got end of file'); + } + + return node; + }, + + parseSet: function() { + var tag = this.peekToken(); + if(!this.skipSymbol('set')) { + this.fail('parseSet: expected set', tag.lineno, tag.colno); + } + + var node = new nodes.Set(tag.lineno, tag.colno, []); + + var target; + while((target = this.parsePrimary())) { + node.targets.push(target); + + if(!this.skip(lexer.TOKEN_COMMA)) { + break; + } + } + + if(!this.skipValue(lexer.TOKEN_OPERATOR, '=')) { + if (!this.skip(lexer.TOKEN_BLOCK_END)) { + this.fail('parseSet: expected = or block end in set tag', + tag.lineno, + tag.colno); + } + else { + node.body = new nodes.Capture( + tag.lineno, + tag.colno, + this.parseUntilBlocks('endset') + ); + node.value = null; + this.advanceAfterBlockEnd(); + } + } + else { + node.value = this.parseExpression(); + this.advanceAfterBlockEnd(tag.value); + } + + return node; + }, + + parseStatement: function () { + var tok = this.peekToken(); + var node; + + if(tok.type !== lexer.TOKEN_SYMBOL) { + this.fail('tag name expected', tok.lineno, tok.colno); + } + + if(this.breakOnBlocks && + lib.indexOf(this.breakOnBlocks, tok.value) !== -1) { + return null; + } + + switch(tok.value) { + case 'raw': return this.parseRaw(); + case 'verbatim': return this.parseRaw('verbatim'); + case 'if': + case 'ifAsync': + return this.parseIf(); + case 'for': + case 'asyncEach': + case 'asyncAll': + return this.parseFor(); + case 'block': return this.parseBlock(); + case 'extends': return this.parseExtends(); + case 'include': return this.parseInclude(); + case 'set': return this.parseSet(); + case 'macro': return this.parseMacro(); + case 'call': return this.parseCall(); + case 'import': return this.parseImport(); + case 'from': return this.parseFrom(); + case 'filter': return this.parseFilterStatement(); + default: + if (this.extensions.length) { + for (var i = 0; i < this.extensions.length; i++) { + var ext = this.extensions[i]; + if (lib.indexOf(ext.tags || [], tok.value) !== -1) { + return ext.parse(this, nodes, lexer); + } + } + } + this.fail('unknown block tag: ' + tok.value, tok.lineno, tok.colno); + } + + return node; + }, + + parseRaw: function(tagName) { + tagName = tagName || 'raw'; + var endTagName = 'end' + tagName; + // Look for upcoming raw blocks (ignore all other kinds of blocks) + var rawBlockRegex = new RegExp('([\\s\\S]*?){%\\s*(' + tagName + '|' + endTagName + ')\\s*(?=%})%}'); + var rawLevel = 1; + var str = ''; + var matches = null; + + // Skip opening raw token + // Keep this token to track line and column numbers + var begun = this.advanceAfterBlockEnd(); + + // Exit when there's nothing to match + // or when we've found the matching "endraw" block + while((matches = this.tokens._extractRegex(rawBlockRegex)) && rawLevel > 0) { + var all = matches[0]; + var pre = matches[1]; + var blockName = matches[2]; + + // Adjust rawlevel + if(blockName === tagName) { + rawLevel += 1; + } else if(blockName === endTagName) { + rawLevel -= 1; + } + + // Add to str + if(rawLevel === 0) { + // We want to exclude the last "endraw" + str += pre; + // Move tokenizer to beginning of endraw block + this.tokens.backN(all.length - pre.length); + } else { + str += all; + } + } + + return new nodes.Output( + begun.lineno, + begun.colno, + [new nodes.TemplateData(begun.lineno, begun.colno, str)] + ); + }, + + parsePostfix: function(node) { + var lookup, tok = this.peekToken(); + + while(tok) { + if(tok.type === lexer.TOKEN_LEFT_PAREN) { + // Function call + node = new nodes.FunCall(tok.lineno, + tok.colno, + node, + this.parseSignature()); + } + else if(tok.type === lexer.TOKEN_LEFT_BRACKET) { + // Reference + lookup = this.parseAggregate(); + if(lookup.children.length > 1) { + this.fail('invalid index'); + } + + node = new nodes.LookupVal(tok.lineno, + tok.colno, + node, + lookup.children[0]); + } + else if(tok.type === lexer.TOKEN_OPERATOR && tok.value === '.') { + // Reference + this.nextToken(); + var val = this.nextToken(); + + if(val.type !== lexer.TOKEN_SYMBOL) { + this.fail('expected name as lookup value, got ' + val.value, + val.lineno, + val.colno); + } + + // Make a literal string because it's not a variable + // reference + lookup = new nodes.Literal(val.lineno, + val.colno, + val.value); + + node = new nodes.LookupVal(tok.lineno, + tok.colno, + node, + lookup); + } + else { + break; + } + + tok = this.peekToken(); + } + + return node; + }, + + parseExpression: function() { + var node = this.parseInlineIf(); + return node; + }, + + parseInlineIf: function() { + var node = this.parseOr(); + if(this.skipSymbol('if')) { + var cond_node = this.parseOr(); + var body_node = node; + node = new nodes.InlineIf(node.lineno, node.colno); + node.body = body_node; + node.cond = cond_node; + if(this.skipSymbol('else')) { + node.else_ = this.parseOr(); + } else { + node.else_ = null; + } + } + + return node; + }, + + parseOr: function() { + var node = this.parseAnd(); + while(this.skipSymbol('or')) { + var node2 = this.parseAnd(); + node = new nodes.Or(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseAnd: function() { + var node = this.parseNot(); + while(this.skipSymbol('and')) { + var node2 = this.parseNot(); + node = new nodes.And(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseNot: function() { + var tok = this.peekToken(); + if(this.skipSymbol('not')) { + return new nodes.Not(tok.lineno, + tok.colno, + this.parseNot()); + } + return this.parseIn(); + }, + + parseIn: function() { + var node = this.parseCompare(); + while(1) { + // check if the next token is 'not' + var tok = this.nextToken(); + if (!tok) { break; } + var invert = tok.type === lexer.TOKEN_SYMBOL && tok.value === 'not'; + // if it wasn't 'not', put it back + if (!invert) { this.pushToken(tok); } + if (this.skipSymbol('in')) { + var node2 = this.parseCompare(); + node = new nodes.In(node.lineno, + node.colno, + node, + node2); + if (invert) { + node = new nodes.Not(node.lineno, + node.colno, + node); + } + } + else { + // if we'd found a 'not' but this wasn't an 'in', put back the 'not' + if (invert) { this.pushToken(tok); } + break; + } + } + return node; + }, + + parseCompare: function() { + var compareOps = ['==', '===', '!=', '!==', '<', '>', '<=', '>=']; + var expr = this.parseConcat(); + var ops = []; + + while(1) { + var tok = this.nextToken(); + + if(!tok) { + break; + } + else if(lib.indexOf(compareOps, tok.value) !== -1) { + ops.push(new nodes.CompareOperand(tok.lineno, + tok.colno, + this.parseConcat(), + tok.value)); + } + else { + this.pushToken(tok); + break; + } + } + + if(ops.length) { + return new nodes.Compare(ops[0].lineno, + ops[0].colno, + expr, + ops); + } + else { + return expr; + } + }, + + // finds the '~' for string concatenation + parseConcat: function(){ + var node = this.parseAdd(); + while(this.skipValue(lexer.TOKEN_TILDE, '~')) { + var node2 = this.parseAdd(); + node = new nodes.Concat(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseAdd: function() { + var node = this.parseSub(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '+')) { + var node2 = this.parseSub(); + node = new nodes.Add(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseSub: function() { + var node = this.parseMul(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '-')) { + var node2 = this.parseMul(); + node = new nodes.Sub(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseMul: function() { + var node = this.parseDiv(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '*')) { + var node2 = this.parseDiv(); + node = new nodes.Mul(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseDiv: function() { + var node = this.parseFloorDiv(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '/')) { + var node2 = this.parseFloorDiv(); + node = new nodes.Div(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseFloorDiv: function() { + var node = this.parseMod(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '//')) { + var node2 = this.parseMod(); + node = new nodes.FloorDiv(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseMod: function() { + var node = this.parsePow(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '%')) { + var node2 = this.parsePow(); + node = new nodes.Mod(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parsePow: function() { + var node = this.parseUnary(); + while(this.skipValue(lexer.TOKEN_OPERATOR, '**')) { + var node2 = this.parseUnary(); + node = new nodes.Pow(node.lineno, + node.colno, + node, + node2); + } + return node; + }, + + parseUnary: function(noFilters) { + var tok = this.peekToken(); + var node; + + if(this.skipValue(lexer.TOKEN_OPERATOR, '-')) { + node = new nodes.Neg(tok.lineno, + tok.colno, + this.parseUnary(true)); + } + else if(this.skipValue(lexer.TOKEN_OPERATOR, '+')) { + node = new nodes.Pos(tok.lineno, + tok.colno, + this.parseUnary(true)); + } + else { + node = this.parsePrimary(); + } + + if(!noFilters) { + node = this.parseFilter(node); + } + + return node; + }, + + parsePrimary: function (noPostfix) { + var tok = this.nextToken(); + var val; + var node = null; + + if(!tok) { + this.fail('expected expression, got end of file'); + } + else if(tok.type === lexer.TOKEN_STRING) { + val = tok.value; + } + else if(tok.type === lexer.TOKEN_INT) { + val = parseInt(tok.value, 10); + } + else if(tok.type === lexer.TOKEN_FLOAT) { + val = parseFloat(tok.value); + } + else if(tok.type === lexer.TOKEN_BOOLEAN) { + if(tok.value === 'true') { + val = true; + } + else if(tok.value === 'false') { + val = false; + } + else { + this.fail('invalid boolean: ' + tok.value, + tok.lineno, + tok.colno); + } + } + else if(tok.type === lexer.TOKEN_NONE) { + val = null; + } + else if (tok.type === lexer.TOKEN_REGEX) { + val = new RegExp(tok.value.body, tok.value.flags); + } + + if(val !== undefined) { + node = new nodes.Literal(tok.lineno, tok.colno, val); + } + else if(tok.type === lexer.TOKEN_SYMBOL) { + node = new nodes.Symbol(tok.lineno, tok.colno, tok.value); + + if(!noPostfix) { + node = this.parsePostfix(node); + } + } + else { + // See if it's an aggregate type, we need to push the + // current delimiter token back on + this.pushToken(tok); + node = this.parseAggregate(); + } + + if(node) { + return node; + } + else { + this.fail('unexpected token: ' + tok.value, + tok.lineno, + tok.colno); + } + }, + + parseFilterName: function() { + var tok = this.expect(lexer.TOKEN_SYMBOL); + var name = tok.value; + + while(this.skipValue(lexer.TOKEN_OPERATOR, '.')) { + name += '.' + this.expect(lexer.TOKEN_SYMBOL).value; + } + + return new nodes.Symbol(tok.lineno, tok.colno, name); + }, + + parseFilterArgs: function(node) { + if(this.peekToken().type === lexer.TOKEN_LEFT_PAREN) { + // Get a FunCall node and add the parameters to the + // filter + var call = this.parsePostfix(node); + return call.args.children; + } + return []; + }, + + parseFilter: function(node) { + while(this.skip(lexer.TOKEN_PIPE)) { + var name = this.parseFilterName(); + + node = new nodes.Filter( + name.lineno, + name.colno, + name, + new nodes.NodeList( + name.lineno, + name.colno, + [node].concat(this.parseFilterArgs(node)) + ) + ); + } + + return node; + }, + + parseFilterStatement: function() { + var filterTok = this.peekToken(); + if(!this.skipSymbol('filter')) { + this.fail('parseFilterStatement: expected filter'); + } + + var name = this.parseFilterName(); + var args = this.parseFilterArgs(name); + + this.advanceAfterBlockEnd(filterTok.value); + var body = new nodes.Capture( + name.lineno, + name.colno, + this.parseUntilBlocks('endfilter') + ); + this.advanceAfterBlockEnd(); + + var node = new nodes.Filter( + name.lineno, + name.colno, + name, + new nodes.NodeList( + name.lineno, + name.colno, + [body].concat(args) + ) + ); + + return new nodes.Output( + name.lineno, + name.colno, + [node] + ); + }, + + parseAggregate: function() { + var tok = this.nextToken(); + var node; + + switch(tok.type) { + case lexer.TOKEN_LEFT_PAREN: + node = new nodes.Group(tok.lineno, tok.colno); break; + case lexer.TOKEN_LEFT_BRACKET: + node = new nodes.Array(tok.lineno, tok.colno); break; + case lexer.TOKEN_LEFT_CURLY: + node = new nodes.Dict(tok.lineno, tok.colno); break; + default: + return null; + } + + while(1) { + var type = this.peekToken().type; + if(type === lexer.TOKEN_RIGHT_PAREN || + type === lexer.TOKEN_RIGHT_BRACKET || + type === lexer.TOKEN_RIGHT_CURLY) { + this.nextToken(); + break; + } + + if(node.children.length > 0) { + if(!this.skip(lexer.TOKEN_COMMA)) { + this.fail('parseAggregate: expected comma after expression', + tok.lineno, + tok.colno); + } + } + + if(node instanceof nodes.Dict) { + // TODO: check for errors + var key = this.parsePrimary(); + + // We expect a key/value pair for dicts, separated by a + // colon + if(!this.skip(lexer.TOKEN_COLON)) { + this.fail('parseAggregate: expected colon after dict key', + tok.lineno, + tok.colno); + } + + // TODO: check for errors + var value = this.parseExpression(); + node.addChild(new nodes.Pair(key.lineno, + key.colno, + key, + value)); + } + else { + // TODO: check for errors + var expr = this.parseExpression(); + node.addChild(expr); + } + } + + return node; + }, + + parseSignature: function(tolerant, noParens) { + var tok = this.peekToken(); + if(!noParens && tok.type !== lexer.TOKEN_LEFT_PAREN) { + if(tolerant) { + return null; + } + else { + this.fail('expected arguments', tok.lineno, tok.colno); + } + } + + if(tok.type === lexer.TOKEN_LEFT_PAREN) { + tok = this.nextToken(); + } + + var args = new nodes.NodeList(tok.lineno, tok.colno); + var kwargs = new nodes.KeywordArgs(tok.lineno, tok.colno); + var checkComma = false; + + while(1) { + tok = this.peekToken(); + if(!noParens && tok.type === lexer.TOKEN_RIGHT_PAREN) { + this.nextToken(); + break; + } + else if(noParens && tok.type === lexer.TOKEN_BLOCK_END) { + break; + } + + if(checkComma && !this.skip(lexer.TOKEN_COMMA)) { + this.fail('parseSignature: expected comma after expression', + tok.lineno, + tok.colno); + } + else { + var arg = this.parseExpression(); + + if(this.skipValue(lexer.TOKEN_OPERATOR, '=')) { + kwargs.addChild( + new nodes.Pair(arg.lineno, + arg.colno, + arg, + this.parseExpression()) + ); + } + else { + args.addChild(arg); + } + } + + checkComma = true; + } + + if(kwargs.children.length) { + args.addChild(kwargs); + } + + return args; + }, + + parseUntilBlocks: function(/* blockNames */) { + var prev = this.breakOnBlocks; + this.breakOnBlocks = lib.toArray(arguments); + + var ret = this.parse(); + + this.breakOnBlocks = prev; + return ret; + }, + + parseNodes: function () { + var tok; + var buf = []; + + while((tok = this.nextToken())) { + if(tok.type === lexer.TOKEN_DATA) { + var data = tok.value; + var nextToken = this.peekToken(); + var nextVal = nextToken && nextToken.value; + + // If the last token has "-" we need to trim the + // leading whitespace of the data. This is marked with + // the `dropLeadingWhitespace` variable. + if(this.dropLeadingWhitespace) { + // TODO: this could be optimized (don't use regex) + data = data.replace(/^\s*/, ''); + this.dropLeadingWhitespace = false; + } + + // Same for the succeeding block start token + if(nextToken && + ((nextToken.type === lexer.TOKEN_BLOCK_START && + nextVal.charAt(nextVal.length - 1) === '-') || + (nextToken.type === lexer.TOKEN_VARIABLE_START && + nextVal.charAt(this.tokens.tags.VARIABLE_START.length) + === '-') || + (nextToken.type === lexer.TOKEN_COMMENT && + nextVal.charAt(this.tokens.tags.COMMENT_START.length) + === '-'))) { + // TODO: this could be optimized (don't use regex) + data = data.replace(/\s*$/, ''); + } + + buf.push(new nodes.Output(tok.lineno, + tok.colno, + [new nodes.TemplateData(tok.lineno, + tok.colno, + data)])); + } + else if(tok.type === lexer.TOKEN_BLOCK_START) { + this.dropLeadingWhitespace = false; + var n = this.parseStatement(); + if(!n) { + break; + } + buf.push(n); + } + else if(tok.type === lexer.TOKEN_VARIABLE_START) { + var e = this.parseExpression(); + this.dropLeadingWhitespace = false; + this.advanceAfterVariableEnd(); + buf.push(new nodes.Output(tok.lineno, tok.colno, [e])); + } + else if(tok.type === lexer.TOKEN_COMMENT) { + this.dropLeadingWhitespace = tok.value.charAt( + tok.value.length - this.tokens.tags.COMMENT_END.length - 1 + ) === '-'; + } else { + // Ignore comments, otherwise this should be an error + this.fail('Unexpected token at top-level: ' + + tok.type, tok.lineno, tok.colno); + + } + } + + return buf; + }, + + parse: function() { + return new nodes.NodeList(0, 0, this.parseNodes()); + }, + + parseAsRoot: function() { + return new nodes.Root(0, 0, this.parseNodes()); + } + }); + + // var util = require('util'); + + // var l = lexer.lex('{%- if x -%}\n hello {% endif %}'); + // var t; + // while((t = l.nextToken())) { + // console.log(util.inspect(t)); + // } + + // var p = new Parser(lexer.lex('hello {% filter title %}' + + // 'Hello madam how are you' + + // '{% endfilter %}')); + // var n = p.parseAsRoot(); + // nodes.printNodes(n); + + module.exports = { + parse: function(src, extensions, opts) { + var p = new Parser(lexer.lex(src, opts)); + if (extensions !== undefined) { + p.extensions = extensions; + } + return p.parseAsRoot(); + } + }; + + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lib = __webpack_require__(1); + + var whitespaceChars = ' \n\t\r\u00A0'; + var delimChars = '()[]{}%*-+~/#,:|.<>=!'; + var intChars = '0123456789'; + + var BLOCK_START = '{%'; + var BLOCK_END = '%}'; + var VARIABLE_START = '{{'; + var VARIABLE_END = '}}'; + var COMMENT_START = '{#'; + var COMMENT_END = '#}'; + + var TOKEN_STRING = 'string'; + var TOKEN_WHITESPACE = 'whitespace'; + var TOKEN_DATA = 'data'; + var TOKEN_BLOCK_START = 'block-start'; + var TOKEN_BLOCK_END = 'block-end'; + var TOKEN_VARIABLE_START = 'variable-start'; + var TOKEN_VARIABLE_END = 'variable-end'; + var TOKEN_COMMENT = 'comment'; + var TOKEN_LEFT_PAREN = 'left-paren'; + var TOKEN_RIGHT_PAREN = 'right-paren'; + var TOKEN_LEFT_BRACKET = 'left-bracket'; + var TOKEN_RIGHT_BRACKET = 'right-bracket'; + var TOKEN_LEFT_CURLY = 'left-curly'; + var TOKEN_RIGHT_CURLY = 'right-curly'; + var TOKEN_OPERATOR = 'operator'; + var TOKEN_COMMA = 'comma'; + var TOKEN_COLON = 'colon'; + var TOKEN_TILDE = 'tilde'; + var TOKEN_PIPE = 'pipe'; + var TOKEN_INT = 'int'; + var TOKEN_FLOAT = 'float'; + var TOKEN_BOOLEAN = 'boolean'; + var TOKEN_NONE = 'none'; + var TOKEN_SYMBOL = 'symbol'; + var TOKEN_SPECIAL = 'special'; + var TOKEN_REGEX = 'regex'; + + function token(type, value, lineno, colno) { + return { + type: type, + value: value, + lineno: lineno, + colno: colno + }; + } + + function Tokenizer(str, opts) { + this.str = str; + this.index = 0; + this.len = str.length; + this.lineno = 0; + this.colno = 0; + + this.in_code = false; + + opts = opts || {}; + + var tags = opts.tags || {}; + this.tags = { + BLOCK_START: tags.blockStart || BLOCK_START, + BLOCK_END: tags.blockEnd || BLOCK_END, + VARIABLE_START: tags.variableStart || VARIABLE_START, + VARIABLE_END: tags.variableEnd || VARIABLE_END, + COMMENT_START: tags.commentStart || COMMENT_START, + COMMENT_END: tags.commentEnd || COMMENT_END + }; + + this.trimBlocks = !!opts.trimBlocks; + this.lstripBlocks = !!opts.lstripBlocks; + } + + Tokenizer.prototype.nextToken = function() { + var lineno = this.lineno; + var colno = this.colno; + var tok; + + if(this.in_code) { + // Otherwise, if we are in a block parse it as code + var cur = this.current(); + + if(this.is_finished()) { + // We have nothing else to parse + return null; + } + else if(cur === '"' || cur === '\'') { + // We've hit a string + return token(TOKEN_STRING, this.parseString(cur), lineno, colno); + } + else if((tok = this._extract(whitespaceChars))) { + // We hit some whitespace + return token(TOKEN_WHITESPACE, tok, lineno, colno); + } + else if((tok = this._extractString(this.tags.BLOCK_END)) || + (tok = this._extractString('-' + this.tags.BLOCK_END))) { + // Special check for the block end tag + // + // It is a requirement that start and end tags are composed of + // delimiter characters (%{}[] etc), and our code always + // breaks on delimiters so we can assume the token parsing + // doesn't consume these elsewhere + this.in_code = false; + if(this.trimBlocks) { + cur = this.current(); + if(cur === '\n') { + // Skip newline + this.forward(); + }else if(cur === '\r'){ + // Skip CRLF newline + this.forward(); + cur = this.current(); + if(cur === '\n'){ + this.forward(); + }else{ + // Was not a CRLF, so go back + this.back(); + } + } + } + return token(TOKEN_BLOCK_END, tok, lineno, colno); + } + else if((tok = this._extractString(this.tags.VARIABLE_END)) || + (tok = this._extractString('-' + this.tags.VARIABLE_END))) { + // Special check for variable end tag (see above) + this.in_code = false; + return token(TOKEN_VARIABLE_END, tok, lineno, colno); + } + else if (cur === 'r' && this.str.charAt(this.index + 1) === '/') { + // Skip past 'r/'. + this.forwardN(2); + + // Extract until the end of the regex -- / ends it, \/ does not. + var regexBody = ''; + while (!this.is_finished()) { + if (this.current() === '/' && this.previous() !== '\\') { + this.forward(); + break; + } else { + regexBody += this.current(); + this.forward(); + } + } + + // Check for flags. + // The possible flags are according to https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp) + var POSSIBLE_FLAGS = ['g', 'i', 'm', 'y']; + var regexFlags = ''; + while (!this.is_finished()) { + var isCurrentAFlag = POSSIBLE_FLAGS.indexOf(this.current()) !== -1; + if (isCurrentAFlag) { + regexFlags += this.current(); + this.forward(); + } else { + break; + } + } + + return token(TOKEN_REGEX, {body: regexBody, flags: regexFlags}, lineno, colno); + } + else if(delimChars.indexOf(cur) !== -1) { + // We've hit a delimiter (a special char like a bracket) + this.forward(); + var complexOps = ['==', '===', '!=', '!==', '<=', '>=', '//', '**']; + var curComplex = cur + this.current(); + var type; + + if(lib.indexOf(complexOps, curComplex) !== -1) { + this.forward(); + cur = curComplex; + + // See if this is a strict equality/inequality comparator + if(lib.indexOf(complexOps, curComplex + this.current()) !== -1) { + cur = curComplex + this.current(); + this.forward(); + } + } + + switch(cur) { + case '(': type = TOKEN_LEFT_PAREN; break; + case ')': type = TOKEN_RIGHT_PAREN; break; + case '[': type = TOKEN_LEFT_BRACKET; break; + case ']': type = TOKEN_RIGHT_BRACKET; break; + case '{': type = TOKEN_LEFT_CURLY; break; + case '}': type = TOKEN_RIGHT_CURLY; break; + case ',': type = TOKEN_COMMA; break; + case ':': type = TOKEN_COLON; break; + case '~': type = TOKEN_TILDE; break; + case '|': type = TOKEN_PIPE; break; + default: type = TOKEN_OPERATOR; + } + + return token(type, cur, lineno, colno); + } + else { + // We are not at whitespace or a delimiter, so extract the + // text and parse it + tok = this._extractUntil(whitespaceChars + delimChars); + + if(tok.match(/^[-+]?[0-9]+$/)) { + if(this.current() === '.') { + this.forward(); + var dec = this._extract(intChars); + return token(TOKEN_FLOAT, tok + '.' + dec, lineno, colno); + } + else { + return token(TOKEN_INT, tok, lineno, colno); + } + } + else if(tok.match(/^(true|false)$/)) { + return token(TOKEN_BOOLEAN, tok, lineno, colno); + } + else if(tok === 'none') { + return token(TOKEN_NONE, tok, lineno, colno); + } + else if(tok) { + return token(TOKEN_SYMBOL, tok, lineno, colno); + } + else { + throw new Error('Unexpected value while parsing: ' + tok); + } + } + } + else { + // Parse out the template text, breaking on tag + // delimiters because we need to look for block/variable start + // tags (don't use the full delimChars for optimization) + var beginChars = (this.tags.BLOCK_START.charAt(0) + + this.tags.VARIABLE_START.charAt(0) + + this.tags.COMMENT_START.charAt(0) + + this.tags.COMMENT_END.charAt(0)); + + if(this.is_finished()) { + return null; + } + else if((tok = this._extractString(this.tags.BLOCK_START + '-')) || + (tok = this._extractString(this.tags.BLOCK_START))) { + this.in_code = true; + return token(TOKEN_BLOCK_START, tok, lineno, colno); + } + else if((tok = this._extractString(this.tags.VARIABLE_START + '-')) || + (tok = this._extractString(this.tags.VARIABLE_START))) { + this.in_code = true; + return token(TOKEN_VARIABLE_START, tok, lineno, colno); + } + else { + tok = ''; + var data; + var in_comment = false; + + if(this._matches(this.tags.COMMENT_START)) { + in_comment = true; + tok = this._extractString(this.tags.COMMENT_START); + } + + // Continually consume text, breaking on the tag delimiter + // characters and checking to see if it's a start tag. + // + // We could hit the end of the template in the middle of + // our looping, so check for the null return value from + // _extractUntil + while((data = this._extractUntil(beginChars)) !== null) { + tok += data; + + if((this._matches(this.tags.BLOCK_START) || + this._matches(this.tags.VARIABLE_START) || + this._matches(this.tags.COMMENT_START)) && + !in_comment) { + if(this.lstripBlocks && + this._matches(this.tags.BLOCK_START) && + this.colno > 0 && + this.colno <= tok.length) { + var lastLine = tok.slice(-this.colno); + if(/^\s+$/.test(lastLine)) { + // Remove block leading whitespace from beginning of the string + tok = tok.slice(0, -this.colno); + if(!tok.length) { + // All data removed, collapse to avoid unnecessary nodes + // by returning next token (block start) + return this.nextToken(); + } + } + } + // If it is a start tag, stop looping + break; + } + else if(this._matches(this.tags.COMMENT_END)) { + if(!in_comment) { + throw new Error('unexpected end of comment'); + } + tok += this._extractString(this.tags.COMMENT_END); + break; + } + else { + // It does not match any tag, so add the character and + // carry on + tok += this.current(); + this.forward(); + } + } + + if(data === null && in_comment) { + throw new Error('expected end of comment, got end of file'); + } + + return token(in_comment ? TOKEN_COMMENT : TOKEN_DATA, + tok, + lineno, + colno); + } + } + + throw new Error('Could not parse text'); + }; + + Tokenizer.prototype.parseString = function(delimiter) { + this.forward(); + + var str = ''; + + while(!this.is_finished() && this.current() !== delimiter) { + var cur = this.current(); + + if(cur === '\\') { + this.forward(); + switch(this.current()) { + case 'n': str += '\n'; break; + case 't': str += '\t'; break; + case 'r': str += '\r'; break; + default: + str += this.current(); + } + this.forward(); + } + else { + str += cur; + this.forward(); + } + } + + this.forward(); + return str; + }; + + Tokenizer.prototype._matches = function(str) { + if(this.index + str.length > this.len) { + return null; + } + + var m = this.str.slice(this.index, this.index + str.length); + return m === str; + }; + + Tokenizer.prototype._extractString = function(str) { + if(this._matches(str)) { + this.index += str.length; + return str; + } + return null; + }; + + Tokenizer.prototype._extractUntil = function(charString) { + // Extract all non-matching chars, with the default matching set + // to everything + return this._extractMatching(true, charString || ''); + }; + + Tokenizer.prototype._extract = function(charString) { + // Extract all matching chars (no default, so charString must be + // explicit) + return this._extractMatching(false, charString); + }; + + Tokenizer.prototype._extractMatching = function (breakOnMatch, charString) { + // Pull out characters until a breaking char is hit. + // If breakOnMatch is false, a non-matching char stops it. + // If breakOnMatch is true, a matching char stops it. + + if(this.is_finished()) { + return null; + } + + var first = charString.indexOf(this.current()); + + // Only proceed if the first character doesn't meet our condition + if((breakOnMatch && first === -1) || + (!breakOnMatch && first !== -1)) { + var t = this.current(); + this.forward(); + + // And pull out all the chars one at a time until we hit a + // breaking char + var idx = charString.indexOf(this.current()); + + while(((breakOnMatch && idx === -1) || + (!breakOnMatch && idx !== -1)) && !this.is_finished()) { + t += this.current(); + this.forward(); + + idx = charString.indexOf(this.current()); + } + + return t; + } + + return ''; + }; + + Tokenizer.prototype._extractRegex = function(regex) { + var matches = this.currentStr().match(regex); + if(!matches) { + return null; + } + + // Move forward whatever was matched + this.forwardN(matches[0].length); + + return matches; + }; + + Tokenizer.prototype.is_finished = function() { + return this.index >= this.len; + }; + + Tokenizer.prototype.forwardN = function(n) { + for(var i=0; i 0) || !inline) { + for(var j=0; j argNames.length) { + args = Array.prototype.slice.call(arguments, 0, argNames.length); + + // Positional arguments that should be passed in as + // keyword arguments (essentially default values) + var vals = Array.prototype.slice.call(arguments, args.length, argCount); + for(i = 0; i < vals.length; i++) { + if(i < kwargNames.length) { + kwargs[kwargNames[i]] = vals[i]; + } + } + + args.push(kwargs); + } + else if(argCount < argNames.length) { + args = Array.prototype.slice.call(arguments, 0, argCount); + + for(i = argCount; i < argNames.length; i++) { + var arg = argNames[i]; + + // Keyword arguments that should be passed as + // positional arguments, i.e. the caller explicitly + // used the name of a positional arg + args.push(kwargs[arg]); + delete kwargs[arg]; + } + + args.push(kwargs); + } + else { + args = arguments; + } + + return func.apply(this, args); + }; + } + + function makeKeywordArgs(obj) { + obj.__keywords = true; + return obj; + } + + function getKeywordArgs(args) { + var len = args.length; + if(len) { + var lastArg = args[len - 1]; + if(lastArg && lastArg.hasOwnProperty('__keywords')) { + return lastArg; + } + } + return {}; + } + + function numArgs(args) { + var len = args.length; + if(len === 0) { + return 0; + } + + var lastArg = args[len - 1]; + if(lastArg && lastArg.hasOwnProperty('__keywords')) { + return len - 1; + } + else { + return len; + } + } + + // A SafeString object indicates that the string should not be + // autoescaped. This happens magically because autoescaping only + // occurs on primitive string objects. + function SafeString(val) { + if(typeof val !== 'string') { + return val; + } + + this.val = val; + this.length = val.length; + } + + SafeString.prototype = Object.create(String.prototype, { + length: { writable: true, configurable: true, value: 0 } + }); + SafeString.prototype.valueOf = function() { + return this.val; + }; + SafeString.prototype.toString = function() { + return this.val; + }; + + function copySafeness(dest, target) { + if(dest instanceof SafeString) { + return new SafeString(target); + } + return target.toString(); + } + + function markSafe(val) { + var type = typeof val; + + if(type === 'string') { + return new SafeString(val); + } + else if(type !== 'function') { + return val; + } + else { + return function() { + var ret = val.apply(this, arguments); + + if(typeof ret === 'string') { + return new SafeString(ret); + } + + return ret; + }; + } + } + + function suppressValue(val, autoescape) { + val = (val !== undefined && val !== null) ? val : ''; + + if(autoescape && !(val instanceof SafeString)) { + val = lib.escape(val.toString()); + } + + return val; + } + + function ensureDefined(val, lineno, colno) { + if(val === null || val === undefined) { + throw new lib.TemplateError( + 'attempted to output null or undefined value', + lineno + 1, + colno + 1 + ); + } + return val; + } + + function memberLookup(obj, val) { + obj = obj || {}; + + if(typeof obj[val] === 'function') { + return function() { + return obj[val].apply(obj, arguments); + }; + } + + return obj[val]; + } + + function callWrap(obj, name, context, args) { + if(!obj) { + throw new Error('Unable to call `' + name + '`, which is undefined or falsey'); + } + else if(typeof obj !== 'function') { + throw new Error('Unable to call `' + name + '`, which is not a function'); + } + + // jshint validthis: true + return obj.apply(context, args); + } + + function contextOrFrameLookup(context, frame, name) { + var val = frame.lookup(name); + return (val !== undefined) ? + val : + context.lookup(name); + } + + function handleError(error, lineno, colno) { + if(error.lineno) { + return error; + } + else { + return new lib.TemplateError(error, lineno, colno); + } + } + + function asyncEach(arr, dimen, iter, cb) { + if(lib.isArray(arr)) { + var len = arr.length; + + lib.asyncIter(arr, function(item, i, next) { + switch(dimen) { + case 1: iter(item, i, len, next); break; + case 2: iter(item[0], item[1], i, len, next); break; + case 3: iter(item[0], item[1], item[2], i, len, next); break; + default: + item.push(i, next); + iter.apply(this, item); + } + }, cb); + } + else { + lib.asyncFor(arr, function(key, val, i, len, next) { + iter(key, val, i, len, next); + }, cb); + } + } + + function asyncAll(arr, dimen, func, cb) { + var finished = 0; + var len, i; + var outputArr; + + function done(i, output) { + finished++; + outputArr[i] = output; + + if(finished === len) { + cb(null, outputArr.join('')); + } + } + + if(lib.isArray(arr)) { + len = arr.length; + outputArr = new Array(len); + + if(len === 0) { + cb(null, ''); + } + else { + for(i = 0; i < arr.length; i++) { + var item = arr[i]; + + switch(dimen) { + case 1: func(item, i, len, done); break; + case 2: func(item[0], item[1], i, len, done); break; + case 3: func(item[0], item[1], item[2], i, len, done); break; + default: + item.push(i, done); + // jshint validthis: true + func.apply(this, item); + } + } + } + } + else { + var keys = lib.keys(arr); + len = keys.length; + outputArr = new Array(len); + + if(len === 0) { + cb(null, ''); + } + else { + for(i = 0; i < keys.length; i++) { + var k = keys[i]; + func(k, arr[k], i, len, done); + } + } + } + } + + module.exports = { + Frame: Frame, + makeMacro: makeMacro, + makeKeywordArgs: makeKeywordArgs, + numArgs: numArgs, + suppressValue: suppressValue, + ensureDefined: ensureDefined, + memberLookup: memberLookup, + contextOrFrameLookup: contextOrFrameLookup, + callWrap: callWrap, + handleError: handleError, + isArray: lib.isArray, + keys: lib.keys, + SafeString: SafeString, + copySafeness: copySafeness, + markSafe: markSafe, + asyncEach: asyncEach, + asyncAll: asyncAll, + inOperator: lib.inOperator + }; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lib = __webpack_require__(1); + var r = __webpack_require__(12); + + function normalize(value, defaultValue) { + if(value === null || value === undefined || value === false) { + return defaultValue; + } + return value; + } + + var filters = { + abs: function(n) { + return Math.abs(n); + }, + + batch: function(arr, linecount, fill_with) { + var i; + var res = []; + var tmp = []; + + for(i = 0; i < arr.length; i++) { + if(i % linecount === 0 && tmp.length) { + res.push(tmp); + tmp = []; + } + + tmp.push(arr[i]); + } + + if(tmp.length) { + if(fill_with) { + for(i = tmp.length; i < linecount; i++) { + tmp.push(fill_with); + } + } + + res.push(tmp); + } + + return res; + }, + + capitalize: function(str) { + str = normalize(str, ''); + var ret = str.toLowerCase(); + return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1)); + }, + + center: function(str, width) { + str = normalize(str, ''); + width = width || 80; + + if(str.length >= width) { + return str; + } + + var spaces = width - str.length; + var pre = lib.repeat(' ', spaces/2 - spaces % 2); + var post = lib.repeat(' ', spaces/2); + return r.copySafeness(str, pre + str + post); + }, + + 'default': function(val, def, bool) { + if(bool) { + return val ? val : def; + } + else { + return (val !== undefined) ? val : def; + } + }, + + dictsort: function(val, case_sensitive, by) { + if (!lib.isObject(val)) { + throw new lib.TemplateError('dictsort filter: val must be an object'); + } + + var array = []; + for (var k in val) { + // deliberately include properties from the object's prototype + array.push([k,val[k]]); + } + + var si; + if (by === undefined || by === 'key') { + si = 0; + } else if (by === 'value') { + si = 1; + } else { + throw new lib.TemplateError( + 'dictsort filter: You can only sort by either key or value'); + } + + array.sort(function(t1, t2) { + var a = t1[si]; + var b = t2[si]; + + if (!case_sensitive) { + if (lib.isString(a)) { + a = a.toUpperCase(); + } + if (lib.isString(b)) { + b = b.toUpperCase(); + } + } + + return a > b ? 1 : (a === b ? 0 : -1); + }); + + return array; + }, + + dump: function(obj, spaces) { + return JSON.stringify(obj, null, spaces); + }, + + escape: function(str) { + if(str instanceof r.SafeString) { + return str; + } + str = (str === null || str === undefined) ? '' : str; + return r.markSafe(lib.escape(str.toString())); + }, + + safe: function(str) { + if (str instanceof r.SafeString) { + return str; + } + str = (str === null || str === undefined) ? '' : str; + return r.markSafe(str.toString()); + }, + + first: function(arr) { + return arr[0]; + }, + + groupby: function(arr, attr) { + return lib.groupBy(arr, attr); + }, + + indent: function(str, width, indentfirst) { + str = normalize(str, ''); + + if (str === '') return ''; + + width = width || 4; + var res = ''; + var lines = str.split('\n'); + var sp = lib.repeat(' ', width); + + for(var i=0; i\n')); + }, + + random: function(arr) { + return arr[Math.floor(Math.random() * arr.length)]; + }, + + rejectattr: function(arr, attr) { + return arr.filter(function (item) { + return !item[attr]; + }); + }, + + selectattr: function(arr, attr) { + return arr.filter(function (item) { + return !!item[attr]; + }); + }, + + replace: function(str, old, new_, maxCount) { + var originalStr = str; + + if (old instanceof RegExp) { + return str.replace(old, new_); + } + + if(typeof maxCount === 'undefined'){ + maxCount = -1; + } + + var res = ''; // Output + + // Cast Numbers in the search term to string + if(typeof old === 'number'){ + old = old + ''; + } + else if(typeof old !== 'string') { + // If it is something other than number or string, + // return the original string + return str; + } + + // Cast numbers in the replacement to string + if(typeof str === 'number'){ + str = str + ''; + } + + // If by now, we don't have a string, throw it back + if(typeof str !== 'string' && !(str instanceof r.SafeString)){ + return str; + } + + // ShortCircuits + if(old === ''){ + // Mimic the python behaviour: empty string is replaced + // by replacement e.g. "abc"|replace("", ".") -> .a.b.c. + res = new_ + str.split('').join(new_) + new_; + return r.copySafeness(str, res); + } + + var nextIndex = str.indexOf(old); + // if # of replacements to perform is 0, or the string to does + // not contain the old value, return the string + if(maxCount === 0 || nextIndex === -1){ + return str; + } + + var pos = 0; + var count = 0; // # of replacements made + + while(nextIndex > -1 && (maxCount === -1 || count < maxCount)){ + // Grab the next chunk of src string and add it with the + // replacement, to the result + res += str.substring(pos, nextIndex) + new_; + // Increment our pointer in the src string + pos = nextIndex + old.length; + count++; + // See if there are any more replacements to be made + nextIndex = str.indexOf(old, pos); + } + + // We've either reached the end, or done the max # of + // replacements, tack on any remaining string + if(pos < str.length) { + res += str.substring(pos); + } + + return r.copySafeness(originalStr, res); + }, + + reverse: function(val) { + var arr; + if(lib.isString(val)) { + arr = filters.list(val); + } + else { + // Copy it + arr = lib.map(val, function(v) { return v; }); + } + + arr.reverse(); + + if(lib.isString(val)) { + return r.copySafeness(val, arr.join('')); + } + return arr; + }, + + round: function(val, precision, method) { + precision = precision || 0; + var factor = Math.pow(10, precision); + var rounder; + + if(method === 'ceil') { + rounder = Math.ceil; + } + else if(method === 'floor') { + rounder = Math.floor; + } + else { + rounder = Math.round; + } + + return rounder(val * factor) / factor; + }, + + slice: function(arr, slices, fillWith) { + var sliceLength = Math.floor(arr.length / slices); + var extra = arr.length % slices; + var offset = 0; + var res = []; + + for(var i=0; i= extra) { + slice.push(fillWith); + } + res.push(slice); + } + + return res; + }, + + sum: function(arr, attr, start) { + var sum = 0; + + if(typeof start === 'number'){ + sum += start; + } + + if(attr) { + arr = lib.map(arr, function(v) { + return v[attr]; + }); + } + + for(var i = 0; i < arr.length; i++) { + sum += arr[i]; + } + + return sum; + }, + + sort: r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function(arr, reverse, caseSens, attr) { + // Copy it + arr = lib.map(arr, function(v) { return v; }); + + arr.sort(function(a, b) { + var x, y; + + if(attr) { + x = a[attr]; + y = b[attr]; + } + else { + x = a; + y = b; + } + + if(!caseSens && lib.isString(x) && lib.isString(y)) { + x = x.toLowerCase(); + y = y.toLowerCase(); + } + + if(x < y) { + return reverse ? 1 : -1; + } + else if(x > y) { + return reverse ? -1: 1; + } + else { + return 0; + } + }); + + return arr; + }), + + string: function(obj) { + return r.copySafeness(obj, obj); + }, + + striptags: function(input, preserve_linebreaks) { + input = normalize(input, ''); + preserve_linebreaks = preserve_linebreaks || false; + var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi; + var trimmedInput = filters.trim(input.replace(tags, '')); + var res = ''; + if (preserve_linebreaks) { + res = trimmedInput + .replace(/^ +| +$/gm, '') // remove leading and trailing spaces + .replace(/ +/g, ' ') // squash adjacent spaces + .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF) + .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks + } else { + res = trimmedInput.replace(/\s+/gi, ' '); + } + return r.copySafeness(input, res); + }, + + title: function(str) { + str = normalize(str, ''); + var words = str.split(' '); + for(var i = 0; i < words.length; i++) { + words[i] = filters.capitalize(words[i]); + } + return r.copySafeness(str, words.join(' ')); + }, + + trim: function(str) { + return r.copySafeness(str, str.replace(/^\s*|\s*$/g, '')); + }, + + truncate: function(input, length, killwords, end) { + var orig = input; + input = normalize(input, ''); + length = length || 255; + + if (input.length <= length) + return input; + + if (killwords) { + input = input.substring(0, length); + } else { + var idx = input.lastIndexOf(' ', length); + if(idx === -1) { + idx = length; + } + + input = input.substring(0, idx); + } + + input += (end !== undefined && end !== null) ? end : '...'; + return r.copySafeness(orig, input); + }, + + upper: function(str) { + str = normalize(str, ''); + return str.toUpperCase(); + }, + + urlencode: function(obj) { + var enc = encodeURIComponent; + if (lib.isString(obj)) { + return enc(obj); + } else { + var parts; + if (lib.isArray(obj)) { + parts = obj.map(function(item) { + return enc(item[0]) + '=' + enc(item[1]); + }); + } else { + parts = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + parts.push(enc(k) + '=' + enc(obj[k])); + } + } + } + return parts.join('&'); + } + }, + + urlize: function(str, length, nofollow) { + if (isNaN(length)) length = Infinity; + + var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : ''); + + // For the jinja regexp, see + // https://github.com/mitsuhiko/jinja2/blob/f15b814dcba6aa12bc74d1f7d0c881d55f7126be/jinja2/utils.py#L20-L23 + var puncRE = /^(?:\(|<|<)?(.*?)(?:\.|,|\)|\n|>)?$/; + // from http://blog.gerv.net/2011/05/html5_email_address_regexp/ + var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i; + var httpHttpsRE = /^https?:\/\/.*$/; + var wwwRE = /^www\./; + var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/; + + var words = str.split(/(\s+)/).filter(function(word) { + // If the word has no length, bail. This can happen for str with + // trailing whitespace. + return word && word.length; + }).map(function(word) { + var matches = word.match(puncRE); + var possibleUrl = matches && matches[1] || word; + + // url that starts with http or https + if (httpHttpsRE.test(possibleUrl)) + return '' + possibleUrl.substr(0, length) + ''; + + // url that starts with www. + if (wwwRE.test(possibleUrl)) + return '' + possibleUrl.substr(0, length) + ''; + + // an email address of the form username@domain.tld + if (emailRE.test(possibleUrl)) + return '' + possibleUrl + ''; + + // url that ends in .com, .org or .net that is not an email address + if (tldRE.test(possibleUrl)) + return '' + possibleUrl.substr(0, length) + ''; + + return word; + + }); + + return words.join(''); + }, + + wordcount: function(str) { + str = normalize(str, ''); + var words = (str) ? str.match(/\w+/g) : null; + return (words) ? words.length : null; + }, +// CUSTOM FILTER + dateFormater:function(data){ + return moment(data,"YYYY-mm-DD").format("mm-DD-YYYY"); + }, + dateFormatertextbox:function(data){ + return moment(data,"DD/mm/YYYY").format("mm-DD-YYYY"); + }, + + timestampConvert:function(datas){ + // TIMESTAMP TO DATE + if(datas != undefined || datas!= null){ + return moment.unix(datas/1000).format("MM-DD-YYYY"); + } + + }, + + timestampToTime:function(data){ + // TIMESTAMP TO TIME CONVERTION + return moment.unix(data/1000).format("HH:mm"); + }, + + 'float': function(val, def) { + var res = parseFloat(val); + return isNaN(res) ? def : res; + }, + + 'int': function(val, def) { + var res = parseInt(val, 10); + return isNaN(res) ? def : res; + } + }; + + // Aliases + filters.d = filters['default']; + filters.e = filters.escape; + + module.exports = filters; + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Loader = __webpack_require__(15); + var PrecompiledLoader = __webpack_require__(16); + + var WebLoader = Loader.extend({ + init: function(baseURL, opts) { + this.baseURL = baseURL || '.'; + opts = opts || {}; + + // By default, the cache is turned off because there's no way + // to "watch" templates over HTTP, so they are re-downloaded + // and compiled each time. (Remember, PRECOMPILE YOUR + // TEMPLATES in production!) + this.useCache = !!opts.useCache; + + // We default `async` to false so that the simple synchronous + // API can be used when you aren't doing anything async in + // your templates (which is most of the time). This performs a + // sync ajax request, but that's ok because it should *only* + // happen in development. PRECOMPILE YOUR TEMPLATES. + this.async = !!opts.async; + }, + + resolve: function(from, to) { // jshint ignore:line + throw new Error('relative templates not support in the browser yet'); + }, + + getSource: function(name, cb) { + var useCache = this.useCache; + var result; + this.fetch(this.baseURL + '/' + name, function(err, src) { + if(err) { + if(cb) { + cb(err.content); + } else { + if (err.status === 404) { + result = null; + } else { + throw err.content; + } + } + } + else { + result = { src: src, + path: name, + noCache: !useCache }; + if(cb) { + cb(null, result); + } + } + }); + + // if this WebLoader isn't running asynchronously, the + // fetch above would actually run sync and we'll have a + // result here + return result; + }, + + fetch: function(url, cb) { + // Only in the browser please + var ajax; + var loading = true; + + if(window.XMLHttpRequest) { // Mozilla, Safari, ... + ajax = new XMLHttpRequest(); + } + else if(window.ActiveXObject) { // IE 8 and older + /* global ActiveXObject */ + ajax = new ActiveXObject('Microsoft.XMLHTTP'); + } + + ajax.onreadystatechange = function() { + if(ajax.readyState === 4 && loading) { + loading = false; + if(ajax.status === 0 || ajax.status === 200) { + cb(null, ajax.responseText); + } + else { + cb({ status: ajax.status, content: ajax.responseText }); + } + } + }; + + url += (url.indexOf('?') === -1 ? '?' : '&') + 's=' + + (new Date().getTime()); + + ajax.open('GET', url, this.async); + ajax.send(); + } + }); + + module.exports = { + WebLoader: WebLoader, + PrecompiledLoader: PrecompiledLoader + }; + + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var path = __webpack_require__(3); + var Obj = __webpack_require__(6); + var lib = __webpack_require__(1); + + var Loader = Obj.extend({ + on: function(name, func) { + this.listeners = this.listeners || {}; + this.listeners[name] = this.listeners[name] || []; + this.listeners[name].push(func); + }, + + emit: function(name /*, arg1, arg2, ...*/) { + var args = Array.prototype.slice.call(arguments, 1); + + if(this.listeners && this.listeners[name]) { + lib.each(this.listeners[name], function(listener) { + listener.apply(null, args); + }); + } + }, + + resolve: function(from, to) { + return path.resolve(path.dirname(from), to); + }, + + isRelative: function(filename) { + return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0); + } + }); + + module.exports = Loader; + + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Loader = __webpack_require__(15); + + var PrecompiledLoader = Loader.extend({ + init: function(compiledTemplates) { + this.precompiled = compiledTemplates || {}; + }, + + getSource: function(name) { + if (this.precompiled[name]) { + return { + src: { type: 'code', + obj: this.precompiled[name] }, + path: name + }; + } + return null; + } + }); + + module.exports = PrecompiledLoader; + + +/***/ }, +/* 17 */ +/***/ function(module, exports) { + + 'use strict'; + + function cycler(items) { + var index = -1; + + return { + current: null, + reset: function() { + index = -1; + this.current = null; + }, + + next: function() { + index++; + if(index >= items.length) { + index = 0; + } + + this.current = items[index]; + return this.current; + }, + }; + + } + + function joiner(sep) { + sep = sep || ','; + var first = true; + + return function() { + var val = first ? '' : sep; + first = false; + return val; + }; + } + + // Making this a function instead so it returns a new object + // each time it's called. That way, if something like an environment + // uses it, they will each have their own copy. + function globals() { + return { + range: function(start, stop, step) { + if(typeof stop === 'undefined') { + stop = start; + start = 0; + step = 1; + } + else if(!step) { + step = 1; + } + + var arr = []; + var i; + if (step > 0) { + for (i=start; istop; i+=step) { + arr.push(i); + } + } + return arr; + }, + + // lipsum: function(n, html, min, max) { + // }, + + cycler: function() { + return cycler(Array.prototype.slice.call(arguments)); + }, + + joiner: function(sep) { + return joiner(sep); + } + }; + } + + module.exports = globals; + + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(setImmediate, process) {// MIT license (by Elan Shanker). + (function(globals) { + 'use strict'; + + var executeSync = function(){ + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'function'){ + args[0].apply(null, args.splice(1)); + } + }; + + var executeAsync = function(fn){ + if (typeof setImmediate === 'function') { + setImmediate(fn); + } else if (typeof process !== 'undefined' && process.nextTick) { + process.nextTick(fn); + } else { + setTimeout(fn, 0); + } + }; + + var makeIterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + var _isArray = Array.isArray || function(maybeArray){ + return Object.prototype.toString.call(maybeArray) === '[object Array]'; + }; + + var waterfall = function (tasks, callback, forceAsync) { + var nextTick = forceAsync ? executeAsync : executeSync; + callback = callback || function () {}; + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } else { + args.push(callback); + } + nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(makeIterator(tasks))(); + }; + + if (true) { + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () { + return waterfall; + }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // RequireJS + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = waterfall; // CommonJS + } else { + globals.waterfall = waterfall; //