diff --git a/hw7/Claudio_Maggioni/package.json b/hw7/Claudio_Maggioni/package.json index 1fdb255..0cc0ad8 100644 --- a/hw7/Claudio_Maggioni/package.json +++ b/hw7/Claudio_Maggioni/package.json @@ -4,6 +4,7 @@ "description": "Exercise 7 of Web Atelier. Express.js and Mongoose", "main": "app.js", "scripts": { + "dustc": "cd ./views; dustc *.dust partials/*.dust -o ../public/js/views.js", "start": "DEBUG='canvas-server' nodemon ./bin/www", "test": "npm run test-mocha", "test-mocha": "./node_modules/mocha/bin/mocha -R spec ./test/routes ./test/hypermedia" diff --git a/hw7/Claudio_Maggioni/public/dustjs-linkedin/LICENSE b/hw7/Claudio_Maggioni/public/dustjs-linkedin/LICENSE new file mode 100644 index 0000000..1c59043 --- /dev/null +++ b/hw7/Claudio_Maggioni/public/dustjs-linkedin/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Aleksander Williams + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.js b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.js new file mode 100644 index 0000000..10afb21 --- /dev/null +++ b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.js @@ -0,0 +1,1157 @@ +/*! dustjs-linkedin - v2.7.5 +* http://dustjs.com/ +* Copyright (c) 2016 Aleksander Williams; Released under the MIT License */ +(function (root, factory) { + if (typeof define === 'function' && define.amd && define.amd.dust === true) { + define('dust.core', [], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.dust = factory(); + } +}(this, function() { + var dust = { + "version": "2.7.5" + }, + NONE = 'NONE', ERROR = 'ERROR', WARN = 'WARN', INFO = 'INFO', DEBUG = 'DEBUG', + EMPTY_FUNC = function() {}; + + dust.config = { + whitespace: false, + amd: false, + cjs: false, + cache: true + }; + + // Directive aliases to minify code + dust._aliases = { + "write": "w", + "end": "e", + "map": "m", + "render": "r", + "reference": "f", + "section": "s", + "exists": "x", + "notexists": "nx", + "block": "b", + "partial": "p", + "helper": "h" + }; + + (function initLogging() { + /*global process, console*/ + var loggingLevels = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, NONE: 4 }, + consoleLog, + log; + + if (typeof console !== 'undefined' && console.log) { + consoleLog = console.log; + if(typeof consoleLog === 'function') { + log = function() { + consoleLog.apply(console, arguments); + }; + } else { + log = function() { + consoleLog(Array.prototype.slice.apply(arguments).join(' ')); + }; + } + } else { + log = EMPTY_FUNC; + } + + /** + * Filters messages based on `dust.debugLevel`. + * This default implementation will print to the console if it exists. + * @param {String|Error} message the message to print/throw + * @param {String} type the severity of the message(ERROR, WARN, INFO, or DEBUG) + * @public + */ + dust.log = function(message, type) { + type = type || INFO; + if (loggingLevels[type] >= loggingLevels[dust.debugLevel]) { + log('[DUST:' + type + ']', message); + } + }; + + dust.debugLevel = NONE; + if(typeof process !== 'undefined' && process.env && /\bdust\b/.test(process.env.DEBUG)) { + dust.debugLevel = DEBUG; + } + + }()); + + dust.helpers = {}; + + dust.cache = {}; + + dust.register = function(name, tmpl) { + if (!name) { + return; + } + tmpl.templateName = name; + if (dust.config.cache !== false) { + dust.cache[name] = tmpl; + } + }; + + dust.render = function(nameOrTemplate, context, callback) { + var chunk = new Stub(callback).head; + try { + load(nameOrTemplate, chunk, context).end(); + } catch (err) { + chunk.setError(err); + } + }; + + dust.stream = function(nameOrTemplate, context) { + var stream = new Stream(), + chunk = stream.head; + dust.nextTick(function() { + try { + load(nameOrTemplate, chunk, context).end(); + } catch (err) { + chunk.setError(err); + } + }); + return stream; + }; + + /** + * Extracts a template function (body_0) from whatever is passed. + * @param nameOrTemplate {*} Could be: + * - the name of a template to load from cache + * - a CommonJS-compiled template (a function with a `template` property) + * - a template function + * @param loadFromCache {Boolean} if false, don't look in the cache + * @return {Function} a template function, if found + */ + function getTemplate(nameOrTemplate, loadFromCache/*=true*/) { + if(!nameOrTemplate) { + return; + } + if(typeof nameOrTemplate === 'function' && nameOrTemplate.template) { + // Sugar away CommonJS module templates + return nameOrTemplate.template; + } + if(dust.isTemplateFn(nameOrTemplate)) { + // Template functions passed directly + return nameOrTemplate; + } + if(loadFromCache !== false) { + // Try loading a template with this name from cache + return dust.cache[nameOrTemplate]; + } + } + + function load(nameOrTemplate, chunk, context) { + if(!nameOrTemplate) { + return chunk.setError(new Error('No template or template name provided to render')); + } + + var template = getTemplate(nameOrTemplate, dust.config.cache); + + if (template) { + return template(chunk, Context.wrap(context, template.templateName)); + } else { + if (dust.onLoad) { + return chunk.map(function(chunk) { + // Alias just so it's easier to read that this would always be a name + var name = nameOrTemplate; + // Three possible scenarios for a successful callback: + // - `require(nameOrTemplate)(dust); cb()` + // - `src = readFile('src.dust'); cb(null, src)` + // - `compiledTemplate = require(nameOrTemplate)(dust); cb(null, compiledTemplate)` + function done(err, srcOrTemplate) { + var template; + if (err) { + return chunk.setError(err); + } + // Prefer a template that is passed via callback over the cached version. + template = getTemplate(srcOrTemplate, false) || getTemplate(name, dust.config.cache); + if (!template) { + // It's a template string, compile it and register under `name` + if(dust.compile) { + template = dust.loadSource(dust.compile(srcOrTemplate, name)); + } else { + return chunk.setError(new Error('Dust compiler not available')); + } + } + template(chunk, Context.wrap(context, template.templateName)).end(); + } + + if(dust.onLoad.length === 3) { + dust.onLoad(name, context.options, done); + } else { + dust.onLoad(name, done); + } + }); + } + return chunk.setError(new Error('Template Not Found: ' + nameOrTemplate)); + } + } + + dust.loadSource = function(source) { + /*jshint evil:true*/ + return eval(source); + }; + + if (Array.isArray) { + dust.isArray = Array.isArray; + } else { + dust.isArray = function(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; + } + + dust.nextTick = (function() { + return function(callback) { + setTimeout(callback, 0); + }; + })(); + + /** + * Dust has its own rules for what is "empty"-- which is not the same as falsy. + * Empty arrays, null, and undefined are empty + */ + dust.isEmpty = function(value) { + if (value === 0) { + return false; + } + if (dust.isArray(value) && !value.length) { + return true; + } + return !value; + }; + + dust.isEmptyObject = function(obj) { + var key; + if (obj === null) { + return false; + } + if (obj === undefined) { + return false; + } + if (obj.length > 0) { + return false; + } + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + return false; + } + } + return true; + }; + + dust.isTemplateFn = function(elem) { + return typeof elem === 'function' && + elem.__dustBody; + }; + + /** + * Decide somewhat-naively if something is a Thenable. + * @param elem {*} object to inspect + * @return {Boolean} is `elem` a Thenable? + */ + dust.isThenable = function(elem) { + return elem && + typeof elem === 'object' && + typeof elem.then === 'function'; + }; + + /** + * Decide very naively if something is a Stream. + * @param elem {*} object to inspect + * @return {Boolean} is `elem` a Stream? + */ + dust.isStreamable = function(elem) { + return elem && + typeof elem.on === 'function' && + typeof elem.pipe === 'function'; + }; + + // apply the filter chain and return the output string + dust.filter = function(string, auto, filters, context) { + var i, len, name, filter; + if (filters) { + for (i = 0, len = filters.length; i < len; i++) { + name = filters[i]; + if (!name.length) { + continue; + } + filter = dust.filters[name]; + if (name === 's') { + auto = null; + } else if (typeof filter === 'function') { + string = filter(string, context); + } else { + dust.log('Invalid filter `' + name + '`', WARN); + } + } + } + // by default always apply the h filter, unless asked to unescape with |s + if (auto) { + string = dust.filters[auto](string, context); + } + return string; + }; + + dust.filters = { + h: function(value) { return dust.escapeHtml(value); }, + j: function(value) { return dust.escapeJs(value); }, + u: encodeURI, + uc: encodeURIComponent, + js: function(value) { return dust.escapeJSON(value); }, + jp: function(value) { + if (!JSON) {dust.log('JSON is undefined; could not parse `' + value + '`', WARN); + return value; + } else { + return JSON.parse(value); + } + } + }; + + function Context(stack, global, options, blocks, templateName) { + if(stack !== undefined && !(stack instanceof Stack)) { + stack = new Stack(stack); + } + this.stack = stack; + this.global = global; + this.options = options; + this.blocks = blocks; + this.templateName = templateName; + this._isContext = true; + } + + dust.makeBase = dust.context = function(global, options) { + return new Context(undefined, global, options); + }; + + dust.isContext = function(obj) { + return typeof obj === "object" && obj._isContext === true; + }; + + /** + * Factory function that creates a closure scope around a Thenable-callback. + * Returns a function that can be passed to a Thenable that will resume a + * Context lookup once the Thenable resolves with new data, adding that new + * data to the lookup stack. + */ + function getWithResolvedData(ctx, cur, down) { + return function(data) { + return ctx.push(data)._get(cur, down); + }; + } + + Context.wrap = function(context, name) { + if (dust.isContext(context)) { + return context; + } + return new Context(context, {}, {}, null, name); + }; + + /** + * Public API for getting a value from the context. + * @method get + * @param {string|array} path The path to the value. Supported formats are: + * 'key' + * 'path.to.key' + * '.path.to.key' + * ['path', 'to', 'key'] + * ['key'] + * @param {boolean} [cur=false] Boolean which determines if the search should be limited to the + * current context (true), or if get should search in parent contexts as well (false). + * @public + * @returns {string|object} + */ + Context.prototype.get = function(path, cur) { + if (typeof path === 'string') { + if (path[0] === '.') { + cur = true; + path = path.substr(1); + } + path = path.split('.'); + } + return this._get(cur, path); + }; + + /** + * Get a value from the context + * @method _get + * @param {boolean} cur Get only from the current context + * @param {array} down An array of each step in the path + * @private + * @return {string | object} + */ + Context.prototype._get = function(cur, down) { + var ctx = this.stack || {}, + i = 1, + value, first, len, ctxThis, fn; + + first = down[0]; + len = down.length; + + if (cur && len === 0) { + ctxThis = ctx; + ctx = ctx.head; + } else { + if (!cur) { + // Search up the stack for the first value + while (ctx) { + if (ctx.isObject) { + ctxThis = ctx.head; + value = ctx.head[first]; + if (value !== undefined) { + break; + } + } + ctx = ctx.tail; + } + + // Try looking in the global context if we haven't found anything yet + if (value !== undefined) { + ctx = value; + } else { + ctx = this.global && this.global[first]; + } + } else if (ctx) { + // if scope is limited by a leading dot, don't search up the tree + if(ctx.head) { + ctx = ctx.head[first]; + } else { + // context's head is empty, value we are searching for is not defined + ctx = undefined; + } + } + + while (ctx && i < len) { + if (dust.isThenable(ctx)) { + // Bail early by returning a Thenable for the remainder of the search tree + return ctx.then(getWithResolvedData(this, cur, down.slice(i))); + } + ctxThis = ctx; + ctx = ctx[down[i]]; + i++; + } + } + + if (typeof ctx === 'function') { + fn = function() { + try { + return ctx.apply(ctxThis, arguments); + } catch (err) { + dust.log(err, ERROR); + throw err; + } + }; + fn.__dustBody = !!ctx.__dustBody; + return fn; + } else { + if (ctx === undefined) { + dust.log('Cannot find reference `{' + down.join('.') + '}` in template `' + this.getTemplateName() + '`', INFO); + } + return ctx; + } + }; + + Context.prototype.getPath = function(cur, down) { + return this._get(cur, down); + }; + + Context.prototype.push = function(head, idx, len) { + if(head === undefined) { + dust.log("Not pushing an undefined variable onto the context", INFO); + return this; + } + return this.rebase(new Stack(head, this.stack, idx, len)); + }; + + Context.prototype.pop = function() { + var head = this.current(); + this.stack = this.stack && this.stack.tail; + return head; + }; + + Context.prototype.rebase = function(head) { + return new Context(head, this.global, this.options, this.blocks, this.getTemplateName()); + }; + + Context.prototype.clone = function() { + var context = this.rebase(); + context.stack = this.stack; + return context; + }; + + Context.prototype.current = function() { + return this.stack && this.stack.head; + }; + + Context.prototype.getBlock = function(key) { + var blocks, len, fn; + + if (typeof key === 'function') { + key = key(new Chunk(), this).data.join(''); + } + + blocks = this.blocks; + + if (!blocks) { + dust.log('No blocks for context `' + key + '` in template `' + this.getTemplateName() + '`', DEBUG); + return false; + } + + len = blocks.length; + while (len--) { + fn = blocks[len][key]; + if (fn) { + return fn; + } + } + + dust.log('Malformed template `' + this.getTemplateName() + '` was missing one or more blocks.'); + return false; + }; + + Context.prototype.shiftBlocks = function(locals) { + var blocks = this.blocks, + newBlocks; + + if (locals) { + if (!blocks) { + newBlocks = [locals]; + } else { + newBlocks = blocks.concat([locals]); + } + return new Context(this.stack, this.global, this.options, newBlocks, this.getTemplateName()); + } + return this; + }; + + Context.prototype.resolve = function(body) { + var chunk; + + if(typeof body !== 'function') { + return body; + } + chunk = new Chunk().render(body, this); + if(chunk instanceof Chunk) { + return chunk.data.join(''); // ie7 perf + } + return chunk; + }; + + Context.prototype.getTemplateName = function() { + return this.templateName; + }; + + function Stack(head, tail, idx, len) { + this.tail = tail; + this.isObject = head && typeof head === 'object'; + this.head = head; + this.index = idx; + this.of = len; + } + + function Stub(callback) { + this.head = new Chunk(this); + this.callback = callback; + this.out = ''; + } + + Stub.prototype.flush = function() { + var chunk = this.head; + + while (chunk) { + if (chunk.flushable) { + this.out += chunk.data.join(''); //ie7 perf + } else if (chunk.error) { + this.callback(chunk.error); + dust.log('Rendering failed with error `' + chunk.error + '`', ERROR); + this.flush = EMPTY_FUNC; + return; + } else { + return; + } + chunk = chunk.next; + this.head = chunk; + } + this.callback(null, this.out); + }; + + /** + * Creates an interface sort of like a Streams2 ReadableStream. + */ + function Stream() { + this.head = new Chunk(this); + } + + Stream.prototype.flush = function() { + var chunk = this.head; + + while(chunk) { + if (chunk.flushable) { + this.emit('data', chunk.data.join('')); //ie7 perf + } else if (chunk.error) { + this.emit('error', chunk.error); + this.emit('end'); + dust.log('Streaming failed with error `' + chunk.error + '`', ERROR); + this.flush = EMPTY_FUNC; + return; + } else { + return; + } + chunk = chunk.next; + this.head = chunk; + } + this.emit('end'); + }; + + /** + * Executes listeners for `type` by passing data. Note that this is different from a + * Node stream, which can pass an arbitrary number of arguments + * @return `true` if event had listeners, `false` otherwise + */ + Stream.prototype.emit = function(type, data) { + var events = this.events || {}, + handlers = events[type] || [], + i, l; + + if (!handlers.length) { + dust.log('Stream broadcasting, but no listeners for `' + type + '`', DEBUG); + return false; + } + + handlers = handlers.slice(0); + for (i = 0, l = handlers.length; i < l; i++) { + handlers[i](data); + } + return true; + }; + + Stream.prototype.on = function(type, callback) { + var events = this.events = this.events || {}, + handlers = events[type] = events[type] || []; + + if(typeof callback !== 'function') { + dust.log('No callback function provided for `' + type + '` event listener', WARN); + } else { + handlers.push(callback); + } + return this; + }; + + /** + * Pipes to a WritableStream. Note that backpressure isn't implemented, + * so we just write as fast as we can. + * @param stream {WritableStream} + * @return self + */ + Stream.prototype.pipe = function(stream) { + if(typeof stream.write !== 'function' || + typeof stream.end !== 'function') { + dust.log('Incompatible stream passed to `pipe`', WARN); + return this; + } + + var destEnded = false; + + if(typeof stream.emit === 'function') { + stream.emit('pipe', this); + } + + if(typeof stream.on === 'function') { + stream.on('error', function() { + destEnded = true; + }); + } + + return this + .on('data', function(data) { + if(destEnded) { + return; + } + try { + stream.write(data, 'utf8'); + } catch (err) { + dust.log(err, ERROR); + } + }) + .on('end', function() { + if(destEnded) { + return; + } + try { + stream.end(); + destEnded = true; + } catch (err) { + dust.log(err, ERROR); + } + }); + }; + + function Chunk(root, next, taps) { + this.root = root; + this.next = next; + this.data = []; //ie7 perf + this.flushable = false; + this.taps = taps; + } + + Chunk.prototype.write = function(data) { + var taps = this.taps; + + if (taps) { + data = taps.go(data); + } + this.data.push(data); + return this; + }; + + Chunk.prototype.end = function(data) { + if (data) { + this.write(data); + } + this.flushable = true; + this.root.flush(); + return this; + }; + + Chunk.prototype.map = function(callback) { + var cursor = new Chunk(this.root, this.next, this.taps), + branch = new Chunk(this.root, cursor, this.taps); + + this.next = branch; + this.flushable = true; + try { + callback(branch); + } catch(err) { + dust.log(err, ERROR); + branch.setError(err); + } + return cursor; + }; + + Chunk.prototype.tap = function(tap) { + var taps = this.taps; + + if (taps) { + this.taps = taps.push(tap); + } else { + this.taps = new Tap(tap); + } + return this; + }; + + Chunk.prototype.untap = function() { + this.taps = this.taps.tail; + return this; + }; + + Chunk.prototype.render = function(body, context) { + return body(this, context); + }; + + Chunk.prototype.reference = function(elem, context, auto, filters) { + if (typeof elem === 'function') { + elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]); + if (elem instanceof Chunk) { + return elem; + } else { + return this.reference(elem, context, auto, filters); + } + } + if (dust.isThenable(elem)) { + return this.await(elem, context, null, auto, filters); + } else if (dust.isStreamable(elem)) { + return this.stream(elem, context, null, auto, filters); + } else if (!dust.isEmpty(elem)) { + return this.write(dust.filter(elem, auto, filters, context)); + } else { + return this; + } + }; + + Chunk.prototype.section = function(elem, context, bodies, params) { + var body = bodies.block, + skip = bodies['else'], + chunk = this, + i, len, head; + + if (typeof elem === 'function' && !dust.isTemplateFn(elem)) { + try { + elem = elem.apply(context.current(), [this, context, bodies, params]); + } catch(err) { + dust.log(err, ERROR); + return this.setError(err); + } + // Functions that return chunks are assumed to have handled the chunk manually. + // Make that chunk the current one and go to the next method in the chain. + if (elem instanceof Chunk) { + return elem; + } + } + + if (dust.isEmptyObject(bodies)) { + // No bodies to render, and we've already invoked any function that was available in + // hopes of returning a Chunk. + return chunk; + } + + if (!dust.isEmptyObject(params)) { + context = context.push(params); + } + + /* + Dust's default behavior is to enumerate over the array elem, passing each object in the array to the block. + When elem resolves to a value or object instead of an array, Dust sets the current context to the value + and renders the block one time. + */ + if (dust.isArray(elem)) { + if (body) { + len = elem.length; + if (len > 0) { + head = context.stack && context.stack.head || {}; + head.$len = len; + for (i = 0; i < len; i++) { + head.$idx = i; + chunk = body(chunk, context.push(elem[i], i, len)); + } + head.$idx = undefined; + head.$len = undefined; + return chunk; + } else if (skip) { + return skip(this, context); + } + } + } else if (dust.isThenable(elem)) { + return this.await(elem, context, bodies); + } else if (dust.isStreamable(elem)) { + return this.stream(elem, context, bodies); + } else if (elem === true) { + // true is truthy but does not change context + if (body) { + return body(this, context); + } + } else if (elem || elem === 0) { + // everything that evaluates to true are truthy ( e.g. Non-empty strings and Empty objects are truthy. ) + // zero is truthy + // for anonymous functions that did not returns a chunk, truthiness is evaluated based on the return value + if (body) { + return body(this, context.push(elem)); + } + // nonexistent, scalar false value, scalar empty string, null, + // undefined are all falsy + } else if (skip) { + return skip(this, context); + } + dust.log('Section without corresponding key in template `' + context.getTemplateName() + '`', DEBUG); + return this; + }; + + Chunk.prototype.exists = function(elem, context, bodies) { + var body = bodies.block, + skip = bodies['else']; + + if (!dust.isEmpty(elem)) { + if (body) { + return body(this, context); + } + dust.log('No block for exists check in template `' + context.getTemplateName() + '`', DEBUG); + } else if (skip) { + return skip(this, context); + } + return this; + }; + + Chunk.prototype.notexists = function(elem, context, bodies) { + var body = bodies.block, + skip = bodies['else']; + + if (dust.isEmpty(elem)) { + if (body) { + return body(this, context); + } + dust.log('No block for not-exists check in template `' + context.getTemplateName() + '`', DEBUG); + } else if (skip) { + return skip(this, context); + } + return this; + }; + + Chunk.prototype.block = function(elem, context, bodies) { + var body = elem || bodies.block; + + if (body) { + return body(this, context); + } + return this; + }; + + Chunk.prototype.partial = function(elem, context, partialContext, params) { + var head; + + if(params === undefined) { + // Compatibility for < 2.7.0 where `partialContext` did not exist + params = partialContext; + partialContext = context; + } + + if (!dust.isEmptyObject(params)) { + partialContext = partialContext.clone(); + head = partialContext.pop(); + partialContext = partialContext.push(params) + .push(head); + } + + if (dust.isTemplateFn(elem)) { + // The eventual result of evaluating `elem` is a partial name + // Load the partial after getting its name and end the async chunk + return this.capture(elem, context, function(name, chunk) { + partialContext.templateName = name; + load(name, chunk, partialContext).end(); + }); + } else { + partialContext.templateName = elem; + return load(elem, this, partialContext); + } + }; + + Chunk.prototype.helper = function(name, context, bodies, params, auto) { + var chunk = this, + filters = params.filters, + ret; + + // Pre-2.7.1 compat: if auto is undefined, it's an old template. Automatically escape + if (auto === undefined) { + auto = 'h'; + } + + // handle invalid helpers, similar to invalid filters + if(dust.helpers[name]) { + try { + ret = dust.helpers[name](chunk, context, bodies, params); + if (ret instanceof Chunk) { + return ret; + } + if(typeof filters === 'string') { + filters = filters.split('|'); + } + if (!dust.isEmptyObject(bodies)) { + return chunk.section(ret, context, bodies, params); + } + // Helpers act slightly differently from functions in context in that they will act as + // a reference if they are self-closing (due to grammar limitations) + // In the Chunk.await function we check to make sure bodies is null before acting as a reference + return chunk.reference(ret, context, auto, filters); + } catch(err) { + dust.log('Error in helper `' + name + '`: ' + err.message, ERROR); + return chunk.setError(err); + } + } else { + dust.log('Helper `' + name + '` does not exist', WARN); + return chunk; + } + }; + + /** + * Reserve a chunk to be evaluated once a thenable is resolved or rejected + * @param thenable {Thenable} the target thenable to await + * @param context {Context} context to use to render the deferred chunk + * @param bodies {Object} must contain a "body", may contain an "error" + * @param auto {String} automatically apply this filter if the Thenable is a reference + * @param filters {Array} apply these filters if the Thenable is a reference + * @return {Chunk} + */ + Chunk.prototype.await = function(thenable, context, bodies, auto, filters) { + return this.map(function(chunk) { + thenable.then(function(data) { + if (bodies) { + chunk = chunk.section(data, context, bodies); + } else { + // Actually a reference. Self-closing sections don't render + chunk = chunk.reference(data, context, auto, filters); + } + chunk.end(); + }, function(err) { + var errorBody = bodies && bodies.error; + if(errorBody) { + chunk.render(errorBody, context.push(err)).end(); + } else { + dust.log('Unhandled promise rejection in `' + context.getTemplateName() + '`', INFO); + chunk.end(); + } + }); + }); + }; + + /** + * Reserve a chunk to be evaluated with the contents of a streamable. + * Currently an error event will bomb out the stream. Once an error + * is received, we push it to an {:error} block if one exists, and log otherwise, + * then stop listening to the stream. + * @param streamable {Streamable} the target streamable that will emit events + * @param context {Context} context to use to render each thunk + * @param bodies {Object} must contain a "body", may contain an "error" + * @return {Chunk} + */ + Chunk.prototype.stream = function(stream, context, bodies, auto, filters) { + var body = bodies && bodies.block, + errorBody = bodies && bodies.error; + return this.map(function(chunk) { + var ended = false; + stream + .on('data', function data(thunk) { + if(ended) { + return; + } + if(body) { + // Fork a new chunk out of the blockstream so that we can flush it independently + chunk = chunk.map(function(chunk) { + chunk.render(body, context.push(thunk)).end(); + }); + } else if(!bodies) { + // When actually a reference, don't fork, just write into the master async chunk + chunk = chunk.reference(thunk, context, auto, filters); + } + }) + .on('error', function error(err) { + if(ended) { + return; + } + if(errorBody) { + chunk.render(errorBody, context.push(err)); + } else { + dust.log('Unhandled stream error in `' + context.getTemplateName() + '`', INFO); + } + if(!ended) { + ended = true; + chunk.end(); + } + }) + .on('end', function end() { + if(!ended) { + ended = true; + chunk.end(); + } + }); + }); + }; + + Chunk.prototype.capture = function(body, context, callback) { + return this.map(function(chunk) { + var stub = new Stub(function(err, out) { + if (err) { + chunk.setError(err); + } else { + callback(out, chunk); + } + }); + body(stub.head, context).end(); + }); + }; + + Chunk.prototype.setError = function(err) { + this.error = err; + this.root.flush(); + return this; + }; + + // Chunk aliases + for(var f in Chunk.prototype) { + if(dust._aliases[f]) { + Chunk.prototype[dust._aliases[f]] = Chunk.prototype[f]; + } + } + + function Tap(head, tail) { + this.head = head; + this.tail = tail; + } + + Tap.prototype.push = function(tap) { + return new Tap(tap, this); + }; + + Tap.prototype.go = function(value) { + var tap = this; + + while(tap) { + value = tap.head(value); + tap = tap.tail; + } + return value; + }; + + var HCHARS = /[&<>"']/, + AMP = /&/g, + LT = //g, + QUOT = /\"/g, + SQUOT = /\'/g; + + dust.escapeHtml = function(s) { + if (typeof s === "string" || (s && typeof s.toString === "function")) { + if (typeof s !== "string") { + s = s.toString(); + } + if (!HCHARS.test(s)) { + return s; + } + return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"').replace(SQUOT, '''); + } + return s; + }; + + var BS = /\\/g, + FS = /\//g, + CR = /\r/g, + LS = /\u2028/g, + PS = /\u2029/g, + NL = /\n/g, + LF = /\f/g, + SQ = /'/g, + DQ = /"/g, + TB = /\t/g; + + dust.escapeJs = function(s) { + if (typeof s === 'string') { + return s + .replace(BS, '\\\\') + .replace(FS, '\\/') + .replace(DQ, '\\"') + .replace(SQ, '\\\'') + .replace(CR, '\\r') + .replace(LS, '\\u2028') + .replace(PS, '\\u2029') + .replace(NL, '\\n') + .replace(LF, '\\f') + .replace(TB, '\\t'); + } + return s; + }; + + dust.escapeJSON = function(o) { + if (!JSON) { + dust.log('JSON is undefined; could not escape `' + o + '`', WARN); + return o; + } else { + return JSON.stringify(o) + .replace(LS, '\\u2028') + .replace(PS, '\\u2029') + .replace(LT, '\\u003c'); + } + }; + + return dust; + +})); + +if (typeof define === "function" && define.amd && define.amd.dust === true) { + define(["require", "dust.core"], function(require, dust) { + dust.onLoad = function(name, cb) { + require([name], function() { + cb(); + }); + }; + return dust; + }); +} diff --git a/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.min.js b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.min.js new file mode 100644 index 0000000..92d2725 --- /dev/null +++ b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-core.min.js @@ -0,0 +1,4 @@ +/*! dustjs-linkedin - v2.7.5 +* http://dustjs.com/ +* Copyright (c) 2016 Aleksander Williams; Released under the MIT License */ +!function(a,b){"function"==typeof define&&define.amd&&define.amd.dust===!0?define("dust.core",[],b):"object"==typeof exports?module.exports=b():a.dust=b()}(this,function(){function getTemplate(a,b){return a?"function"==typeof a&&a.template?a.template:dust.isTemplateFn(a)?a:b!==!1?dust.cache[a]:void 0:void 0}function load(a,b,c){if(!a)return b.setError(new Error("No template or template name provided to render"));var d=getTemplate(a,dust.config.cache);return d?d(b,Context.wrap(c,d.templateName)):dust.onLoad?b.map(function(b){function d(a,d){var f;if(a)return b.setError(a);if(f=getTemplate(d,!1)||getTemplate(e,dust.config.cache),!f){if(!dust.compile)return b.setError(new Error("Dust compiler not available"));f=dust.loadSource(dust.compile(d,e))}f(b,Context.wrap(c,f.templateName)).end()}var e=a;3===dust.onLoad.length?dust.onLoad(e,c.options,d):dust.onLoad(e,d)}):b.setError(new Error("Template Not Found: "+a))}function Context(a,b,c,d,e){void 0===a||a instanceof Stack||(a=new Stack(a)),this.stack=a,this.global=b,this.options=c,this.blocks=d,this.templateName=e,this._isContext=!0}function getWithResolvedData(a,b,c){return function(d){return a.push(d)._get(b,c)}}function Stack(a,b,c,d){this.tail=b,this.isObject=a&&"object"==typeof a,this.head=a,this.index=c,this.of=d}function Stub(a){this.head=new Chunk(this),this.callback=a,this.out=""}function Stream(){this.head=new Chunk(this)}function Chunk(a,b,c){this.root=a,this.next=b,this.data=[],this.flushable=!1,this.taps=c}function Tap(a,b){this.head=a,this.tail=b}var dust={version:"2.7.5"},NONE="NONE",ERROR="ERROR",WARN="WARN",INFO="INFO",DEBUG="DEBUG",EMPTY_FUNC=function(){};dust.config={whitespace:!1,amd:!1,cjs:!1,cache:!0},dust._aliases={write:"w",end:"e",map:"m",render:"r",reference:"f",section:"s",exists:"x",notexists:"nx",block:"b",partial:"p",helper:"h"},function(){var a,b,c={DEBUG:0,INFO:1,WARN:2,ERROR:3,NONE:4};"undefined"!=typeof console&&console.log?(a=console.log,b="function"==typeof a?function(){a.apply(console,arguments)}:function(){a(Array.prototype.slice.apply(arguments).join(" "))}):b=EMPTY_FUNC,dust.log=function(a,d){d=d||INFO,c[d]>=c[dust.debugLevel]&&b("[DUST:"+d+"]",a)},dust.debugLevel=NONE,"undefined"!=typeof process&&process.env&&/\bdust\b/.test(process.env.DEBUG)&&(dust.debugLevel=DEBUG)}(),dust.helpers={},dust.cache={},dust.register=function(a,b){a&&(b.templateName=a,dust.config.cache!==!1&&(dust.cache[a]=b))},dust.render=function(a,b,c){var d=new Stub(c).head;try{load(a,d,b).end()}catch(e){d.setError(e)}},dust.stream=function(a,b){var c=new Stream,d=c.head;return dust.nextTick(function(){try{load(a,d,b).end()}catch(c){d.setError(c)}}),c},dust.loadSource=function(source){return eval(source)},dust.isArray=Array.isArray?Array.isArray:function(a){return"[object Array]"===Object.prototype.toString.call(a)},dust.nextTick=function(){return function(a){setTimeout(a,0)}}(),dust.isEmpty=function(a){return 0===a?!1:dust.isArray(a)&&!a.length?!0:!a},dust.isEmptyObject=function(a){var b;if(null===a)return!1;if(void 0===a)return!1;if(a.length>0)return!1;for(b in a)if(Object.prototype.hasOwnProperty.call(a,b))return!1;return!0},dust.isTemplateFn=function(a){return"function"==typeof a&&a.__dustBody},dust.isThenable=function(a){return a&&"object"==typeof a&&"function"==typeof a.then},dust.isStreamable=function(a){return a&&"function"==typeof a.on&&"function"==typeof a.pipe},dust.filter=function(a,b,c,d){var e,f,g,h;if(c)for(e=0,f=c.length;f>e;e++)g=c[e],g.length&&(h=dust.filters[g],"s"===g?b=null:"function"==typeof h?a=h(a,d):dust.log("Invalid filter `"+g+"`",WARN));return b&&(a=dust.filters[b](a,d)),a},dust.filters={h:function(a){return dust.escapeHtml(a)},j:function(a){return dust.escapeJs(a)},u:encodeURI,uc:encodeURIComponent,js:function(a){return dust.escapeJSON(a)},jp:function(a){return JSON?JSON.parse(a):(dust.log("JSON is undefined; could not parse `"+a+"`",WARN),a)}},dust.makeBase=dust.context=function(a,b){return new Context(void 0,a,b)},dust.isContext=function(a){return"object"==typeof a&&a._isContext===!0},Context.wrap=function(a,b){return dust.isContext(a)?a:new Context(a,{},{},null,b)},Context.prototype.get=function(a,b){return"string"==typeof a&&("."===a[0]&&(b=!0,a=a.substr(1)),a=a.split(".")),this._get(b,a)},Context.prototype._get=function(a,b){var c,d,e,f,g,h=this.stack||{},i=1;if(d=b[0],e=b.length,a&&0===e)f=h,h=h.head;else{if(a)h&&(h=h.head?h.head[d]:void 0);else{for(;h&&(!h.isObject||(f=h.head,c=h.head[d],void 0===c));)h=h.tail;h=void 0!==c?c:this.global&&this.global[d]}for(;h&&e>i;){if(dust.isThenable(h))return h.then(getWithResolvedData(this,a,b.slice(i)));f=h,h=h[b[i]],i++}}return"function"==typeof h?(g=function(){try{return h.apply(f,arguments)}catch(a){throw dust.log(a,ERROR),a}},g.__dustBody=!!h.__dustBody,g):(void 0===h&&dust.log("Cannot find reference `{"+b.join(".")+"}` in template `"+this.getTemplateName()+"`",INFO),h)},Context.prototype.getPath=function(a,b){return this._get(a,b)},Context.prototype.push=function(a,b,c){return void 0===a?(dust.log("Not pushing an undefined variable onto the context",INFO),this):this.rebase(new Stack(a,this.stack,b,c))},Context.prototype.pop=function(){var a=this.current();return this.stack=this.stack&&this.stack.tail,a},Context.prototype.rebase=function(a){return new Context(a,this.global,this.options,this.blocks,this.getTemplateName())},Context.prototype.clone=function(){var a=this.rebase();return a.stack=this.stack,a},Context.prototype.current=function(){return this.stack&&this.stack.head},Context.prototype.getBlock=function(a){var b,c,d;if("function"==typeof a&&(a=a(new Chunk,this).data.join("")),b=this.blocks,!b)return dust.log("No blocks for context `"+a+"` in template `"+this.getTemplateName()+"`",DEBUG),!1;for(c=b.length;c--;)if(d=b[c][a])return d;return dust.log("Malformed template `"+this.getTemplateName()+"` was missing one or more blocks."),!1},Context.prototype.shiftBlocks=function(a){var b,c=this.blocks;return a?(b=c?c.concat([a]):[a],new Context(this.stack,this.global,this.options,b,this.getTemplateName())):this},Context.prototype.resolve=function(a){var b;return"function"!=typeof a?a:(b=(new Chunk).render(a,this),b instanceof Chunk?b.data.join(""):b)},Context.prototype.getTemplateName=function(){return this.templateName},Stub.prototype.flush=function(){for(var a=this.head;a;){if(!a.flushable)return a.error?(this.callback(a.error),dust.log("Rendering failed with error `"+a.error+"`",ERROR),void(this.flush=EMPTY_FUNC)):void 0;this.out+=a.data.join(""),a=a.next,this.head=a}this.callback(null,this.out)},Stream.prototype.flush=function(){for(var a=this.head;a;){if(!a.flushable)return a.error?(this.emit("error",a.error),this.emit("end"),dust.log("Streaming failed with error `"+a.error+"`",ERROR),void(this.flush=EMPTY_FUNC)):void 0;this.emit("data",a.data.join("")),a=a.next,this.head=a}this.emit("end")},Stream.prototype.emit=function(a,b){var c,d,e=this.events||{},f=e[a]||[];if(!f.length)return dust.log("Stream broadcasting, but no listeners for `"+a+"`",DEBUG),!1;for(f=f.slice(0),c=0,d=f.length;d>c;c++)f[c](b);return!0},Stream.prototype.on=function(a,b){var c=this.events=this.events||{},d=c[a]=c[a]||[];return"function"!=typeof b?dust.log("No callback function provided for `"+a+"` event listener",WARN):d.push(b),this},Stream.prototype.pipe=function(a){if("function"!=typeof a.write||"function"!=typeof a.end)return dust.log("Incompatible stream passed to `pipe`",WARN),this;var b=!1;return"function"==typeof a.emit&&a.emit("pipe",this),"function"==typeof a.on&&a.on("error",function(){b=!0}),this.on("data",function(c){if(!b)try{a.write(c,"utf8")}catch(d){dust.log(d,ERROR)}}).on("end",function(){if(!b)try{a.end(),b=!0}catch(c){dust.log(c,ERROR)}})},Chunk.prototype.write=function(a){var b=this.taps;return b&&(a=b.go(a)),this.data.push(a),this},Chunk.prototype.end=function(a){return a&&this.write(a),this.flushable=!0,this.root.flush(),this},Chunk.prototype.map=function(a){var b=new Chunk(this.root,this.next,this.taps),c=new Chunk(this.root,b,this.taps);this.next=c,this.flushable=!0;try{a(c)}catch(d){dust.log(d,ERROR),c.setError(d)}return b},Chunk.prototype.tap=function(a){var b=this.taps;return this.taps=b?b.push(a):new Tap(a),this},Chunk.prototype.untap=function(){return this.taps=this.taps.tail,this},Chunk.prototype.render=function(a,b){return a(this,b)},Chunk.prototype.reference=function(a,b,c,d){return"function"==typeof a?(a=a.apply(b.current(),[this,b,null,{auto:c,filters:d}]),a instanceof Chunk?a:this.reference(a,b,c,d)):dust.isThenable(a)?this.await(a,b,null,c,d):dust.isStreamable(a)?this.stream(a,b,null,c,d):dust.isEmpty(a)?this:this.write(dust.filter(a,c,d,b))},Chunk.prototype.section=function(a,b,c,d){var e,f,g,h=c.block,i=c["else"],j=this;if("function"==typeof a&&!dust.isTemplateFn(a)){try{a=a.apply(b.current(),[this,b,c,d])}catch(k){return dust.log(k,ERROR),this.setError(k)}if(a instanceof Chunk)return a}if(dust.isEmptyObject(c))return j;if(dust.isEmptyObject(d)||(b=b.push(d)),dust.isArray(a)){if(h){if(f=a.length,f>0){for(g=b.stack&&b.stack.head||{},g.$len=f,e=0;f>e;e++)g.$idx=e,j=h(j,b.push(a[e],e,f));return g.$idx=void 0,g.$len=void 0,j}if(i)return i(this,b)}}else{if(dust.isThenable(a))return this.await(a,b,c);if(dust.isStreamable(a))return this.stream(a,b,c);if(a===!0){if(h)return h(this,b)}else if(a||0===a){if(h)return h(this,b.push(a))}else if(i)return i(this,b)}return dust.log("Section without corresponding key in template `"+b.getTemplateName()+"`",DEBUG),this},Chunk.prototype.exists=function(a,b,c){var d=c.block,e=c["else"];if(dust.isEmpty(a)){if(e)return e(this,b)}else{if(d)return d(this,b);dust.log("No block for exists check in template `"+b.getTemplateName()+"`",DEBUG)}return this},Chunk.prototype.notexists=function(a,b,c){var d=c.block,e=c["else"];if(dust.isEmpty(a)){if(d)return d(this,b);dust.log("No block for not-exists check in template `"+b.getTemplateName()+"`",DEBUG)}else if(e)return e(this,b);return this},Chunk.prototype.block=function(a,b,c){var d=a||c.block;return d?d(this,b):this},Chunk.prototype.partial=function(a,b,c,d){var e;return void 0===d&&(d=c,c=b),dust.isEmptyObject(d)||(c=c.clone(),e=c.pop(),c=c.push(d).push(e)),dust.isTemplateFn(a)?this.capture(a,b,function(a,b){c.templateName=a,load(a,b,c).end()}):(c.templateName=a,load(a,this,c))},Chunk.prototype.helper=function(a,b,c,d,e){var f,g=this,h=d.filters;if(void 0===e&&(e="h"),!dust.helpers[a])return dust.log("Helper `"+a+"` does not exist",WARN),g;try{return f=dust.helpers[a](g,b,c,d),f instanceof Chunk?f:("string"==typeof h&&(h=h.split("|")),dust.isEmptyObject(c)?g.reference(f,b,e,h):g.section(f,b,c,d))}catch(i){return dust.log("Error in helper `"+a+"`: "+i.message,ERROR),g.setError(i)}},Chunk.prototype.await=function(a,b,c,d,e){return this.map(function(f){a.then(function(a){f=c?f.section(a,b,c):f.reference(a,b,d,e),f.end()},function(a){var d=c&&c.error;d?f.render(d,b.push(a)).end():(dust.log("Unhandled promise rejection in `"+b.getTemplateName()+"`",INFO),f.end())})})},Chunk.prototype.stream=function(a,b,c,d,e){var f=c&&c.block,g=c&&c.error;return this.map(function(h){var i=!1;a.on("data",function(a){i||(f?h=h.map(function(c){c.render(f,b.push(a)).end()}):c||(h=h.reference(a,b,d,e)))}).on("error",function(a){i||(g?h.render(g,b.push(a)):dust.log("Unhandled stream error in `"+b.getTemplateName()+"`",INFO),i||(i=!0,h.end()))}).on("end",function(){i||(i=!0,h.end())})})},Chunk.prototype.capture=function(a,b,c){return this.map(function(d){var e=new Stub(function(a,b){a?d.setError(a):c(b,d)});a(e.head,b).end()})},Chunk.prototype.setError=function(a){return this.error=a,this.root.flush(),this};for(var f in Chunk.prototype)dust._aliases[f]&&(Chunk.prototype[dust._aliases[f]]=Chunk.prototype[f]);Tap.prototype.push=function(a){return new Tap(a,this)},Tap.prototype.go=function(a){for(var b=this;b;)a=b.head(a),b=b.tail;return a};var HCHARS=/[&<>"']/,AMP=/&/g,LT=//g,QUOT=/\"/g,SQUOT=/\'/g;dust.escapeHtml=function(a){return"string"==typeof a||a&&"function"==typeof a.toString?("string"!=typeof a&&(a=a.toString()),HCHARS.test(a)?a.replace(AMP,"&").replace(LT,"<").replace(GT,">").replace(QUOT,""").replace(SQUOT,"'"):a):a};var BS=/\\/g,FS=/\//g,CR=/\r/g,LS=/\u2028/g,PS=/\u2029/g,NL=/\n/g,LF=/\f/g,SQ=/'/g,DQ=/"/g,TB=/\t/g;return dust.escapeJs=function(a){return"string"==typeof a?a.replace(BS,"\\\\").replace(FS,"\\/").replace(DQ,'\\"').replace(SQ,"\\'").replace(CR,"\\r").replace(LS,"\\u2028").replace(PS,"\\u2029").replace(NL,"\\n").replace(LF,"\\f").replace(TB,"\\t"):a},dust.escapeJSON=function(a){return JSON?JSON.stringify(a).replace(LS,"\\u2028").replace(PS,"\\u2029").replace(LT,"\\u003c"):(dust.log("JSON is undefined; could not escape `"+a+"`",WARN),a)},dust}),"function"==typeof define&&define.amd&&define.amd.dust===!0&&define(["require","dust.core"],function(require,dust){return dust.onLoad=function(a,b){require([a],function(){b()})},dust}); \ No newline at end of file diff --git a/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-full.js b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-full.js new file mode 100644 index 0000000..37b9f02 --- /dev/null +++ b/hw7/Claudio_Maggioni/public/dustjs-linkedin/dust-full.js @@ -0,0 +1,4359 @@ +/*! dustjs-linkedin - v2.7.5 +* http://dustjs.com/ +* Copyright (c) 2016 Aleksander Williams; Released under the MIT License */ +(function (root, factory) { + if (typeof define === 'function' && define.amd && define.amd.dust === true) { + define('dust.core', [], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.dust = factory(); + } +}(this, function() { + var dust = { + "version": "2.7.5" + }, + NONE = 'NONE', ERROR = 'ERROR', WARN = 'WARN', INFO = 'INFO', DEBUG = 'DEBUG', + EMPTY_FUNC = function() {}; + + dust.config = { + whitespace: false, + amd: false, + cjs: false, + cache: true + }; + + // Directive aliases to minify code + dust._aliases = { + "write": "w", + "end": "e", + "map": "m", + "render": "r", + "reference": "f", + "section": "s", + "exists": "x", + "notexists": "nx", + "block": "b", + "partial": "p", + "helper": "h" + }; + + (function initLogging() { + /*global process, console*/ + var loggingLevels = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, NONE: 4 }, + consoleLog, + log; + + if (typeof console !== 'undefined' && console.log) { + consoleLog = console.log; + if(typeof consoleLog === 'function') { + log = function() { + consoleLog.apply(console, arguments); + }; + } else { + log = function() { + consoleLog(Array.prototype.slice.apply(arguments).join(' ')); + }; + } + } else { + log = EMPTY_FUNC; + } + + /** + * Filters messages based on `dust.debugLevel`. + * This default implementation will print to the console if it exists. + * @param {String|Error} message the message to print/throw + * @param {String} type the severity of the message(ERROR, WARN, INFO, or DEBUG) + * @public + */ + dust.log = function(message, type) { + type = type || INFO; + if (loggingLevels[type] >= loggingLevels[dust.debugLevel]) { + log('[DUST:' + type + ']', message); + } + }; + + dust.debugLevel = NONE; + if(typeof process !== 'undefined' && process.env && /\bdust\b/.test(process.env.DEBUG)) { + dust.debugLevel = DEBUG; + } + + }()); + + dust.helpers = {}; + + dust.cache = {}; + + dust.register = function(name, tmpl) { + if (!name) { + return; + } + tmpl.templateName = name; + if (dust.config.cache !== false) { + dust.cache[name] = tmpl; + } + }; + + dust.render = function(nameOrTemplate, context, callback) { + var chunk = new Stub(callback).head; + try { + load(nameOrTemplate, chunk, context).end(); + } catch (err) { + chunk.setError(err); + } + }; + + dust.stream = function(nameOrTemplate, context) { + var stream = new Stream(), + chunk = stream.head; + dust.nextTick(function() { + try { + load(nameOrTemplate, chunk, context).end(); + } catch (err) { + chunk.setError(err); + } + }); + return stream; + }; + + /** + * Extracts a template function (body_0) from whatever is passed. + * @param nameOrTemplate {*} Could be: + * - the name of a template to load from cache + * - a CommonJS-compiled template (a function with a `template` property) + * - a template function + * @param loadFromCache {Boolean} if false, don't look in the cache + * @return {Function} a template function, if found + */ + function getTemplate(nameOrTemplate, loadFromCache/*=true*/) { + if(!nameOrTemplate) { + return; + } + if(typeof nameOrTemplate === 'function' && nameOrTemplate.template) { + // Sugar away CommonJS module templates + return nameOrTemplate.template; + } + if(dust.isTemplateFn(nameOrTemplate)) { + // Template functions passed directly + return nameOrTemplate; + } + if(loadFromCache !== false) { + // Try loading a template with this name from cache + return dust.cache[nameOrTemplate]; + } + } + + function load(nameOrTemplate, chunk, context) { + if(!nameOrTemplate) { + return chunk.setError(new Error('No template or template name provided to render')); + } + + var template = getTemplate(nameOrTemplate, dust.config.cache); + + if (template) { + return template(chunk, Context.wrap(context, template.templateName)); + } else { + if (dust.onLoad) { + return chunk.map(function(chunk) { + // Alias just so it's easier to read that this would always be a name + var name = nameOrTemplate; + // Three possible scenarios for a successful callback: + // - `require(nameOrTemplate)(dust); cb()` + // - `src = readFile('src.dust'); cb(null, src)` + // - `compiledTemplate = require(nameOrTemplate)(dust); cb(null, compiledTemplate)` + function done(err, srcOrTemplate) { + var template; + if (err) { + return chunk.setError(err); + } + // Prefer a template that is passed via callback over the cached version. + template = getTemplate(srcOrTemplate, false) || getTemplate(name, dust.config.cache); + if (!template) { + // It's a template string, compile it and register under `name` + if(dust.compile) { + template = dust.loadSource(dust.compile(srcOrTemplate, name)); + } else { + return chunk.setError(new Error('Dust compiler not available')); + } + } + template(chunk, Context.wrap(context, template.templateName)).end(); + } + + if(dust.onLoad.length === 3) { + dust.onLoad(name, context.options, done); + } else { + dust.onLoad(name, done); + } + }); + } + return chunk.setError(new Error('Template Not Found: ' + nameOrTemplate)); + } + } + + dust.loadSource = function(source) { + /*jshint evil:true*/ + return eval(source); + }; + + if (Array.isArray) { + dust.isArray = Array.isArray; + } else { + dust.isArray = function(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; + } + + dust.nextTick = (function() { + return function(callback) { + setTimeout(callback, 0); + }; + })(); + + /** + * Dust has its own rules for what is "empty"-- which is not the same as falsy. + * Empty arrays, null, and undefined are empty + */ + dust.isEmpty = function(value) { + if (value === 0) { + return false; + } + if (dust.isArray(value) && !value.length) { + return true; + } + return !value; + }; + + dust.isEmptyObject = function(obj) { + var key; + if (obj === null) { + return false; + } + if (obj === undefined) { + return false; + } + if (obj.length > 0) { + return false; + } + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + return false; + } + } + return true; + }; + + dust.isTemplateFn = function(elem) { + return typeof elem === 'function' && + elem.__dustBody; + }; + + /** + * Decide somewhat-naively if something is a Thenable. + * @param elem {*} object to inspect + * @return {Boolean} is `elem` a Thenable? + */ + dust.isThenable = function(elem) { + return elem && + typeof elem === 'object' && + typeof elem.then === 'function'; + }; + + /** + * Decide very naively if something is a Stream. + * @param elem {*} object to inspect + * @return {Boolean} is `elem` a Stream? + */ + dust.isStreamable = function(elem) { + return elem && + typeof elem.on === 'function' && + typeof elem.pipe === 'function'; + }; + + // apply the filter chain and return the output string + dust.filter = function(string, auto, filters, context) { + var i, len, name, filter; + if (filters) { + for (i = 0, len = filters.length; i < len; i++) { + name = filters[i]; + if (!name.length) { + continue; + } + filter = dust.filters[name]; + if (name === 's') { + auto = null; + } else if (typeof filter === 'function') { + string = filter(string, context); + } else { + dust.log('Invalid filter `' + name + '`', WARN); + } + } + } + // by default always apply the h filter, unless asked to unescape with |s + if (auto) { + string = dust.filters[auto](string, context); + } + return string; + }; + + dust.filters = { + h: function(value) { return dust.escapeHtml(value); }, + j: function(value) { return dust.escapeJs(value); }, + u: encodeURI, + uc: encodeURIComponent, + js: function(value) { return dust.escapeJSON(value); }, + jp: function(value) { + if (!JSON) {dust.log('JSON is undefined; could not parse `' + value + '`', WARN); + return value; + } else { + return JSON.parse(value); + } + } + }; + + function Context(stack, global, options, blocks, templateName) { + if(stack !== undefined && !(stack instanceof Stack)) { + stack = new Stack(stack); + } + this.stack = stack; + this.global = global; + this.options = options; + this.blocks = blocks; + this.templateName = templateName; + this._isContext = true; + } + + dust.makeBase = dust.context = function(global, options) { + return new Context(undefined, global, options); + }; + + dust.isContext = function(obj) { + return typeof obj === "object" && obj._isContext === true; + }; + + /** + * Factory function that creates a closure scope around a Thenable-callback. + * Returns a function that can be passed to a Thenable that will resume a + * Context lookup once the Thenable resolves with new data, adding that new + * data to the lookup stack. + */ + function getWithResolvedData(ctx, cur, down) { + return function(data) { + return ctx.push(data)._get(cur, down); + }; + } + + Context.wrap = function(context, name) { + if (dust.isContext(context)) { + return context; + } + return new Context(context, {}, {}, null, name); + }; + + /** + * Public API for getting a value from the context. + * @method get + * @param {string|array} path The path to the value. Supported formats are: + * 'key' + * 'path.to.key' + * '.path.to.key' + * ['path', 'to', 'key'] + * ['key'] + * @param {boolean} [cur=false] Boolean which determines if the search should be limited to the + * current context (true), or if get should search in parent contexts as well (false). + * @public + * @returns {string|object} + */ + Context.prototype.get = function(path, cur) { + if (typeof path === 'string') { + if (path[0] === '.') { + cur = true; + path = path.substr(1); + } + path = path.split('.'); + } + return this._get(cur, path); + }; + + /** + * Get a value from the context + * @method _get + * @param {boolean} cur Get only from the current context + * @param {array} down An array of each step in the path + * @private + * @return {string | object} + */ + Context.prototype._get = function(cur, down) { + var ctx = this.stack || {}, + i = 1, + value, first, len, ctxThis, fn; + + first = down[0]; + len = down.length; + + if (cur && len === 0) { + ctxThis = ctx; + ctx = ctx.head; + } else { + if (!cur) { + // Search up the stack for the first value + while (ctx) { + if (ctx.isObject) { + ctxThis = ctx.head; + value = ctx.head[first]; + if (value !== undefined) { + break; + } + } + ctx = ctx.tail; + } + + // Try looking in the global context if we haven't found anything yet + if (value !== undefined) { + ctx = value; + } else { + ctx = this.global && this.global[first]; + } + } else if (ctx) { + // if scope is limited by a leading dot, don't search up the tree + if(ctx.head) { + ctx = ctx.head[first]; + } else { + // context's head is empty, value we are searching for is not defined + ctx = undefined; + } + } + + while (ctx && i < len) { + if (dust.isThenable(ctx)) { + // Bail early by returning a Thenable for the remainder of the search tree + return ctx.then(getWithResolvedData(this, cur, down.slice(i))); + } + ctxThis = ctx; + ctx = ctx[down[i]]; + i++; + } + } + + if (typeof ctx === 'function') { + fn = function() { + try { + return ctx.apply(ctxThis, arguments); + } catch (err) { + dust.log(err, ERROR); + throw err; + } + }; + fn.__dustBody = !!ctx.__dustBody; + return fn; + } else { + if (ctx === undefined) { + dust.log('Cannot find reference `{' + down.join('.') + '}` in template `' + this.getTemplateName() + '`', INFO); + } + return ctx; + } + }; + + Context.prototype.getPath = function(cur, down) { + return this._get(cur, down); + }; + + Context.prototype.push = function(head, idx, len) { + if(head === undefined) { + dust.log("Not pushing an undefined variable onto the context", INFO); + return this; + } + return this.rebase(new Stack(head, this.stack, idx, len)); + }; + + Context.prototype.pop = function() { + var head = this.current(); + this.stack = this.stack && this.stack.tail; + return head; + }; + + Context.prototype.rebase = function(head) { + return new Context(head, this.global, this.options, this.blocks, this.getTemplateName()); + }; + + Context.prototype.clone = function() { + var context = this.rebase(); + context.stack = this.stack; + return context; + }; + + Context.prototype.current = function() { + return this.stack && this.stack.head; + }; + + Context.prototype.getBlock = function(key) { + var blocks, len, fn; + + if (typeof key === 'function') { + key = key(new Chunk(), this).data.join(''); + } + + blocks = this.blocks; + + if (!blocks) { + dust.log('No blocks for context `' + key + '` in template `' + this.getTemplateName() + '`', DEBUG); + return false; + } + + len = blocks.length; + while (len--) { + fn = blocks[len][key]; + if (fn) { + return fn; + } + } + + dust.log('Malformed template `' + this.getTemplateName() + '` was missing one or more blocks.'); + return false; + }; + + Context.prototype.shiftBlocks = function(locals) { + var blocks = this.blocks, + newBlocks; + + if (locals) { + if (!blocks) { + newBlocks = [locals]; + } else { + newBlocks = blocks.concat([locals]); + } + return new Context(this.stack, this.global, this.options, newBlocks, this.getTemplateName()); + } + return this; + }; + + Context.prototype.resolve = function(body) { + var chunk; + + if(typeof body !== 'function') { + return body; + } + chunk = new Chunk().render(body, this); + if(chunk instanceof Chunk) { + return chunk.data.join(''); // ie7 perf + } + return chunk; + }; + + Context.prototype.getTemplateName = function() { + return this.templateName; + }; + + function Stack(head, tail, idx, len) { + this.tail = tail; + this.isObject = head && typeof head === 'object'; + this.head = head; + this.index = idx; + this.of = len; + } + + function Stub(callback) { + this.head = new Chunk(this); + this.callback = callback; + this.out = ''; + } + + Stub.prototype.flush = function() { + var chunk = this.head; + + while (chunk) { + if (chunk.flushable) { + this.out += chunk.data.join(''); //ie7 perf + } else if (chunk.error) { + this.callback(chunk.error); + dust.log('Rendering failed with error `' + chunk.error + '`', ERROR); + this.flush = EMPTY_FUNC; + return; + } else { + return; + } + chunk = chunk.next; + this.head = chunk; + } + this.callback(null, this.out); + }; + + /** + * Creates an interface sort of like a Streams2 ReadableStream. + */ + function Stream() { + this.head = new Chunk(this); + } + + Stream.prototype.flush = function() { + var chunk = this.head; + + while(chunk) { + if (chunk.flushable) { + this.emit('data', chunk.data.join('')); //ie7 perf + } else if (chunk.error) { + this.emit('error', chunk.error); + this.emit('end'); + dust.log('Streaming failed with error `' + chunk.error + '`', ERROR); + this.flush = EMPTY_FUNC; + return; + } else { + return; + } + chunk = chunk.next; + this.head = chunk; + } + this.emit('end'); + }; + + /** + * Executes listeners for `type` by passing data. Note that this is different from a + * Node stream, which can pass an arbitrary number of arguments + * @return `true` if event had listeners, `false` otherwise + */ + Stream.prototype.emit = function(type, data) { + var events = this.events || {}, + handlers = events[type] || [], + i, l; + + if (!handlers.length) { + dust.log('Stream broadcasting, but no listeners for `' + type + '`', DEBUG); + return false; + } + + handlers = handlers.slice(0); + for (i = 0, l = handlers.length; i < l; i++) { + handlers[i](data); + } + return true; + }; + + Stream.prototype.on = function(type, callback) { + var events = this.events = this.events || {}, + handlers = events[type] = events[type] || []; + + if(typeof callback !== 'function') { + dust.log('No callback function provided for `' + type + '` event listener', WARN); + } else { + handlers.push(callback); + } + return this; + }; + + /** + * Pipes to a WritableStream. Note that backpressure isn't implemented, + * so we just write as fast as we can. + * @param stream {WritableStream} + * @return self + */ + Stream.prototype.pipe = function(stream) { + if(typeof stream.write !== 'function' || + typeof stream.end !== 'function') { + dust.log('Incompatible stream passed to `pipe`', WARN); + return this; + } + + var destEnded = false; + + if(typeof stream.emit === 'function') { + stream.emit('pipe', this); + } + + if(typeof stream.on === 'function') { + stream.on('error', function() { + destEnded = true; + }); + } + + return this + .on('data', function(data) { + if(destEnded) { + return; + } + try { + stream.write(data, 'utf8'); + } catch (err) { + dust.log(err, ERROR); + } + }) + .on('end', function() { + if(destEnded) { + return; + } + try { + stream.end(); + destEnded = true; + } catch (err) { + dust.log(err, ERROR); + } + }); + }; + + function Chunk(root, next, taps) { + this.root = root; + this.next = next; + this.data = []; //ie7 perf + this.flushable = false; + this.taps = taps; + } + + Chunk.prototype.write = function(data) { + var taps = this.taps; + + if (taps) { + data = taps.go(data); + } + this.data.push(data); + return this; + }; + + Chunk.prototype.end = function(data) { + if (data) { + this.write(data); + } + this.flushable = true; + this.root.flush(); + return this; + }; + + Chunk.prototype.map = function(callback) { + var cursor = new Chunk(this.root, this.next, this.taps), + branch = new Chunk(this.root, cursor, this.taps); + + this.next = branch; + this.flushable = true; + try { + callback(branch); + } catch(err) { + dust.log(err, ERROR); + branch.setError(err); + } + return cursor; + }; + + Chunk.prototype.tap = function(tap) { + var taps = this.taps; + + if (taps) { + this.taps = taps.push(tap); + } else { + this.taps = new Tap(tap); + } + return this; + }; + + Chunk.prototype.untap = function() { + this.taps = this.taps.tail; + return this; + }; + + Chunk.prototype.render = function(body, context) { + return body(this, context); + }; + + Chunk.prototype.reference = function(elem, context, auto, filters) { + if (typeof elem === 'function') { + elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]); + if (elem instanceof Chunk) { + return elem; + } else { + return this.reference(elem, context, auto, filters); + } + } + if (dust.isThenable(elem)) { + return this.await(elem, context, null, auto, filters); + } else if (dust.isStreamable(elem)) { + return this.stream(elem, context, null, auto, filters); + } else if (!dust.isEmpty(elem)) { + return this.write(dust.filter(elem, auto, filters, context)); + } else { + return this; + } + }; + + Chunk.prototype.section = function(elem, context, bodies, params) { + var body = bodies.block, + skip = bodies['else'], + chunk = this, + i, len, head; + + if (typeof elem === 'function' && !dust.isTemplateFn(elem)) { + try { + elem = elem.apply(context.current(), [this, context, bodies, params]); + } catch(err) { + dust.log(err, ERROR); + return this.setError(err); + } + // Functions that return chunks are assumed to have handled the chunk manually. + // Make that chunk the current one and go to the next method in the chain. + if (elem instanceof Chunk) { + return elem; + } + } + + if (dust.isEmptyObject(bodies)) { + // No bodies to render, and we've already invoked any function that was available in + // hopes of returning a Chunk. + return chunk; + } + + if (!dust.isEmptyObject(params)) { + context = context.push(params); + } + + /* + Dust's default behavior is to enumerate over the array elem, passing each object in the array to the block. + When elem resolves to a value or object instead of an array, Dust sets the current context to the value + and renders the block one time. + */ + if (dust.isArray(elem)) { + if (body) { + len = elem.length; + if (len > 0) { + head = context.stack && context.stack.head || {}; + head.$len = len; + for (i = 0; i < len; i++) { + head.$idx = i; + chunk = body(chunk, context.push(elem[i], i, len)); + } + head.$idx = undefined; + head.$len = undefined; + return chunk; + } else if (skip) { + return skip(this, context); + } + } + } else if (dust.isThenable(elem)) { + return this.await(elem, context, bodies); + } else if (dust.isStreamable(elem)) { + return this.stream(elem, context, bodies); + } else if (elem === true) { + // true is truthy but does not change context + if (body) { + return body(this, context); + } + } else if (elem || elem === 0) { + // everything that evaluates to true are truthy ( e.g. Non-empty strings and Empty objects are truthy. ) + // zero is truthy + // for anonymous functions that did not returns a chunk, truthiness is evaluated based on the return value + if (body) { + return body(this, context.push(elem)); + } + // nonexistent, scalar false value, scalar empty string, null, + // undefined are all falsy + } else if (skip) { + return skip(this, context); + } + dust.log('Section without corresponding key in template `' + context.getTemplateName() + '`', DEBUG); + return this; + }; + + Chunk.prototype.exists = function(elem, context, bodies) { + var body = bodies.block, + skip = bodies['else']; + + if (!dust.isEmpty(elem)) { + if (body) { + return body(this, context); + } + dust.log('No block for exists check in template `' + context.getTemplateName() + '`', DEBUG); + } else if (skip) { + return skip(this, context); + } + return this; + }; + + Chunk.prototype.notexists = function(elem, context, bodies) { + var body = bodies.block, + skip = bodies['else']; + + if (dust.isEmpty(elem)) { + if (body) { + return body(this, context); + } + dust.log('No block for not-exists check in template `' + context.getTemplateName() + '`', DEBUG); + } else if (skip) { + return skip(this, context); + } + return this; + }; + + Chunk.prototype.block = function(elem, context, bodies) { + var body = elem || bodies.block; + + if (body) { + return body(this, context); + } + return this; + }; + + Chunk.prototype.partial = function(elem, context, partialContext, params) { + var head; + + if(params === undefined) { + // Compatibility for < 2.7.0 where `partialContext` did not exist + params = partialContext; + partialContext = context; + } + + if (!dust.isEmptyObject(params)) { + partialContext = partialContext.clone(); + head = partialContext.pop(); + partialContext = partialContext.push(params) + .push(head); + } + + if (dust.isTemplateFn(elem)) { + // The eventual result of evaluating `elem` is a partial name + // Load the partial after getting its name and end the async chunk + return this.capture(elem, context, function(name, chunk) { + partialContext.templateName = name; + load(name, chunk, partialContext).end(); + }); + } else { + partialContext.templateName = elem; + return load(elem, this, partialContext); + } + }; + + Chunk.prototype.helper = function(name, context, bodies, params, auto) { + var chunk = this, + filters = params.filters, + ret; + + // Pre-2.7.1 compat: if auto is undefined, it's an old template. Automatically escape + if (auto === undefined) { + auto = 'h'; + } + + // handle invalid helpers, similar to invalid filters + if(dust.helpers[name]) { + try { + ret = dust.helpers[name](chunk, context, bodies, params); + if (ret instanceof Chunk) { + return ret; + } + if(typeof filters === 'string') { + filters = filters.split('|'); + } + if (!dust.isEmptyObject(bodies)) { + return chunk.section(ret, context, bodies, params); + } + // Helpers act slightly differently from functions in context in that they will act as + // a reference if they are self-closing (due to grammar limitations) + // In the Chunk.await function we check to make sure bodies is null before acting as a reference + return chunk.reference(ret, context, auto, filters); + } catch(err) { + dust.log('Error in helper `' + name + '`: ' + err.message, ERROR); + return chunk.setError(err); + } + } else { + dust.log('Helper `' + name + '` does not exist', WARN); + return chunk; + } + }; + + /** + * Reserve a chunk to be evaluated once a thenable is resolved or rejected + * @param thenable {Thenable} the target thenable to await + * @param context {Context} context to use to render the deferred chunk + * @param bodies {Object} must contain a "body", may contain an "error" + * @param auto {String} automatically apply this filter if the Thenable is a reference + * @param filters {Array} apply these filters if the Thenable is a reference + * @return {Chunk} + */ + Chunk.prototype.await = function(thenable, context, bodies, auto, filters) { + return this.map(function(chunk) { + thenable.then(function(data) { + if (bodies) { + chunk = chunk.section(data, context, bodies); + } else { + // Actually a reference. Self-closing sections don't render + chunk = chunk.reference(data, context, auto, filters); + } + chunk.end(); + }, function(err) { + var errorBody = bodies && bodies.error; + if(errorBody) { + chunk.render(errorBody, context.push(err)).end(); + } else { + dust.log('Unhandled promise rejection in `' + context.getTemplateName() + '`', INFO); + chunk.end(); + } + }); + }); + }; + + /** + * Reserve a chunk to be evaluated with the contents of a streamable. + * Currently an error event will bomb out the stream. Once an error + * is received, we push it to an {:error} block if one exists, and log otherwise, + * then stop listening to the stream. + * @param streamable {Streamable} the target streamable that will emit events + * @param context {Context} context to use to render each thunk + * @param bodies {Object} must contain a "body", may contain an "error" + * @return {Chunk} + */ + Chunk.prototype.stream = function(stream, context, bodies, auto, filters) { + var body = bodies && bodies.block, + errorBody = bodies && bodies.error; + return this.map(function(chunk) { + var ended = false; + stream + .on('data', function data(thunk) { + if(ended) { + return; + } + if(body) { + // Fork a new chunk out of the blockstream so that we can flush it independently + chunk = chunk.map(function(chunk) { + chunk.render(body, context.push(thunk)).end(); + }); + } else if(!bodies) { + // When actually a reference, don't fork, just write into the master async chunk + chunk = chunk.reference(thunk, context, auto, filters); + } + }) + .on('error', function error(err) { + if(ended) { + return; + } + if(errorBody) { + chunk.render(errorBody, context.push(err)); + } else { + dust.log('Unhandled stream error in `' + context.getTemplateName() + '`', INFO); + } + if(!ended) { + ended = true; + chunk.end(); + } + }) + .on('end', function end() { + if(!ended) { + ended = true; + chunk.end(); + } + }); + }); + }; + + Chunk.prototype.capture = function(body, context, callback) { + return this.map(function(chunk) { + var stub = new Stub(function(err, out) { + if (err) { + chunk.setError(err); + } else { + callback(out, chunk); + } + }); + body(stub.head, context).end(); + }); + }; + + Chunk.prototype.setError = function(err) { + this.error = err; + this.root.flush(); + return this; + }; + + // Chunk aliases + for(var f in Chunk.prototype) { + if(dust._aliases[f]) { + Chunk.prototype[dust._aliases[f]] = Chunk.prototype[f]; + } + } + + function Tap(head, tail) { + this.head = head; + this.tail = tail; + } + + Tap.prototype.push = function(tap) { + return new Tap(tap, this); + }; + + Tap.prototype.go = function(value) { + var tap = this; + + while(tap) { + value = tap.head(value); + tap = tap.tail; + } + return value; + }; + + var HCHARS = /[&<>"']/, + AMP = /&/g, + LT = //g, + QUOT = /\"/g, + SQUOT = /\'/g; + + dust.escapeHtml = function(s) { + if (typeof s === "string" || (s && typeof s.toString === "function")) { + if (typeof s !== "string") { + s = s.toString(); + } + if (!HCHARS.test(s)) { + return s; + } + return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"').replace(SQUOT, '''); + } + return s; + }; + + var BS = /\\/g, + FS = /\//g, + CR = /\r/g, + LS = /\u2028/g, + PS = /\u2029/g, + NL = /\n/g, + LF = /\f/g, + SQ = /'/g, + DQ = /"/g, + TB = /\t/g; + + dust.escapeJs = function(s) { + if (typeof s === 'string') { + return s + .replace(BS, '\\\\') + .replace(FS, '\\/') + .replace(DQ, '\\"') + .replace(SQ, '\\\'') + .replace(CR, '\\r') + .replace(LS, '\\u2028') + .replace(PS, '\\u2029') + .replace(NL, '\\n') + .replace(LF, '\\f') + .replace(TB, '\\t'); + } + return s; + }; + + dust.escapeJSON = function(o) { + if (!JSON) { + dust.log('JSON is undefined; could not escape `' + o + '`', WARN); + return o; + } else { + return JSON.stringify(o) + .replace(LS, '\\u2028') + .replace(PS, '\\u2029') + .replace(LT, '\\u003c'); + } + }; + + return dust; + +})); + +(function(root, factory) { + if (typeof define === "function" && define.amd && define.amd.dust === true) { + define("dust.parse", ["dust.core"], function(dust) { + return factory(dust).parse; + }); + } else if (typeof exports === 'object') { + // in Node, require this file if we want to use the parser as a standalone module + module.exports = factory(require('./dust')); + // @see server file for parser methods exposed in node + } else { + // in the browser, store the factory output if we want to use the parser directly + factory(root.dust); + } +}(this, function(dust) { + var parser = (function() { + /* + * Generated by PEG.js 0.8.0. + * + * http://pegjs.majda.cz/ + */ + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function SyntaxError(message, expected, found, offset, line, column) { + this.message = message; + this.expected = expected; + this.found = found; + this.offset = offset; + this.line = line; + this.column = column; + + this.name = "SyntaxError"; + } + + peg$subclass(SyntaxError, Error); + + function parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + + peg$FAILED = {}, + + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + + peg$c0 = [], + peg$c1 = function(p) { + var body = ["body"].concat(p); + return withPosition(body); + }, + peg$c2 = { type: "other", description: "section" }, + peg$c3 = peg$FAILED, + peg$c4 = null, + peg$c5 = function(t, b, e, n) { + if( (!n) || (t[1].text !== n.text) ) { + error("Expected end tag for "+t[1].text+" but it was not found."); + } + return true; + }, + peg$c6 = void 0, + peg$c7 = function(t, b, e, n) { + e.push(["param", ["literal", "block"], b]); + t.push(e, ["filters"]); + return withPosition(t) + }, + peg$c8 = "/", + peg$c9 = { type: "literal", value: "/", description: "\"/\"" }, + peg$c10 = function(t) { + t.push(["bodies"], ["filters"]); + return withPosition(t) + }, + peg$c11 = /^[#?\^<+@%]/, + peg$c12 = { type: "class", value: "[#?\\^<+@%]", description: "[#?\\^<+@%]" }, + peg$c13 = function(t, n, c, p) { return [t, n, c, p] }, + peg$c14 = { type: "other", description: "end tag" }, + peg$c15 = function(n) { return n }, + peg$c16 = ":", + peg$c17 = { type: "literal", value: ":", description: "\":\"" }, + peg$c18 = function(n) {return n}, + peg$c19 = function(n) { return n ? ["context", n] : ["context"] }, + peg$c20 = { type: "other", description: "params" }, + peg$c21 = "=", + peg$c22 = { type: "literal", value: "=", description: "\"=\"" }, + peg$c23 = function(k, v) {return ["param", ["literal", k], v]}, + peg$c24 = function(p) { return ["params"].concat(p) }, + peg$c25 = { type: "other", description: "bodies" }, + peg$c26 = function(p) { return ["bodies"].concat(p) }, + peg$c27 = { type: "other", description: "reference" }, + peg$c28 = function(n, f) { return withPosition(["reference", n, f]) }, + peg$c29 = { type: "other", description: "partial" }, + peg$c30 = ">", + peg$c31 = { type: "literal", value: ">", description: "\">\"" }, + peg$c32 = "+", + peg$c33 = { type: "literal", value: "+", description: "\"+\"" }, + peg$c34 = function(k) {return ["literal", k]}, + peg$c35 = function(s, n, c, p) { + var key = (s === ">") ? "partial" : s; + return withPosition([key, n, c, p]) + }, + peg$c36 = { type: "other", description: "filters" }, + peg$c37 = "|", + peg$c38 = { type: "literal", value: "|", description: "\"|\"" }, + peg$c39 = function(f) { return ["filters"].concat(f) }, + peg$c40 = { type: "other", description: "special" }, + peg$c41 = "~", + peg$c42 = { type: "literal", value: "~", description: "\"~\"" }, + peg$c43 = function(k) { return withPosition(["special", k]) }, + peg$c44 = { type: "other", description: "identifier" }, + peg$c45 = function(p) { + var arr = ["path"].concat(p); + arr.text = p[1].join('.').replace(/,line,\d+,col,\d+/g,''); + return arr; + }, + peg$c46 = function(k) { + var arr = ["key", k]; + arr.text = k; + return arr; + }, + peg$c47 = { type: "other", description: "number" }, + peg$c48 = function(n) { return ['literal', n]; }, + peg$c49 = { type: "other", description: "float" }, + peg$c50 = ".", + peg$c51 = { type: "literal", value: ".", description: "\".\"" }, + peg$c52 = function(l, r) { return parseFloat(l + "." + r); }, + peg$c53 = { type: "other", description: "unsigned_integer" }, + peg$c54 = /^[0-9]/, + peg$c55 = { type: "class", value: "[0-9]", description: "[0-9]" }, + peg$c56 = function(digits) { return makeInteger(digits); }, + peg$c57 = { type: "other", description: "signed_integer" }, + peg$c58 = "-", + peg$c59 = { type: "literal", value: "-", description: "\"-\"" }, + peg$c60 = function(sign, n) { return n * -1; }, + peg$c61 = { type: "other", description: "integer" }, + peg$c62 = { type: "other", description: "path" }, + peg$c63 = function(k, d) { + d = d[0]; + if (k && d) { + d.unshift(k); + return withPosition([false, d]) + } + return withPosition([true, d]) + }, + peg$c64 = function(d) { + if (d.length > 0) { + return withPosition([true, d[0]]) + } + return withPosition([true, []]) + }, + peg$c65 = { type: "other", description: "key" }, + peg$c66 = /^[a-zA-Z_$]/, + peg$c67 = { type: "class", value: "[a-zA-Z_$]", description: "[a-zA-Z_$]" }, + peg$c68 = /^[0-9a-zA-Z_$\-]/, + peg$c69 = { type: "class", value: "[0-9a-zA-Z_$\\-]", description: "[0-9a-zA-Z_$\\-]" }, + peg$c70 = function(h, t) { return h + t.join('') }, + peg$c71 = { type: "other", description: "array" }, + peg$c72 = function(n) {return n.join('')}, + peg$c73 = function(a) {return a; }, + peg$c74 = function(i, nk) { if(nk) { nk.unshift(i); } else {nk = [i] } return nk; }, + peg$c75 = { type: "other", description: "array_part" }, + peg$c76 = function(k) {return k}, + peg$c77 = function(d, a) { if (a) { return d.concat(a); } else { return d; } }, + peg$c78 = { type: "other", description: "inline" }, + peg$c79 = "\"", + peg$c80 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c81 = function() { return withPosition(["literal", ""]) }, + peg$c82 = function(l) { return withPosition(["literal", l]) }, + peg$c83 = function(p) { return withPosition(["body"].concat(p)) }, + peg$c84 = function(l) { return ["buffer", l] }, + peg$c85 = { type: "other", description: "buffer" }, + peg$c86 = function(e, w) { return withPosition(["format", e, w.join('')]) }, + peg$c87 = { type: "any", description: "any character" }, + peg$c88 = function(c) {return c}, + peg$c89 = function(b) { return withPosition(["buffer", b.join('')]) }, + peg$c90 = { type: "other", description: "literal" }, + peg$c91 = /^[^"]/, + peg$c92 = { type: "class", value: "[^\"]", description: "[^\"]" }, + peg$c93 = function(b) { return b.join('') }, + peg$c94 = "\\\"", + peg$c95 = { type: "literal", value: "\\\"", description: "\"\\\\\\\"\"" }, + peg$c96 = function() { return '"' }, + peg$c97 = { type: "other", description: "raw" }, + peg$c98 = "{`", + peg$c99 = { type: "literal", value: "{`", description: "\"{`\"" }, + peg$c100 = "`}", + peg$c101 = { type: "literal", value: "`}", description: "\"`}\"" }, + peg$c102 = function(character) {return character}, + peg$c103 = function(rawText) { return withPosition(["raw", rawText.join('')]) }, + peg$c104 = { type: "other", description: "comment" }, + peg$c105 = "{!", + peg$c106 = { type: "literal", value: "{!", description: "\"{!\"" }, + peg$c107 = "!}", + peg$c108 = { type: "literal", value: "!}", description: "\"!}\"" }, + peg$c109 = function(c) { return withPosition(["comment", c.join('')]) }, + peg$c110 = /^[#?\^><+%:@\/~%]/, + peg$c111 = { type: "class", value: "[#?\\^><+%:@\\/~%]", description: "[#?\\^><+%:@\\/~%]" }, + peg$c112 = "{", + peg$c113 = { type: "literal", value: "{", description: "\"{\"" }, + peg$c114 = "}", + peg$c115 = { type: "literal", value: "}", description: "\"}\"" }, + peg$c116 = "[", + peg$c117 = { type: "literal", value: "[", description: "\"[\"" }, + peg$c118 = "]", + peg$c119 = { type: "literal", value: "]", description: "\"]\"" }, + peg$c120 = "\n", + peg$c121 = { type: "literal", value: "\n", description: "\"\\n\"" }, + peg$c122 = "\r\n", + peg$c123 = { type: "literal", value: "\r\n", description: "\"\\r\\n\"" }, + peg$c124 = "\r", + peg$c125 = { type: "literal", value: "\r", description: "\"\\r\"" }, + peg$c126 = "\u2028", + peg$c127 = { type: "literal", value: "\u2028", description: "\"\\u2028\"" }, + peg$c128 = "\u2029", + peg$c129 = { type: "literal", value: "\u2029", description: "\"\\u2029\"" }, + peg$c130 = /^[\t\x0B\f \xA0\uFEFF]/, + peg$c131 = { type: "class", value: "[\\t\\x0B\\f \\xA0\\uFEFF]", description: "[\\t\\x0B\\f \\xA0\\uFEFF]" }, + + peg$currPos = 0, + peg$reportedPos = 0, + peg$cachedPos = 0, + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$reportedPos, peg$currPos); + } + + function offset() { + return peg$reportedPos; + } + + function line() { + return peg$computePosDetails(peg$reportedPos).line; + } + + function column() { + return peg$computePosDetails(peg$reportedPos).column; + } + + function expected(description) { + throw peg$buildException( + null, + [{ type: "other", description: description }], + peg$reportedPos + ); + } + + function error(message) { + throw peg$buildException(message, null, peg$reportedPos); + } + + function peg$computePosDetails(pos) { + function advance(details, startPos, endPos) { + var p, ch; + + for (p = startPos; p < endPos; p++) { + ch = input.charAt(p); + if (ch === "\n") { + if (!details.seenCR) { details.line++; } + details.column = 1; + details.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + details.line++; + details.column = 1; + details.seenCR = true; + } else { + details.column++; + details.seenCR = false; + } + } + } + + if (peg$cachedPos !== pos) { + if (peg$cachedPos > pos) { + peg$cachedPos = 0; + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; + } + advance(peg$cachedPosDetails, peg$cachedPos, pos); + peg$cachedPos = pos; + } + + return peg$cachedPosDetails; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildException(message, expected, pos) { + function cleanupExpected(expected) { + var i = 1; + + expected.sort(function(a, b) { + if (a.description < b.description) { + return -1; + } else if (a.description > b.description) { + return 1; + } else { + return 0; + } + }); + + while (i < expected.length) { + if (expected[i - 1] === expected[i]) { + expected.splice(i, 1); + } else { + i++; + } + } + } + + function buildMessage(expected, found) { + function stringEscape(s) { + function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } + + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\x08/g, '\\b') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\f/g, '\\f') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) + .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) + .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); + } + + var expectedDescs = new Array(expected.length), + expectedDesc, foundDesc, i; + + for (i = 0; i < expected.length; i++) { + expectedDescs[i] = expected[i].description; + } + + expectedDesc = expected.length > 1 + ? expectedDescs.slice(0, -1).join(", ") + + " or " + + expectedDescs[expected.length - 1] + : expectedDescs[0]; + + foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; + + return "Expected " + expectedDesc + " but " + foundDesc + " found."; + } + + var posDetails = peg$computePosDetails(pos), + found = pos < input.length ? input.charAt(pos) : null; + + if (expected !== null) { + cleanupExpected(expected); + } + + return new SyntaxError( + message !== null ? message : buildMessage(expected, found), + expected, + found, + pos, + posDetails.line, + posDetails.column + ); + } + + function peg$parsestart() { + var s0; + + s0 = peg$parsebody(); + + return s0; + } + + function peg$parsebody() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parsepart(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsepart(); + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c1(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsepart() { + var s0; + + s0 = peg$parseraw(); + if (s0 === peg$FAILED) { + s0 = peg$parsecomment(); + if (s0 === peg$FAILED) { + s0 = peg$parsesection(); + if (s0 === peg$FAILED) { + s0 = peg$parsepartial(); + if (s0 === peg$FAILED) { + s0 = peg$parsespecial(); + if (s0 === peg$FAILED) { + s0 = peg$parsereference(); + if (s0 === peg$FAILED) { + s0 = peg$parsebuffer(); + } + } + } + } + } + } + + return s0; + } + + function peg$parsesection() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsesec_tag_start(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + if (s2 !== peg$FAILED) { + s3 = peg$parserd(); + if (s3 !== peg$FAILED) { + s4 = peg$parsebody(); + if (s4 !== peg$FAILED) { + s5 = peg$parsebodies(); + if (s5 !== peg$FAILED) { + s6 = peg$parseend_tag(); + if (s6 === peg$FAILED) { + s6 = peg$c4; + } + if (s6 !== peg$FAILED) { + peg$reportedPos = peg$currPos; + s7 = peg$c5(s1, s4, s5, s6); + if (s7) { + s7 = peg$c6; + } else { + s7 = peg$c3; + } + if (s7 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c7(s1, s4, s5, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsesec_tag_start(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s3 = peg$c8; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parserd(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c10(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + + return s0; + } + + function peg$parsesec_tag_start() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + if (peg$c11.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c12); } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + if (s3 !== peg$FAILED) { + s4 = peg$parseidentifier(); + if (s4 !== peg$FAILED) { + s5 = peg$parsecontext(); + if (s5 !== peg$FAILED) { + s6 = peg$parseparams(); + if (s6 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c13(s2, s4, s5, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + + return s0; + } + + function peg$parseend_tag() { + var s0, s1, s2, s3, s4, s5, s6; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s2 = peg$c8; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + if (s3 !== peg$FAILED) { + s4 = peg$parseidentifier(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); + } + if (s5 !== peg$FAILED) { + s6 = peg$parserd(); + if (s6 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c15(s4); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c14); } + } + + return s0; + } + + function peg$parsecontext() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 58) { + s2 = peg$c16; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c17); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parseidentifier(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s1; + s2 = peg$c18(s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$c3; + } + } else { + peg$currPos = s1; + s1 = peg$c3; + } + if (s1 === peg$FAILED) { + s1 = peg$c4; + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c19(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseparams() { + var s0, s1, s2, s3, s4, s5, s6; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = []; + s4 = peg$parsews(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + } else { + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s5 = peg$c21; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsenumber(); + if (s6 === peg$FAILED) { + s6 = peg$parseidentifier(); + if (s6 === peg$FAILED) { + s6 = peg$parseinline(); + } + } + if (s6 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c23(s4, s6); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = []; + s4 = peg$parsews(); + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + } else { + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s5 = peg$c21; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c22); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsenumber(); + if (s6 === peg$FAILED) { + s6 = peg$parseidentifier(); + if (s6 === peg$FAILED) { + s6 = peg$parseinline(); + } + } + if (s6 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c23(s4, s6); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c24(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + + return s0; + } + + function peg$parsebodies() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = peg$parseld(); + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s4 = peg$c16; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c17); } + } + if (s4 !== peg$FAILED) { + s5 = peg$parsekey(); + if (s5 !== peg$FAILED) { + s6 = peg$parserd(); + if (s6 !== peg$FAILED) { + s7 = peg$parsebody(); + if (s7 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c23(s5, s7); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = peg$parseld(); + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s4 = peg$c16; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c17); } + } + if (s4 !== peg$FAILED) { + s5 = peg$parsekey(); + if (s5 !== peg$FAILED) { + s6 = peg$parserd(); + if (s6 !== peg$FAILED) { + s7 = peg$parsebody(); + if (s7 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c23(s5, s7); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c26(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c25); } + } + + return s0; + } + + function peg$parsereference() { + var s0, s1, s2, s3, s4; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + s2 = peg$parseidentifier(); + if (s2 !== peg$FAILED) { + s3 = peg$parsefilters(); + if (s3 !== peg$FAILED) { + s4 = peg$parserd(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c28(s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c27); } + } + + return s0; + } + + function peg$parsepartial() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s2 = peg$c30; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c31); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 43) { + s2 = peg$c32; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c33); } + } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + if (s3 !== peg$FAILED) { + s4 = peg$currPos; + s5 = peg$parsekey(); + if (s5 !== peg$FAILED) { + peg$reportedPos = s4; + s5 = peg$c34(s5); + } + s4 = s5; + if (s4 === peg$FAILED) { + s4 = peg$parseinline(); + } + if (s4 !== peg$FAILED) { + s5 = peg$parsecontext(); + if (s5 !== peg$FAILED) { + s6 = peg$parseparams(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); + } + if (s7 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s8 = peg$c8; + peg$currPos++; + } else { + s8 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + if (s8 !== peg$FAILED) { + s9 = peg$parserd(); + if (s9 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c35(s2, s4, s5, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + + return s0; + } + + function peg$parsefilters() { + var s0, s1, s2, s3, s4; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 124) { + s3 = peg$c37; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c18(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 124) { + s3 = peg$c37; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c18(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c39(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c36); } + } + + return s0; + } + + function peg$parsespecial() { + var s0, s1, s2, s3, s4; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 126) { + s2 = peg$c41; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c42); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsekey(); + if (s3 !== peg$FAILED) { + s4 = peg$parserd(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c43(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c40); } + } + + return s0; + } + + function peg$parseidentifier() { + var s0, s1; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsepath(); + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c45(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsekey(); + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c46(s1); + } + s0 = s1; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c44); } + } + + return s0; + } + + function peg$parsenumber() { + var s0, s1; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsefloat(); + if (s1 === peg$FAILED) { + s1 = peg$parseinteger(); + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c48(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c47); } + } + + return s0; + } + + function peg$parsefloat() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseinteger(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 46) { + s2 = peg$c50; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c51); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parseunsigned_integer(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c52(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c49); } + } + + return s0; + } + + function peg$parseunsigned_integer() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + if (peg$c54.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c54.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + } + } else { + s1 = peg$c3; + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c56(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c53); } + } + + return s0; + } + + function peg$parsesigned_integer() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 45) { + s1 = peg$c58; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c59); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseunsigned_integer(); + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c60(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c57); } + } + + return s0; + } + + function peg$parseinteger() { + var s0, s1; + + peg$silentFails++; + s0 = peg$parsesigned_integer(); + if (s0 === peg$FAILED) { + s0 = peg$parseunsigned_integer(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c61); } + } + + return s0; + } + + function peg$parsepath() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsekey(); + if (s1 === peg$FAILED) { + s1 = peg$c4; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsearray_part(); + if (s3 === peg$FAILED) { + s3 = peg$parsearray(); + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsearray_part(); + if (s3 === peg$FAILED) { + s3 = peg$parsearray(); + } + } + } else { + s2 = peg$c3; + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c63(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s1 = peg$c50; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c51); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsearray_part(); + if (s3 === peg$FAILED) { + s3 = peg$parsearray(); + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsearray_part(); + if (s3 === peg$FAILED) { + s3 = peg$parsearray(); + } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c64(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + + return s0; + } + + function peg$parsekey() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (peg$c66.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c67); } + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$c68.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c69); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$c68.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c69); } + } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c70(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c65); } + } + + return s0; + } + + function peg$parsearray() { + var s0, s1, s2, s3, s4, s5; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parselb(); + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + s4 = []; + if (peg$c54.test(input.charAt(peg$currPos))) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + if (s5 !== peg$FAILED) { + while (s5 !== peg$FAILED) { + s4.push(s5); + if (peg$c54.test(input.charAt(peg$currPos))) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + } + } else { + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + peg$reportedPos = s3; + s4 = peg$c72(s4); + } + s3 = s4; + if (s3 === peg$FAILED) { + s3 = peg$parseidentifier(); + } + if (s3 !== peg$FAILED) { + s4 = peg$parserb(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s1; + s2 = peg$c73(s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$c3; + } + } else { + peg$currPos = s1; + s1 = peg$c3; + } + } else { + peg$currPos = s1; + s1 = peg$c3; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsearray_part(); + if (s2 === peg$FAILED) { + s2 = peg$c4; + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c74(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c71); } + } + + return s0; + } + + function peg$parsearray_part() { + var s0, s1, s2, s3, s4; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s3 = peg$c50; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c51); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c76(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s3 = peg$c50; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c51); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsekey(); + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c76(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + } else { + s1 = peg$c3; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsearray(); + if (s2 === peg$FAILED) { + s2 = peg$c4; + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c77(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c75); } + } + + return s0; + } + + function peg$parseinline() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c79; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s2 = peg$c79; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c81(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c79; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseliteral(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c79; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c82(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c79; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseinline_part(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseinline_part(); + } + } else { + s2 = peg$c3; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c79; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + + return s0; + } + + function peg$parseinline_part() { + var s0, s1; + + s0 = peg$parsespecial(); + if (s0 === peg$FAILED) { + s0 = peg$parsereference(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseliteral(); + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c84(s1); + } + s0 = s1; + } + } + + return s0; + } + + function peg$parsebuffer() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseeol(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c86(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = peg$currPos; + peg$silentFails++; + s4 = peg$parsetag(); + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = peg$c6; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseraw(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parsecomment(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = peg$c6; + } else { + peg$currPos = s5; + s5 = peg$c3; + } + if (s5 !== peg$FAILED) { + s6 = peg$currPos; + peg$silentFails++; + s7 = peg$parseeol(); + peg$silentFails--; + if (s7 === peg$FAILED) { + s6 = peg$c6; + } else { + peg$currPos = s6; + s6 = peg$c3; + } + if (s6 !== peg$FAILED) { + if (input.length > peg$currPos) { + s7 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s7 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c88(s7); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = peg$currPos; + peg$silentFails++; + s4 = peg$parsetag(); + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = peg$c6; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseraw(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parsecomment(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = peg$c6; + } else { + peg$currPos = s5; + s5 = peg$c3; + } + if (s5 !== peg$FAILED) { + s6 = peg$currPos; + peg$silentFails++; + s7 = peg$parseeol(); + peg$silentFails--; + if (s7 === peg$FAILED) { + s6 = peg$c6; + } else { + peg$currPos = s6; + s6 = peg$c3; + } + if (s6 !== peg$FAILED) { + if (input.length > peg$currPos) { + s7 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s7 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c88(s7); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + } else { + s1 = peg$c3; + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c89(s1); + } + s0 = s1; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c85); } + } + + return s0; + } + + function peg$parseliteral() { + var s0, s1, s2, s3, s4; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = peg$currPos; + peg$silentFails++; + s4 = peg$parsetag(); + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = peg$c6; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseesc(); + if (s4 === peg$FAILED) { + if (peg$c91.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c92); } + } + } + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c88(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = peg$currPos; + peg$silentFails++; + s4 = peg$parsetag(); + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = peg$c6; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + if (s3 !== peg$FAILED) { + s4 = peg$parseesc(); + if (s4 === peg$FAILED) { + if (peg$c91.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c92); } + } + } + if (s4 !== peg$FAILED) { + peg$reportedPos = s2; + s3 = peg$c88(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } else { + peg$currPos = s2; + s2 = peg$c3; + } + } + } else { + s1 = peg$c3; + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c93(s1); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c90); } + } + + return s0; + } + + function peg$parseesc() { + var s0, s1; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c94) { + s1 = peg$c94; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c95); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c96(); + } + s0 = s1; + + return s0; + } + + function peg$parseraw() { + var s0, s1, s2, s3, s4, s5; + + peg$silentFails++; + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c98) { + s1 = peg$c98; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c99); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c100) { + s5 = peg$c100; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c101); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s3; + s4 = peg$c102(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } else { + peg$currPos = s3; + s3 = peg$c3; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c100) { + s5 = peg$c100; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c101); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s3; + s4 = peg$c102(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } + if (s2 !== peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c100) { + s3 = peg$c100; + peg$currPos += 2; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c101); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c103(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c97); } + } + + return s0; + } + + function peg$parsecomment() { + var s0, s1, s2, s3, s4, s5; + + peg$silentFails++; + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c105) { + s1 = peg$c105; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c106); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c107) { + s5 = peg$c107; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c108); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s3; + s4 = peg$c88(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } else { + peg$currPos = s3; + s3 = peg$c3; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c107) { + s5 = peg$c107; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c108); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = peg$c6; + } else { + peg$currPos = s4; + s4 = peg$c3; + } + if (s4 !== peg$FAILED) { + if (input.length > peg$currPos) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s3; + s4 = peg$c88(s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } else { + peg$currPos = s3; + s3 = peg$c3; + } + } + if (s2 !== peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c107) { + s3 = peg$c107; + peg$currPos += 2; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c108); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c109(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c104); } + } + + return s0; + } + + function peg$parsetag() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$parseld(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + if (s2 !== peg$FAILED) { + if (peg$c110.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c111); } + } + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$currPos; + s7 = peg$currPos; + peg$silentFails++; + s8 = peg$parserd(); + peg$silentFails--; + if (s8 === peg$FAILED) { + s7 = peg$c6; + } else { + peg$currPos = s7; + s7 = peg$c3; + } + if (s7 !== peg$FAILED) { + s8 = peg$currPos; + peg$silentFails++; + s9 = peg$parseeol(); + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = peg$c6; + } else { + peg$currPos = s8; + s8 = peg$c3; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s9 !== peg$FAILED) { + s7 = [s7, s8, s9]; + s6 = s7; + } else { + peg$currPos = s6; + s6 = peg$c3; + } + } else { + peg$currPos = s6; + s6 = peg$c3; + } + } else { + peg$currPos = s6; + s6 = peg$c3; + } + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$currPos; + s7 = peg$currPos; + peg$silentFails++; + s8 = peg$parserd(); + peg$silentFails--; + if (s8 === peg$FAILED) { + s7 = peg$c6; + } else { + peg$currPos = s7; + s7 = peg$c3; + } + if (s7 !== peg$FAILED) { + s8 = peg$currPos; + peg$silentFails++; + s9 = peg$parseeol(); + peg$silentFails--; + if (s9 === peg$FAILED) { + s8 = peg$c6; + } else { + peg$currPos = s8; + s8 = peg$c3; + } + if (s8 !== peg$FAILED) { + if (input.length > peg$currPos) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + if (s9 !== peg$FAILED) { + s7 = [s7, s8, s9]; + s6 = s7; + } else { + peg$currPos = s6; + s6 = peg$c3; + } + } else { + peg$currPos = s6; + s6 = peg$c3; + } + } else { + peg$currPos = s6; + s6 = peg$c3; + } + } + } else { + s5 = peg$c3; + } + if (s5 !== peg$FAILED) { + s6 = []; + s7 = peg$parsews(); + while (s7 !== peg$FAILED) { + s6.push(s7); + s7 = peg$parsews(); + } + if (s6 !== peg$FAILED) { + s7 = peg$parserd(); + if (s7 !== peg$FAILED) { + s1 = [s1, s2, s3, s4, s5, s6, s7]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + } else { + peg$currPos = s0; + s0 = peg$c3; + } + if (s0 === peg$FAILED) { + s0 = peg$parsereference(); + } + + return s0; + } + + function peg$parseld() { + var s0; + + if (input.charCodeAt(peg$currPos) === 123) { + s0 = peg$c112; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c113); } + } + + return s0; + } + + function peg$parserd() { + var s0; + + if (input.charCodeAt(peg$currPos) === 125) { + s0 = peg$c114; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c115); } + } + + return s0; + } + + function peg$parselb() { + var s0; + + if (input.charCodeAt(peg$currPos) === 91) { + s0 = peg$c116; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c117); } + } + + return s0; + } + + function peg$parserb() { + var s0; + + if (input.charCodeAt(peg$currPos) === 93) { + s0 = peg$c118; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c119); } + } + + return s0; + } + + function peg$parseeol() { + var s0; + + if (input.charCodeAt(peg$currPos) === 10) { + s0 = peg$c120; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c121); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c122) { + s0 = peg$c122; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c123); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 13) { + s0 = peg$c124; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c125); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 8232) { + s0 = peg$c126; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c127); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 8233) { + s0 = peg$c128; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c129); } + } + } + } + } + } + + return s0; + } + + function peg$parsews() { + var s0; + + if (peg$c130.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c131); } + } + if (s0 === peg$FAILED) { + s0 = peg$parseeol(); + } + + return s0; + } + + + function makeInteger(arr) { + return parseInt(arr.join(''), 10); + } + function withPosition(arr) { + return arr.concat([['line', line()], ['col', column()]]); + } + + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail({ type: "end", description: "end of input" }); + } + + throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); + } + } + + return { + SyntaxError: SyntaxError, + parse: parse + }; +})(); + + // expose parser methods + dust.parse = parser.parse; + + return parser; +})); + +(function(root, factory) { + if (typeof define === "function" && define.amd && define.amd.dust === true) { + define("dust.compile", ["dust.core", "dust.parse"], function(dust, parse) { + return factory(parse, dust).compile; + }); + } else if (typeof exports === 'object') { + // in Node, require this file if we want to use the compiler as a standalone module + module.exports = factory(require('./parser').parse, require('./dust')); + } else { + // in the browser, store the factory output if we want to use the compiler directly + factory(root.dust.parse, root.dust); + } +}(this, function(parse, dust) { + var compiler = {}, + isArray = dust.isArray; + + + compiler.compile = function(source, name) { + // the name parameter is optional. + // this can happen for templates that are rendered immediately (renderSource which calls compileFn) or + // for templates that are compiled as a callable (compileFn) + // + // for the common case (using compile and render) a name is required so that templates will be cached by name and rendered later, by name. + + try { + var ast = filterAST(parse(source)); + return compile(ast, name); + } + catch (err) + { + if (!err.line || !err.column) { + throw err; + } + throw new SyntaxError(err.message + ' At line : ' + err.line + ', column : ' + err.column); + } + }; + + function filterAST(ast) { + var context = {}; + return compiler.filterNode(context, ast); + } + + compiler.filterNode = function(context, node) { + return compiler.optimizers[node[0]](context, node); + }; + + compiler.optimizers = { + body: compactBuffers, + buffer: noop, + special: convertSpecial, + format: format, + reference: visit, + '#': visit, + '?': visit, + '^': visit, + '<': visit, + '+': visit, + '@': visit, + '%': visit, + partial: visit, + context: visit, + params: visit, + bodies: visit, + param: visit, + filters: noop, + key: noop, + path: noop, + literal: noop, + raw: noop, + comment: nullify, + line: nullify, + col: nullify + }; + + compiler.pragmas = { + esc: function(compiler, context, bodies) { + var old = compiler.auto, + out; + if (!context) { + context = 'h'; + } + compiler.auto = (context === 's') ? '' : context; + out = compileParts(compiler, bodies.block); + compiler.auto = old; + return out; + } + }; + + function visit(context, node) { + var out = [node[0]], + i, len, res; + for (i=1, len=node.length; i=c[dust.debugLevel]&&b("[DUST:"+d+"]",a)},dust.debugLevel=NONE,"undefined"!=typeof process&&process.env&&/\bdust\b/.test(process.env.DEBUG)&&(dust.debugLevel=DEBUG)}(),dust.helpers={},dust.cache={},dust.register=function(a,b){a&&(b.templateName=a,dust.config.cache!==!1&&(dust.cache[a]=b))},dust.render=function(a,b,c){var d=new Stub(c).head;try{load(a,d,b).end()}catch(e){d.setError(e)}},dust.stream=function(a,b){var c=new Stream,d=c.head;return dust.nextTick(function(){try{load(a,d,b).end()}catch(c){d.setError(c)}}),c},dust.loadSource=function(source){return eval(source)},dust.isArray=Array.isArray?Array.isArray:function(a){return"[object Array]"===Object.prototype.toString.call(a)},dust.nextTick=function(){return function(a){setTimeout(a,0)}}(),dust.isEmpty=function(a){return 0===a?!1:dust.isArray(a)&&!a.length?!0:!a},dust.isEmptyObject=function(a){var b;if(null===a)return!1;if(void 0===a)return!1;if(a.length>0)return!1;for(b in a)if(Object.prototype.hasOwnProperty.call(a,b))return!1;return!0},dust.isTemplateFn=function(a){return"function"==typeof a&&a.__dustBody},dust.isThenable=function(a){return a&&"object"==typeof a&&"function"==typeof a.then},dust.isStreamable=function(a){return a&&"function"==typeof a.on&&"function"==typeof a.pipe},dust.filter=function(a,b,c,d){var e,f,g,h;if(c)for(e=0,f=c.length;f>e;e++)g=c[e],g.length&&(h=dust.filters[g],"s"===g?b=null:"function"==typeof h?a=h(a,d):dust.log("Invalid filter `"+g+"`",WARN));return b&&(a=dust.filters[b](a,d)),a},dust.filters={h:function(a){return dust.escapeHtml(a)},j:function(a){return dust.escapeJs(a)},u:encodeURI,uc:encodeURIComponent,js:function(a){return dust.escapeJSON(a)},jp:function(a){return JSON?JSON.parse(a):(dust.log("JSON is undefined; could not parse `"+a+"`",WARN),a)}},dust.makeBase=dust.context=function(a,b){return new Context(void 0,a,b)},dust.isContext=function(a){return"object"==typeof a&&a._isContext===!0},Context.wrap=function(a,b){return dust.isContext(a)?a:new Context(a,{},{},null,b)},Context.prototype.get=function(a,b){return"string"==typeof a&&("."===a[0]&&(b=!0,a=a.substr(1)),a=a.split(".")),this._get(b,a)},Context.prototype._get=function(a,b){var c,d,e,f,g,h=this.stack||{},i=1;if(d=b[0],e=b.length,a&&0===e)f=h,h=h.head;else{if(a)h&&(h=h.head?h.head[d]:void 0);else{for(;h&&(!h.isObject||(f=h.head,c=h.head[d],void 0===c));)h=h.tail;h=void 0!==c?c:this.global&&this.global[d]}for(;h&&e>i;){if(dust.isThenable(h))return h.then(getWithResolvedData(this,a,b.slice(i)));f=h,h=h[b[i]],i++}}return"function"==typeof h?(g=function(){try{return h.apply(f,arguments)}catch(a){throw dust.log(a,ERROR),a}},g.__dustBody=!!h.__dustBody,g):(void 0===h&&dust.log("Cannot find reference `{"+b.join(".")+"}` in template `"+this.getTemplateName()+"`",INFO),h)},Context.prototype.getPath=function(a,b){return this._get(a,b)},Context.prototype.push=function(a,b,c){return void 0===a?(dust.log("Not pushing an undefined variable onto the context",INFO),this):this.rebase(new Stack(a,this.stack,b,c))},Context.prototype.pop=function(){var a=this.current();return this.stack=this.stack&&this.stack.tail,a},Context.prototype.rebase=function(a){return new Context(a,this.global,this.options,this.blocks,this.getTemplateName())},Context.prototype.clone=function(){var a=this.rebase();return a.stack=this.stack,a},Context.prototype.current=function(){return this.stack&&this.stack.head},Context.prototype.getBlock=function(a){var b,c,d;if("function"==typeof a&&(a=a(new Chunk,this).data.join("")),b=this.blocks,!b)return dust.log("No blocks for context `"+a+"` in template `"+this.getTemplateName()+"`",DEBUG),!1;for(c=b.length;c--;)if(d=b[c][a])return d;return dust.log("Malformed template `"+this.getTemplateName()+"` was missing one or more blocks."),!1},Context.prototype.shiftBlocks=function(a){var b,c=this.blocks;return a?(b=c?c.concat([a]):[a],new Context(this.stack,this.global,this.options,b,this.getTemplateName())):this},Context.prototype.resolve=function(a){var b;return"function"!=typeof a?a:(b=(new Chunk).render(a,this),b instanceof Chunk?b.data.join(""):b)},Context.prototype.getTemplateName=function(){return this.templateName},Stub.prototype.flush=function(){for(var a=this.head;a;){if(!a.flushable)return a.error?(this.callback(a.error),dust.log("Rendering failed with error `"+a.error+"`",ERROR),void(this.flush=EMPTY_FUNC)):void 0;this.out+=a.data.join(""),a=a.next,this.head=a}this.callback(null,this.out)},Stream.prototype.flush=function(){for(var a=this.head;a;){if(!a.flushable)return a.error?(this.emit("error",a.error),this.emit("end"),dust.log("Streaming failed with error `"+a.error+"`",ERROR),void(this.flush=EMPTY_FUNC)):void 0;this.emit("data",a.data.join("")),a=a.next,this.head=a}this.emit("end")},Stream.prototype.emit=function(a,b){var c,d,e=this.events||{},f=e[a]||[];if(!f.length)return dust.log("Stream broadcasting, but no listeners for `"+a+"`",DEBUG),!1;for(f=f.slice(0),c=0,d=f.length;d>c;c++)f[c](b);return!0},Stream.prototype.on=function(a,b){var c=this.events=this.events||{},d=c[a]=c[a]||[];return"function"!=typeof b?dust.log("No callback function provided for `"+a+"` event listener",WARN):d.push(b),this},Stream.prototype.pipe=function(a){if("function"!=typeof a.write||"function"!=typeof a.end)return dust.log("Incompatible stream passed to `pipe`",WARN),this;var b=!1;return"function"==typeof a.emit&&a.emit("pipe",this),"function"==typeof a.on&&a.on("error",function(){b=!0}),this.on("data",function(c){if(!b)try{a.write(c,"utf8")}catch(d){dust.log(d,ERROR)}}).on("end",function(){if(!b)try{a.end(),b=!0}catch(c){dust.log(c,ERROR)}})},Chunk.prototype.write=function(a){var b=this.taps;return b&&(a=b.go(a)),this.data.push(a),this},Chunk.prototype.end=function(a){return a&&this.write(a),this.flushable=!0,this.root.flush(),this},Chunk.prototype.map=function(a){var b=new Chunk(this.root,this.next,this.taps),c=new Chunk(this.root,b,this.taps);this.next=c,this.flushable=!0;try{a(c)}catch(d){dust.log(d,ERROR),c.setError(d)}return b},Chunk.prototype.tap=function(a){var b=this.taps;return this.taps=b?b.push(a):new Tap(a),this},Chunk.prototype.untap=function(){return this.taps=this.taps.tail,this},Chunk.prototype.render=function(a,b){return a(this,b)},Chunk.prototype.reference=function(a,b,c,d){return"function"==typeof a?(a=a.apply(b.current(),[this,b,null,{auto:c,filters:d}]),a instanceof Chunk?a:this.reference(a,b,c,d)):dust.isThenable(a)?this.await(a,b,null,c,d):dust.isStreamable(a)?this.stream(a,b,null,c,d):dust.isEmpty(a)?this:this.write(dust.filter(a,c,d,b))},Chunk.prototype.section=function(a,b,c,d){var e,f,g,h=c.block,i=c["else"],j=this;if("function"==typeof a&&!dust.isTemplateFn(a)){try{a=a.apply(b.current(),[this,b,c,d])}catch(k){return dust.log(k,ERROR),this.setError(k)}if(a instanceof Chunk)return a}if(dust.isEmptyObject(c))return j;if(dust.isEmptyObject(d)||(b=b.push(d)),dust.isArray(a)){if(h){if(f=a.length,f>0){for(g=b.stack&&b.stack.head||{},g.$len=f,e=0;f>e;e++)g.$idx=e,j=h(j,b.push(a[e],e,f));return g.$idx=void 0,g.$len=void 0,j}if(i)return i(this,b)}}else{if(dust.isThenable(a))return this.await(a,b,c);if(dust.isStreamable(a))return this.stream(a,b,c);if(a===!0){if(h)return h(this,b)}else if(a||0===a){if(h)return h(this,b.push(a))}else if(i)return i(this,b)}return dust.log("Section without corresponding key in template `"+b.getTemplateName()+"`",DEBUG),this},Chunk.prototype.exists=function(a,b,c){var d=c.block,e=c["else"];if(dust.isEmpty(a)){if(e)return e(this,b)}else{if(d)return d(this,b);dust.log("No block for exists check in template `"+b.getTemplateName()+"`",DEBUG)}return this},Chunk.prototype.notexists=function(a,b,c){var d=c.block,e=c["else"];if(dust.isEmpty(a)){if(d)return d(this,b);dust.log("No block for not-exists check in template `"+b.getTemplateName()+"`",DEBUG)}else if(e)return e(this,b);return this},Chunk.prototype.block=function(a,b,c){var d=a||c.block;return d?d(this,b):this},Chunk.prototype.partial=function(a,b,c,d){var e;return void 0===d&&(d=c,c=b),dust.isEmptyObject(d)||(c=c.clone(),e=c.pop(),c=c.push(d).push(e)),dust.isTemplateFn(a)?this.capture(a,b,function(a,b){c.templateName=a,load(a,b,c).end()}):(c.templateName=a,load(a,this,c))},Chunk.prototype.helper=function(a,b,c,d,e){var f,g=this,h=d.filters;if(void 0===e&&(e="h"),!dust.helpers[a])return dust.log("Helper `"+a+"` does not exist",WARN),g;try{return f=dust.helpers[a](g,b,c,d),f instanceof Chunk?f:("string"==typeof h&&(h=h.split("|")),dust.isEmptyObject(c)?g.reference(f,b,e,h):g.section(f,b,c,d))}catch(i){return dust.log("Error in helper `"+a+"`: "+i.message,ERROR),g.setError(i)}},Chunk.prototype.await=function(a,b,c,d,e){return this.map(function(f){a.then(function(a){f=c?f.section(a,b,c):f.reference(a,b,d,e),f.end()},function(a){var d=c&&c.error;d?f.render(d,b.push(a)).end():(dust.log("Unhandled promise rejection in `"+b.getTemplateName()+"`",INFO),f.end())})})},Chunk.prototype.stream=function(a,b,c,d,e){var f=c&&c.block,g=c&&c.error;return this.map(function(h){var i=!1;a.on("data",function(a){i||(f?h=h.map(function(c){c.render(f,b.push(a)).end()}):c||(h=h.reference(a,b,d,e)))}).on("error",function(a){i||(g?h.render(g,b.push(a)):dust.log("Unhandled stream error in `"+b.getTemplateName()+"`",INFO),i||(i=!0,h.end()))}).on("end",function(){i||(i=!0,h.end())})})},Chunk.prototype.capture=function(a,b,c){return this.map(function(d){var e=new Stub(function(a,b){a?d.setError(a):c(b,d)});a(e.head,b).end()})},Chunk.prototype.setError=function(a){return this.error=a,this.root.flush(),this};for(var f in Chunk.prototype)dust._aliases[f]&&(Chunk.prototype[dust._aliases[f]]=Chunk.prototype[f]);Tap.prototype.push=function(a){return new Tap(a,this)},Tap.prototype.go=function(a){for(var b=this;b;)a=b.head(a),b=b.tail;return a};var HCHARS=/[&<>"']/,AMP=/&/g,LT=//g,QUOT=/\"/g,SQUOT=/\'/g;dust.escapeHtml=function(a){return"string"==typeof a||a&&"function"==typeof a.toString?("string"!=typeof a&&(a=a.toString()),HCHARS.test(a)?a.replace(AMP,"&").replace(LT,"<").replace(GT,">").replace(QUOT,""").replace(SQUOT,"'"):a):a};var BS=/\\/g,FS=/\//g,CR=/\r/g,LS=/\u2028/g,PS=/\u2029/g,NL=/\n/g,LF=/\f/g,SQ=/'/g,DQ=/"/g,TB=/\t/g;return dust.escapeJs=function(a){return"string"==typeof a?a.replace(BS,"\\\\").replace(FS,"\\/").replace(DQ,'\\"').replace(SQ,"\\'").replace(CR,"\\r").replace(LS,"\\u2028").replace(PS,"\\u2029").replace(NL,"\\n").replace(LF,"\\f").replace(TB,"\\t"):a},dust.escapeJSON=function(a){return JSON?JSON.stringify(a).replace(LS,"\\u2028").replace(PS,"\\u2029").replace(LT,"\\u003c"):(dust.log("JSON is undefined; could not escape `"+a+"`",WARN),a)},dust}),function(a,b){"function"==typeof define&&define.amd&&define.amd.dust===!0?define("dust.parse",["dust.core"],function(dust){return b(dust).parse}):"object"==typeof exports?module.exports=b(require("./dust")):b(a.dust)}(this,function(dust){var a=function(){function a(a,b){function c(){this.constructor=a}c.prototype=b.prototype,a.prototype=new c}function b(a,b,c,d,e,f){this.message=a,this.expected=b,this.found=c,this.offset=d,this.line=e,this.column=f,this.name="SyntaxError"}function c(a){function c(){return f(wc).line}function d(){return f(wc).column}function e(a){throw h(a,null,wc)}function f(b){function c(b,c,d){var e,f;for(e=c;d>e;e++)f=a.charAt(e),"\n"===f?(b.seenCR||b.line++,b.column=1,b.seenCR=!1):"\r"===f||"\u2028"===f||"\u2029"===f?(b.line++,b.column=1,b.seenCR=!0):(b.column++,b.seenCR=!1)}return xc!==b&&(xc>b&&(xc=0,yc={line:1,column:1,seenCR:!1}),c(yc,xc,b),xc=b),yc}function g(a){zc>vc||(vc>zc&&(zc=vc,Ac=[]),Ac.push(a))}function h(c,d,e){function g(a){var b=1;for(a.sort(function(a,b){return a.descriptionb.description?1:0});b1?g.slice(0,-1).join(", ")+" or "+g[a.length-1]:g[0],e=b?'"'+c(b)+'"':"end of input","Expected "+d+" but "+e+" found."}var i=f(e),j=evc?(j=a.charAt(vc),vc++):(j=X,0===Bc&&g(Eb)),j!==X?(wc=d,e=Fb(j),d=e):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa),d!==X)for(;d!==X;)c.push(d),d=vc,e=vc,Bc++,f=M(),Bc--,f===X?e=da:(vc=e,e=aa),e!==X?(f=vc,Bc++,h=K(),Bc--,h===X?f=da:(vc=f,f=aa),f!==X?(h=vc,Bc++,i=L(),Bc--,i===X?h=da:(vc=h,h=aa),h!==X?(i=vc,Bc++,j=R(),Bc--,j===X?i=da:(vc=i,i=aa),i!==X?(a.length>vc?(j=a.charAt(vc),vc++):(j=X,0===Bc&&g(Eb)),j!==X?(wc=d,e=Fb(j),d=e):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa)):(vc=d,d=aa);else c=aa;c!==X&&(wc=b,c=Gb(c)),b=c}return Bc--,b===X&&(c=X,0===Bc&&g(Cb)),b}function I(){var b,c,d,e,f;if(Bc++,b=vc,c=[],d=vc,e=vc,Bc++,f=M(),Bc--,f===X?e=da:(vc=e,e=aa),e!==X?(f=J(),f===X&&(Ib.test(a.charAt(vc))?(f=a.charAt(vc),vc++):(f=X,0===Bc&&g(Jb))),f!==X?(wc=d,e=Fb(f),d=e):(vc=d,d=aa)):(vc=d,d=aa),d!==X)for(;d!==X;)c.push(d),d=vc,e=vc,Bc++,f=M(),Bc--,f===X?e=da:(vc=e,e=aa),e!==X?(f=J(),f===X&&(Ib.test(a.charAt(vc))?(f=a.charAt(vc),vc++):(f=X,0===Bc&&g(Jb))),f!==X?(wc=d,e=Fb(f),d=e):(vc=d,d=aa)):(vc=d,d=aa);else c=aa;return c!==X&&(wc=b,c=Kb(c)),b=c,Bc--,b===X&&(c=X,0===Bc&&g(Hb)),b}function J(){var b,c;return b=vc,a.substr(vc,2)===Lb?(c=Lb,vc+=2):(c=X,0===Bc&&g(Mb)),c!==X&&(wc=b,c=Nb()),b=c}function K(){var b,c,d,e,f,h;if(Bc++,b=vc,a.substr(vc,2)===Pb?(c=Pb,vc+=2):(c=X,0===Bc&&g(Qb)),c!==X){for(d=[],e=vc,f=vc,Bc++,a.substr(vc,2)===Rb?(h=Rb,vc+=2):(h=X,0===Bc&&g(Sb)),Bc--,h===X?f=da:(vc=f,f=aa),f!==X?(a.length>vc?(h=a.charAt(vc),vc++):(h=X,0===Bc&&g(Eb)),h!==X?(wc=e,f=Tb(h),e=f):(vc=e,e=aa)):(vc=e,e=aa);e!==X;)d.push(e),e=vc,f=vc,Bc++,a.substr(vc,2)===Rb?(h=Rb,vc+=2):(h=X,0===Bc&&g(Sb)),Bc--,h===X?f=da:(vc=f,f=aa),f!==X?(a.length>vc?(h=a.charAt(vc),vc++):(h=X,0===Bc&&g(Eb)),h!==X?(wc=e,f=Tb(h),e=f):(vc=e,e=aa)):(vc=e,e=aa);d!==X?(a.substr(vc,2)===Rb?(e=Rb,vc+=2):(e=X,0===Bc&&g(Sb)),e!==X?(wc=b,c=Ub(d),b=c):(vc=b,b=aa)):(vc=b,b=aa)}else vc=b,b=aa;return Bc--,b===X&&(c=X,0===Bc&&g(Ob)),b}function L(){var b,c,d,e,f,h;if(Bc++,b=vc,a.substr(vc,2)===Wb?(c=Wb,vc+=2):(c=X,0===Bc&&g(Xb)),c!==X){for(d=[],e=vc,f=vc,Bc++,a.substr(vc,2)===Yb?(h=Yb,vc+=2):(h=X,0===Bc&&g(Zb)),Bc--,h===X?f=da:(vc=f,f=aa),f!==X?(a.length>vc?(h=a.charAt(vc),vc++):(h=X,0===Bc&&g(Eb)),h!==X?(wc=e,f=Fb(h),e=f):(vc=e,e=aa)):(vc=e,e=aa);e!==X;)d.push(e),e=vc,f=vc,Bc++,a.substr(vc,2)===Yb?(h=Yb,vc+=2):(h=X,0===Bc&&g(Zb)),Bc--,h===X?f=da:(vc=f,f=aa),f!==X?(a.length>vc?(h=a.charAt(vc),vc++):(h=X,0===Bc&&g(Eb)),h!==X?(wc=e,f=Fb(h),e=f):(vc=e,e=aa)):(vc=e,e=aa);d!==X?(a.substr(vc,2)===Yb?(e=Yb,vc+=2):(e=X,0===Bc&&g(Zb)),e!==X?(wc=b,c=$b(d),b=c):(vc=b,b=aa)):(vc=b,b=aa)}else vc=b,b=aa;return Bc--,b===X&&(c=X,0===Bc&&g(Vb)),b}function M(){var b,c,d,e,f,h,i,j,k,l;if(b=vc,c=N(),c!==X){for(d=[],e=S();e!==X;)d.push(e),e=S();if(d!==X)if(_b.test(a.charAt(vc))?(e=a.charAt(vc),vc++):(e=X,0===Bc&&g(ac)),e!==X){for(f=[],h=S();h!==X;)f.push(h),h=S();if(f!==X){if(h=[],i=vc,j=vc,Bc++,k=O(),Bc--,k===X?j=da:(vc=j,j=aa),j!==X?(k=vc,Bc++,l=R(),Bc--,l===X?k=da:(vc=k,k=aa),k!==X?(a.length>vc?(l=a.charAt(vc),vc++):(l=X,0===Bc&&g(Eb)),l!==X?(j=[j,k,l],i=j):(vc=i,i=aa)):(vc=i,i=aa)):(vc=i,i=aa),i!==X)for(;i!==X;)h.push(i),i=vc,j=vc,Bc++,k=O(),Bc--,k===X?j=da:(vc=j,j=aa),j!==X?(k=vc,Bc++,l=R(),Bc--,l===X?k=da:(vc=k,k=aa),k!==X?(a.length>vc?(l=a.charAt(vc),vc++):(l=X,0===Bc&&g(Eb)),l!==X?(j=[j,k,l],i=j):(vc=i,i=aa)):(vc=i,i=aa)):(vc=i,i=aa);else h=aa;if(h!==X){for(i=[],j=S();j!==X;)i.push(j),j=S();i!==X?(j=O(),j!==X?(c=[c,d,e,f,h,i,j],b=c):(vc=b,b=aa)):(vc=b,b=aa)}else vc=b,b=aa}else vc=b,b=aa}else vc=b,b=aa;else vc=b,b=aa}else vc=b,b=aa;return b===X&&(b=r()),b}function N(){var b;return 123===a.charCodeAt(vc)?(b=bc,vc++):(b=X,0===Bc&&g(cc)),b}function O(){var b;return 125===a.charCodeAt(vc)?(b=dc,vc++):(b=X,0===Bc&&g(ec)),b}function P(){var b;return 91===a.charCodeAt(vc)?(b=fc,vc++):(b=X,0===Bc&&g(gc)),b}function Q(){var b;return 93===a.charCodeAt(vc)?(b=hc,vc++):(b=X,0===Bc&&g(ic)),b}function R(){var b;return 10===a.charCodeAt(vc)?(b=jc,vc++):(b=X,0===Bc&&g(kc)),b===X&&(a.substr(vc,2)===lc?(b=lc,vc+=2):(b=X,0===Bc&&g(mc)),b===X&&(13===a.charCodeAt(vc)?(b=nc,vc++):(b=X,0===Bc&&g(oc)),b===X&&(8232===a.charCodeAt(vc)?(b=pc,vc++):(b=X,0===Bc&&g(qc)),b===X&&(8233===a.charCodeAt(vc)?(b=rc,vc++):(b=X,0===Bc&&g(sc)))))),b}function S(){var b;return tc.test(a.charAt(vc))?(b=a.charAt(vc),vc++):(b=X,0===Bc&&g(uc)),b===X&&(b=R()),b}function T(a){return parseInt(a.join(""),10)}function U(a){return a.concat([["line",c()],["col",d()]])}var V,W=arguments.length>1?arguments[1]:{},X={},Y={start:i},Z=i,$=function(a){var b=["body"].concat(a);return U(b)},_={type:"other",description:"section"},aa=X,ba=null,ca=function(a,b,c,d){return d&&a[1].text===d.text||e("Expected end tag for "+a[1].text+" but it was not found."),!0},da=void 0,ea=function(a,b,c){return c.push(["param",["literal","block"],b]),a.push(c,["filters"]),U(a)},fa="/",ga={type:"literal",value:"/",description:'"/"'},ha=function(a){return a.push(["bodies"],["filters"]),U(a)},ia=/^[#?\^<+@%]/,ja={type:"class",value:"[#?\\^<+@%]",description:"[#?\\^<+@%]"},ka=function(a,b,c,d){return[a,b,c,d]},la={type:"other",description:"end tag"},ma=function(a){return a},na=":",oa={type:"literal",value:":",description:'":"'},pa=function(a){return a},qa=function(a){return a?["context",a]:["context"]},ra={type:"other",description:"params"},sa="=",ta={type:"literal",value:"=",description:'"="'},ua=function(a,b){return["param",["literal",a],b]},va=function(a){return["params"].concat(a)},wa={type:"other",description:"bodies"},xa=function(a){return["bodies"].concat(a)},ya={type:"other",description:"reference"},za=function(a,b){return U(["reference",a,b])},Aa={type:"other",description:"partial"},Ba=">",Ca={type:"literal",value:">",description:'">"'},Da="+",Ea={type:"literal",value:"+",description:'"+"'},Fa=function(a){return["literal",a]},Ga=function(a,b,c,d){var e=">"===a?"partial":a;return U([e,b,c,d])},Ha={type:"other",description:"filters"},Ia="|",Ja={type:"literal",value:"|",description:'"|"'},Ka=function(a){return["filters"].concat(a)},La={type:"other",description:"special"},Ma="~",Na={type:"literal",value:"~",description:'"~"'},Oa=function(a){return U(["special",a])},Pa={type:"other",description:"identifier"},Qa=function(a){var b=["path"].concat(a);return b.text=a[1].join(".").replace(/,line,\d+,col,\d+/g,""),b},Ra=function(a){var b=["key",a];return b.text=a,b},Sa={type:"other",description:"number"},Ta=function(a){return["literal",a]},Ua={type:"other",description:"float"},Va=".",Wa={type:"literal",value:".",description:'"."'},Xa=function(a,b){return parseFloat(a+"."+b)},Ya={type:"other",description:"unsigned_integer"},Za=/^[0-9]/,$a={type:"class",value:"[0-9]",description:"[0-9]"},_a=function(a){return T(a)},ab={type:"other",description:"signed_integer"},bb="-",cb={type:"literal",value:"-",description:'"-"'},db=function(a,b){return-1*b},eb={type:"other",description:"integer"},fb={type:"other",description:"path"},gb=function(a,b){return b=b[0],a&&b?(b.unshift(a),U([!1,b])):U([!0,b])},hb=function(a){return U(a.length>0?[!0,a[0]]:[!0,[]])},ib={type:"other",description:"key"},jb=/^[a-zA-Z_$]/,kb={type:"class",value:"[a-zA-Z_$]",description:"[a-zA-Z_$]"},lb=/^[0-9a-zA-Z_$\-]/,mb={type:"class",value:"[0-9a-zA-Z_$\\-]",description:"[0-9a-zA-Z_$\\-]"},nb=function(a,b){return a+b.join("")},ob={type:"other",description:"array"},pb=function(a){return a.join("")},qb=function(a){return a},rb=function(a,b){return b?b.unshift(a):b=[a],b},sb={type:"other",description:"array_part"},tb=function(a){return a},ub=function(a,b){return b?a.concat(b):a},vb={type:"other",description:"inline"},wb='"',xb={type:"literal",value:'"',description:'"\\""'},yb=function(){return U(["literal",""])},zb=function(a){return U(["literal",a])},Ab=function(a){return U(["body"].concat(a))},Bb=function(a){return["buffer",a]},Cb={type:"other",description:"buffer"},Db=function(a,b){return U(["format",a,b.join("")])},Eb={type:"any",description:"any character"},Fb=function(a){return a},Gb=function(a){return U(["buffer",a.join("")])},Hb={type:"other",description:"literal"},Ib=/^[^"]/,Jb={type:"class",value:'[^"]',description:'[^"]'},Kb=function(a){return a.join("")},Lb='\\"',Mb={type:"literal",value:'\\"',description:'"\\\\\\""'},Nb=function(){return'"'},Ob={type:"other",description:"raw"},Pb="{`",Qb={type:"literal",value:"{`",description:'"{`"'},Rb="`}",Sb={type:"literal",value:"`}",description:'"`}"'},Tb=function(a){return a},Ub=function(a){return U(["raw",a.join("")])},Vb={type:"other",description:"comment"},Wb="{!",Xb={type:"literal",value:"{!",description:'"{!"'},Yb="!}",Zb={type:"literal",value:"!}",description:'"!}"'},$b=function(a){return U(["comment",a.join("")])},_b=/^[#?\^><+%:@\/~%]/,ac={type:"class",value:"[#?\\^><+%:@\\/~%]",description:"[#?\\^><+%:@\\/~%]"},bc="{",cc={type:"literal",value:"{",description:'"{"'},dc="}",ec={type:"literal",value:"}",description:'"}"'},fc="[",gc={type:"literal",value:"[",description:'"["'},hc="]",ic={type:"literal",value:"]",description:'"]"' +},jc="\n",kc={type:"literal",value:"\n",description:'"\\n"'},lc="\r\n",mc={type:"literal",value:"\r\n",description:'"\\r\\n"'},nc="\r",oc={type:"literal",value:"\r",description:'"\\r"'},pc="\u2028",qc={type:"literal",value:"\u2028",description:'"\\u2028"'},rc="\u2029",sc={type:"literal",value:"\u2029",description:'"\\u2029"'},tc=/^[\t\x0B\f \xA0\uFEFF]/,uc={type:"class",value:"[\\t\\x0B\\f \\xA0\\uFEFF]",description:"[\\t\\x0B\\f \\xA0\\uFEFF]"},vc=0,wc=0,xc=0,yc={line:1,column:1,seenCR:!1},zc=0,Ac=[],Bc=0;if("startRule"in W){if(!(W.startRule in Y))throw new Error("Can't start parsing from rule \""+W.startRule+'".');Z=Y[W.startRule]}if(V=Z(),V!==X&&vc===a.length)return V;throw V!==X&&vcc;c++)e=r.filterNode(a,b[c]),e&&f.push(e);return f}function d(a,b){var c,d,e,f,g=[b[0]];for(d=1,e=b.length;e>d;d++)f=r.filterNode(a,b[d]),f&&("buffer"===f[0]||"format"===f[0]?c?(c[0]="buffer"===f[0]?"buffer":c[0],c[1]+=f.slice(1,-2).join("")):(c=f,g.push(f)):(c=null,g.push(f)));return g}function e(a,b){return["buffer",t[b[1]],b[2],b[3]]}function f(a,b){return b}function g(){}function h(a,b){return dust.config.whitespace?(b.splice(1,2,b.slice(1,-2).join("")),b):null}function i(a,b){var c,d={name:b,bodies:[],blocks:{},index:0,auto:"h"},e=dust.escapeJs(b),f=b?'"'+e+'",':"",g="function(dust){",h=r.compileNode(d,a);return b&&(g+='dust.register("'+e+'",'+h+");"),g+=j(d)+k(d)+"return "+h+"}",c="("+g+"(dust));",dust.config.amd?"define("+f+'["dust.core"],'+g+");":dust.config.cjs?"module.exports=function(dust){var tmpl="+c+"var f="+q().toString()+";f.template=tmpl;return f}":c}function j(a){var b,c=[],d=a.blocks;for(b in d)c.push('"'+b+'":'+d[b]);return c.length?(a.blocks="ctx=ctx.shiftBlocks(blocks);","var blocks={"+c.join(",")+"};"):(a.blocks="",a.blocks)}function k(a){var b,c,d=[],e=a.bodies,f=a.blocks;for(b=0,c=e.length;c>b;b++)d[b]="function body_"+b+"(chk,ctx){"+f+"return chk"+e[b]+";}body_"+b+".__dustBody=!0;";return d.join("")}function l(a,b){var c,d,e="";for(c=1,d=b.length;d>c;c++)e+=r.compileNode(a,b[c]);return e}function m(a,b,c){return"."+(dust._aliases[c]||c)+"("+r.compileNode(a,b[1])+","+r.compileNode(a,b[2])+","+r.compileNode(a,b[4])+","+r.compileNode(a,b[3])+")"}function n(a){return a.replace(u,"\\\\").replace(v,'\\"').replace(w,"\\f").replace(x,"\\n").replace(y,"\\r").replace(z,"\\t")}function o(a,b,c){var d=dust.loadSource(dust.compile(a));return q(d)(b,c)}function p(a,b){var c=dust.loadSource(dust.compile(a,b));return q(c)}function q(a){return function(b,c){var d=c?"render":"stream";return dust[d](a,b,c)}}var r={},s=dust.isArray;r.compile=function(c,d){try{var e=b(a(c));return i(e,d)}catch(f){if(!f.line||!f.column)throw f;throw new SyntaxError(f.message+" At line : "+f.line+", column : "+f.column)}},r.filterNode=function(a,b){return r.optimizers[b[0]](a,b)},r.optimizers={body:d,buffer:f,special:e,format:h,reference:c,"#":c,"?":c,"^":c,"<":c,"+":c,"@":c,"%":c,partial:c,context:c,params:c,bodies:c,param:c,filters:f,key:f,path:f,literal:f,raw:f,comment:g,line:g,col:g},r.pragmas={esc:function(a,b,c){var d,e=a.auto;return b||(b="h"),a.auto="s"===b?"":b,d=l(a,c.block),a.auto=e,d}};var t={s:" ",n:"\n",r:"\r",lb:"{",rb:"}"};r.compileNode=function(a,b){return r.nodes[b[0]](a,b)},r.nodes={body:function(a,b){var c=a.index++,d="body_"+c;return a.bodies[c]=l(a,b),d},buffer:function(a,b){return".w("+A(b[1])+")"},format:function(a,b){return".w("+A(b[1])+")"},reference:function(a,b){return".f("+r.compileNode(a,b[1])+",ctx,"+r.compileNode(a,b[2])+")"},"#":function(a,b){return m(a,b,"section")},"?":function(a,b){return m(a,b,"exists")},"^":function(a,b){return m(a,b,"notexists")},"<":function(a,b){for(var c=b[4],d=1,e=c.length;e>d;d++){var f=c[d],g=f[1][1];if("block"===g)return a.blocks[b[1].text]=r.compileNode(a,f[2]),""}return""},"+":function(a,b){return"undefined"==typeof b[1].text&&"undefined"==typeof b[4]?".b(ctx.getBlock("+r.compileNode(a,b[1])+",chk, ctx),"+r.compileNode(a,b[2])+", {},"+r.compileNode(a,b[3])+")":".b(ctx.getBlock("+A(b[1].text)+"),"+r.compileNode(a,b[2])+","+r.compileNode(a,b[4])+","+r.compileNode(a,b[3])+")"},"@":function(a,b){return".h("+A(b[1].text)+","+r.compileNode(a,b[2])+","+r.compileNode(a,b[4])+","+r.compileNode(a,b[3])+","+r.compileNode(a,b[5])+")"},"%":function(a,b){var c,d,e,f,g,h,i,j,k,l=b[1][1];if(!r.pragmas[l])return"";for(c=b[4],d={},j=1,k=c.length;k>j;j++)h=c[j],d[h[1][1]]=h[2];for(e=b[3],f={},j=1,k=e.length;k>j;j++)i=e[j],f[i[1][1]]=i[2][1];return g=b[2][1]?b[2][1].text:null,r.pragmas[l](a,g,d,f)},partial:function(a,b){return".p("+r.compileNode(a,b[1])+",ctx,"+r.compileNode(a,b[2])+","+r.compileNode(a,b[3])+")"},context:function(a,b){return b[1]?"ctx.rebase("+r.compileNode(a,b[1])+")":"ctx"},params:function(a,b){for(var c=[],d=1,e=b.length;e>d;d++)c.push(r.compileNode(a,b[d]));return c.length?"{"+c.join(",")+"}":"{}"},bodies:function(a,b){for(var c=[],d=1,e=b.length;e>d;d++)c.push(r.compileNode(a,b[d]));return"{"+c.join(",")+"}"},param:function(a,b){return r.compileNode(a,b[1])+":"+r.compileNode(a,b[2])},filters:function(a,b){for(var c=[],d=1,e=b.length;e>d;d++){var f=b[d];c.push('"'+f+'"')}return'"'+a.auto+'"'+(c.length?",["+c.join(",")+"]":"")},key:function(a,b){return'ctx.get(["'+b[1]+'"], false)'},path:function(a,b){for(var c=b[1],d=b[2],e=[],f=0,g=d.length;g>f;f++)e.push(s(d[f])?r.compileNode(a,d[f]):'"'+d[f]+'"');return"ctx.getPath("+c+", ["+e.join(",")+"])"},literal:function(a,b){return A(b[1])},raw:function(a,b){return".w("+A(b[1])+")"}};var u=/\\/g,v=/"/g,w=/\f/g,x=/\n/g,y=/\r/g,z=/\t/g,A="undefined"==typeof JSON?function(a){return'"'+n(a)+'"'}:JSON.stringify;return dust.compiler=r,dust.compile=dust.compiler.compile,dust.renderSource=o,dust.compileFn=p,dust.filterNode=r.filterNode,dust.optimizers=r.optimizers,dust.pragmas=r.pragmas,dust.compileNode=r.compileNode,dust.nodes=r.nodes,r}),"function"==typeof define&&define.amd&&define.amd.dust===!0&&define(["require","dust.core","dust.compile"],function(require,dust){return dust.onLoad=function(a,b){require([a],function(){b()})},dust}); \ No newline at end of file diff --git a/hw7/Claudio_Maggioni/public/js/fetch.js b/hw7/Claudio_Maggioni/public/js/fetch.js index caebd7b..c883480 100644 --- a/hw7/Claudio_Maggioni/public/js/fetch.js +++ b/hw7/Claudio_Maggioni/public/js/fetch.js @@ -81,6 +81,7 @@ function doJSONRequest(method, url, headers, data){ headers['Content-Type'] = JSON_MIME; } - return doFetchRequest(method, url, headers, data).then(res => res.json()); + return doFetchRequest(method, url, headers, data) + .then(res => res.status == 204 ? {} : res.json()); } diff --git a/hw7/Claudio_Maggioni/public/js/views.js b/hw7/Claudio_Maggioni/public/js/views.js new file mode 100644 index 0000000..7581c0d --- /dev/null +++ b/hw7/Claudio_Maggioni/public/js/views.js @@ -0,0 +1,5 @@ +(function(dust){dust.register("favourites",body_0);function body_0(chk,ctx){return chk.w("").x(ctx.get(["bookmarked"], false),ctx,{"else":body_1,"block":body_2},{}).w("").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).s(ctx.get(["favs"], false),ctx,{"else":body_5,"block":body_6},{}).w("");}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("Favourites");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("Bookmarked");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("

Favourites

");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("

Bookmarked

");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("No favourites.");}body_5.__dustBody=!0;function body_6(chk,ctx){return chk.w("
").p("favourite_partial",ctx,ctx,{"name":ctx.get(["name"], false),"dataURL":ctx.get(["dataURL"], false),"_id":ctx.get(["_id"], false),"bookmarked":ctx.get(["bookmarked"], false),"details":"true"}).w("
");}body_6.__dustBody=!0;return body_0}(dust)); +(function(dust){dust.register("500",body_0);function body_0(chk,ctx){return chk.w("

Error 500

").f(ctx.get(["err"], false),ctx,"h").w("
");}body_0.__dustBody=!0;return body_0}(dust)); +(function(dust){dust.register("index",body_0);function body_0(chk,ctx){return chk.w("OO-JS Exercise - Web Atelier 2017

OO-JS Exercise: Canvas

");}body_0.__dustBody=!0;return body_0}(dust)); +(function(dust){dust.register("favourite_partial",body_0);function body_0(chk,ctx){return chk.w("

").f(ctx.get(["name"], false),ctx,"h").w("

\"").f(ctx.get(["name"],").x(ctx.get(["b"], false),ctx,{"block":body_1},{}).x(ctx.get(["details"], false),ctx,{"else":body_2,"block":body_5},{});}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("

Bookmarked

");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("



").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).w("
");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("Details");}body_5.__dustBody=!0;return body_0}(dust)); +(function(dust){dust.register("favourite",body_0);function body_0(chk,ctx){return chk.w("").f(ctx.get(["name"], false),ctx,"h").w("").p("favourite_partial",ctx,ctx,{}).w("Favourites list");}body_0.__dustBody=!0;return body_0}(dust)); diff --git a/hw7/Claudio_Maggioni/public/scripts/app.js b/hw7/Claudio_Maggioni/public/scripts/app.js index d5bf617..487dcec 100644 --- a/hw7/Claudio_Maggioni/public/scripts/app.js +++ b/hw7/Claudio_Maggioni/public/scripts/app.js @@ -8,6 +8,149 @@ class App { }; } + render_timestamp = 0; + render_last = null; + render_timeout = null; + + registerFavoriteEvents(_id, dom) { + const form = dom.querySelector('form'); + + + const delay = (f, ...args) => { + const execute = (f, ...args) => { + console.log("don't delay, solve Carzaniga today", ...args); + this.render_timestamp = new Date().getTime(); + this.render_timeout = null; + this.render_last = null; + f(...args); + }; + + if (new Date().getTime() - this.render_timestamp < 100000) { + console.log("delaying", ...args); + this.render_last = () => execute(f, ...args); + if (this.render_timeout === null) { + this.render_timeout = setTimeout(() => this.render_last(), 100); + } + return; + } + + execute(f, ...args); + } + + form.querySelector('input[name=name]').onkeyup = + () => delay(submit, 'data-update', false); + + const submit = (action, update = true) => { + let p; + + const formData = new FormData(form); + const name = formData.get('name'); + const dataURL = formData.get('dataURL'); + + switch (action) { + case 'data-update': + p = doJSONRequest('PUT', '/favorites/' + _id, {}, + { name, dataURL }); + break; + case 'data-delete': + p = doJSONRequest('DELETE', '/favorites/' + _id); + break; + case 'data-bookmark': + p = doJSONRequest('PUT', `/favorites/${_id}/bookmarked`, + {}, { bookmarked: true }); + break; + case 'data-del-bookmark': + p = doJSONRequest('PUT', `/favorites/${_id}/bookmarked`, + {}, { bookmarked: false }); + break; + default: + console.warn(action, ' is not a valid action'); + return; + } + + p.catch(console.error); + + if (action == 'data-delete' && update) { + p.then(_ => dom.remove()); + } else if (update) { + p.then(e => this.renderFavorite(e, dom)); + } + + if (!update) { + // updating via javascript to not disrupt cursor in name when + // replacing html + dom.querySelector('h3').innerText = name; + } + }; + + form.onsubmit = e => { + e.preventDefault(); + + const formData = new FormData(form); + const name = formData.get('name'); + const dataURL = formData.get('dataURL'); + + const action = e.explicitOriginalTarget.getAttributeNames() + .filter(e => e.startsWith('data-'))[0]; + + submit(action); + }; + } + + renderFavorite(data, div) { + data.bookmarked = data.bookmarked === true || data.bookmarked === 'true'; + dust.render('favourite_partial', + data, + (err, out) => { + if (err) { + console.error(err); + } else { + let dom; + + if (div === 'top' || !div) { + dom = document.createElement('div'); + dom.id = 'favorite_' + data._id; + dom.innerHTML = out; + + if (div === 'top') { + this.favourites.prepend(dom); + } else { + this.favourites.appendChild(dom); + } + } else { + div.innerHTML = out; + dom = div; + } + dom.className = data.bookmarked ? 'bookmarked' : ''; + + this.registerFavoriteEvents(data._id, dom); + } + }); + } + + getFavorites(nameFilter, onlyBookmarked = false) { + let url = '/favorites/search?ajax=true'; + + if (nameFilter) { + url += '&name=' + encodeURIComponent(nameFilter); + } + + if (onlyBookmarked) { + url += '&bookmarked=true'; + } + + doFetchRequest('GET', url, { 'Accept': 'text/html' }) + .then(res => res.text()) + .then(html => { + this.favourites.innerHTML = html; + this.favourites.childNodes.forEach(e => { + const id = e.id.substring('favorite_'.length); + this.registerFavoriteEvents(id, e); + }); + }) + .catch(console.error); + } + constructor(conf) { if (!(typeof conf === 'object' && conf)) { throw new Error('Argument conf different from specification'); @@ -21,6 +164,23 @@ class App { this.ctx = this.canvas.getContext('2d'); this.favourites = document.querySelector('div#favourites'); + this.getFavorites(false); + + const nameFilter = document.getElementById('name-filter'); + const bookmarkFilter = document.getElementById('bookmarked-filter'); + + const onSearch = () => { + const name = nameFilter.value; + const bookmark = bookmarkFilter.checked; + + this.getFavorites(name, bookmark); + } + + nameFilter.onkeyup = onSearch; + bookmarkFilter.onclick = onSearch; + + + if (typeof conf.buttons === 'object' && conf.buttons) { this.buttons = {} for (const b of ['clear', 'undo', 'camera']) @@ -44,37 +204,16 @@ class App { if (this.buttons.camera) { this.buttons.camera.addEventListener('click', () => { const base64 = this.canvas.toDataURL(); - const img = document.createElement('img'); - img.src = base64; - const form = document.createElement('form'); - form.method = 'POST'; - form.action = '/favorites'; + const data = { + dataURL: base64, + name: 'My New Masterpiece', + bookmarked: false + }; - const image = document.createElement('input'); - image.type = 'hidden'; - image.name = 'dataURL'; - image.value = base64; - form.appendChild(image); - - const lblName = document.createElement('label'); - lblName.setAttribute('for', 'name'); - lblName.innerText = 'Name:'; - form.appendChild(lblName); - - const name = document.createElement('input'); - name.type = 'text'; - name.name = 'name'; - name.placeholder = 'Name'; - name.value = 'New Name'; - form.appendChild(name); - - const submit = document.createElement('button'); - submit.innerText = 'Save'; - form.appendChild(submit); - - this.favourites.appendChild(img); - this.favourites.appendChild(form); + doJSONRequest("POST", "/favorites", {}, data) + .then(data => this.renderFavorite(data, 'top')) + .catch(console.error); }); } @@ -85,17 +224,6 @@ class App { const imgCanvas = document.createElement('canvas'); imgCanvas.width = this.canvas.width; imgCanvas.height = this.canvas.height; - const imgCtx = imgCanvas.getContext('2d'); - imgCtx.drawImage(player, 0, 0, canvas.width, canvas.height); - const imgData = imgCtx.getImageData(0, 0, imgCanvas.width, - imgCanvas.height); - - for (let i = 0; i < data.length; i += 4) { - const pixel = (data[i] + 2 * data[i+1] + data[i+2]) / 4; - data[i] = data[i+1] = data[i+2] = pixel; - } - imgCtx.putImageData(imgData, 0, 0); - const img = document.createElement('img'); img.src = imgCanvas.toDataURL(); img.addEventListener('load', () => { diff --git a/hw7/Claudio_Maggioni/routes/favourites_db_asaw/router.js b/hw7/Claudio_Maggioni/routes/favourites_db_asaw/router.js index ae1385d..6b0e0ea 100644 --- a/hw7/Claudio_Maggioni/routes/favourites_db_asaw/router.js +++ b/hw7/Claudio_Maggioni/routes/favourites_db_asaw/router.js @@ -13,6 +13,9 @@ const { error, catchErrs, renderFav, parseId, notFound } = require('../utils'); async function findAndRender(filter, req, res) { try { + if (filter.name) { + filter.name = { $regex: filter.name, $options: 'i' }; + } const favs = await Favorite.find(filter); renderFav(req, res, favs); } catch(e) { @@ -57,6 +60,7 @@ router.get('/search', async (req, res) => { const filter = Object.assign({}, req.query); delete filter['dataURL']; delete filter['_method']; + delete filter['ajax']; await findAndRender(filter, req, res); }); @@ -110,6 +114,7 @@ function handleUpdate(partial = false) { } res.status = 200; + Object.assign(fav, edit); renderFav(req, res, fav, false); } catch (e) { error(e, res); @@ -139,24 +144,22 @@ router.delete('/:id', async (req, res) => { } }); -router.put('/:id/bookmarked', (req, res) => { +router.put('/:id/bookmarked', async (req, res) => { + if (req.body.bookmarked !== true && req.body.bookmarked !== false && + req.body.bookmarked !== "true" && req.body.bookmarked !== "false") { + res.writeHead(400, { 'Content-Type': 'text/plain' }); + res.end('Bad PUT bookmark form parameters'); + } + try { - const fav = Favorite.findByIdAndUpdate(parseId(req), { - $set: { bookmarked: req.body.bookmarked } - }, { new: true }); + const fav = await Favorite.findById(parseId(req)); + fav.bookmarked = req.body.bookmarked === true || + req.body.bookmarked === "true"; + fav.save(); - if (notFound(fav, res)) { - return; - } - - if (!req.body.bookmarked) { - res.writeHead(400, { 'Content-Type': 'text/plain' }); - res.end('Bad PUT bookmark form parameters'); - } else { - renderFav(req, res, fav, false); - } + renderFav(req, res, fav, false); } catch (e) { - error(e, res); + notFound(null, res); } }); diff --git a/hw7/Claudio_Maggioni/routes/utils.js b/hw7/Claudio_Maggioni/routes/utils.js index 0225b51..e9a15e2 100644 --- a/hw7/Claudio_Maggioni/routes/utils.js +++ b/hw7/Claudio_Maggioni/routes/utils.js @@ -28,8 +28,13 @@ function renderFav(req, res, favs, list = true) { }; if (req.accepts('html')) { - res.render(list ? 'favourites.dust' : 'favourite.dust', - list ? { favs } : favs); + if (req.query.ajax === 'true' && list) { + res.render('server_side.dust', { favs }); + } else if (list) { + res.render('favourites.dust', { favs }); + } else { + res.render('favorite.dust', favs); + } } else if (req.accepts('json')) { if (list) { favs = favs.map(makeTestsPass); diff --git a/hw7/Claudio_Maggioni/views/favourite.dust b/hw7/Claudio_Maggioni/views/favourite.dust index 314dccb..b67731c 100644 --- a/hw7/Claudio_Maggioni/views/favourite.dust +++ b/hw7/Claudio_Maggioni/views/favourite.dust @@ -1,13 +1,14 @@ {! vim: set ts=2 sw=2 et tw=120: !} - - - {name} - - - {>"favourite_partial" /} - + + +{name} + + +{>"favourite_partial" /} +Favourites list + diff --git a/hw7/Claudio_Maggioni/views/favourite_partial.dust b/hw7/Claudio_Maggioni/views/favourite_partial.dust index 3956706..bffde38 100644 --- a/hw7/Claudio_Maggioni/views/favourite_partial.dust +++ b/hw7/Claudio_Maggioni/views/favourite_partial.dust @@ -4,25 +4,24 @@ {name} {?b}

- Bookmarked +Bookmarked

{/b} {?details} Details {:else} -
- - -
-
-
- {?bookmarked} - - {:else} - - {/bookmarked} + + + +
+
+
+{?bookmarked} + +{:else} + +{/bookmarked}
-Favourites list {/details} diff --git a/hw7/Claudio_Maggioni/views/index.dust b/hw7/Claudio_Maggioni/views/index.dust index 27d5932..b116cf7 100644 --- a/hw7/Claudio_Maggioni/views/index.dust +++ b/hw7/Claudio_Maggioni/views/index.dust @@ -2,7 +2,6 @@ - OO-JS Exercise - Web Atelier 2017 @@ -25,12 +24,19 @@ -

Favourites

-
- {#favs} - {>"favourite_partial" name=name dataURL=dataURL _id=_id bookmarked=bookmarked details="true" /} - {/favs} +
+
+ + +
+ +
+
+
+ + + diff --git a/hw7/Claudio_Maggioni/views/server_side.dust b/hw7/Claudio_Maggioni/views/server_side.dust new file mode 100644 index 0000000..28de764 --- /dev/null +++ b/hw7/Claudio_Maggioni/views/server_side.dust @@ -0,0 +1,9 @@ +{! vim: set ts=2 sw=2 et tw=120: !} + +{#favs} +
+ {>"favourite_partial" name=name dataURL=dataURL _id=_id bookmarked=bookmarked /} +
+{/favs} + +