diff --git a/README.rst b/README.rst index 4f9a3f7..9f347e8 100644 --- a/README.rst +++ b/README.rst @@ -367,3 +367,34 @@ the dispatcher invokes ``certidude`` in order to generate RSA keys, submit CSR, fetch signed certificate, create NetworkManager configuration for the VPN connection and finally to bring up the VPN tunnel as well. + + +Development +----------- + +Clone the repository: + +.. code:: bash + + git clone https://github.com/laurivosandi/certidude + cd certidude + +To generate templates: + +.. code:: bash + + apt-get install npm nodejs + npm install nunjucks + nunjucks-precompile --include "\\.html$" --include "\\.svg" certidude/static/ > certidude/static/js/templates.js + +To run from source tree: + +.. code:: bash + + PYTHONPATH=. KRB5_KTNAME=/etc/certidude/server.keytab LANG=C.UTF-8 python3 misc/certidude + +To install the package from the source: + +.. code:: bash + + python3 setup.py install --single-version-externally-managed --root / diff --git a/certidude/static/index.html b/certidude/static/index.html index ed05e61..f677127 100644 --- a/certidude/static/index.html +++ b/certidude/static/index.html @@ -6,7 +6,8 @@ Certidude server - + + diff --git a/certidude/static/js/certidude.js b/certidude/static/js/certidude.js index 9edcdbe..533e43d 100644 --- a/certidude/static/js/certidude.js +++ b/certidude/static/js/certidude.js @@ -50,7 +50,7 @@ function onLogEntry (e) { var entry = JSON.parse(e.data); if ($("#log_level_" + entry.severity).prop("checked")) { console.info("Received log entry:", entry); - $("#log_entries").prepend(nunjucks.render("logentry.html", { + $("#log_entries").prepend(nunjucks.render("views/logentry.html", { entry: { created: new Date(entry.created).toLocaleString(), message: entry.message, @@ -69,7 +69,7 @@ function onRequestSubmitted(e) { success: function(request, status, xhr) { console.info(request); $("#pending_requests").prepend( - nunjucks.render('request.html', { request: request })); + nunjucks.render('views/request.html', { request: request })); } }); } @@ -83,7 +83,7 @@ function onClientUp(e) { console.log("Adding security association:" + e.data); var lease = JSON.parse(e.data); var $status = $("#signed_certificates [data-dn='" + lease.identity + "'] .status"); - $status.html(nunjucks.render('status.html', { + $status.html(nunjucks.render('views/status.html', { lease: { address: lease.address, identity: lease.identity, @@ -96,7 +96,7 @@ function onClientDown(e) { console.log("Removing security association:" + e.data); var lease = JSON.parse(e.data); var $status = $("#signed_certificates [data-dn='" + lease.identity + "'] .status"); - $status.html(nunjucks.render('status.html', { + $status.html(nunjucks.render('views/status.html', { lease: { address: lease.address, identity: lease.identity, @@ -116,7 +116,7 @@ function onRequestSigned(e) { success: function(certificate, status, xhr) { console.info(certificate); $("#signed_certificates").prepend( - nunjucks.render('signed.html', { certificate: certificate })); + nunjucks.render('views/signed.html', { certificate: certificate })); } }); } @@ -172,7 +172,7 @@ $(document).ready(function() { } else { var msg = { title: "Error " + response.status, description: response.statusText } } - $("#container").html(nunjucks.render('error.html', { message: msg })); + $("#container").html(nunjucks.render('views/error.html', { message: msg })); }, success: function(session, status, xhr) { console.info("Opening EventSource from:", session.event_channel); @@ -197,7 +197,7 @@ $(document).ready(function() { /** * Render authority views **/ - $("#container").html(nunjucks.render('authority.html', { session: session, window: window })); + $("#container").html(nunjucks.render('views/authority.html', { session: session, window: window })); console.info("Swtiching to requests section"); $("section").hide(); $("section#requests").show(); @@ -239,7 +239,7 @@ $(document).ready(function() { dataType: "json", success: function(configuration, status, xhr) { console.info("Appending " + configuration.length + " configuration items"); - $("#config").html(nunjucks.render('configuration.html', { configuration:configuration})); + $("#config").html(nunjucks.render('views/configuration.html', { configuration:configuration})); /** * Fetch tags for certificates */ @@ -278,7 +278,7 @@ $(document).ready(function() { console.info("Detected rogue client:", leases[j]); continue; } - $status.html(nunjucks.render('status.html', { + $status.html(nunjucks.render('views/status.html', { lease: { address: leases[j].address, identity: leases[j].identity, @@ -301,7 +301,7 @@ $(document).ready(function() { console.info("Got", entries.length, "log entries"); for (var j = 0; j < entries.length; j++) { if ($("#log_level_" + entries[j].severity).prop("checked")) { - $("#log_entries").append(nunjucks.render("logentry.html", { + $("#log_entries").append(nunjucks.render("views/logentry.html", { entry: { created: new Date(entries[j].created).toLocaleString("et-EE"), message: entries[j].message, diff --git a/certidude/static/js/nunjucks-slim.js b/certidude/static/js/nunjucks-slim.js new file mode 100644 index 0000000..0b0914b --- /dev/null +++ b/certidude/static/js/nunjucks-slim.js @@ -0,0 +1,2633 @@ +/*! Browser bundle of nunjucks 2.3.0 (slim, only works with precompiled templates) */ +var nunjucks = +/******/ (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__(11); + var loaders = __webpack_require__(3); + 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__(3); + module.exports.parser = __webpack_require__(3); + module.exports.lexer = __webpack_require__(3); + module.exports.runtime = __webpack_require__(8); + module.exports.lib = lib; + module.exports.nodes = __webpack_require__(3); + + module.exports.installJinjaCompat = __webpack_require__(12); + + // 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; + } + }; + + +/***/ }, +/* 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__(3); + var builtin_filters = __webpack_require__(7); + var builtin_loaders = __webpack_require__(3); + var runtime = __webpack_require__(8); + var globals = __webpack_require__(9); + 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__(10); + + // 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(!this.globals[name]) { + 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); + 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); + } + }); + + 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 r = __webpack_require__(8); + + 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) { + return JSON.stringify(obj); + }, + + escape: function(str) { + if(typeof str === 'string' || + str instanceof r.SafeString) { + return lib.escape(str); + } + return str; + }, + + safe: function(str) { + return r.markSafe(str); + }, + + 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 .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; + }, + + 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; + }, + + '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; + + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lib = __webpack_require__(1); + var Obj = __webpack_require__(6); + + // Frames keep track of scoping both at compile-time and run-time so + // we know how to access variables. Block tags can introduce special + // variables, for example. + var Frame = Obj.extend({ + init: function(parent) { + this.variables = {}; + this.parent = parent; + this.topLevel = false; + }, + + set: function(name, val, resolveUp) { + // Allow variables with dots by automatically creating the + // nested structure + var parts = name.split('.'); + var obj = this.variables; + var frame = this; + + if(resolveUp) { + if((frame = this.resolve(parts[0]))) { + frame.set(name, val); + return; + } + frame = this; + } + + for(var i=0; i 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 && typeof val === 'string') { + val = lib.escape(val); + } + + 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 !== null) ? + 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 + }; + + +/***/ }, +/* 9 */ +/***/ 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(!stop) { + 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; + + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Loader = __webpack_require__(11); + + 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; + + +/***/ }, +/* 11 */ +/***/ 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; + + +/***/ }, +/* 12 */ +/***/ function(module, exports) { + + function installCompat() { + 'use strict'; + + // This must be called like `nunjucks.installCompat` so that `this` + // references the nunjucks instance + var runtime = this.runtime; // jshint ignore:line + var lib = this.lib; // jshint ignore:line + + var orig_contextOrFrameLookup = runtime.contextOrFrameLookup; + runtime.contextOrFrameLookup = function(context, frame, key) { + var val = orig_contextOrFrameLookup.apply(this, arguments); + if (val === undefined) { + switch (key) { + case 'True': + return true; + case 'False': + return false; + case 'None': + return null; + } + } + + return val; + }; + + var orig_memberLookup = runtime.memberLookup; + var ARRAY_MEMBERS = { + pop: function(index) { + if (index === undefined) { + return this.pop(); + } + if (index >= this.length || index < 0) { + throw new Error('KeyError'); + } + return this.splice(index, 1); + }, + remove: function(element) { + for (var i = 0; i < this.length; i++) { + if (this[i] === element) { + return this.splice(i, 1); + } + } + throw new Error('ValueError'); + }, + count: function(element) { + var count = 0; + for (var i = 0; i < this.length; i++) { + if (this[i] === element) { + count++; + } + } + return count; + }, + index: function(element) { + var i; + if ((i = this.indexOf(element)) === -1) { + throw new Error('ValueError'); + } + return i; + }, + find: function(element) { + return this.indexOf(element); + }, + insert: function(index, elem) { + return this.splice(index, 0, elem); + } + }; + var OBJECT_MEMBERS = { + items: function() { + var ret = []; + for(var k in this) { + ret.push([k, this[k]]); + } + return ret; + }, + values: function() { + var ret = []; + for(var k in this) { + ret.push(this[k]); + } + return ret; + }, + keys: function() { + var ret = []; + for(var k in this) { + ret.push(k); + } + return ret; + }, + get: function(key, def) { + var output = this[key]; + if (output === undefined) { + output = def; + } + return output; + }, + has_key: function(key) { + return this.hasOwnProperty(key); + }, + pop: function(key, def) { + var output = this[key]; + if (output === undefined && def !== undefined) { + output = def; + } else if (output === undefined) { + throw new Error('KeyError'); + } else { + delete this[key]; + } + return output; + }, + popitem: function() { + for (var k in this) { + // Return the first object pair. + var val = this[k]; + delete this[k]; + return [k, val]; + } + throw new Error('KeyError'); + }, + setdefault: function(key, def) { + if (key in this) { + return this[key]; + } + if (def === undefined) { + def = null; + } + return this[key] = def; + }, + update: function(kwargs) { + for (var k in kwargs) { + this[k] = kwargs[k]; + } + return null; // Always returns None + } + }; + OBJECT_MEMBERS.iteritems = OBJECT_MEMBERS.items; + OBJECT_MEMBERS.itervalues = OBJECT_MEMBERS.values; + OBJECT_MEMBERS.iterkeys = OBJECT_MEMBERS.keys; + runtime.memberLookup = function(obj, val, autoescape) { // jshint ignore:line + obj = obj || {}; + + // If the object is an object, return any of the methods that Python would + // otherwise provide. + if (lib.isArray(obj) && ARRAY_MEMBERS.hasOwnProperty(val)) { + return function() {return ARRAY_MEMBERS[val].apply(obj, arguments);}; + } + + if (lib.isObject(obj) && OBJECT_MEMBERS.hasOwnProperty(val)) { + return function() {return OBJECT_MEMBERS[val].apply(obj, arguments);}; + } + + return orig_memberLookup.apply(this, arguments); + }; + } + + module.exports = installCompat; + + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/certidude/static/js/nunjucks-slim.min.js b/certidude/static/js/nunjucks-slim.min.js new file mode 100644 index 0000000..08bde32 --- /dev/null +++ b/certidude/static/js/nunjucks-slim.min.js @@ -0,0 +1,2 @@ +/*! Browser bundle of nunjucks 2.3.0 (slim, only works with precompiled templates) */ +var nunjucks=function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";var n=r(1),i=r(2),o=r(11),s=r(3),u=r(3);t.exports={},t.exports.Environment=i.Environment,t.exports.Template=i.Template,t.exports.Loader=o,t.exports.FileSystemLoader=s.FileSystemLoader,t.exports.PrecompiledLoader=s.PrecompiledLoader,t.exports.WebLoader=s.WebLoader,t.exports.compiler=r(3),t.exports.parser=r(3),t.exports.lexer=r(3),t.exports.runtime=r(8),t.exports.lib=n,t.exports.nodes=r(3),t.exports.installJinjaCompat=r(12);var a;t.exports.configure=function(t,e){e=e||{},n.isObject(t)&&(e=t,t=null);var r;return s.FileSystemLoader?r=new s.FileSystemLoader(t,{watch:e.watch,noCache:e.noCache}):s.WebLoader&&(r=new s.WebLoader(t,{useCache:e.web&&e.web.useCache,async:e.web&&e.web.async})),a=new i.Environment(r,e),e&&e.express&&a.express(e.express),a},t.exports.compile=function(e,r,n,i){return a||t.exports.configure(),new t.exports.Template(e,r,n,i)},t.exports.render=function(e,r,n){return a||t.exports.configure(),a.render(e,r,n)},t.exports.renderString=function(e,r,n){return a||t.exports.configure(),a.renderString(e,r,n)},u&&(t.exports.precompile=u.precompile,t.exports.precompileString=u.precompileString)},function(t,e){"use strict";var r=Array.prototype,n=Object.prototype,i={"&":"&",'"':""","'":"'","<":"<",">":">"},o=/[&"'<>]/g,s=function(t){return i[t]},e=t.exports={};e.prettifyError=function(t,r,n){if(n.Update||(n=new e.TemplateError(n)),n.Update(t),!r){var i=n;n=new Error(i.message),n.name=i.name}return n},e.TemplateError=function(t,e,r){var n=this;if(t instanceof Error){n=t,t=t.name+": "+t.message;try{n.name=""}catch(i){n=this}}else Error.captureStackTrace&&Error.captureStackTrace(n);return n.name="Template render error",n.message=t,n.lineno=e,n.colno=r,n.firstUpdate=!0,n.Update=function(t){var e="("+(t||"unknown path")+")";return this.firstUpdate&&(this.lineno&&this.colno?e+=" [Line "+this.lineno+", Column "+this.colno+"]":this.lineno&&(e+=" [Line "+this.lineno+"]")),e+="\n ",this.firstUpdate&&(e+=" "),this.message=e+(this.message||""),this.firstUpdate=!1,this},n},e.TemplateError.prototype=Error.prototype,e.escape=function(t){return t.replace(o,s)},e.isFunction=function(t){return"[object Function]"===n.toString.call(t)},e.isArray=Array.isArray||function(t){return"[object Array]"===n.toString.call(t)},e.isString=function(t){return"[object String]"===n.toString.call(t)},e.isObject=function(t){return"[object Object]"===n.toString.call(t)},e.groupBy=function(t,r){for(var n={},i=e.isFunction(r)?r:function(t){return t[r]},o=0;on;n++)r+=t;return r},e.each=function(t,e,n){if(null!=t)if(r.each&&t.each===r.each)t.forEach(e,n);else if(t.length===+t.length)for(var i=0,o=t.length;o>i;i++)e.call(n,t[i],i,t)},e.map=function(t,e){var n=[];if(null==t)return n;if(r.map&&t.map===r.map)return t.map(e);for(var i=0;iu?r(e,t[e],u,s,i):n()}var o=e.keys(t),s=o.length,u=-1;i()},e.indexOf=Array.prototype.indexOf?function(t,e,r){return Array.prototype.indexOf.call(t,e,r)}:function(t,e,r){var n=this.length>>>0;for(r=+r||0,Math.abs(r)===1/0&&(r=0),0>r&&(r+=n,0>r&&(r=0));n>r;r++)if(t[r]===e)return r;return-1},Array.prototype.map||(Array.prototype.map=function(){throw new Error("map is unimplemented for this js engine")}),e.keys=function(t){if(Object.prototype.keys)return t.keys();var e=[];for(var r in t)t.hasOwnProperty(r)&&e.push(r);return e}},function(t,e,r){"use strict";function n(t,e,r){s(function(){t(e,r)})}var i,o=r(3),s=r(4),u=r(1),a=r(6),c=r(3),l=r(7),f=r(3),p=r(8),h=r(9),v=p.Frame;f.PrecompiledLoader=r(10);var d=a.extend({init:function(t,e){e=this.opts=e||{},this.opts.dev=!!e.dev,this.opts.autoescape=null!=e.autoescape?e.autoescape:!0,this.opts.throwOnUndefined=!!e.throwOnUndefined,this.opts.trimBlocks=!!e.trimBlocks,this.opts.lstripBlocks=!!e.lstripBlocks,this.loaders=[],t?this.loaders=u.isArray(t)?t:[t]:f.FileSystemLoader?this.loaders=[new f.FileSystemLoader("views")]:f.WebLoader&&(this.loaders=[new f.WebLoader("/views")]),window.nunjucksPrecompiled&&this.loaders.unshift(new f.PrecompiledLoader(window.nunjucksPrecompiled)),this.initCache(),this.globals=h(),this.filters={},this.asyncFilters=[],this.extensions={},this.extensionsList=[];for(var r in l)this.addFilter(r,l[r])},initCache:function(){u.each(this.loaders,function(t){t.cache={},"function"==typeof t.on&&t.on("update",function(e){t.cache[e]=null})})},addExtension:function(t,e){return e._name=t,this.extensions[t]=e,this.extensionsList.push(e),this},removeExtension:function(t){var e=this.getExtension(t);e&&(this.extensionsList=u.without(this.extensionsList,e),delete this.extensions[t])},getExtension:function(t){return this.extensions[t]},hasExtension:function(t){return!!this.extensions[t]},addGlobal:function(t,e){return this.globals[t]=e,this},getGlobal:function(t){if(!this.globals[t])throw new Error("global not found: "+t);return this.globals[t]},addFilter:function(t,e,r){var n=e;return r&&this.asyncFilters.push(t),this.filters[t]=n,this},getFilter:function(t){if(!this.filters[t])throw new Error("filter not found: "+t);return this.filters[t]},resolveTemplate:function(t,e,r){var n=t.isRelative&&e?t.isRelative(r):!1;return n&&t.resolve?t.resolve(e,r):r},getTemplate:function(t,e,r,n,o){var s=this,a=null;if(t&&t.raw&&(t=t.raw),u.isFunction(r)&&(o=r,r=null,e=e||!1),u.isFunction(e)&&(o=e,e=!1),t instanceof i)a=t;else{if("string"!=typeof t)throw new Error("template names must be a string: "+t);for(var c=0;cl){for(var e=0,r=u.length-c;r>e;e++)u[e]=u[e+c];u.length-=c,c=0}}u.length=0,c=0,a=!1}function i(t){var e=1,r=new f(t),n=document.createTextNode("");return r.observe(n,{characterData:!0}),function(){e=-e,n.data=e}}function o(t){return function(){function e(){clearTimeout(r),clearInterval(n),t()}var r=setTimeout(e,0),n=setInterval(e,50)}}t.exports=r;var s,u=[],a=!1,c=0,l=1024,f=e.MutationObserver||e.WebKitMutationObserver;s="function"==typeof f?i(n):o(n),r.requestFlush=s,r.makeRequestCallFromTimer=o}).call(e,function(){return this}())},function(t,e){"use strict";function r(t,e,n){var i=function(){};i.prototype=t.prototype;var o=new i,s=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;n=n||{};for(var u in n){var a=n[u],c=o[u];"function"==typeof c&&"function"==typeof a&&s.test(a)?o[u]=function(t,e){return function(){var r=this.parent;this.parent=e;var n=t.apply(this,arguments);return this.parent=r,n}}(a,c):o[u]=a}o.typename=e;var l=function(){o.init&&o.init.apply(this,arguments)};return l.prototype=o,l.prototype.constructor=l,l.extend=function(t,e){return"object"==typeof t&&(e=t,t="anonymous"),r(l,t,e)},l}t.exports=r(Object,"Object",{})},function(t,e,r){"use strict";function n(t,e){return null===t||void 0===t||t===!1?e:t}var i=r(1),o=r(8),s={abs:function(t){return Math.abs(t)},batch:function(t,e,r){var n,i=[],o=[];for(n=0;nn;n++)o.push(r);i.push(o)}return i},capitalize:function(t){t=n(t,"");var e=t.toLowerCase();return o.copySafeness(t,e.charAt(0).toUpperCase()+e.slice(1))},center:function(t,e){if(t=n(t,""),e=e||80,t.length>=e)return t;var r=e-t.length,s=i.repeat(" ",r/2-r%2),u=i.repeat(" ",r/2);return o.copySafeness(t,s+t+u)},"default":function(t,e,r){return r?t?t:e:void 0!==t?t:e},dictsort:function(t,e,r){if(!i.isObject(t))throw new i.TemplateError("dictsort filter: val must be an object");var n=[];for(var o in t)n.push([o,t[o]]);var s;if(void 0===r||"key"===r)s=0;else{if("value"!==r)throw new i.TemplateError("dictsort filter: You can only sort by either key or value");s=1}return n.sort(function(t,r){var n=t[s],o=r[s];return e||(i.isString(n)&&(n=n.toUpperCase()),i.isString(o)&&(o=o.toUpperCase())),n>o?1:n===o?0:-1}),n},dump:function(t){return JSON.stringify(t)},escape:function(t){return"string"==typeof t||t instanceof o.SafeString?i.escape(t):t},safe:function(t){return o.markSafe(t)},first:function(t){return t[0]},groupby:function(t,e){return i.groupBy(t,e)},indent:function(t,e,r){if(t=n(t,""),""===t)return"";e=e||4;for(var s="",u=t.split("\n"),a=i.repeat(" ",e),c=0;c-1&&(-1===n||n>c);)s+=t.substring(a,u)+r,a=u+e.length,c++,u=t.indexOf(e,a);return au;u++){var a=o+u*n;i>u&&o++;var c=o+(u+1)*n,l=t.slice(a,c);r&&u>=i&&l.push(r),s.push(l)}return s},sort:o.makeMacro(["value","reverse","case_sensitive","attribute"],[],function(t,e,r,n){return t=i.map(t,function(t){return t}),t.sort(function(t,o){var s,u;return n?(s=t[n],u=o[n]):(s=t,u=o),!r&&i.isString(s)&&i.isString(u)&&(s=s.toLowerCase(),u=u.toLowerCase()),u>s?e?1:-1:s>u?e?-1:1:0}),t}),string:function(t){return o.copySafeness(t,t)},striptags:function(t,e){t=n(t,""),e=e||!1;var r=/<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi,i=s.trim(t.replace(r,"")),u="";return u=e?i.replace(/^ +| +$/gm,"").replace(/ +/g," ").replace(/(\r\n)/g,"\n").replace(/\n\n\n+/g,"\n\n"):i.replace(/\s+/gi," "),o.copySafeness(t,u)},title:function(t){t=n(t,"");for(var e=t.split(" "),r=0;r"+c.substr(0,e)+"":u.test(c)?'"+c.substr(0,e)+"":o.test(c)?''+c+"":a.test(c)?'"+c.substr(0,e)+"":t});return c.join(" ")},wordcount:function(t){t=n(t,"");var e=t?t.match(/\w+/g):null;return e?e.length:null},"float":function(t,e){var r=parseFloat(t);return isNaN(r)?e:r},"int":function(t,e){var r=parseInt(t,10);return isNaN(r)?e:r}};s.d=s["default"],s.e=s.escape,t.exports=s},function(t,e,r){"use strict";function n(t,e,r){return function(){var n,i,u=s(arguments),a=o(arguments);if(u>t.length){n=Array.prototype.slice.call(arguments,0,t.length);var c=Array.prototype.slice.call(arguments,n.length,u);for(i=0;i=t.length&&(e=0),this.current=t[e],this.current}}}function n(t){t=t||",";var e=!0;return function(){var r=e?"":t;return e=!1,r}}function i(){return{range:function(t,e,r){e?r||(r=1):(e=t,t=0,r=1);var n,i=[];if(r>0)for(n=t;e>n;n+=r)i.push(n);else for(n=t;n>e;n+=r)i.push(n);return i},cycler:function(){return r(Array.prototype.slice.call(arguments))},joiner:function(t){return n(t)}}}t.exports=i},function(t,e,r){"use strict";var n=r(11),i=n.extend({init:function(t){this.precompiled=t||{}},getSource:function(t){return this.precompiled[t]?{src:{type:"code",obj:this.precompiled[t]},path:t}:null}});t.exports=i},function(t,e,r){"use strict";var n=r(3),i=r(6),o=r(1),s=i.extend({on:function(t,e){this.listeners=this.listeners||{},this.listeners[t]=this.listeners[t]||[],this.listeners[t].push(e)},emit:function(t){var e=Array.prototype.slice.call(arguments,1);this.listeners&&this.listeners[t]&&o.each(this.listeners[t],function(t){t.apply(null,e)})},resolve:function(t,e){return n.resolve(n.dirname(t),e)},isRelative:function(t){return 0===t.indexOf("./")||0===t.indexOf("../")}});t.exports=s},function(t,e){function r(){"use strict";var t=this.runtime,e=this.lib,r=t.contextOrFrameLookup;t.contextOrFrameLookup=function(t,e,n){var i=r.apply(this,arguments);if(void 0===i)switch(n){case"True":return!0;case"False":return!1;case"None":return null}return i};var n=t.memberLookup,i={pop:function(t){if(void 0===t)return this.pop();if(t>=this.length||0>t)throw new Error("KeyError");return this.splice(t,1)},remove:function(t){for(var e=0;e': '>' + }; + + 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; + } + }; + + +/***/ }, +/* 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 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(!this.globals[name]) { + 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); + 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); + } + }); + + 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('('); + this.compile(node.right, frame); + this.emit('.indexOf('); + this.compile(node.left, frame); + this.emit(') !== -1)'); + }, + + 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'); + + if(!this.peekToken()) { + this.fail('parseBlock: expected endblock, got end of file'); + } + + this.advanceAfterBlockEnd(); + + 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')) { + 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 or elif', + tag.lineno, + tag.colno); + } + + node.cond = this.parseExpression(); + this.advanceAfterBlockEnd(tag.value); + + node.body = this.parseUntilBlocks('elif', 'else', 'endif'); + var tok = this.peekToken(); + + switch(tok && tok.value) { + 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, '=')) { + this.fail('parseSet: expected = in set tag', + tag.lineno, + tag.colno); + } + + 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 '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() { + // Look for upcoming raw blocks (ignore all other kinds of blocks) + var rawBlockRegex = /([\s\S]*?){%\s*(raw|endraw)\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 === 'raw') { + rawLevel += 1; + } else if(blockName === 'endraw') { + 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 = this.parseUntilBlocks('endfilter'); + this.advanceAfterBlockEnd(); + + var node = new nodes.Filter( + name.lineno, + name.colno, + name, + new nodes.NodeList( + name.lineno, + name.colno, + // Body is a NodeList with an Output node as a child, + // need to strip those + body.children[0].children.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 succeding block start token + if(nextToken && + nextToken.type === lexer.TOKEN_BLOCK_START && + nextVal.charAt(nextVal.length - 1) === '-') { + // 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) { + var n = this.parseStatement(); + if(!n) { + break; + } + buf.push(n); + } + else if(tok.type === lexer.TOKEN_VARIABLE_START) { + var e = this.parseExpression(); + this.advanceAfterVariableEnd(); + buf.push(new nodes.Output(tok.lineno, tok.colno, [e])); + } + else if(tok.type !== lexer.TOKEN_COMMENT) { + // 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))) { + // 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; + } + + 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))) { + 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 && typeof val === 'string') { + val = lib.escape(val); + } + + 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 !== null) ? + 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 + }; + + +/***/ }, +/* 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) { + return JSON.stringify(obj); + }, + + escape: function(str) { + if(typeof str === 'string' || + str instanceof r.SafeString) { + return lib.escape(str); + } + return str; + }, + + safe: function(str) { + return r.markSafe(str); + }, + + 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 .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; + }, + + 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; + }, + + '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(!stop) { + 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) { + + function installCompat() { + 'use strict'; + + // This must be called like `nunjucks.installCompat` so that `this` + // references the nunjucks instance + var runtime = this.runtime; // jshint ignore:line + var lib = this.lib; // jshint ignore:line + + var orig_contextOrFrameLookup = runtime.contextOrFrameLookup; + runtime.contextOrFrameLookup = function(context, frame, key) { + var val = orig_contextOrFrameLookup.apply(this, arguments); + if (val === undefined) { + switch (key) { + case 'True': + return true; + case 'False': + return false; + case 'None': + return null; + } + } + + return val; + }; + + var orig_memberLookup = runtime.memberLookup; + var ARRAY_MEMBERS = { + pop: function(index) { + if (index === undefined) { + return this.pop(); + } + if (index >= this.length || index < 0) { + throw new Error('KeyError'); + } + return this.splice(index, 1); + }, + remove: function(element) { + for (var i = 0; i < this.length; i++) { + if (this[i] === element) { + return this.splice(i, 1); + } + } + throw new Error('ValueError'); + }, + count: function(element) { + var count = 0; + for (var i = 0; i < this.length; i++) { + if (this[i] === element) { + count++; + } + } + return count; + }, + index: function(element) { + var i; + if ((i = this.indexOf(element)) === -1) { + throw new Error('ValueError'); + } + return i; + }, + find: function(element) { + return this.indexOf(element); + }, + insert: function(index, elem) { + return this.splice(index, 0, elem); + } + }; + var OBJECT_MEMBERS = { + items: function() { + var ret = []; + for(var k in this) { + ret.push([k, this[k]]); + } + return ret; + }, + values: function() { + var ret = []; + for(var k in this) { + ret.push(this[k]); + } + return ret; + }, + keys: function() { + var ret = []; + for(var k in this) { + ret.push(k); + } + return ret; + }, + get: function(key, def) { + var output = this[key]; + if (output === undefined) { + output = def; + } + return output; + }, + has_key: function(key) { + return this.hasOwnProperty(key); + }, + pop: function(key, def) { + var output = this[key]; + if (output === undefined && def !== undefined) { + output = def; + } else if (output === undefined) { + throw new Error('KeyError'); + } else { + delete this[key]; + } + return output; + }, + popitem: function() { + for (var k in this) { + // Return the first object pair. + var val = this[k]; + delete this[k]; + return [k, val]; + } + throw new Error('KeyError'); + }, + setdefault: function(key, def) { + if (key in this) { + return this[key]; + } + if (def === undefined) { + def = null; + } + return this[key] = def; + }, + update: function(kwargs) { + for (var k in kwargs) { + this[k] = kwargs[k]; + } + return null; // Always returns None + } + }; + OBJECT_MEMBERS.iteritems = OBJECT_MEMBERS.items; + OBJECT_MEMBERS.itervalues = OBJECT_MEMBERS.values; + OBJECT_MEMBERS.iterkeys = OBJECT_MEMBERS.keys; + runtime.memberLookup = function(obj, val, autoescape) { // jshint ignore:line + obj = obj || {}; + + // If the object is an object, return any of the methods that Python would + // otherwise provide. + if (lib.isArray(obj) && ARRAY_MEMBERS.hasOwnProperty(val)) { + return function() {return ARRAY_MEMBERS[val].apply(obj, arguments);}; + } + + if (lib.isObject(obj) && OBJECT_MEMBERS.hasOwnProperty(val)) { + return function() {return OBJECT_MEMBERS[val].apply(obj, arguments);}; + } + + return orig_memberLookup.apply(this, arguments); + }; + } + + module.exports = installCompat; + + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/certidude/static/js/nunjucks.min.js b/certidude/static/js/nunjucks.min.js index 0e7c3ee..12870b4 100644 --- a/certidude/static/js/nunjucks.min.js +++ b/certidude/static/js/nunjucks.min.js @@ -1,4 +1,4 @@ -/*! Browser bundle of nunjucks 2.1.0 */ -var nunjucks=function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";var i=n(4),r=n(10),s=n(15),o=n(14),a=n(3);e.exports={},e.exports.Environment=r.Environment,e.exports.Template=r.Template,e.exports.Loader=s,e.exports.FileSystemLoader=o.FileSystemLoader,e.exports.PrecompiledLoader=o.PrecompiledLoader,e.exports.WebLoader=o.WebLoader,e.exports.compiler=n(1),e.exports.parser=n(6),e.exports.lexer=n(7),e.exports.runtime=n(9),e.exports.lib=i,e.exports.installJinjaCompat=n(18);var l;e.exports.configure=function(e,t){t=t||{},i.isObject(e)&&(t=e,e=null);var n;return o.FileSystemLoader?n=new o.FileSystemLoader(e,{watch:t.watch,noCache:t.noCache}):o.WebLoader&&(n=new o.WebLoader(e,{useCache:t.web&&t.web.useCache,async:t.web&&t.web.async})),l=new r.Environment(n,t),t&&t.express&&l.express(t.express),l},e.exports.compile=function(t,n,i,r){return l||e.exports.configure(),new e.exports.Template(t,n,i,r)},e.exports.render=function(t,n,i){return l||e.exports.configure(),l.render(t,n,i)},e.exports.renderString=function(t,n,i){return l||e.exports.configure(),l.renderString(t,n,i)},a&&(e.exports.precompile=a.precompile,e.exports.precompileString=a.precompileString)},function(e,t,n){"use strict";function i(e){return function(t,n){this.compile(t.left,n),this.emit(e),this.compile(t.right,n)}}var r=n(4),s=n(6),o=n(8),a=n(2),l=n(5),c=n(9).Frame,h={"==":"==","!=":"!=","<":"<",">":">","<=":"<=",">=":">="},u=l.extend({init:function(e,t){this.templateName=e,this.codebuf=[],this.lastId=0,this.buffer=null,this.bufferStack=[],this.scopeClosers="",this.inBlock=!1,this.throwOnUndefined=t},fail:function(e,t,n){throw void 0!==t&&(t+=1),void 0!==n&&(n+=1),new r.TemplateError(e,t,n)},pushBufferId:function(e){this.bufferStack.push(this.buffer),this.buffer=e,this.emit("var "+this.buffer+' = "";')},popBufferId:function(){this.buffer=this.bufferStack.pop()},emit:function(e){this.codebuf.push(e)},emitLine:function(e){this.emit(e+"\n")},emitLines:function(){r.each(r.toArray(arguments),function(e){this.emitLine(e)},this)},emitFuncBegin:function(e){this.buffer="output",this.scopeClosers="",this.emitLine("function "+e+"(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(e){e||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(e){var t=this.scopeClosers;this.scopeClosers="",e.call(this),this.closeScopeLevels(),this.scopeClosers=t},makeCallback:function(e){var t=this.tmpid();return"function("+t+(e?","+e:"")+") {\nif("+t+") { cb("+t+"); return; }"},tmpid:function(){return this.lastId++,"t_"+this.lastId},_templateName:function(){return null==this.templateName?"undefined":JSON.stringify(this.templateName)},_compileChildren:function(e,t){for(var n=e.children,i=0,r=n.length;r>i;i++)this.compile(n[i],t)},_compileAggregate:function(e,t,n,i){n&&this.emit(n);for(var r=0;r0&&this.emit(","),this.compile(e.children[r],t);i&&this.emit(i)},_compileExpression:function(e,t){this.assertType(e,a.Literal,a.Symbol,a.Group,a.Array,a.Dict,a.FunCall,a.Caller,a.Filter,a.LookupVal,a.Compare,a.InlineIf,a.In,a.And,a.Or,a.Not,a.Add,a.Concat,a.Sub,a.Mul,a.Div,a.FloorDiv,a.Mod,a.Pow,a.Neg,a.Pos,a.Compare,a.NodeList),this.compile(e,t)},assertType:function(e){for(var t=r.toArray(arguments).slice(1),n=!1,i=0;i0&&this.emit(","),e){var i=this.tmpid();this.emitLine("function(cb) {"),this.emitLine("if(!cb) { cb = function(err) { if(err) { throw err; }}}"),this.pushBufferId(i),this.withScopedSyntax(function(){this.compile(e,t),this.emitLine("cb(null, "+i+");")}),this.popBufferId(),this.emitLine("return "+i+";"),this.emitLine("}")}else this.emit("null")},this),n){var l=this.tmpid();this.emitLine(", "+this.makeCallback(l)),this.emitLine(this.buffer+" += runtime.suppressValue("+l+", "+o+" && env.opts.autoescape);"),this.addScopeLevel()}else this.emit(")"),this.emit(", "+o+" && env.opts.autoescape);\n")},compileCallExtensionAsync:function(e,t){this.compileCallExtension(e,t,!0)},compileNodeList:function(e,t){this._compileChildren(e,t)},compileLiteral:function(e){if("string"==typeof e.value){var t=e.value.replace(/\\/g,"\\\\");t=t.replace(/"/g,'\\"'),t=t.replace(/\n/g,"\\n"),t=t.replace(/\r/g,"\\r"),t=t.replace(/\t/g,"\\t"),this.emit('"'+t+'"')}else null===e.value?this.emit("null"):this.emit(e.value.toString())},compileSymbol:function(e,t){var n,i=e.value;(n=t.lookup(i))?this.emit(n):this.emit('runtime.contextOrFrameLookup(context, frame, "'+i+'")')},compileGroup:function(e,t){this._compileAggregate(e,t,"(",")")},compileArray:function(e,t){this._compileAggregate(e,t,"[","]")},compileDict:function(e,t){this._compileAggregate(e,t,"{","}")},compilePair:function(e,t){var n=e.key,i=e.value;n instanceof a.Symbol?n=new a.Literal(n.lineno,n.colno,n.value):n instanceof a.Literal&&"string"==typeof n.value||this.fail("compilePair: Dict keys must be strings or names",n.lineno,n.colno),this.compile(n,t),this.emit(": "),this._compileExpression(i,t)},compileInlineIf:function(e,t){this.emit("("),this.compile(e.cond,t),this.emit("?"),this.compile(e.body,t),this.emit(":"),null!==e.else_?this.compile(e.else_,t):this.emit('""'),this.emit(")")},compileIn:function(e,t){this.emit("("),this.compile(e.right,t),this.emit(".indexOf("),this.compile(e.left,t),this.emit(") !== -1)")},compileOr:i(" || "),compileAnd:i(" && "),compileAdd:i(" + "),compileConcat:i(' + "" + '),compileSub:i(" - "),compileMul:i(" * "),compileDiv:i(" / "),compileMod:i(" % "),compileNot:function(e,t){this.emit("!"),this.compile(e.target,t)},compileFloorDiv:function(e,t){this.emit("Math.floor("),this.compile(e.left,t),this.emit(" / "),this.compile(e.right,t),this.emit(")")},compilePow:function(e,t){this.emit("Math.pow("),this.compile(e.left,t),this.emit(", "),this.compile(e.right,t),this.emit(")")},compileNeg:function(e,t){this.emit("-"),this.compile(e.target,t)},compilePos:function(e,t){this.emit("+"),this.compile(e.target,t)},compileCompare:function(e,t){this.compile(e.expr,t);for(var n=0;n0||!i))for(var o=0;n>o;o++)t.stdout.write(" ");s===r.length-1?t.stdout.write(r[s]):t.stdout.write(r[s]+"\n")}}if(n=n||0,i(e.typename+": ",n),e instanceof c)i("\n"),s.each(e.children,function(e){r(e,n+2)});else if(e instanceof re)i(e.extName+"."+e.prop),i("\n"),e.args&&r(e.args,n+2),e.contentArgs&&s.each(e.contentArgs,function(e){r(e,n+2)});else{var o=null,l=null;if(e.iterFields(function(e,t){e instanceof a?(o=o||{},o[t]=e):(l=l||{},l[t]=e)}),l?i(JSON.stringify(l,null,2)+"\n",null,!0):i("\n"),o)for(var h in o)r(o[h],n+2)}}var s=n(4),o=n(5),a=o.extend("Node",{init:function(e,t){this.lineno=e,this.colno=t;for(var n=this.fields,i=0,r=n.length;r>i;i++){var s=n[i],o=arguments[i+2];void 0===o&&(o=null),this[s]=o}},findAll:function(e,t){t=t||[];var n,r;if(this instanceof c){var s=this.children;for(n=0,r=s.length;r>n;n++)i(s[n],e,t)}else{var o=this.fields;for(n=0,r=o.length;r>n;n++)i(this[o[n]],e,t)}return t},iterFields:function(e){s.each(this.fields,function(t){e(this[t],t)},this)}}),l=a.extend("Value",{fields:["value"]}),c=a.extend("NodeList",{fields:["children"],init:function(e,t,n){this.parent(e,t,n||[])},addChild:function(e){this.children.push(e)}}),h=c.extend("Root"),u=l.extend("Literal"),p=l.extend("Symbol"),f=c.extend("Group"),m=c.extend("Array"),d=a.extend("Pair",{fields:["key","value"]}),v=c.extend("Dict"),g=a.extend("LookupVal",{fields:["target","val"]}),y=a.extend("If",{fields:["cond","body","else_"]}),k=y.extend("IfAsync"),x=a.extend("InlineIf",{fields:["cond","body","else_"]}),b=a.extend("For",{fields:["arr","name","body","else_"]}),E=b.extend("AsyncEach"),w=b.extend("AsyncAll"),T=a.extend("Macro",{fields:["name","args","body"]}),L=T.extend("Caller"),_=a.extend("Import",{fields:["template","target","withContext"]}),O=a.extend("FromImport",{fields:["template","names","withContext"],init:function(e,t,n,i,r){this.parent(e,t,n,i||new c,r)}}),A=a.extend("FunCall",{fields:["name","args"]}),S=A.extend("Filter"),N=S.extend("FilterAsync",{fields:["name","args","symbol"]}),C=v.extend("KeywordArgs"),B=a.extend("Block",{fields:["name","body"]}),F=a.extend("Super",{fields:["blockName","symbol"]}),R=a.extend("TemplateRef",{fields:["template"]}),K=R.extend("Extends"),I=R.extend("Include"),M=a.extend("Set",{fields:["targets","value"]}),P=c.extend("Output"),D=u.extend("TemplateData"),V=a.extend("UnaryOp",{fields:["target"]}),j=a.extend("BinOp",{fields:["left","right"]}),U=j.extend("In"),W=j.extend("Or"),G=j.extend("And"),Y=V.extend("Not"),H=j.extend("Add"),$=j.extend("Concat"),z=j.extend("Sub"),X=j.extend("Mul"),q=j.extend("Div"),J=j.extend("FloorDiv"),Q=j.extend("Mod"),Z=j.extend("Pow"),ee=V.extend("Neg"),te=V.extend("Pos"),ne=a.extend("Compare",{fields:["expr","ops"]}),ie=a.extend("CompareOperand",{fields:["expr","type"]}),re=a.extend("CallExtension",{fields:["extName","prop","args","contentArgs"],init:function(e,t,n,i){this.extName=e._name||e,this.prop=t,this.args=n||new c,this.contentArgs=i||[],this.autoescape=e.autoescape}}),se=re.extend("CallExtensionAsync");e.exports={Node:a,Root:h,NodeList:c,Value:l,Literal:u,Symbol:p,Group:f,Array:m,Pair:d,Dict:v,Output:P,TemplateData:D,If:y,IfAsync:k,InlineIf:x,For:b,AsyncEach:E,AsyncAll:w,Macro:T,Caller:L,Import:_,FromImport:O,FunCall:A,Filter:S,FilterAsync:N,KeywordArgs:C,Block:B,Super:F,Extends:K,Include:I,Set:M,LookupVal:g,BinOp:j,In:U,Or:W,And:G,Not:Y,Add:H,Concat:$,Sub:z,Mul:X,Div:q,FloorDiv:J,Mod:Q,Pow:Z,Neg:ee,Pos:te,Compare:ne,CompareOperand:ie,CallExtension:re,CallExtensionAsync:se,printNodes:r}}).call(t,n(3))},function(e,t){},function(e,t){"use strict";var n=Array.prototype,i=Object.prototype,r={"&":"&",'"':""","'":"'","<":"<",">":">"},s=/[&"'<>]/g,o=function(e){return r[e]},t=e.exports={};t.prettifyError=function(e,n,i){if(i.Update||(i=new t.TemplateError(i)),i.Update(e),!n){var r=i;i=new Error(r.message),i.name=r.name}return i},t.TemplateError=function(e,t,n){var i=this;if(e instanceof Error){i=e,e=e.name+": "+e.message;try{i.name=""}catch(r){i=this}}else Error.captureStackTrace&&Error.captureStackTrace(i);return i.name="Template render error",i.message=e,i.lineno=t,i.colno=n,i.firstUpdate=!0,i.Update=function(e){var t="("+(e||"unknown path")+")";return this.firstUpdate&&(this.lineno&&this.colno?t+=" [Line "+this.lineno+", Column "+this.colno+"]":this.lineno&&(t+=" [Line "+this.lineno+"]")),t+="\n ",this.firstUpdate&&(t+=" "),this.message=t+(this.message||""),this.firstUpdate=!1,this},i},t.TemplateError.prototype=Error.prototype,t.escape=function(e){return e.replace(s,o)},t.isFunction=function(e){return"[object Function]"===i.toString.call(e)},t.isArray=Array.isArray||function(e){return"[object Array]"===i.toString.call(e)},t.isString=function(e){return"[object String]"===i.toString.call(e)},t.isObject=function(e){return"[object Object]"===i.toString.call(e)},t.groupBy=function(e,n){for(var i={},r=t.isFunction(n)?n:function(e){return e[n]},s=0;si;i++)n+=e;return n},t.each=function(e,t,i){if(null!=e)if(n.each&&e.each===n.each)e.forEach(t,i);else if(e.length===+e.length)for(var r=0,s=e.length;s>r;r++)t.call(i,e[r],r,e)},t.map=function(e,t){var i=[];if(null==e)return i;if(n.map&&e.map===n.map)return e.map(t);for(var r=0;ra?n(t,e[t],a,o,r):i()}var s=t.keys(e),o=s.length,a=-1;r()},t.indexOf=Array.prototype.indexOf?function(e,t,n){return Array.prototype.indexOf.call(e,t,n)}:function(e,t,n){var i=this.length>>>0;for(n=+n||0,Math.abs(n)===1/0&&(n=0),0>n&&(n+=i,0>n&&(n=0));i>n;n++)if(e[n]===t)return n;return-1},Array.prototype.map||(Array.prototype.map=function(){throw new Error("map is unimplemented for this js engine")}),t.keys=function(e){if(Object.prototype.keys)return e.keys();var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n);return t}},function(e,t){"use strict";function n(e,t,i){var r=function(){};r.prototype=e.prototype;var s=new r,o=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;i=i||{};for(var a in i){var l=i[a],c=s[a];"function"==typeof c&&"function"==typeof l&&o.test(l)?s[a]=function(e,t){return function(){var n=this.parent;this.parent=t;var i=e.apply(this,arguments);return this.parent=n,i}}(l,c):s[a]=l}s.typename=t;var h=function(){s.init&&s.init.apply(this,arguments)};return h.prototype=s,h.prototype.constructor=h,h.extend=function(e,t){return"object"==typeof e&&(t=e,e="anonymous"),n(h,e,t)},h}e.exports=n(Object,"Object",{})},function(e,t,n){"use strict";var i=n(7),r=n(2),s=n(5),o=n(4),a=s.extend({init:function(e){this.tokens=e,this.peeked=null,this.breakOnBlocks=null,this.dropLeadingWhitespace=!1,this.extensions=[]},nextToken:function(e){var t;if(this.peeked){if(e||this.peeked.type!==i.TOKEN_WHITESPACE)return t=this.peeked,this.peeked=null,t;this.peeked=null}if(t=this.tokens.nextToken(),!e)for(;t&&t.type===i.TOKEN_WHITESPACE;)t=this.tokens.nextToken();return t},peekToken:function(){return this.peeked=this.peeked||this.nextToken(),this.peeked},pushToken:function(e){if(this.peeked)throw new Error("pushToken: can only push one token on between reads");this.peeked=e},fail:function(e,t,n){if((void 0===t||void 0===n)&&this.peekToken()){var i=this.peekToken();t=i.lineno,n=i.colno}throw void 0!==t&&(t+=1),void 0!==n&&(n+=1),new o.TemplateError(e,t,n)},skip:function(e){var t=this.nextToken();return t&&t.type===e?!0:(this.pushToken(t),!1)},expect:function(e){var t=this.nextToken();return t.type!==e&&this.fail("expected "+e+", got "+t.type,t.lineno,t.colno),t},skipValue:function(e,t){var n=this.nextToken();return n&&n.type===e&&n.value===t?!0:(this.pushToken(n),!1)},skipSymbol:function(e){return this.skipValue(i.TOKEN_SYMBOL,e)},advanceAfterBlockEnd:function(e){var t;return e||(t=this.peekToken(),t||this.fail("unexpected end of file"),t.type!==i.TOKEN_SYMBOL&&this.fail("advanceAfterBlockEnd: expected symbol token or explicit name to be passed"),e=this.nextToken().value),t=this.nextToken(),t&&t.type===i.TOKEN_BLOCK_END?"-"===t.value.charAt(0)&&(this.dropLeadingWhitespace=!0):this.fail("expected block end in "+e+" statement"),t},advanceAfterVariableEnd:function(){this.skip(i.TOKEN_VARIABLE_END)||this.fail("expected variable end")},parseFor:function(){var e,t,n=this.peekToken();this.skipSymbol("for")?(e=new r.For(n.lineno,n.colno),t="endfor"):this.skipSymbol("asyncEach")?(e=new r.AsyncEach(n.lineno,n.colno),t="endeach"):this.skipSymbol("asyncAll")?(e=new r.AsyncAll(n.lineno,n.colno),t="endall"):this.fail("parseFor: expected for{Async}",n.lineno,n.colno),e.name=this.parsePrimary(),e.name instanceof r.Symbol||this.fail("parseFor: variable name expected for loop");var s=this.peekToken().type;if(s===i.TOKEN_COMMA){var o=e.name;for(e.name=new r.Array(o.lineno,o.colno),e.name.addChild(o);this.skip(i.TOKEN_COMMA);){var a=this.parsePrimary();e.name.addChild(a)}}return this.skipSymbol("in")||this.fail('parseFor: expected "in" keyword for loop',n.lineno,n.colno),e.arr=this.parseExpression(),this.advanceAfterBlockEnd(n.value),e.body=this.parseUntilBlocks(t,"else"),this.skipSymbol("else")&&(this.advanceAfterBlockEnd("else"),e.else_=this.parseUntilBlocks(t)),this.advanceAfterBlockEnd(),e},parseMacro:function(){var e=this.peekToken();this.skipSymbol("macro")||this.fail("expected macro");var t=this.parsePrimary(!0),n=this.parseSignature(),i=new r.Macro(e.lineno,e.colno,t,n);return this.advanceAfterBlockEnd(e.value),i.body=this.parseUntilBlocks("endmacro"),this.advanceAfterBlockEnd(),i},parseCall:function(){var e=this.peekToken();this.skipSymbol("call")||this.fail("expected call");var t=this.parseSignature(!0)||new r.NodeList,n=this.parsePrimary();this.advanceAfterBlockEnd(e.value);var i=this.parseUntilBlocks("endcall");this.advanceAfterBlockEnd();var s=new r.Symbol(e.lineno,e.colno,"caller"),o=new r.Caller(e.lineno,e.colno,s,t,i),a=n.args.children;a[a.length-1]instanceof r.KeywordArgs||a.push(new r.KeywordArgs);var l=a[a.length-1];return l.addChild(new r.Pair(e.lineno,e.colno,s,o)),new r.Output(e.lineno,e.colno,[n])},parseWithContext:function(){var e=this.peekToken(),t=null;return this.skipSymbol("with")?t=!0:this.skipSymbol("without")&&(t=!1),null!==t&&(this.skipSymbol("context")||this.fail("parseFrom: expected context after with/without",e.lineno,e.colno)),t},parseImport:function(){var e=this.peekToken();this.skipSymbol("import")||this.fail("parseImport: expected import",e.lineno,e.colno);var t=this.parseExpression();this.skipSymbol("as")||this.fail('parseImport: expected "as" keyword',e.lineno,e.colno);var n=this.parsePrimary(),i=this.parseWithContext(),s=new r.Import(e.lineno,e.colno,t,n,i);return this.advanceAfterBlockEnd(e.value),s},parseFrom:function(){var e=this.peekToken();this.skipSymbol("from")||this.fail("parseFrom: expected from");var t=this.parsePrimary();this.skipSymbol("import")||this.fail("parseFrom: expected import",e.lineno,e.colno);for(var n,s=new r.NodeList;;){var o=this.peekToken();if(o.type===i.TOKEN_BLOCK_END){s.children.length||this.fail("parseFrom: Expected at least one import name",e.lineno,e.colno),"-"===o.value.charAt(0)&&(this.dropLeadingWhitespace=!0),this.nextToken();break}s.children.length>0&&!this.skip(i.TOKEN_COMMA)&&this.fail("parseFrom: expected comma",e.lineno,e.colno);var a=this.parsePrimary();if("_"===a.value.charAt(0)&&this.fail("parseFrom: names starting with an underscore cannot be imported",a.lineno,a.colno),this.skipSymbol("as")){var l=this.parsePrimary();s.addChild(new r.Pair(a.lineno,a.colno,a,l))}else s.addChild(a);n=this.parseWithContext()}return new r.FromImport(e.lineno,e.colno,t,s,n)},parseBlock:function(){var e=this.peekToken();this.skipSymbol("block")||this.fail("parseBlock: expected block",e.lineno,e.colno);var t=new r.Block(e.lineno,e.colno);return t.name=this.parsePrimary(),t.name instanceof r.Symbol||this.fail("parseBlock: variable name expected",e.lineno,e.colno),this.advanceAfterBlockEnd(e.value),t.body=this.parseUntilBlocks("endblock"),this.peekToken()||this.fail("parseBlock: expected endblock, got end of file"),this.advanceAfterBlockEnd(),t},parseTemplateRef:function(e,t){var n=this.peekToken();this.skipSymbol(e)||this.fail("parseTemplateRef: expected "+e);var i=new t(n.lineno,n.colno);return i.template=this.parseExpression(),this.advanceAfterBlockEnd(n.value),i},parseExtends:function(){return this.parseTemplateRef("extends",r.Extends); -},parseInclude:function(){return this.parseTemplateRef("include",r.Include)},parseIf:function(){var e,t=this.peekToken();this.skipSymbol("if")||this.skipSymbol("elif")?e=new r.If(t.lineno,t.colno):this.skipSymbol("ifAsync")?e=new r.IfAsync(t.lineno,t.colno):this.fail("parseIf: expected if or elif",t.lineno,t.colno),e.cond=this.parseExpression(),this.advanceAfterBlockEnd(t.value),e.body=this.parseUntilBlocks("elif","else","endif");var n=this.peekToken();switch(n&&n.value){case"elif":e.else_=this.parseIf();break;case"else":this.advanceAfterBlockEnd(),e.else_=this.parseUntilBlocks("endif"),this.advanceAfterBlockEnd();break;case"endif":e.else_=null,this.advanceAfterBlockEnd();break;default:this.fail("parseIf: expected endif, else, or endif, got end of file")}return e},parseSet:function(){var e=this.peekToken();this.skipSymbol("set")||this.fail("parseSet: expected set",e.lineno,e.colno);for(var t,n=new r.Set(e.lineno,e.colno,[]);(t=this.parsePrimary())&&(n.targets.push(t),this.skip(i.TOKEN_COMMA)););return this.skipValue(i.TOKEN_OPERATOR,"=")||this.fail("parseSet: expected = in set tag",e.lineno,e.colno),n.value=this.parseExpression(),this.advanceAfterBlockEnd(e.value),n},parseStatement:function(){var e,t=this.peekToken();if(t.type!==i.TOKEN_SYMBOL&&this.fail("tag name expected",t.lineno,t.colno),this.breakOnBlocks&&-1!==o.indexOf(this.breakOnBlocks,t.value))return null;switch(t.value){case"raw":return this.parseRaw();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 n=0;n0;){var o=i[0],a=i[1],l=i[2];"raw"===l?t+=1:"endraw"===l&&(t-=1),0===t?(n+=a,this.tokens.backN(o.length-a.length)):n+=o}return new r.Output(s.lineno,s.colno,[new r.TemplateData(s.lineno,s.colno,n)])},parsePostfix:function(e){for(var t,n=this.peekToken();n;){if(n.type===i.TOKEN_LEFT_PAREN)e=new r.FunCall(n.lineno,n.colno,e,this.parseSignature());else if(n.type===i.TOKEN_LEFT_BRACKET)t=this.parseAggregate(),t.children.length>1&&this.fail("invalid index"),e=new r.LookupVal(n.lineno,n.colno,e,t.children[0]);else{if(n.type!==i.TOKEN_OPERATOR||"."!==n.value)break;this.nextToken();var s=this.nextToken();s.type!==i.TOKEN_SYMBOL&&this.fail("expected name as lookup value, got "+s.value,s.lineno,s.colno),t=new r.Literal(s.lineno,s.colno,s.value),e=new r.LookupVal(n.lineno,n.colno,e,t)}n=this.peekToken()}return e},parseExpression:function(){var e=this.parseInlineIf();return e},parseInlineIf:function(){var e=this.parseOr();if(this.skipSymbol("if")){var t=this.parseOr(),n=e;e=new r.InlineIf(e.lineno,e.colno),e.body=n,e.cond=t,this.skipSymbol("else")?e.else_=this.parseOr():e.else_=null}return e},parseOr:function(){for(var e=this.parseAnd();this.skipSymbol("or");){var t=this.parseAnd();e=new r.Or(e.lineno,e.colno,e,t)}return e},parseAnd:function(){for(var e=this.parseNot();this.skipSymbol("and");){var t=this.parseNot();e=new r.And(e.lineno,e.colno,e,t)}return e},parseNot:function(){var e=this.peekToken();return this.skipSymbol("not")?new r.Not(e.lineno,e.colno,this.parseNot()):this.parseIn()},parseIn:function(){for(var e=this.parseCompare();;){var t=this.nextToken();if(!t)break;var n=t.type===i.TOKEN_SYMBOL&&"not"===t.value;if(n||this.pushToken(t),!this.skipSymbol("in")){n&&this.pushToken(t);break}var s=this.parseCompare();e=new r.In(e.lineno,e.colno,e,s),n&&(e=new r.Not(e.lineno,e.colno,e))}return e},parseCompare:function(){for(var e=["==","!=","<",">","<=",">="],t=this.parseConcat(),n=[];;){var i=this.nextToken();if(!i)break;if(-1===o.indexOf(e,i.value)){this.pushToken(i);break}n.push(new r.CompareOperand(i.lineno,i.colno,this.parseConcat(),i.value))}return n.length?new r.Compare(n[0].lineno,n[0].colno,t,n):t},parseConcat:function(){for(var e=this.parseAdd();this.skipValue(i.TOKEN_TILDE,"~");){var t=this.parseAdd();e=new r.Concat(e.lineno,e.colno,e,t)}return e},parseAdd:function(){for(var e=this.parseSub();this.skipValue(i.TOKEN_OPERATOR,"+");){var t=this.parseSub();e=new r.Add(e.lineno,e.colno,e,t)}return e},parseSub:function(){for(var e=this.parseMul();this.skipValue(i.TOKEN_OPERATOR,"-");){var t=this.parseMul();e=new r.Sub(e.lineno,e.colno,e,t)}return e},parseMul:function(){for(var e=this.parseDiv();this.skipValue(i.TOKEN_OPERATOR,"*");){var t=this.parseDiv();e=new r.Mul(e.lineno,e.colno,e,t)}return e},parseDiv:function(){for(var e=this.parseFloorDiv();this.skipValue(i.TOKEN_OPERATOR,"/");){var t=this.parseFloorDiv();e=new r.Div(e.lineno,e.colno,e,t)}return e},parseFloorDiv:function(){for(var e=this.parseMod();this.skipValue(i.TOKEN_OPERATOR,"//");){var t=this.parseMod();e=new r.FloorDiv(e.lineno,e.colno,e,t)}return e},parseMod:function(){for(var e=this.parsePow();this.skipValue(i.TOKEN_OPERATOR,"%");){var t=this.parsePow();e=new r.Mod(e.lineno,e.colno,e,t)}return e},parsePow:function(){for(var e=this.parseUnary();this.skipValue(i.TOKEN_OPERATOR,"**");){var t=this.parseUnary();e=new r.Pow(e.lineno,e.colno,e,t)}return e},parseUnary:function(e){var t,n=this.peekToken();return t=this.skipValue(i.TOKEN_OPERATOR,"-")?new r.Neg(n.lineno,n.colno,this.parseUnary(!0)):this.skipValue(i.TOKEN_OPERATOR,"+")?new r.Pos(n.lineno,n.colno,this.parseUnary(!0)):this.parsePrimary(),e||(t=this.parseFilter(t)),t},parsePrimary:function(e){var t,n=this.nextToken(),s=null;return n?n.type===i.TOKEN_STRING?t=n.value:n.type===i.TOKEN_INT?t=parseInt(n.value,10):n.type===i.TOKEN_FLOAT?t=parseFloat(n.value):n.type===i.TOKEN_BOOLEAN?"true"===n.value?t=!0:"false"===n.value?t=!1:this.fail("invalid boolean: "+n.value,n.lineno,n.colno):n.type===i.TOKEN_NONE?t=null:n.type===i.TOKEN_REGEX&&(t=new RegExp(n.value.body,n.value.flags)):this.fail("expected expression, got end of file"),void 0!==t?s=new r.Literal(n.lineno,n.colno,t):n.type===i.TOKEN_SYMBOL?(s=new r.Symbol(n.lineno,n.colno,n.value),e||(s=this.parsePostfix(s))):(this.pushToken(n),s=this.parseAggregate()),s?s:void this.fail("unexpected token: "+n.value,n.lineno,n.colno)},parseFilterName:function(){for(var e=this.expect(i.TOKEN_SYMBOL),t=e.value;this.skipValue(i.TOKEN_OPERATOR,".");)t+="."+this.expect(i.TOKEN_SYMBOL).value;return new r.Symbol(e.lineno,e.colno,t)},parseFilterArgs:function(e){if(this.peekToken().type===i.TOKEN_LEFT_PAREN){var t=this.parsePostfix(e);return t.args.children}return[]},parseFilter:function(e){for(;this.skip(i.TOKEN_PIPE);){var t=this.parseFilterName();e=new r.Filter(t.lineno,t.colno,t,new r.NodeList(t.lineno,t.colno,[e].concat(this.parseFilterArgs(e))))}return e},parseFilterStatement:function(){var e=this.peekToken();this.skipSymbol("filter")||this.fail("parseFilterStatement: expected filter");var t=this.parseFilterName(),n=this.parseFilterArgs(t);this.advanceAfterBlockEnd(e.value);var i=this.parseUntilBlocks("endfilter");this.advanceAfterBlockEnd();var s=new r.Filter(t.lineno,t.colno,t,new r.NodeList(t.lineno,t.colno,i.children[0].children.concat(n)));return new r.Output(t.lineno,t.colno,[s])},parseAggregate:function(){var e,t=this.nextToken();switch(t.type){case i.TOKEN_LEFT_PAREN:e=new r.Group(t.lineno,t.colno);break;case i.TOKEN_LEFT_BRACKET:e=new r.Array(t.lineno,t.colno);break;case i.TOKEN_LEFT_CURLY:e=new r.Dict(t.lineno,t.colno);break;default:return null}for(;;){var n=this.peekToken().type;if(n===i.TOKEN_RIGHT_PAREN||n===i.TOKEN_RIGHT_BRACKET||n===i.TOKEN_RIGHT_CURLY){this.nextToken();break}if(e.children.length>0&&(this.skip(i.TOKEN_COMMA)||this.fail("parseAggregate: expected comma after expression",t.lineno,t.colno)),e instanceof r.Dict){var s=this.parsePrimary();this.skip(i.TOKEN_COLON)||this.fail("parseAggregate: expected colon after dict key",t.lineno,t.colno);var o=this.parseExpression();e.addChild(new r.Pair(s.lineno,s.colno,s,o))}else{var a=this.parseExpression();e.addChild(a)}}return e},parseSignature:function(e,t){var n=this.peekToken();if(!t&&n.type!==i.TOKEN_LEFT_PAREN){if(e)return null;this.fail("expected arguments",n.lineno,n.colno)}n.type===i.TOKEN_LEFT_PAREN&&(n=this.nextToken());for(var s=new r.NodeList(n.lineno,n.colno),o=new r.KeywordArgs(n.lineno,n.colno),a=!1;;){if(n=this.peekToken(),!t&&n.type===i.TOKEN_RIGHT_PAREN){this.nextToken();break}if(t&&n.type===i.TOKEN_BLOCK_END)break;if(a&&!this.skip(i.TOKEN_COMMA))this.fail("parseSignature: expected comma after expression",n.lineno,n.colno);else{var l=this.parseExpression();this.skipValue(i.TOKEN_OPERATOR,"=")?o.addChild(new r.Pair(l.lineno,l.colno,l,this.parseExpression())):s.addChild(l)}a=!0}return o.children.length&&s.addChild(o),s},parseUntilBlocks:function(){var e=this.breakOnBlocks;this.breakOnBlocks=o.toArray(arguments);var t=this.parse();return this.breakOnBlocks=e,t},parseNodes:function(){for(var e,t=[];e=this.nextToken();)if(e.type===i.TOKEN_DATA){var n=e.value,s=this.peekToken(),o=s&&s.value;this.dropLeadingWhitespace&&(n=n.replace(/^\s*/,""),this.dropLeadingWhitespace=!1),s&&s.type===i.TOKEN_BLOCK_START&&"-"===o.charAt(o.length-1)&&(n=n.replace(/\s*$/,"")),t.push(new r.Output(e.lineno,e.colno,[new r.TemplateData(e.lineno,e.colno,n)]))}else if(e.type===i.TOKEN_BLOCK_START){var a=this.parseStatement();if(!a)break;t.push(a)}else if(e.type===i.TOKEN_VARIABLE_START){var l=this.parseExpression();this.advanceAfterVariableEnd(),t.push(new r.Output(e.lineno,e.colno,[l]))}else e.type!==i.TOKEN_COMMENT&&this.fail("Unexpected token at top-level: "+e.type,e.lineno,e.colno);return t},parse:function(){return new r.NodeList(0,0,this.parseNodes())},parseAsRoot:function(){return new r.Root(0,0,this.parseNodes())}});e.exports={parse:function(e,t,n){var r=new a(i.lex(e,n));return void 0!==t&&(r.extensions=t),r.parseAsRoot()}}},function(e,t,n){"use strict";function i(e,t,n,i){return{type:e,value:t,lineno:n,colno:i}}function r(e,t){this.str=e,this.index=0,this.len=e.length,this.lineno=0,this.colno=0,this.in_code=!1,t=t||{};var n=t.tags||{};this.tags={BLOCK_START:n.blockStart||c,BLOCK_END:n.blockEnd||h,VARIABLE_START:n.variableStart||u,VARIABLE_END:n.variableEnd||p,COMMENT_START:n.commentStart||f,COMMENT_END:n.commentEnd||m},this.trimBlocks=!!t.trimBlocks,this.lstripBlocks=!!t.lstripBlocks}var s=n(4),o=" \n \r ",a="()[]{}%*-+~/#,:|.<>=!",l="0123456789",c="{%",h="%}",u="{{",p="}}",f="{#",m="#}",d="string",v="whitespace",g="data",y="block-start",k="block-end",x="variable-start",b="variable-end",E="comment",w="left-paren",T="right-paren",L="left-bracket",_="right-bracket",O="left-curly",A="right-curly",S="operator",N="comma",C="colon",B="tilde",F="pipe",R="int",K="float",I="boolean",M="none",P="symbol",D="special",V="regex";r.prototype.nextToken=function(){var e,t=this.lineno,n=this.colno;if(this.in_code){var r=this.current();if(this.is_finished())return null;if('"'===r||"'"===r)return i(d,this.parseString(r),t,n);if(e=this._extract(o))return i(v,e,t,n);if((e=this._extractString(this.tags.BLOCK_END))||(e=this._extractString("-"+this.tags.BLOCK_END)))return this.in_code=!1,this.trimBlocks&&(r=this.current(),"\n"===r&&this.forward()),i(k,e,t,n);if(e=this._extractString(this.tags.VARIABLE_END))return this.in_code=!1,i(b,e,t,n);if("r"===r&&"/"===this.str.charAt(this.index+1)){this.forwardN(2);for(var c="";!this.is_finished();){if("/"===this.current()&&"\\"!==this.previous()){this.forward();break}c+=this.current(),this.forward()}for(var h=["g","i","m","y"],u="";!this.is_finished();){var p=-1!==h.indexOf(this.current());if(!p)break;u+=this.current(),this.forward()}return i(V,{body:c,flags:u},t,n)}if(-1!==a.indexOf(r)){this.forward();var f,m=["==","!=","<=",">=","//","**"],D=r+this.current();switch(-1!==s.indexOf(m,D)&&(this.forward(),r=D),r){case"(":f=w;break;case")":f=T;break;case"[":f=L;break;case"]":f=_;break;case"{":f=O;break;case"}":f=A;break;case",":f=N;break;case":":f=C;break;case"~":f=B;break;case"|":f=F;break;default:f=S}return i(f,r,t,n)}if(e=this._extractUntil(o+a),e.match(/^[-+]?[0-9]+$/)){if("."===this.current()){this.forward();var j=this._extract(l);return i(K,e+"."+j,t,n)}return i(R,e,t,n)}if(e.match(/^(true|false)$/))return i(I,e,t,n);if("none"===e)return i(M,e,t,n);if(e)return i(P,e,t,n);throw new Error("Unexpected value while parsing: "+e)}var U=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;if((e=this._extractString(this.tags.BLOCK_START+"-"))||(e=this._extractString(this.tags.BLOCK_START)))return this.in_code=!0,i(y,e,t,n);if(e=this._extractString(this.tags.VARIABLE_START))return this.in_code=!0,i(x,e,t,n);e="";var W,G=!1;for(this._matches(this.tags.COMMENT_START)&&(G=!0,e=this._extractString(this.tags.COMMENT_START));null!==(W=this._extractUntil(U));){if(e+=W,(this._matches(this.tags.BLOCK_START)||this._matches(this.tags.VARIABLE_START)||this._matches(this.tags.COMMENT_START))&&!G){if(this.lstripBlocks&&this._matches(this.tags.BLOCK_START)&&this.colno>0&&this.colno<=e.length){var Y=e.slice(-this.colno);if(/^\s+$/.test(Y)&&(e=e.slice(0,-this.colno),!e.length))return this.nextToken()}break}if(this._matches(this.tags.COMMENT_END)){if(!G)throw new Error("unexpected end of comment");e+=this._extractString(this.tags.COMMENT_END);break}e+=this.current(),this.forward()}if(null===W&&G)throw new Error("expected end of comment, got end of file");return i(G?E:g,e,t,n)},r.prototype.parseString=function(e){this.forward();for(var t="";!this.is_finished()&&this.current()!==e;){var n=this.current();if("\\"===n){switch(this.forward(),this.current()){case"n":t+="\n";break;case"t":t+=" ";break;case"r":t+="\r";break;default:t+=this.current()}this.forward()}else t+=n,this.forward()}return this.forward(),t},r.prototype._matches=function(e){if(this.index+e.length>this.len)return null;var t=this.str.slice(this.index,this.index+e.length);return t===e},r.prototype._extractString=function(e){return this._matches(e)?(this.index+=e.length,e):null},r.prototype._extractUntil=function(e){return this._extractMatching(!0,e||"")},r.prototype._extract=function(e){return this._extractMatching(!1,e)},r.prototype._extractMatching=function(e,t){if(this.is_finished())return null;var n=t.indexOf(this.current());if(e&&-1===n||!e&&-1!==n){var i=this.current();this.forward();for(var r=t.indexOf(this.current());(e&&-1===r||!e&&-1!==r)&&!this.is_finished();)i+=this.current(),this.forward(),r=t.indexOf(this.current());return i}return""},r.prototype._extractRegex=function(e){var t=this.currentStr().match(e);return t?(this.forwardN(t[0].length),t):null},r.prototype.is_finished=function(){return this.index>=this.len},r.prototype.forwardN=function(e){for(var t=0;e>t;t++)this.forward()},r.prototype.forward=function(){this.index++,"\n"===this.previous()?(this.lineno++,this.colno=0):this.colno++},r.prototype.backN=function(e){for(var t=0;e>t;t++)this.back()},r.prototype.back=function(){if(this.index--,"\n"===this.current()){this.lineno--;var e=this.src.lastIndexOf("\n",this.index-1);-1===e?this.colno=this.index:this.colno=this.index-e}else this.colno--},r.prototype.current=function(){return this.is_finished()?"":this.str.charAt(this.index)},r.prototype.currentStr=function(){return this.is_finished()?"":this.str.substr(this.index)},r.prototype.previous=function(){return this.str.charAt(this.index-1)},e.exports={lex:function(e,t){return new r(e,t)},TOKEN_STRING:d,TOKEN_WHITESPACE:v,TOKEN_DATA:g,TOKEN_BLOCK_START:y,TOKEN_BLOCK_END:k,TOKEN_VARIABLE_START:x,TOKEN_VARIABLE_END:b,TOKEN_COMMENT:E,TOKEN_LEFT_PAREN:w,TOKEN_RIGHT_PAREN:T,TOKEN_LEFT_BRACKET:L,TOKEN_RIGHT_BRACKET:_,TOKEN_LEFT_CURLY:O,TOKEN_RIGHT_CURLY:A,TOKEN_OPERATOR:S,TOKEN_COMMA:N,TOKEN_COLON:C,TOKEN_TILDE:B,TOKEN_PIPE:F,TOKEN_INT:R,TOKEN_FLOAT:K,TOKEN_BOOLEAN:I,TOKEN_NONE:M,TOKEN_SYMBOL:P,TOKEN_SPECIAL:D,TOKEN_REGEX:V}},function(e,t,n){"use strict";function i(){return"hole_"+d++}function r(e,t){for(var n=null,i=0;ie.length){i=Array.prototype.slice.call(arguments,0,e.length);var c=Array.prototype.slice.call(arguments,i.length,a);for(r=0;ri;i++)s.push(n);r.push(s)}return r},capitalize:function(e){e=i(e,"");var t=e.toLowerCase();return s.copySafeness(e,t.charAt(0).toUpperCase()+t.slice(1))},center:function(e,t){if(e=i(e,""),t=t||80,e.length>=t)return e;var n=t-e.length,o=r.repeat(" ",n/2-n%2),a=r.repeat(" ",n/2);return s.copySafeness(e,o+e+a)},"default":function(e,t,n){return n===!0||n===!1||o||(o=!0,console.log('[nunjucks] Warning: the "default" filter was used without specifying the type of comparison. 2.0 changed the default behavior from boolean (val ? val : def) to strictly undefined, so you should make sure that doesn\'t break anything. Be explicit about this to make this warning go away, or wait until 2.1. See http://mozilla.github.io/nunjucks/templating.html#defaultvalue-default-boolean')),n?e?e:t:void 0!==e?e:t},dictsort:function(e,t,n){if(!r.isObject(e))throw new r.TemplateError("dictsort filter: val must be an object");var i=[];for(var s in e)i.push([s,e[s]]);var o;if(void 0===n||"key"===n)o=0;else{if("value"!==n)throw new r.TemplateError("dictsort filter: You can only sort by either key or value");o=1}return i.sort(function(e,n){var i=e[o],s=n[o];return t||(r.isString(i)&&(i=i.toUpperCase()),r.isString(s)&&(s=s.toUpperCase())),i>s?1:i===s?0:-1}),i},dump:function(e){return JSON.stringify(e)},escape:function(e){return"string"==typeof e||e instanceof s.SafeString?r.escape(e):e},safe:function(e){return s.markSafe(e)},first:function(e){return e[0]},groupby:function(e,t){return r.groupBy(e,t)},indent:function(e,t,n){if(e=i(e,""),""===e)return"";t=t||4;for(var o="",a=e.split("\n"),l=r.repeat(" ",t),c=0;c-1&&(-1===i||i>c);)o+=e.substring(l,a)+n,l=a+t.length,c++,a=e.indexOf(t,l);return la;a++){var l=s+a*i;r>a&&s++;var c=s+(a+1)*i,h=e.slice(l,c);n&&a>=r&&h.push(n),o.push(h)}return o},sort:s.makeMacro(["value","reverse","case_sensitive","attribute"],[],function(e,t,n,i){return e=r.map(e,function(e){return e}),e.sort(function(e,s){var o,a;return i?(o=e[i],a=s[i]):(o=e,a=s),!n&&r.isString(o)&&r.isString(a)&&(o=o.toLowerCase(),a=a.toLowerCase()),a>o?t?1:-1:o>a?t?-1:1:0}),e}),string:function(e){return s.copySafeness(e,e)},title:function(e){e=i(e,"");for(var t=e.split(" "),n=0;n"+c.substr(0,t)+"":a.test(c)?'"+c.substr(0,t)+"":s.test(c)?''+c+"":l.test(c)?'"+c.substr(0,t)+"":e});return c.join(" ")},wordcount:function(e){e=i(e,"");var t=e?e.match(/\w+/g):null;return t?t.length:null},"float":function(e,t){var n=parseFloat(e);return isNaN(n)?t:n},"int":function(e,t){var n=parseInt(e,10);return isNaN(n)?t:n}};a.d=a["default"],a.e=a.escape,e.exports=a},function(e,t,n){"use strict";function i(){if(l.length)throw l.shift()}function r(e){var t;t=a.length?a.pop():new s,t.task=e,o(t)}function s(){this.task=null}var o=n(13),a=[],l=[],c=o.makeRequestCallFromTimer(i);e.exports=r,s.prototype.call=function(){try{this.task.call()}catch(e){r.onerror?r.onerror(e):(l.push(e),c())}finally{this.task=null,a[a.length]=this}}},function(e,t){(function(t){"use strict";function n(e){a.length||(o(),l=!0),a[a.length]=e}function i(){for(;ch){for(var t=0,n=a.length-c;n>t;t++)a[t]=a[t+c];a.length-=c,c=0}}a.length=0,c=0,l=!1}function r(e){var t=1,n=new u(e),i=document.createTextNode("");return n.observe(i,{characterData:!0}),function(){t=-t,i.data=t}}function s(e){return function(){function t(){clearTimeout(n),clearInterval(i),e()}var n=setTimeout(t,0),i=setInterval(t,50)}}e.exports=n;var o,a=[],l=!1,c=0,h=1024,u=t.MutationObserver||t.WebKitMutationObserver;o="function"==typeof u?r(i):s(i),n.requestFlush=o,n.makeRequestCallFromTimer=s}).call(t,function(){return this}())},function(e,t,n){"use strict";var i=n(15),r=n(16),s=i.extend({init:function(e,t){this.baseURL=e||".",t=t||{},this.useCache=!!t.useCache,this.async=!!t.async},resolve:function(e,t){throw new Error("relative templates not support in the browser yet")},getSource:function(e,t){var n,i=this.useCache;return this.fetch(this.baseURL+"/"+e,function(r,s){if(r){if(!t)throw r;t(r)}else n={src:s,path:e,noCache:!i},t&&t(null,n)}),n},fetch:function(e,t){var n,i=!0;window.XMLHttpRequest?n=new XMLHttpRequest:window.ActiveXObject&&(n=new ActiveXObject("Microsoft.XMLHTTP")),n.onreadystatechange=function(){4===n.readyState&&i&&(i=!1,0===n.status||200===n.status?t(null,n.responseText):t(n.responseText))},e+=(-1===e.indexOf("?")?"?":"&")+"s="+(new Date).getTime(),n.open("GET",e,this.async),n.send()}});e.exports={WebLoader:s,PrecompiledLoader:r}},function(e,t,n){"use strict";var i=n(3),r=n(5),s=n(4),o=r.extend({on:function(e,t){this.listeners=this.listeners||{},this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t)},emit:function(e){var t=Array.prototype.slice.call(arguments,1);this.listeners&&this.listeners[e]&&s.each(this.listeners[e],function(e){e.apply(null,t)})},resolve:function(e,t){return i.resolve(i.dirname(e),t)},isRelative:function(e){return 0===e.indexOf("./")||0===e.indexOf("../")}});e.exports=o},function(e,t,n){"use strict";var i=n(15),r=i.extend({init:function(e){this.precompiled=e||{}},getSource:function(e){return this.precompiled[e]?{src:{type:"code",obj:this.precompiled[e]},path:e}:null}});e.exports=r},function(e,t){"use strict";function n(e){var t=-1;return{current:null,reset:function(){t=-1,this.current=null},next:function(){return t++,t>=e.length&&(t=0),this.current=e[t],this.current}}}function i(e){e=e||",";var t=!0;return function(){var n=t?"":e;return t=!1,n}}var r={range:function(e,t,n){t?n||(n=1):(t=e,e=0,n=1);for(var i=[],r=e;t>r;r+=n)i.push(r);return i},cycler:function(){return n(Array.prototype.slice.call(arguments))},joiner:function(e){return i(e)}};e.exports=r},function(e,t){function n(){"use strict";var e=this.runtime,t=this.lib,n=e.contextOrFrameLookup;e.contextOrFrameLookup=function(e,t,i){var r=n.apply(this,arguments);if(void 0===r)switch(i){case"True":return!0;case"False":return!1;case"None":return null}return r};var i=e.memberLookup,r={pop:function(e){if(void 0===e)return this.pop();if(e>=this.length||0>e)throw new Error("KeyError");return this.splice(e,1)},remove:function(e){for(var t=0;t":">"},s=/[&"'<>]/g,o=function(e){return r[e]},t=e.exports={};t.prettifyError=function(e,n,i){if(i.Update||(i=new t.TemplateError(i)),i.Update(e),!n){var r=i;i=new Error(r.message),i.name=r.name}return i},t.TemplateError=function(e,t,n){var i=this;if(e instanceof Error){i=e,e=e.name+": "+e.message;try{i.name=""}catch(r){i=this}}else Error.captureStackTrace&&Error.captureStackTrace(i);return i.name="Template render error",i.message=e,i.lineno=t,i.colno=n,i.firstUpdate=!0,i.Update=function(e){var t="("+(e||"unknown path")+")";return this.firstUpdate&&(this.lineno&&this.colno?t+=" [Line "+this.lineno+", Column "+this.colno+"]":this.lineno&&(t+=" [Line "+this.lineno+"]")),t+="\n ",this.firstUpdate&&(t+=" "),this.message=t+(this.message||""),this.firstUpdate=!1,this},i},t.TemplateError.prototype=Error.prototype,t.escape=function(e){return e.replace(s,o)},t.isFunction=function(e){return"[object Function]"===i.toString.call(e)},t.isArray=Array.isArray||function(e){return"[object Array]"===i.toString.call(e)},t.isString=function(e){return"[object String]"===i.toString.call(e)},t.isObject=function(e){return"[object Object]"===i.toString.call(e)},t.groupBy=function(e,n){for(var i={},r=t.isFunction(n)?n:function(e){return e[n]},s=0;si;i++)n+=e;return n},t.each=function(e,t,i){if(null!=e)if(n.each&&e.each===n.each)e.forEach(t,i);else if(e.length===+e.length)for(var r=0,s=e.length;s>r;r++)t.call(i,e[r],r,e)},t.map=function(e,t){var i=[];if(null==e)return i;if(n.map&&e.map===n.map)return e.map(t);for(var r=0;ra?n(t,e[t],a,o,r):i()}var s=t.keys(e),o=s.length,a=-1;r()},t.indexOf=Array.prototype.indexOf?function(e,t,n){return Array.prototype.indexOf.call(e,t,n)}:function(e,t,n){var i=this.length>>>0;for(n=+n||0,Math.abs(n)===1/0&&(n=0),0>n&&(n+=i,0>n&&(n=0));i>n;n++)if(e[n]===t)return n;return-1},Array.prototype.map||(Array.prototype.map=function(){throw new Error("map is unimplemented for this js engine")}),t.keys=function(e){if(Object.prototype.keys)return e.keys();var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n);return t}},function(e,t,n){"use strict";function i(e,t,n){o(function(){e(t,n)})}var r,s=n(3),o=n(4),a=n(1),l=n(6),c=n(7),h=n(13),u=n(14),p=n(12),f=n(17),m=p.Frame;u.PrecompiledLoader=n(16);var d=l.extend({init:function(e,t){t=this.opts=t||{},this.opts.dev=!!t.dev,this.opts.autoescape=null!=t.autoescape?t.autoescape:!0,this.opts.throwOnUndefined=!!t.throwOnUndefined,this.opts.trimBlocks=!!t.trimBlocks,this.opts.lstripBlocks=!!t.lstripBlocks,this.loaders=[],e?this.loaders=a.isArray(e)?e:[e]:u.FileSystemLoader?this.loaders=[new u.FileSystemLoader("views")]:u.WebLoader&&(this.loaders=[new u.WebLoader("/views")]),window.nunjucksPrecompiled&&this.loaders.unshift(new u.PrecompiledLoader(window.nunjucksPrecompiled)),this.initCache(),this.globals=f(),this.filters={},this.asyncFilters=[],this.extensions={},this.extensionsList=[];for(var n in h)this.addFilter(n,h[n])},initCache:function(){a.each(this.loaders,function(e){e.cache={},"function"==typeof e.on&&e.on("update",function(t){e.cache[t]=null})})},addExtension:function(e,t){return t._name=e,this.extensions[e]=t,this.extensionsList.push(t),this},removeExtension:function(e){var t=this.getExtension(e);t&&(this.extensionsList=a.without(this.extensionsList,t),delete this.extensions[e])},getExtension:function(e){return this.extensions[e]},hasExtension:function(e){return!!this.extensions[e]},addGlobal:function(e,t){return this.globals[e]=t,this},getGlobal:function(e){if(!this.globals[e])throw new Error("global not found: "+e);return this.globals[e]},addFilter:function(e,t,n){var i=t;return n&&this.asyncFilters.push(e),this.filters[e]=i,this},getFilter:function(e){if(!this.filters[e])throw new Error("filter not found: "+e);return this.filters[e]},resolveTemplate:function(e,t,n){var i=e.isRelative&&t?e.isRelative(n):!1;return i&&e.resolve?e.resolve(t,n):n},getTemplate:function(e,t,n,i,s){var o=this,l=null;if(e&&e.raw&&(e=e.raw),a.isFunction(n)&&(s=n,n=null,t=t||!1),a.isFunction(t)&&(s=t,t=!1),e instanceof r)l=e;else{if("string"!=typeof e)throw new Error("template names must be a string: "+e);for(var c=0;ch){for(var t=0,n=a.length-c;n>t;t++)a[t]=a[t+c];a.length-=c,c=0}}a.length=0,c=0,l=!1}function r(e){var t=1,n=new u(e),i=document.createTextNode("");return n.observe(i,{characterData:!0}),function(){t=-t,i.data=t}}function s(e){return function(){function t(){clearTimeout(n),clearInterval(i),e()}var n=setTimeout(t,0),i=setInterval(t,50)}}e.exports=n;var o,a=[],l=!1,c=0,h=1024,u=t.MutationObserver||t.WebKitMutationObserver;o="function"==typeof u?r(i):s(i),n.requestFlush=o,n.makeRequestCallFromTimer=s}).call(t,function(){return this}())},function(e,t){"use strict";function n(e,t,i){var r=function(){};r.prototype=e.prototype;var s=new r,o=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;i=i||{};for(var a in i){var l=i[a],c=s[a];"function"==typeof c&&"function"==typeof l&&o.test(l)?s[a]=function(e,t){return function(){var n=this.parent;this.parent=t;var i=e.apply(this,arguments);return this.parent=n,i}}(l,c):s[a]=l}s.typename=t;var h=function(){s.init&&s.init.apply(this,arguments)};return h.prototype=s,h.prototype.constructor=h,h.extend=function(e,t){return"object"==typeof e&&(t=e,e="anonymous"),n(h,e,t)},h}e.exports=n(Object,"Object",{})},function(e,t,n){"use strict";function i(e){return function(t,n){this.compile(t.left,n),this.emit(e),this.compile(t.right,n)}}var r=n(1),s=n(8),o=n(11),a=n(10),l=n(6),c=n(12).Frame,h={"==":"==","!=":"!=","<":"<",">":">","<=":"<=",">=":">="},u=l.extend({init:function(e,t){this.templateName=e,this.codebuf=[],this.lastId=0,this.buffer=null,this.bufferStack=[],this.scopeClosers="",this.inBlock=!1,this.throwOnUndefined=t},fail:function(e,t,n){throw void 0!==t&&(t+=1),void 0!==n&&(n+=1),new r.TemplateError(e,t,n)},pushBufferId:function(e){this.bufferStack.push(this.buffer),this.buffer=e,this.emit("var "+this.buffer+' = "";')},popBufferId:function(){this.buffer=this.bufferStack.pop()},emit:function(e){this.codebuf.push(e)},emitLine:function(e){this.emit(e+"\n")},emitLines:function(){r.each(r.toArray(arguments),function(e){this.emitLine(e)},this)},emitFuncBegin:function(e){this.buffer="output",this.scopeClosers="",this.emitLine("function "+e+"(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(e){e||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(e){var t=this.scopeClosers;this.scopeClosers="",e.call(this),this.closeScopeLevels(),this.scopeClosers=t},makeCallback:function(e){var t=this.tmpid();return"function("+t+(e?","+e:"")+") {\nif("+t+") { cb("+t+"); return; }"},tmpid:function(){return this.lastId++,"t_"+this.lastId},_templateName:function(){return null==this.templateName?"undefined":JSON.stringify(this.templateName)},_compileChildren:function(e,t){for(var n=e.children,i=0,r=n.length;r>i;i++)this.compile(n[i],t)},_compileAggregate:function(e,t,n,i){n&&this.emit(n);for(var r=0;r0&&this.emit(","),this.compile(e.children[r],t);i&&this.emit(i)},_compileExpression:function(e,t){this.assertType(e,a.Literal,a.Symbol,a.Group,a.Array,a.Dict,a.FunCall,a.Caller,a.Filter,a.LookupVal,a.Compare,a.InlineIf,a.In,a.And,a.Or,a.Not,a.Add,a.Concat,a.Sub,a.Mul,a.Div,a.FloorDiv,a.Mod,a.Pow,a.Neg,a.Pos,a.Compare,a.NodeList),this.compile(e,t)},assertType:function(e){for(var t=r.toArray(arguments).slice(1),n=!1,i=0;i0&&this.emit(","),e){var i=this.tmpid();this.emitLine("function(cb) {"),this.emitLine("if(!cb) { cb = function(err) { if(err) { throw err; }}}"),this.pushBufferId(i),this.withScopedSyntax(function(){this.compile(e,t),this.emitLine("cb(null, "+i+");")}),this.popBufferId(),this.emitLine("return "+i+";"),this.emitLine("}")}else this.emit("null")},this),n){var l=this.tmpid();this.emitLine(", "+this.makeCallback(l)),this.emitLine(this.buffer+" += runtime.suppressValue("+l+", "+o+" && env.opts.autoescape);"),this.addScopeLevel()}else this.emit(")"),this.emit(", "+o+" && env.opts.autoescape);\n")},compileCallExtensionAsync:function(e,t){this.compileCallExtension(e,t,!0)},compileNodeList:function(e,t){this._compileChildren(e,t)},compileLiteral:function(e){if("string"==typeof e.value){var t=e.value.replace(/\\/g,"\\\\");t=t.replace(/"/g,'\\"'),t=t.replace(/\n/g,"\\n"),t=t.replace(/\r/g,"\\r"),t=t.replace(/\t/g,"\\t"),this.emit('"'+t+'"')}else null===e.value?this.emit("null"):this.emit(e.value.toString())},compileSymbol:function(e,t){var n,i=e.value;(n=t.lookup(i))?this.emit(n):this.emit('runtime.contextOrFrameLookup(context, frame, "'+i+'")')},compileGroup:function(e,t){this._compileAggregate(e,t,"(",")")},compileArray:function(e,t){this._compileAggregate(e,t,"[","]")},compileDict:function(e,t){this._compileAggregate(e,t,"{","}")},compilePair:function(e,t){var n=e.key,i=e.value;n instanceof a.Symbol?n=new a.Literal(n.lineno,n.colno,n.value):n instanceof a.Literal&&"string"==typeof n.value||this.fail("compilePair: Dict keys must be strings or names",n.lineno,n.colno),this.compile(n,t),this.emit(": "),this._compileExpression(i,t)},compileInlineIf:function(e,t){this.emit("("),this.compile(e.cond,t),this.emit("?"),this.compile(e.body,t),this.emit(":"),null!==e.else_?this.compile(e.else_,t):this.emit('""'),this.emit(")")},compileIn:function(e,t){this.emit("("),this.compile(e.right,t),this.emit(".indexOf("),this.compile(e.left,t),this.emit(") !== -1)")},compileOr:i(" || "),compileAnd:i(" && "),compileAdd:i(" + "),compileConcat:i(' + "" + '),compileSub:i(" - "),compileMul:i(" * "),compileDiv:i(" / "),compileMod:i(" % "),compileNot:function(e,t){this.emit("!"),this.compile(e.target,t)},compileFloorDiv:function(e,t){this.emit("Math.floor("),this.compile(e.left,t),this.emit(" / "),this.compile(e.right,t),this.emit(")")},compilePow:function(e,t){this.emit("Math.pow("),this.compile(e.left,t),this.emit(", "),this.compile(e.right,t),this.emit(")")},compileNeg:function(e,t){this.emit("-"),this.compile(e.target,t)},compilePos:function(e,t){this.emit("+"),this.compile(e.target,t)},compileCompare:function(e,t){this.compile(e.expr,t);for(var n=0;n0&&!this.skip(i.TOKEN_COMMA)&&this.fail("parseFrom: expected comma",e.lineno,e.colno);var a=this.parsePrimary();if("_"===a.value.charAt(0)&&this.fail("parseFrom: names starting with an underscore cannot be imported",a.lineno,a.colno),this.skipSymbol("as")){var l=this.parsePrimary();s.addChild(new r.Pair(a.lineno,a.colno,a,l))}else s.addChild(a);n=this.parseWithContext()}return new r.FromImport(e.lineno,e.colno,t,s,n)},parseBlock:function(){var e=this.peekToken();this.skipSymbol("block")||this.fail("parseBlock: expected block",e.lineno,e.colno);var t=new r.Block(e.lineno,e.colno);return t.name=this.parsePrimary(),t.name instanceof r.Symbol||this.fail("parseBlock: variable name expected",e.lineno,e.colno),this.advanceAfterBlockEnd(e.value),t.body=this.parseUntilBlocks("endblock"),this.peekToken()||this.fail("parseBlock: expected endblock, got end of file"),this.advanceAfterBlockEnd(),t},parseExtends:function(){var e="extends",t=this.peekToken();this.skipSymbol(e)||this.fail("parseTemplateRef: expected "+e);var n=new r.Extends(t.lineno,t.colno);return n.template=this.parseExpression(),this.advanceAfterBlockEnd(t.value),n},parseInclude:function(){var e="include",t=this.peekToken();this.skipSymbol(e)||this.fail("parseInclude: expected "+e);var n=new r.Include(t.lineno,t.colno);return n.template=this.parseExpression(),this.skipSymbol("ignore")&&this.skipSymbol("missing")&&(n.ignoreMissing=!0),this.advanceAfterBlockEnd(t.value),n},parseIf:function(){var e,t=this.peekToken();this.skipSymbol("if")||this.skipSymbol("elif")?e=new r.If(t.lineno,t.colno):this.skipSymbol("ifAsync")?e=new r.IfAsync(t.lineno,t.colno):this.fail("parseIf: expected if or elif",t.lineno,t.colno),e.cond=this.parseExpression(),this.advanceAfterBlockEnd(t.value),e.body=this.parseUntilBlocks("elif","else","endif");var n=this.peekToken();switch(n&&n.value){case"elif":e.else_=this.parseIf();break;case"else":this.advanceAfterBlockEnd(),e.else_=this.parseUntilBlocks("endif"),this.advanceAfterBlockEnd();break;case"endif":e.else_=null,this.advanceAfterBlockEnd();break;default:this.fail("parseIf: expected elif, else, or endif, got end of file")}return e},parseSet:function(){var e=this.peekToken();this.skipSymbol("set")||this.fail("parseSet: expected set",e.lineno,e.colno);for(var t,n=new r.Set(e.lineno,e.colno,[]);(t=this.parsePrimary())&&(n.targets.push(t),this.skip(i.TOKEN_COMMA)););return this.skipValue(i.TOKEN_OPERATOR,"=")||this.fail("parseSet: expected = in set tag",e.lineno,e.colno),n.value=this.parseExpression(),this.advanceAfterBlockEnd(e.value),n},parseStatement:function(){var e,t=this.peekToken();if(t.type!==i.TOKEN_SYMBOL&&this.fail("tag name expected",t.lineno,t.colno),this.breakOnBlocks&&-1!==o.indexOf(this.breakOnBlocks,t.value))return null;switch(t.value){case"raw":return this.parseRaw();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 n=0;n0;){var o=i[0],a=i[1],l=i[2];"raw"===l?t+=1:"endraw"===l&&(t-=1),0===t?(n+=a,this.tokens.backN(o.length-a.length)):n+=o}return new r.Output(s.lineno,s.colno,[new r.TemplateData(s.lineno,s.colno,n)])},parsePostfix:function(e){for(var t,n=this.peekToken();n;){if(n.type===i.TOKEN_LEFT_PAREN)e=new r.FunCall(n.lineno,n.colno,e,this.parseSignature());else if(n.type===i.TOKEN_LEFT_BRACKET)t=this.parseAggregate(),t.children.length>1&&this.fail("invalid index"),e=new r.LookupVal(n.lineno,n.colno,e,t.children[0]);else{if(n.type!==i.TOKEN_OPERATOR||"."!==n.value)break;this.nextToken();var s=this.nextToken();s.type!==i.TOKEN_SYMBOL&&this.fail("expected name as lookup value, got "+s.value,s.lineno,s.colno),t=new r.Literal(s.lineno,s.colno,s.value),e=new r.LookupVal(n.lineno,n.colno,e,t)}n=this.peekToken()}return e},parseExpression:function(){var e=this.parseInlineIf();return e},parseInlineIf:function(){var e=this.parseOr();if(this.skipSymbol("if")){var t=this.parseOr(),n=e;e=new r.InlineIf(e.lineno,e.colno),e.body=n,e.cond=t,this.skipSymbol("else")?e.else_=this.parseOr():e.else_=null}return e},parseOr:function(){for(var e=this.parseAnd();this.skipSymbol("or");){var t=this.parseAnd();e=new r.Or(e.lineno,e.colno,e,t)}return e},parseAnd:function(){for(var e=this.parseNot();this.skipSymbol("and");){var t=this.parseNot();e=new r.And(e.lineno,e.colno,e,t)}return e},parseNot:function(){var e=this.peekToken();return this.skipSymbol("not")?new r.Not(e.lineno,e.colno,this.parseNot()):this.parseIn()},parseIn:function(){for(var e=this.parseCompare();;){var t=this.nextToken();if(!t)break;var n=t.type===i.TOKEN_SYMBOL&&"not"===t.value;if(n||this.pushToken(t),!this.skipSymbol("in")){n&&this.pushToken(t);break}var s=this.parseCompare();e=new r.In(e.lineno,e.colno,e,s),n&&(e=new r.Not(e.lineno,e.colno,e))}return e},parseCompare:function(){for(var e=["==","!=","<",">","<=",">="],t=this.parseConcat(),n=[];;){var i=this.nextToken();if(!i)break;if(-1===o.indexOf(e,i.value)){this.pushToken(i);break}n.push(new r.CompareOperand(i.lineno,i.colno,this.parseConcat(),i.value))}return n.length?new r.Compare(n[0].lineno,n[0].colno,t,n):t},parseConcat:function(){for(var e=this.parseAdd();this.skipValue(i.TOKEN_TILDE,"~");){var t=this.parseAdd();e=new r.Concat(e.lineno,e.colno,e,t)}return e},parseAdd:function(){for(var e=this.parseSub();this.skipValue(i.TOKEN_OPERATOR,"+");){var t=this.parseSub();e=new r.Add(e.lineno,e.colno,e,t)}return e},parseSub:function(){for(var e=this.parseMul();this.skipValue(i.TOKEN_OPERATOR,"-");){var t=this.parseMul();e=new r.Sub(e.lineno,e.colno,e,t)}return e},parseMul:function(){for(var e=this.parseDiv();this.skipValue(i.TOKEN_OPERATOR,"*");){var t=this.parseDiv();e=new r.Mul(e.lineno,e.colno,e,t)}return e},parseDiv:function(){for(var e=this.parseFloorDiv();this.skipValue(i.TOKEN_OPERATOR,"/");){var t=this.parseFloorDiv();e=new r.Div(e.lineno,e.colno,e,t)}return e},parseFloorDiv:function(){for(var e=this.parseMod();this.skipValue(i.TOKEN_OPERATOR,"//");){var t=this.parseMod();e=new r.FloorDiv(e.lineno,e.colno,e,t)}return e},parseMod:function(){for(var e=this.parsePow();this.skipValue(i.TOKEN_OPERATOR,"%");){var t=this.parsePow();e=new r.Mod(e.lineno,e.colno,e,t)}return e},parsePow:function(){for(var e=this.parseUnary();this.skipValue(i.TOKEN_OPERATOR,"**");){var t=this.parseUnary();e=new r.Pow(e.lineno,e.colno,e,t)}return e},parseUnary:function(e){var t,n=this.peekToken();return t=this.skipValue(i.TOKEN_OPERATOR,"-")?new r.Neg(n.lineno,n.colno,this.parseUnary(!0)):this.skipValue(i.TOKEN_OPERATOR,"+")?new r.Pos(n.lineno,n.colno,this.parseUnary(!0)):this.parsePrimary(),e||(t=this.parseFilter(t)),t},parsePrimary:function(e){var t,n=this.nextToken(),s=null;return n?n.type===i.TOKEN_STRING?t=n.value:n.type===i.TOKEN_INT?t=parseInt(n.value,10):n.type===i.TOKEN_FLOAT?t=parseFloat(n.value):n.type===i.TOKEN_BOOLEAN?"true"===n.value?t=!0:"false"===n.value?t=!1:this.fail("invalid boolean: "+n.value,n.lineno,n.colno):n.type===i.TOKEN_NONE?t=null:n.type===i.TOKEN_REGEX&&(t=new RegExp(n.value.body,n.value.flags)):this.fail("expected expression, got end of file"),void 0!==t?s=new r.Literal(n.lineno,n.colno,t):n.type===i.TOKEN_SYMBOL?(s=new r.Symbol(n.lineno,n.colno,n.value),e||(s=this.parsePostfix(s))):(this.pushToken(n),s=this.parseAggregate()),s?s:void this.fail("unexpected token: "+n.value,n.lineno,n.colno)},parseFilterName:function(){for(var e=this.expect(i.TOKEN_SYMBOL),t=e.value;this.skipValue(i.TOKEN_OPERATOR,".");)t+="."+this.expect(i.TOKEN_SYMBOL).value;return new r.Symbol(e.lineno,e.colno,t)},parseFilterArgs:function(e){if(this.peekToken().type===i.TOKEN_LEFT_PAREN){var t=this.parsePostfix(e);return t.args.children}return[]},parseFilter:function(e){for(;this.skip(i.TOKEN_PIPE);){var t=this.parseFilterName();e=new r.Filter(t.lineno,t.colno,t,new r.NodeList(t.lineno,t.colno,[e].concat(this.parseFilterArgs(e))))}return e},parseFilterStatement:function(){var e=this.peekToken();this.skipSymbol("filter")||this.fail("parseFilterStatement: expected filter");var t=this.parseFilterName(),n=this.parseFilterArgs(t);this.advanceAfterBlockEnd(e.value);var i=this.parseUntilBlocks("endfilter");this.advanceAfterBlockEnd();var s=new r.Filter(t.lineno,t.colno,t,new r.NodeList(t.lineno,t.colno,i.children[0].children.concat(n)));return new r.Output(t.lineno,t.colno,[s])},parseAggregate:function(){var e,t=this.nextToken();switch(t.type){case i.TOKEN_LEFT_PAREN:e=new r.Group(t.lineno,t.colno);break;case i.TOKEN_LEFT_BRACKET:e=new r.Array(t.lineno,t.colno);break;case i.TOKEN_LEFT_CURLY:e=new r.Dict(t.lineno,t.colno);break;default:return null}for(;;){var n=this.peekToken().type;if(n===i.TOKEN_RIGHT_PAREN||n===i.TOKEN_RIGHT_BRACKET||n===i.TOKEN_RIGHT_CURLY){this.nextToken();break}if(e.children.length>0&&(this.skip(i.TOKEN_COMMA)||this.fail("parseAggregate: expected comma after expression",t.lineno,t.colno)),e instanceof r.Dict){var s=this.parsePrimary();this.skip(i.TOKEN_COLON)||this.fail("parseAggregate: expected colon after dict key",t.lineno,t.colno);var o=this.parseExpression();e.addChild(new r.Pair(s.lineno,s.colno,s,o))}else{var a=this.parseExpression();e.addChild(a)}}return e},parseSignature:function(e,t){var n=this.peekToken();if(!t&&n.type!==i.TOKEN_LEFT_PAREN){if(e)return null;this.fail("expected arguments",n.lineno,n.colno)}n.type===i.TOKEN_LEFT_PAREN&&(n=this.nextToken());for(var s=new r.NodeList(n.lineno,n.colno),o=new r.KeywordArgs(n.lineno,n.colno),a=!1;;){if(n=this.peekToken(),!t&&n.type===i.TOKEN_RIGHT_PAREN){this.nextToken();break}if(t&&n.type===i.TOKEN_BLOCK_END)break;if(a&&!this.skip(i.TOKEN_COMMA))this.fail("parseSignature: expected comma after expression",n.lineno,n.colno);else{var l=this.parseExpression();this.skipValue(i.TOKEN_OPERATOR,"=")?o.addChild(new r.Pair(l.lineno,l.colno,l,this.parseExpression())):s.addChild(l)}a=!0}return o.children.length&&s.addChild(o),s},parseUntilBlocks:function(){var e=this.breakOnBlocks;this.breakOnBlocks=o.toArray(arguments);var t=this.parse();return this.breakOnBlocks=e,t},parseNodes:function(){for(var e,t=[];e=this.nextToken();)if(e.type===i.TOKEN_DATA){var n=e.value,s=this.peekToken(),o=s&&s.value;this.dropLeadingWhitespace&&(n=n.replace(/^\s*/,""),this.dropLeadingWhitespace=!1),s&&s.type===i.TOKEN_BLOCK_START&&"-"===o.charAt(o.length-1)&&(n=n.replace(/\s*$/,"")),t.push(new r.Output(e.lineno,e.colno,[new r.TemplateData(e.lineno,e.colno,n)]))}else if(e.type===i.TOKEN_BLOCK_START){var a=this.parseStatement();if(!a)break;t.push(a)}else if(e.type===i.TOKEN_VARIABLE_START){var l=this.parseExpression();this.advanceAfterVariableEnd(),t.push(new r.Output(e.lineno,e.colno,[l]))}else e.type!==i.TOKEN_COMMENT&&this.fail("Unexpected token at top-level: "+e.type,e.lineno,e.colno);return t},parse:function(){return new r.NodeList(0,0,this.parseNodes())},parseAsRoot:function(){return new r.Root(0,0,this.parseNodes())}});e.exports={parse:function(e,t,n){var r=new a(i.lex(e,n));return void 0!==t&&(r.extensions=t),r.parseAsRoot()}}},function(e,t,n){"use strict";function i(e,t,n,i){return{type:e,value:t,lineno:n,colno:i}}function r(e,t){this.str=e,this.index=0,this.len=e.length,this.lineno=0,this.colno=0,this.in_code=!1,t=t||{};var n=t.tags||{};this.tags={BLOCK_START:n.blockStart||c,BLOCK_END:n.blockEnd||h,VARIABLE_START:n.variableStart||u,VARIABLE_END:n.variableEnd||p,COMMENT_START:n.commentStart||f,COMMENT_END:n.commentEnd||m},this.trimBlocks=!!t.trimBlocks,this.lstripBlocks=!!t.lstripBlocks}var s=n(1),o=" \n \r ",a="()[]{}%*-+~/#,:|.<>=!",l="0123456789",c="{%",h="%}",u="{{",p="}}",f="{#",m="#}",d="string",v="whitespace",g="data",y="block-start",k="block-end",x="variable-start",b="variable-end",E="comment",w="left-paren",T="right-paren",L="left-bracket",_="right-bracket",O="left-curly",A="right-curly",S="operator",N="comma",C="colon",B="tilde",F="pipe",K="int",R="float",I="boolean",M="none",P="symbol",D="special",V="regex";r.prototype.nextToken=function(){var e,t=this.lineno,n=this.colno;if(this.in_code){var r=this.current();if(this.is_finished())return null;if('"'===r||"'"===r)return i(d,this.parseString(r),t,n);if(e=this._extract(o))return i(v,e,t,n);if((e=this._extractString(this.tags.BLOCK_END))||(e=this._extractString("-"+this.tags.BLOCK_END)))return this.in_code=!1,this.trimBlocks&&(r=this.current(),"\n"===r?this.forward():"\r"===r&&(this.forward(),r=this.current(),"\n"===r?this.forward():this.back())),i(k,e,t,n);if(e=this._extractString(this.tags.VARIABLE_END))return this.in_code=!1,i(b,e,t,n);if("r"===r&&"/"===this.str.charAt(this.index+1)){this.forwardN(2);for(var c="";!this.is_finished();){if("/"===this.current()&&"\\"!==this.previous()){this.forward();break}c+=this.current(),this.forward()}for(var h=["g","i","m","y"],u="";!this.is_finished();){var p=-1!==h.indexOf(this.current());if(!p)break;u+=this.current(),this.forward()}return i(V,{body:c,flags:u},t,n)}if(-1!==a.indexOf(r)){this.forward();var f,m=["==","!=","<=",">=","//","**"],D=r+this.current();switch(-1!==s.indexOf(m,D)&&(this.forward(),r=D),r){case"(":f=w;break;case")":f=T;break;case"[":f=L;break;case"]":f=_;break;case"{":f=O;break;case"}":f=A;break;case",":f=N;break;case":":f=C;break;case"~":f=B;break;case"|":f=F;break;default:f=S}return i(f,r,t,n)}if(e=this._extractUntil(o+a),e.match(/^[-+]?[0-9]+$/)){if("."===this.current()){this.forward();var j=this._extract(l);return i(R,e+"."+j,t,n)}return i(K,e,t,n)}if(e.match(/^(true|false)$/))return i(I,e,t,n);if("none"===e)return i(M,e,t,n);if(e)return i(P,e,t,n);throw new Error("Unexpected value while parsing: "+e)}var U=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;if((e=this._extractString(this.tags.BLOCK_START+"-"))||(e=this._extractString(this.tags.BLOCK_START)))return this.in_code=!0,i(y,e,t,n);if(e=this._extractString(this.tags.VARIABLE_START))return this.in_code=!0,i(x,e,t,n);e="";var W,G=!1;for(this._matches(this.tags.COMMENT_START)&&(G=!0,e=this._extractString(this.tags.COMMENT_START));null!==(W=this._extractUntil(U));){if(e+=W,(this._matches(this.tags.BLOCK_START)||this._matches(this.tags.VARIABLE_START)||this._matches(this.tags.COMMENT_START))&&!G){if(this.lstripBlocks&&this._matches(this.tags.BLOCK_START)&&this.colno>0&&this.colno<=e.length){var Y=e.slice(-this.colno);if(/^\s+$/.test(Y)&&(e=e.slice(0,-this.colno),!e.length))return this.nextToken()}break}if(this._matches(this.tags.COMMENT_END)){if(!G)throw new Error("unexpected end of comment");e+=this._extractString(this.tags.COMMENT_END);break}e+=this.current(),this.forward()}if(null===W&&G)throw new Error("expected end of comment, got end of file");return i(G?E:g,e,t,n)},r.prototype.parseString=function(e){this.forward();for(var t="";!this.is_finished()&&this.current()!==e;){var n=this.current();if("\\"===n){switch(this.forward(),this.current()){case"n":t+="\n";break;case"t":t+=" ";break;case"r":t+="\r";break;default:t+=this.current()}this.forward()}else t+=n,this.forward()}return this.forward(),t},r.prototype._matches=function(e){if(this.index+e.length>this.len)return null;var t=this.str.slice(this.index,this.index+e.length);return t===e},r.prototype._extractString=function(e){return this._matches(e)?(this.index+=e.length,e):null},r.prototype._extractUntil=function(e){return this._extractMatching(!0,e||"")},r.prototype._extract=function(e){return this._extractMatching(!1,e)},r.prototype._extractMatching=function(e,t){if(this.is_finished())return null;var n=t.indexOf(this.current());if(e&&-1===n||!e&&-1!==n){var i=this.current();this.forward();for(var r=t.indexOf(this.current());(e&&-1===r||!e&&-1!==r)&&!this.is_finished();)i+=this.current(),this.forward(),r=t.indexOf(this.current());return i}return""},r.prototype._extractRegex=function(e){var t=this.currentStr().match(e);return t?(this.forwardN(t[0].length),t):null},r.prototype.is_finished=function(){return this.index>=this.len},r.prototype.forwardN=function(e){for(var t=0;e>t;t++)this.forward()},r.prototype.forward=function(){this.index++,"\n"===this.previous()?(this.lineno++,this.colno=0):this.colno++},r.prototype.backN=function(e){for(var t=0;e>t;t++)this.back()},r.prototype.back=function(){if(this.index--,"\n"===this.current()){this.lineno--;var e=this.src.lastIndexOf("\n",this.index-1);-1===e?this.colno=this.index:this.colno=this.index-e}else this.colno--},r.prototype.current=function(){return this.is_finished()?"":this.str.charAt(this.index)},r.prototype.currentStr=function(){return this.is_finished()?"":this.str.substr(this.index)},r.prototype.previous=function(){return this.str.charAt(this.index-1)},e.exports={lex:function(e,t){return new r(e,t)},TOKEN_STRING:d,TOKEN_WHITESPACE:v,TOKEN_DATA:g,TOKEN_BLOCK_START:y,TOKEN_BLOCK_END:k,TOKEN_VARIABLE_START:x,TOKEN_VARIABLE_END:b,TOKEN_COMMENT:E,TOKEN_LEFT_PAREN:w,TOKEN_RIGHT_PAREN:T,TOKEN_LEFT_BRACKET:L,TOKEN_RIGHT_BRACKET:_,TOKEN_LEFT_CURLY:O,TOKEN_RIGHT_CURLY:A,TOKEN_OPERATOR:S,TOKEN_COMMA:N,TOKEN_COLON:C,TOKEN_TILDE:B,TOKEN_PIPE:F,TOKEN_INT:K,TOKEN_FLOAT:R,TOKEN_BOOLEAN:I,TOKEN_NONE:M,TOKEN_SYMBOL:P,TOKEN_SPECIAL:D,TOKEN_REGEX:V}},function(e,t,n){(function(t){"use strict";function i(e,t,n){e instanceof t&&n.push(e),e instanceof a&&e.findAll(t,n)}function r(e,n){function i(e,n,i){for(var r=e.split("\n"),s=0;s0||!i))for(var o=0;n>o;o++)t.stdout.write(" ");s===r.length-1?t.stdout.write(r[s]):t.stdout.write(r[s]+"\n")}}if(n=n||0,i(e.typename+": ",n),e instanceof c)i("\n"),s.each(e.children,function(e){r(e,n+2)});else if(e instanceof re)i(e.extName+"."+e.prop),i("\n"),e.args&&r(e.args,n+2),e.contentArgs&&s.each(e.contentArgs,function(e){r(e,n+2)});else{var o=null,l=null;if(e.iterFields(function(e,t){e instanceof a?(o=o||{},o[t]=e):(l=l||{},l[t]=e)}),l?i(JSON.stringify(l,null,2)+"\n",null,!0):i("\n"),o)for(var h in o)r(o[h],n+2)}}var s=n(1),o=n(6),a=o.extend("Node",{init:function(e,t){this.lineno=e,this.colno=t;for(var n=this.fields,i=0,r=n.length;r>i;i++){var s=n[i],o=arguments[i+2];void 0===o&&(o=null),this[s]=o}},findAll:function(e,t){t=t||[];var n,r;if(this instanceof c){var s=this.children;for(n=0,r=s.length;r>n;n++)i(s[n],e,t)}else{var o=this.fields;for(n=0,r=o.length;r>n;n++)i(this[o[n]],e,t)}return t},iterFields:function(e){s.each(this.fields,function(t){e(this[t],t)},this)}}),l=a.extend("Value",{fields:["value"]}),c=a.extend("NodeList",{fields:["children"],init:function(e,t,n){this.parent(e,t,n||[])},addChild:function(e){this.children.push(e)}}),h=c.extend("Root"),u=l.extend("Literal"),p=l.extend("Symbol"),f=c.extend("Group"),m=c.extend("Array"),d=a.extend("Pair",{fields:["key","value"]}),v=c.extend("Dict"),g=a.extend("LookupVal",{fields:["target","val"]}),y=a.extend("If",{fields:["cond","body","else_"]}),k=y.extend("IfAsync"),x=a.extend("InlineIf",{fields:["cond","body","else_"]}),b=a.extend("For",{fields:["arr","name","body","else_"]}),E=b.extend("AsyncEach"),w=b.extend("AsyncAll"),T=a.extend("Macro",{fields:["name","args","body"]}),L=T.extend("Caller"),_=a.extend("Import",{fields:["template","target","withContext"]}),O=a.extend("FromImport",{fields:["template","names","withContext"],init:function(e,t,n,i,r){this.parent(e,t,n,i||new c,r)}}),A=a.extend("FunCall",{fields:["name","args"]}),S=A.extend("Filter"),N=S.extend("FilterAsync",{fields:["name","args","symbol"]}),C=v.extend("KeywordArgs"),B=a.extend("Block",{fields:["name","body"]}),F=a.extend("Super",{fields:["blockName","symbol"]}),K=a.extend("TemplateRef",{fields:["template"]}),R=K.extend("Extends"),I=a.extend("Include",{fields:["template","ignoreMissing"]}),M=a.extend("Set",{fields:["targets","value"]}),P=c.extend("Output"),D=u.extend("TemplateData"),V=a.extend("UnaryOp",{fields:["target"]}),j=a.extend("BinOp",{fields:["left","right"]}),U=j.extend("In"),W=j.extend("Or"),G=j.extend("And"),Y=V.extend("Not"),H=j.extend("Add"),$=j.extend("Concat"),z=j.extend("Sub"),X=j.extend("Mul"),q=j.extend("Div"),J=j.extend("FloorDiv"),Q=j.extend("Mod"),Z=j.extend("Pow"),ee=V.extend("Neg"),te=V.extend("Pos"),ne=a.extend("Compare",{fields:["expr","ops"]}),ie=a.extend("CompareOperand",{fields:["expr","type"]}),re=a.extend("CallExtension",{fields:["extName","prop","args","contentArgs"],init:function(e,t,n,i){this.extName=e._name||e,this.prop=t,this.args=n||new c,this.contentArgs=i||[],this.autoescape=e.autoescape}}),se=re.extend("CallExtensionAsync");e.exports={Node:a,Root:h,NodeList:c,Value:l,Literal:u,Symbol:p,Group:f,Array:m,Pair:d,Dict:v,Output:P,TemplateData:D,If:y,IfAsync:k,InlineIf:x,For:b,AsyncEach:E,AsyncAll:w,Macro:T,Caller:L,Import:_,FromImport:O,FunCall:A,Filter:S,FilterAsync:N,KeywordArgs:C,Block:B,Super:F,Extends:R,Include:I,Set:M,LookupVal:g,BinOp:j,In:U,Or:W,And:G,Not:Y,Add:H,Concat:$,Sub:z,Mul:X,Div:q,FloorDiv:J,Mod:Q,Pow:Z,Neg:ee,Pos:te,Compare:ne,CompareOperand:ie,CallExtension:re,CallExtensionAsync:se,printNodes:r}}).call(t,n(3))},function(e,t,n){"use strict";function i(){return"hole_"+d++}function r(e,t){for(var n=null,i=0;ie.length){i=Array.prototype.slice.call(arguments,0,e.length);var c=Array.prototype.slice.call(arguments,i.length,a);for(r=0;ri;i++)s.push(n);r.push(s)}return r},capitalize:function(e){e=i(e,"");var t=e.toLowerCase();return s.copySafeness(e,t.charAt(0).toUpperCase()+t.slice(1))},center:function(e,t){if(e=i(e,""),t=t||80,e.length>=t)return e;var n=t-e.length,o=r.repeat(" ",n/2-n%2),a=r.repeat(" ",n/2);return s.copySafeness(e,o+e+a)},"default":function(e,t,n){return n?e?e:t:void 0!==e?e:t},dictsort:function(e,t,n){if(!r.isObject(e))throw new r.TemplateError("dictsort filter: val must be an object");var i=[];for(var s in e)i.push([s,e[s]]);var o;if(void 0===n||"key"===n)o=0;else{if("value"!==n)throw new r.TemplateError("dictsort filter: You can only sort by either key or value");o=1}return i.sort(function(e,n){var i=e[o],s=n[o];return t||(r.isString(i)&&(i=i.toUpperCase()),r.isString(s)&&(s=s.toUpperCase())),i>s?1:i===s?0:-1}),i},dump:function(e){return JSON.stringify(e)},escape:function(e){return"string"==typeof e||e instanceof s.SafeString?r.escape(e):e},safe:function(e){return s.markSafe(e)},first:function(e){return e[0]},groupby:function(e,t){return r.groupBy(e,t)},indent:function(e,t,n){if(e=i(e,""),""===e)return"";t=t||4;for(var o="",a=e.split("\n"),l=r.repeat(" ",t),c=0;c-1&&(-1===i||i>c);)o+=e.substring(l,a)+n, +l=a+t.length,c++,a=e.indexOf(t,l);return la;a++){var l=s+a*i;r>a&&s++;var c=s+(a+1)*i,h=e.slice(l,c);n&&a>=r&&h.push(n),o.push(h)}return o},sort:s.makeMacro(["value","reverse","case_sensitive","attribute"],[],function(e,t,n,i){return e=r.map(e,function(e){return e}),e.sort(function(e,s){var o,a;return i?(o=e[i],a=s[i]):(o=e,a=s),!n&&r.isString(o)&&r.isString(a)&&(o=o.toLowerCase(),a=a.toLowerCase()),a>o?t?1:-1:o>a?t?-1:1:0}),e}),string:function(e){return s.copySafeness(e,e)},striptags:function(e,t){e=i(e,""),t=t||!1;var n=/<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi,r=o.trim(e.replace(n,"")),a="";return a=t?r.replace(/^ +| +$/gm,"").replace(/ +/g," ").replace(/(\r\n)/g,"\n").replace(/\n\n\n+/g,"\n\n"):r.replace(/\s+/gi," "),s.copySafeness(e,a)},title:function(e){e=i(e,"");for(var t=e.split(" "),n=0;n"+c.substr(0,t)+"":a.test(c)?'"+c.substr(0,t)+"":s.test(c)?''+c+"":l.test(c)?'"+c.substr(0,t)+"":e});return c.join(" ")},wordcount:function(e){e=i(e,"");var t=e?e.match(/\w+/g):null;return t?t.length:null},"float":function(e,t){var n=parseFloat(e);return isNaN(n)?t:n},"int":function(e,t){var n=parseInt(e,10);return isNaN(n)?t:n}};o.d=o["default"],o.e=o.escape,e.exports=o},function(e,t,n){"use strict";var i=n(15),r=n(16),s=i.extend({init:function(e,t){this.baseURL=e||".",t=t||{},this.useCache=!!t.useCache,this.async=!!t.async},resolve:function(e,t){throw new Error("relative templates not support in the browser yet")},getSource:function(e,t){var n,i=this.useCache;return this.fetch(this.baseURL+"/"+e,function(r,s){if(r)if(t)t(r.content);else{if(404!==r.status)throw r.content;n=null}else n={src:s,path:e,noCache:!i},t&&t(null,n)}),n},fetch:function(e,t){var n,i=!0;window.XMLHttpRequest?n=new XMLHttpRequest:window.ActiveXObject&&(n=new ActiveXObject("Microsoft.XMLHTTP")),n.onreadystatechange=function(){4===n.readyState&&i&&(i=!1,0===n.status||200===n.status?t(null,n.responseText):t({status:n.status,content:n.responseText}))},e+=(-1===e.indexOf("?")?"?":"&")+"s="+(new Date).getTime(),n.open("GET",e,this.async),n.send()}});e.exports={WebLoader:s,PrecompiledLoader:r}},function(e,t,n){"use strict";var i=n(3),r=n(6),s=n(1),o=r.extend({on:function(e,t){this.listeners=this.listeners||{},this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t)},emit:function(e){var t=Array.prototype.slice.call(arguments,1);this.listeners&&this.listeners[e]&&s.each(this.listeners[e],function(e){e.apply(null,t)})},resolve:function(e,t){return i.resolve(i.dirname(e),t)},isRelative:function(e){return 0===e.indexOf("./")||0===e.indexOf("../")}});e.exports=o},function(e,t,n){"use strict";var i=n(15),r=i.extend({init:function(e){this.precompiled=e||{}},getSource:function(e){return this.precompiled[e]?{src:{type:"code",obj:this.precompiled[e]},path:e}:null}});e.exports=r},function(e,t){"use strict";function n(e){var t=-1;return{current:null,reset:function(){t=-1,this.current=null},next:function(){return t++,t>=e.length&&(t=0),this.current=e[t],this.current}}}function i(e){e=e||",";var t=!0;return function(){var n=t?"":e;return t=!1,n}}function r(){return{range:function(e,t,n){t?n||(n=1):(t=e,e=0,n=1);var i,r=[];if(n>0)for(i=e;t>i;i+=n)r.push(i);else for(i=e;i>t;i+=n)r.push(i);return r},cycler:function(){return n(Array.prototype.slice.call(arguments))},joiner:function(e){return i(e)}}}e.exports=r},function(e,t){function n(){"use strict";var e=this.runtime,t=this.lib,n=e.contextOrFrameLookup;e.contextOrFrameLookup=function(e,t,i){var r=n.apply(this,arguments);if(void 0===r)switch(i){case"True":return!0;case"False":return!1;case"None":return null}return r};var i=e.memberLookup,r={pop:function(e){if(void 0===e)return this.pop();if(e>=this.length||0>e)throw new Error("KeyError");return this.splice(e,1)},remove:function(e){for(var t=0;t {% for request in session.requests %} - {% include "request.html" %} + {% include "views/request.html" %} {% endfor %}
  • No certificate signing requests to sign! You can submit a certificate signing request by:

    @@ -31,7 +31,7 @@
      {% for certificate in session.signed | sort | reverse %} - {% include "signed.html" %} + {% include "views/signed.html" %} {% endfor %}
    diff --git a/certidude/static/configuration.html b/certidude/static/views/configuration.html similarity index 92% rename from certidude/static/configuration.html rename to certidude/static/views/configuration.html index b9a57b1..9ea26af 100644 --- a/certidude/static/configuration.html +++ b/certidude/static/views/configuration.html @@ -10,7 +10,7 @@ attaches attribute something diff --git a/certidude/static/error.html b/certidude/static/views/error.html similarity index 100% rename from certidude/static/error.html rename to certidude/static/views/error.html diff --git a/certidude/static/logentry.html b/certidude/static/views/logentry.html similarity index 100% rename from certidude/static/logentry.html rename to certidude/static/views/logentry.html diff --git a/certidude/static/request.html b/certidude/static/views/request.html similarity index 100% rename from certidude/static/request.html rename to certidude/static/views/request.html diff --git a/certidude/static/signed.html b/certidude/static/views/signed.html similarity index 94% rename from certidude/static/signed.html rename to certidude/static/views/signed.html index df28fb5..a1a7178 100644 --- a/certidude/static/signed.html +++ b/certidude/static/views/signed.html @@ -32,11 +32,11 @@
    - {% include 'status.html' %} + {% include 'views/status.html' %}
  • diff --git a/certidude/static/status.html b/certidude/static/views/status.html similarity index 100% rename from certidude/static/status.html rename to certidude/static/views/status.html diff --git a/certidude/static/tagtypes.html b/certidude/static/views/tagtypes.html similarity index 100% rename from certidude/static/tagtypes.html rename to certidude/static/views/tagtypes.html