# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility
import re
regex = r"/\*.*?\*/|//[^\r\n]*"
test_str = ("/*! dustjs-linkedin - v2.7.2\n"
"* http://dustjs.com/\n"
"* Copyright (c) 2015 Aleksander Williams; Released under the MIT License */\n"
"(function (root, factory) {\n"
" if (typeof define === 'function' && define.amd && define.amd.dust === true) {\n"
" define('dust.core', [], factory);\n"
" } else if (typeof exports === 'object') {\n"
" module.exports = factory();\n"
" } else {\n"
" root.dust = factory();\n"
" }\n"
"}(this, function() {\n"
" var dust = {\n"
" \"version\": \"2.7.2\"\n"
" },\n"
" NONE = 'NONE', ERROR = 'ERROR', WARN = 'WARN', INFO = 'INFO', DEBUG = 'DEBUG',\n"
" EMPTY_FUNC = function() {};\n\n"
" dust.config = {\n"
" whitespace: false,\n"
" amd: false,\n"
" cjs: false,\n"
" cache: true\n"
" };\n\n"
" // Directive aliases to minify code\n"
" dust._aliases = {\n"
" \"write\": \"w\",\n"
" \"end\": \"e\",\n"
" \"map\": \"m\",\n"
" \"render\": \"r\",\n"
" \"reference\": \"f\",\n"
" \"section\": \"s\",\n"
" \"exists\": \"x\",\n"
" \"notexists\": \"nx\",\n"
" \"block\": \"b\",\n"
" \"partial\": \"p\",\n"
" \"helper\": \"h\"\n"
" };\n\n"
" (function initLogging() {\n"
" /*global process, console*/\n"
" var loggingLevels = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, NONE: 4 },\n"
" consoleLog,\n"
" log;\n\n"
" if (typeof console !== 'undefined' && console.log) {\n"
" consoleLog = console.log;\n"
" if(typeof consoleLog === 'function') {\n"
" log = function() {\n"
" consoleLog.apply(console, arguments);\n"
" };\n"
" } else {\n"
" log = function() {\n"
" consoleLog(Array.prototype.slice.apply(arguments).join(' '));\n"
" };\n"
" }\n"
" } else {\n"
" log = EMPTY_FUNC;\n"
" }\n\n"
" /**\n"
" * Filters messages based on `dust.debugLevel`.\n"
" * This default implementation will print to the console if it exists.\n"
" * @param {String|Error} message the message to print/throw\n"
" * @param {String} type the severity of the message(ERROR, WARN, INFO, or DEBUG)\n"
" * @public\n"
" */\n"
" dust.log = function(message, type) {\n"
" type = type || INFO;\n"
" if (loggingLevels[type] >= loggingLevels[dust.debugLevel]) {\n"
" log('[DUST:' + type + ']', message);\n"
" }\n"
" };\n\n"
" dust.debugLevel = NONE;\n"
" if(typeof process !== 'undefined' && process.env && /\\bdust\\b/.test(process.env.DEBUG)) {\n"
" dust.debugLevel = DEBUG;\n"
" }\n\n"
" }());\n\n"
" dust.helpers = {};\n\n"
" dust.cache = {};\n\n"
" dust.register = function(name, tmpl) {\n"
" if (!name) {\n"
" return;\n"
" }\n"
" tmpl.templateName = name;\n"
" if (dust.config.cache !== false) {\n"
" dust.cache[name] = tmpl;\n"
" }\n"
" };\n\n"
" dust.render = function(nameOrTemplate, context, callback) {\n"
" var chunk = new Stub(callback).head;\n"
" try {\n"
" load(nameOrTemplate, chunk, context).end();\n"
" } catch (err) {\n"
" chunk.setError(err);\n"
" }\n"
" };\n\n"
" dust.stream = function(nameOrTemplate, context) {\n"
" var stream = new Stream(),\n"
" chunk = stream.head;\n"
" dust.nextTick(function() {\n"
" try {\n"
" load(nameOrTemplate, chunk, context).end();\n"
" } catch (err) {\n"
" chunk.setError(err);\n"
" }\n"
" });\n"
" return stream;\n"
" };\n\n"
" /**\n"
" * Extracts a template function (body_0) from whatever is passed.\n"
" * @param nameOrTemplate {*} Could be:\n"
" * - the name of a template to load from cache\n"
" * - a CommonJS-compiled template (a function with a `template` property)\n"
" * - a template function\n"
" * @param loadFromCache {Boolean} if false, don't look in the cache\n"
" * @return {Function} a template function, if found\n"
" */\n"
" function getTemplate(nameOrTemplate, loadFromCache/*=true*/) {\n"
" if(!nameOrTemplate) {\n"
" return;\n"
" }\n"
" if(typeof nameOrTemplate === 'function' && nameOrTemplate.template) {\n"
" // Sugar away CommonJS module templates\n"
" return nameOrTemplate.template;\n"
" }\n"
" if(dust.isTemplateFn(nameOrTemplate)) {\n"
" // Template functions passed directly\n"
" return nameOrTemplate;\n"
" }\n"
" if(loadFromCache !== false) {\n"
" // Try loading a template with this name from cache\n"
" return dust.cache[nameOrTemplate];\n"
" }\n"
" }\n\n"
" function load(nameOrTemplate, chunk, context) {\n"
" if(!nameOrTemplate) {\n"
" return chunk.setError(new Error('No template or template name provided to render'));\n"
" }\n\n"
" var template = getTemplate(nameOrTemplate, dust.config.cache);\n\n"
" if (template) {\n"
" return template(chunk, Context.wrap(context, template.templateName));\n"
" } else {\n"
" if (dust.onLoad) {\n"
" return chunk.map(function(chunk) {\n"
" // Alias just so it's easier to read that this would always be a name\n"
" var name = nameOrTemplate;\n"
" // Three possible scenarios for a successful callback:\n"
" // - `require(nameOrTemplate)(dust); cb()`\n"
" // - `src = readFile('src.dust'); cb(null, src)`\n"
" // - `compiledTemplate = require(nameOrTemplate)(dust); cb(null, compiledTemplate)`\n"
" function done(err, srcOrTemplate) {\n"
" var template;\n"
" if (err) {\n"
" return chunk.setError(err);\n"
" }\n"
" // Prefer a template that is passed via callback over the cached version.\n"
" template = getTemplate(srcOrTemplate, false) || getTemplate(name, dust.config.cache);\n"
" if (!template) {\n"
" // It's a template string, compile it and register under `name`\n"
" if(dust.compile) {\n"
" template = dust.loadSource(dust.compile(srcOrTemplate, name));\n"
" } else {\n"
" return chunk.setError(new Error('Dust compiler not available'));\n"
" }\n"
" }\n"
" template(chunk, Context.wrap(context, template.templateName)).end();\n"
" }\n\n"
" if(dust.onLoad.length === 3) {\n"
" dust.onLoad(name, context.options, done);\n"
" } else {\n"
" dust.onLoad(name, done);\n"
" }\n"
" });\n"
" }\n"
" return chunk.setError(new Error('Template Not Found: ' + nameOrTemplate));\n"
" }\n"
" }\n\n"
" dust.loadSource = function(source) {\n"
" /*jshint evil:true*/\n"
" return eval(source);\n"
" };\n\n"
" if (Array.isArray) {\n"
" dust.isArray = Array.isArray;\n"
" } else {\n"
" dust.isArray = function(arr) {\n"
" return Object.prototype.toString.call(arr) === '[object Array]';\n"
" };\n"
" }\n\n"
" dust.nextTick = (function() {\n"
" return function(callback) {\n"
" setTimeout(callback, 0);\n"
" };\n"
" })();\n\n"
" /**\n"
" * Dust has its own rules for what is \"empty\"-- which is not the same as falsy.\n"
" * Empty arrays, null, and undefined are empty\n"
" */\n"
" dust.isEmpty = function(value) {\n"
" if (value === 0) {\n"
" return false;\n"
" }\n"
" if (dust.isArray(value) && !value.length) {\n"
" return true;\n"
" }\n"
" return !value;\n"
" };\n\n"
" dust.isEmptyObject = function(obj) {\n"
" var key;\n"
" if (obj === null) {\n"
" return false;\n"
" }\n"
" if (obj === undefined) {\n"
" return false;\n"
" }\n"
" if (obj.length > 0) {\n"
" return false;\n"
" }\n"
" for (key in obj) {\n"
" if (Object.prototype.hasOwnProperty.call(obj, key)) {\n"
" return false;\n"
" }\n"
" }\n"
" return true;\n"
" };\n\n"
" dust.isTemplateFn = function(elem) {\n"
" return typeof elem === 'function' &&\n"
" elem.__dustBody;\n"
" };\n\n"
" /**\n"
" * Decide somewhat-naively if something is a Thenable.\n"
" * @param elem {*} object to inspect\n"
" * @return {Boolean} is `elem` a Thenable?\n"
" */\n"
" dust.isThenable = function(elem) {\n"
" return elem &&\n"
" typeof elem === 'object' &&\n"
" typeof elem.then === 'function';\n"
" };\n\n"
" /**\n"
" * Decide very naively if something is a Stream.\n"
" * @param elem {*} object to inspect\n"
" * @return {Boolean} is `elem` a Stream?\n"
" */\n"
" dust.isStreamable = function(elem) {\n"
" return elem &&\n"
" typeof elem.on === 'function' &&\n"
" typeof elem.pipe === 'function';\n"
" };\n\n"
" // apply the filter chain and return the output string\n"
" dust.filter = function(string, auto, filters, context) {\n"
" var i, len, name, filter;\n"
" if (filters) {\n"
" for (i = 0, len = filters.length; i < len; i++) {\n"
" name = filters[i];\n"
" if (!name.length) {\n"
" continue;\n"
" }\n"
" filter = dust.filters[name];\n"
" if (name === 's') {\n"
" auto = null;\n"
" } else if (typeof filter === 'function') {\n"
" string = filter(string, context);\n"
" } else {\n"
" dust.log('Invalid filter `' + name + '`', WARN);\n"
" }\n"
" }\n"
" }\n"
" // by default always apply the h filter, unless asked to unescape with |s\n"
" if (auto) {\n"
" string = dust.filters[auto](string, context);\n"
" }\n"
" return string;\n"
" };\n\n"
" dust.filters = {\n"
" h: function(value) { return dust.escapeHtml(value); },\n"
" j: function(value) { return dust.escapeJs(value); },\n"
" u: encodeURI,\n"
" uc: encodeURIComponent,\n"
" js: function(value) { return dust.escapeJSON(value); },\n"
" jp: function(value) {\n"
" if (!JSON) {dust.log('JSON is undefined; could not parse `' + value + '`', WARN);\n"
" return value;\n"
" } else {\n"
" return JSON.parse(value);\n"
" }\n"
" }\n"
" };\n\n"
" function Context(stack, global, options, blocks, templateName) {\n"
" if(stack !== undefined && !(stack instanceof Stack)) {\n"
" stack = new Stack(stack);\n"
" }\n"
" this.stack = stack;\n"
" this.global = global;\n"
" this.options = options;\n"
" this.blocks = blocks;\n"
" this.templateName = templateName;\n"
" }\n\n"
" dust.makeBase = dust.context = function(global, options) {\n"
" return new Context(undefined, global, options);\n"
" };\n\n"
" /**\n"
" * Factory function that creates a closure scope around a Thenable-callback.\n"
" * Returns a function that can be passed to a Thenable that will resume a\n"
" * Context lookup once the Thenable resolves with new data, adding that new\n"
" * data to the lookup stack.\n"
" */\n"
" function getWithResolvedData(ctx, cur, down) {\n"
" return function(data) {\n"
" return ctx.push(data)._get(cur, down);\n"
" };\n"
" }\n\n"
" Context.wrap = function(context, name) {\n"
" if (context instanceof Context) {\n"
" return context;\n"
" }\n"
" return new Context(context, {}, {}, null, name);\n"
" };\n\n"
" /**\n"
" * Public API for getting a value from the context.\n"
" * @method get\n"
" * @param {string|array} path The path to the value. Supported formats are:\n"
" * 'key'\n"
" * 'path.to.key'\n"
" * '.path.to.key'\n"
" * ['path', 'to', 'key']\n"
" * ['key']\n"
" * @param {boolean} [cur=false] Boolean which determines if the search should be limited to the\n"
" * current context (true), or if get should search in parent contexts as well (false).\n"
" * @public\n"
" * @returns {string|object}\n"
" */\n"
" Context.prototype.get = function(path, cur) {\n"
" if (typeof path === 'string') {\n"
" if (path[0] === '.') {\n"
" cur = true;\n"
" path = path.substr(1);\n"
" }\n"
" path = path.split('.');\n"
" }\n"
" return this._get(cur, path);\n"
" };\n\n"
" /**\n"
" * Get a value from the context\n"
" * @method _get\n"
" * @param {boolean} cur Get only from the current context\n"
" * @param {array} down An array of each step in the path\n"
" * @private\n"
" * @return {string | object}\n"
" */\n"
" Context.prototype._get = function(cur, down) {\n"
" var ctx = this.stack || {},\n"
" i = 1,\n"
" value, first, len, ctxThis, fn;\n\n"
" first = down[0];\n"
" len = down.length;\n\n"
" if (cur && len === 0) {\n"
" ctxThis = ctx;\n"
" ctx = ctx.head;\n"
" } else {\n"
" if (!cur) {\n"
" // Search up the stack for the first value\n"
" while (ctx) {\n"
" if (ctx.isObject) {\n"
" ctxThis = ctx.head;\n"
" value = ctx.head[first];\n"
" if (value !== undefined) {\n"
" break;\n"
" }\n"
" }\n"
" ctx = ctx.tail;\n"
" }\n\n"
" // Try looking in the global context if we haven't found anything yet\n"
" if (value !== undefined) {\n"
" ctx = value;\n"
" } else {\n"
" ctx = this.global && this.global[first];\n"
" }\n"
" } else if (ctx) {\n"
" // if scope is limited by a leading dot, don't search up the tree\n"
" if(ctx.head) {\n"
" ctx = ctx.head[first];\n"
" } else {\n"
" // context's head is empty, value we are searching for is not defined\n"
" ctx = undefined;\n"
" }\n"
" }\n\n"
" while (ctx && i < len) {\n"
" if (dust.isThenable(ctx)) {\n"
" // Bail early by returning a Thenable for the remainder of the search tree\n"
" return ctx.then(getWithResolvedData(this, cur, down.slice(i)));\n"
" }\n"
" ctxThis = ctx;\n"
" ctx = ctx[down[i]];\n"
" i++;\n"
" }\n"
" }\n\n"
" if (typeof ctx === 'function') {\n"
" fn = function() {\n"
" try {\n"
" return ctx.apply(ctxThis, arguments);\n"
" } catch (err) {\n"
" dust.log(err, ERROR);\n"
" throw err;\n"
" }\n"
" };\n"
" fn.__dustBody = !!ctx.__dustBody;\n"
" return fn;\n"
" } else {\n"
" if (ctx === undefined) {\n"
" dust.log('Cannot find reference `{' + down.join('.') + '}` in template `' + this.getTemplateName() + '`', INFO);\n"
" }\n"
" return ctx;\n"
" }\n"
" };\n\n"
" Context.prototype.getPath = function(cur, down) {\n"
" return this._get(cur, down);\n"
" };\n\n"
" Context.prototype.push = function(head, idx, len) {\n"
" if(head === undefined) {\n"
" dust.log(\"Not pushing an undefined variable onto the context\", INFO);\n"
" return this;\n"
" }\n"
" return this.rebase(new Stack(head, this.stack, idx, len));\n"
" };\n\n"
" Context.prototype.pop = function() {\n"
" var head = this.current();\n"
" this.stack = this.stack && this.stack.tail;\n"
" return head;\n"
" };\n\n"
" Context.prototype.rebase = function(head) {\n"
" return new Context(head, this.global, this.options, this.blocks, this.getTemplateName());\n"
" };\n\n"
" Context.prototype.clone = function() {\n"
" var context = this.rebase();\n"
" context.stack = this.stack;\n"
" return context;\n"
" };\n\n"
" Context.prototype.current = function() {\n"
" return this.stack && this.stack.head;\n"
" };\n\n"
" Context.prototype.getBlock = function(key) {\n"
" var blocks, len, fn;\n\n"
" if (typeof key === 'function') {\n"
" key = key(new Chunk(), this).data.join('');\n"
" }\n\n"
" blocks = this.blocks;\n\n"
" if (!blocks) {\n"
" dust.log('No blocks for context `' + key + '` in template `' + this.getTemplateName() + '`', DEBUG);\n"
" return false;\n"
" }\n\n"
" len = blocks.length;\n"
" while (len--) {\n"
" fn = blocks[len][key];\n"
" if (fn) {\n"
" return fn;\n"
" }\n"
" }\n\n"
" dust.log('Malformed template `' + this.getTemplateName() + '` was missing one or more blocks.');\n"
" return false;\n"
" };\n\n"
" Context.prototype.shiftBlocks = function(locals) {\n"
" var blocks = this.blocks,\n"
" newBlocks;\n\n"
" if (locals) {\n"
" if (!blocks) {\n"
" newBlocks = [locals];\n"
" } else {\n"
" newBlocks = blocks.concat([locals]);\n"
" }\n"
" return new Context(this.stack, this.global, this.options, newBlocks, this.getTemplateName());\n"
" }\n"
" return this;\n"
" };\n\n"
" Context.prototype.resolve = function(body) {\n"
" var chunk;\n\n"
" if(typeof body !== 'function') {\n"
" return body;\n"
" }\n"
" chunk = new Chunk().render(body, this);\n"
" if(chunk instanceof Chunk) {\n"
" return chunk.data.join(''); // ie7 perf\n"
" }\n"
" return chunk;\n"
" };\n\n"
" Context.prototype.getTemplateName = function() {\n"
" return this.templateName;\n"
" };\n\n"
" function Stack(head, tail, idx, len) {\n"
" this.tail = tail;\n"
" this.isObject = head && typeof head === 'object';\n"
" this.head = head;\n"
" this.index = idx;\n"
" this.of = len;\n"
" }\n\n"
" function Stub(callback) {\n"
" this.head = new Chunk(this);\n"
" this.callback = callback;\n"
" this.out = '';\n"
" }\n\n"
" Stub.prototype.flush = function() {\n"
" var chunk = this.head;\n\n"
" while (chunk) {\n"
" if (chunk.flushable) {\n"
" this.out += chunk.data.join(''); //ie7 perf\n"
" } else if (chunk.error) {\n"
" this.callback(chunk.error);\n"
" dust.log('Rendering failed with error `' + chunk.error + '`', ERROR);\n"
" this.flush = EMPTY_FUNC;\n"
" return;\n"
" } else {\n"
" return;\n"
" }\n"
" chunk = chunk.next;\n"
" this.head = chunk;\n"
" }\n"
" this.callback(null, this.out);\n"
" };\n\n"
" /**\n"
" * Creates an interface sort of like a Streams2 ReadableStream.\n"
" */\n"
" function Stream() {\n"
" this.head = new Chunk(this);\n"
" }\n\n"
" Stream.prototype.flush = function() {\n"
" var chunk = this.head;\n\n"
" while(chunk) {\n"
" if (chunk.flushable) {\n"
" this.emit('data', chunk.data.join('')); //ie7 perf\n"
" } else if (chunk.error) {\n"
" this.emit('error', chunk.error);\n"
" this.emit('end');\n"
" dust.log('Streaming failed with error `' + chunk.error + '`', ERROR);\n"
" this.flush = EMPTY_FUNC;\n"
" return;\n"
" } else {\n"
" return;\n"
" }\n"
" chunk = chunk.next;\n"
" this.head = chunk;\n"
" }\n"
" this.emit('end');\n"
" };\n\n"
" /**\n"
" * Executes listeners for `type` by passing data. Note that this is different from a\n"
" * Node stream, which can pass an arbitrary number of arguments\n"
" * @return `true` if event had listeners, `false` otherwise\n"
" */\n"
" Stream.prototype.emit = function(type, data) {\n"
" var events = this.events || {},\n"
" handlers = events[type] || [],\n"
" i, l;\n\n"
" if (!handlers.length) {\n"
" dust.log('Stream broadcasting, but no listeners for `' + type + '`', DEBUG);\n"
" return false;\n"
" }\n\n"
" handlers = handlers.slice(0);\n"
" for (i = 0, l = handlers.length; i < l; i++) {\n"
" handlers[i](data);\n"
" }\n"
" return true;\n"
" };\n\n"
" Stream.prototype.on = function(type, callback) {\n"
" var events = this.events = this.events || {},\n"
" handlers = events[type] = events[type] || [];\n\n"
" if(typeof callback !== 'function') {\n"
" dust.log('No callback function provided for `' + type + '` event listener', WARN);\n"
" } else {\n"
" handlers.push(callback);\n"
" }\n"
" return this;\n"
" };\n\n"
" /**\n"
" * Pipes to a WritableStream. Note that backpressure isn't implemented,\n"
" * so we just write as fast as we can.\n"
" * @param stream {WritableStream}\n"
" * @return self\n"
" */\n"
" Stream.prototype.pipe = function(stream) {\n"
" if(typeof stream.write !== 'function' ||\n"
" typeof stream.end !== 'function') {\n"
" dust.log('Incompatible stream passed to `pipe`', WARN);\n"
" return this;\n"
" }\n\n"
" var destEnded = false;\n\n"
" if(typeof stream.emit === 'function') {\n"
" stream.emit('pipe', this);\n"
" }\n\n"
" if(typeof stream.on === 'function') {\n"
" stream.on('error', function() {\n"
" destEnded = true;\n"
" });\n"
" }\n\n"
" return this\n"
" .on('data', function(data) {\n"
" if(destEnded) {\n"
" return;\n"
" }\n"
" try {\n"
" stream.write(data, 'utf8');\n"
" } catch (err) {\n"
" dust.log(err, ERROR);\n"
" }\n"
" })\n"
" .on('end', function() {\n"
" if(destEnded) {\n"
" return;\n"
" }\n"
" try {\n"
" stream.end();\n"
" destEnded = true;\n"
" } catch (err) {\n"
" dust.log(err, ERROR);\n"
" }\n"
" });\n"
" };\n\n"
" function Chunk(root, next, taps) {\n"
" this.root = root;\n"
" this.next = next;\n"
" this.data = []; //ie7 perf\n"
" this.flushable = false;\n"
" this.taps = taps;\n"
" }\n\n"
" Chunk.prototype.write = function(data) {\n"
" var taps = this.taps;\n\n"
" if (taps) {\n"
" data = taps.go(data);\n"
" }\n"
" this.data.push(data);\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.end = function(data) {\n"
" if (data) {\n"
" this.write(data);\n"
" }\n"
" this.flushable = true;\n"
" this.root.flush();\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.map = function(callback) {\n"
" var cursor = new Chunk(this.root, this.next, this.taps),\n"
" branch = new Chunk(this.root, cursor, this.taps);\n\n"
" this.next = branch;\n"
" this.flushable = true;\n"
" try {\n"
" callback(branch);\n"
" } catch(err) {\n"
" dust.log(err, ERROR);\n"
" branch.setError(err);\n"
" }\n"
" return cursor;\n"
" };\n\n"
" Chunk.prototype.tap = function(tap) {\n"
" var taps = this.taps;\n\n"
" if (taps) {\n"
" this.taps = taps.push(tap);\n"
" } else {\n"
" this.taps = new Tap(tap);\n"
" }\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.untap = function() {\n"
" this.taps = this.taps.tail;\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.render = function(body, context) {\n"
" return body(this, context);\n"
" };\n\n"
" Chunk.prototype.reference = function(elem, context, auto, filters) {\n"
" if (typeof elem === 'function') {\n"
" elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]);\n"
" if (elem instanceof Chunk) {\n"
" return elem;\n"
" } else {\n"
" return this.reference(elem, context, auto, filters);\n"
" }\n"
" }\n"
" if (dust.isThenable(elem)) {\n"
" return this.await(elem, context, null, auto, filters);\n"
" } else if (dust.isStreamable(elem)) {\n"
" return this.stream(elem, context, null, auto, filters);\n"
" } else if (!dust.isEmpty(elem)) {\n"
" return this.write(dust.filter(elem, auto, filters, context));\n"
" } else {\n"
" return this;\n"
" }\n"
" };\n\n"
" Chunk.prototype.section = function(elem, context, bodies, params) {\n"
" var body = bodies.block,\n"
" skip = bodies['else'],\n"
" chunk = this,\n"
" i, len, head;\n\n"
" if (typeof elem === 'function' && !dust.isTemplateFn(elem)) {\n"
" try {\n"
" elem = elem.apply(context.current(), [this, context, bodies, params]);\n"
" } catch(err) {\n"
" dust.log(err, ERROR);\n"
" return this.setError(err);\n"
" }\n"
" // Functions that return chunks are assumed to have handled the chunk manually.\n"
" // Make that chunk the current one and go to the next method in the chain.\n"
" if (elem instanceof Chunk) {\n"
" return elem;\n"
" }\n"
" }\n\n"
" if (dust.isEmptyObject(bodies)) {\n"
" // No bodies to render, and we've already invoked any function that was available in\n"
" // hopes of returning a Chunk.\n"
" return chunk;\n"
" }\n\n"
" if (!dust.isEmptyObject(params)) {\n"
" context = context.push(params);\n"
" }\n\n"
" /*\n"
" Dust's default behavior is to enumerate over the array elem, passing each object in the array to the block.\n"
" When elem resolves to a value or object instead of an array, Dust sets the current context to the value\n"
" and renders the block one time.\n"
" */\n"
" if (dust.isArray(elem)) {\n"
" if (body) {\n"
" len = elem.length;\n"
" if (len > 0) {\n"
" head = context.stack && context.stack.head || {};\n"
" head.$len = len;\n"
" for (i = 0; i < len; i++) {\n"
" head.$idx = i;\n"
" chunk = body(chunk, context.push(elem[i], i, len));\n"
" }\n"
" head.$idx = undefined;\n"
" head.$len = undefined;\n"
" return chunk;\n"
" } else if (skip) {\n"
" return skip(this, context);\n"
" }\n"
" }\n"
" } else if (dust.isThenable(elem)) {\n"
" return this.await(elem, context, bodies);\n"
" } else if (dust.isStreamable(elem)) {\n"
" return this.stream(elem, context, bodies);\n"
" } else if (elem === true) {\n"
" // true is truthy but does not change context\n"
" if (body) {\n"
" return body(this, context);\n"
" }\n"
" } else if (elem || elem === 0) {\n"
" // everything that evaluates to true are truthy ( e.g. Non-empty strings and Empty objects are truthy. )\n"
" // zero is truthy\n"
" // for anonymous functions that did not returns a chunk, truthiness is evaluated based on the return value\n"
" if (body) {\n"
" return body(this, context.push(elem));\n"
" }\n"
" // nonexistent, scalar false value, scalar empty string, null,\n"
" // undefined are all falsy\n"
" } else if (skip) {\n"
" return skip(this, context);\n"
" }\n"
" dust.log('Section without corresponding key in template `' + context.getTemplateName() + '`', DEBUG);\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.exists = function(elem, context, bodies) {\n"
" var body = bodies.block,\n"
" skip = bodies['else'];\n\n"
" if (!dust.isEmpty(elem)) {\n"
" if (body) {\n"
" return body(this, context);\n"
" }\n"
" dust.log('No block for exists check in template `' + context.getTemplateName() + '`', DEBUG);\n"
" } else if (skip) {\n"
" return skip(this, context);\n"
" }\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.notexists = function(elem, context, bodies) {\n"
" var body = bodies.block,\n"
" skip = bodies['else'];\n\n"
" if (dust.isEmpty(elem)) {\n"
" if (body) {\n"
" return body(this, context);\n"
" }\n"
" dust.log('No block for not-exists check in template `' + context.getTemplateName() + '`', DEBUG);\n"
" } else if (skip) {\n"
" return skip(this, context);\n"
" }\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.block = function(elem, context, bodies) {\n"
" var body = elem || bodies.block;\n\n"
" if (body) {\n"
" return body(this, context);\n"
" }\n"
" return this;\n"
" };\n\n"
" Chunk.prototype.partial = function(elem, context, partialContext, params) {\n"
" var head;\n\n"
" if(params === undefined) {\n"
" // Compatibility for < 2.7.0 where `partialContext` did not exist\n"
" params = partialContext;\n"
" partialContext = context;\n"
" }\n\n"
" if (!dust.isEmptyObject(params)) {\n"
" partialContext = partialContext.clone();\n"
" head = partialContext.pop();\n"
" partialContext = partialContext.push(params)\n"
" .push(head);\n"
" }\n\n"
" if (dust.isTemplateFn(elem)) {\n"
" // The eventual result of evaluating `elem` is a partial name\n"
" // Load the partial after getting its name and end the async chunk\n"
" return this.capture(elem, context, function(name, chunk) {\n"
" partialContext.templateName = name;\n"
" load(name, chunk, partialContext).end();\n"
" });\n"
" } else {\n"
" partialContext.templateName = elem;\n"
" return load(elem, this, partialContext);\n"
" }\n"
" };\n\n"
" Chunk.prototype.helper = function(name, context, bodies, params, auto) {\n"
" var chunk = this,\n"
" filters = params.filters,\n"
" ret;\n\n"
" // Pre-2.7.1 compat: if auto is undefined, it's an old template. Automatically escape\n"
" if (auto === undefined) {\n"
" auto = 'h';\n"
" }\n\n"
" // handle invalid helpers, similar to invalid filters\n"
" if(dust.helpers[name]) {\n"
" try {\n"
" ret = dust.helpers[name](chunk, context, bodies, params);\n"
" if (ret instanceof Chunk) {\n"
" return ret;\n"
" }\n"
" if(typeof filters === 'string') {\n"
" filters = filters.split('|');\n"
" }\n"
" if (!dust.isEmptyObject(bodies)) {\n"
" return chunk.section(ret, context, bodies, params);\n"
" }\n"
" // Helpers act slightly differently from functions in context in that they will act as\n"
" // a reference if they are self-closing (due to grammar limitations)\n"
" // In the Chunk.await function we check to make sure bodies is null before acting as a reference\n"
" return chunk.reference(ret, context, auto, filters);\n"
" } catch(err) {\n"
" dust.log('Error in helper `' + name + '`: ' + err.message, ERROR);\n"
" return chunk.setError(err);\n"
" }\n"
" } else {\n"
" dust.log('Helper `' + name + '` does not exist', WARN);\n"
" return chunk;\n"
" }\n"
" };\n\n"
" /**\n"
" * Reserve a chunk to be evaluated once a thenable is resolved or rejected\n"
" * @param thenable {Thenable} the target thenable to await\n"
" * @param context {Context} context to use to render the deferred chunk\n"
" * @param bodies {Object} must contain a \"body\", may contain an \"error\"\n"
" * @param auto {String} automatically apply this filter if the Thenable is a reference\n"
" * @param filters {Array} apply these filters if the Thenable is a reference\n"
" * @return {Chunk}\n"
" */\n"
" Chunk.prototype.await = function(thenable, context, bodies, auto, filters) {\n"
" return this.map(function(chunk) {\n"
" thenable.then(function(data) {\n"
" if (bodies) {\n"
" chunk = chunk.section(data, context, bodies);\n"
" } else {\n"
" // Actually a reference. Self-closing sections don't render\n"
" chunk = chunk.reference(data, context, auto, filters);\n"
" }\n"
" chunk.end();\n"
" }, function(err) {\n"
" var errorBody = bodies && bodies.error;\n"
" if(errorBody) {\n"
" chunk.render(errorBody, context.push(err)).end();\n"
" } else {\n"
" dust.log('Unhandled promise rejection in `' + context.getTemplateName() + '`', INFO);\n"
" chunk.end();\n"
" }\n"
" });\n"
" });\n"
" };\n\n"
" /**\n"
" * Reserve a chunk to be evaluated with the contents of a streamable.\n"
" * Currently an error event will bomb out the stream. Once an error\n"
" * is received, we push it to an {:error} block if one exists, and log otherwise,\n"
" * then stop listening to the stream.\n"
" * @param streamable {Streamable} the target streamable that will emit events\n"
" * @param context {Context} context to use to render each thunk\n"
" * @param bodies {Object} must contain a \"body\", may contain an \"error\"\n"
" * @return {Chunk}\n"
" */\n"
" Chunk.prototype.stream = function(stream, context, bodies, auto, filters) {\n"
" var body = bodies && bodies.block,\n"
" errorBody = bodies && bodies.error;\n"
" return this.map(function(chunk) {\n"
" var ended = false;\n"
" stream\n"
" .on('data', function data(thunk) {\n"
" if(ended) {\n"
" return;\n"
" }\n"
" if(body) {\n"
" // Fork a new chunk out of the blockstream so that we can flush it independently\n"
" chunk = chunk.map(function(chunk) {\n"
" chunk.render(body, context.push(thunk)).end();\n"
" });\n"
" } else if(!bodies) {\n"
" // When actually a reference, don't fork, just write into the master async chunk\n"
" chunk = chunk.reference(thunk, context, auto, filters);\n"
" }\n"
" })\n"
" .on('error', function error(err) {\n"
" if(ended) {\n"
" return;\n"
" }\n"
" if(errorBody) {\n"
" chunk.render(errorBody, context.push(err));\n"
" } else {\n"
" dust.log('Unhandled stream error in `' + context.getTemplateName() + '`', INFO);\n"
" }\n"
" if(!ended) {\n"
" ended = true;\n"
" chunk.end();\n"
" }\n"
" })\n"
" .on('end', function end() {\n"
" if(!ended) {\n"
" ended = true;\n"
" chunk.end();\n"
" }\n"
" });\n"
" });\n"
" };\n\n"
" Chunk.prototype.capture = function(body, context, callback) {\n"
" return this.map(function(chunk) {\n"
" var stub = new Stub(function(err, out) {\n"
" if (err) {\n"
" chunk.setError(err);\n"
" } else {\n"
" callback(out, chunk);\n"
" }\n"
" });\n"
" body(stub.head, context).end();\n"
" });\n"
" };\n\n"
" Chunk.prototype.setError = function(err) {\n"
" this.error = err;\n"
" this.root.flush();\n"
" return this;\n"
" };\n\n"
" // Chunk aliases\n"
" for(var f in Chunk.prototype) {\n"
" if(dust._aliases[f]) {\n"
" Chunk.prototype[dust._aliases[f]] = Chunk.prototype[f];\n"
" }\n"
" }\n\n"
" function Tap(head, tail) {\n"
" this.head = head;\n"
" this.tail = tail;\n"
" }\n\n"
" Tap.prototype.push = function(tap) {\n"
" return new Tap(tap, this);\n"
" };\n\n"
" Tap.prototype.go = function(value) {\n"
" var tap = this;\n\n"
" while(tap) {\n"
" value = tap.head(value);\n"
" tap = tap.tail;\n"
" }\n"
" return value;\n"
" };\n\n"
" var HCHARS = /[&<>\"']/,\n"
" AMP = /&/g,\n"
" LT = /</g,\n"
" GT = />/g,\n"
" QUOT = /\\\"/g,\n"
" SQUOT = /\\'/g;\n\n"
" dust.escapeHtml = function(s) {\n"
" if (typeof s === \"string\" || (s && typeof s.toString === \"function\")) {\n"
" if (typeof s !== \"string\") {\n"
" s = s.toString();\n"
" }\n"
" if (!HCHARS.test(s)) {\n"
" return s;\n"
" }\n"
" return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"').replace(SQUOT, ''');\n"
" }\n"
" return s;\n"
" };\n\n"
" var BS = /\\\\/g,\n"
" FS = /\\//g,\n"
" CR = /\\r/g,\n"
" LS = /\\u2028/g,\n"
" PS = /\\u2029/g,\n"
" NL = /\\n/g,\n"
" LF = /\\f/g,\n"
" SQ = /'/g,\n"
" DQ = /\"/g,\n"
" TB = /\\t/g;\n\n"
" dust.escapeJs = function(s) {\n"
" if (typeof s === 'string') {\n"
" return s\n"
" .replace(BS, '\\\\\\\\')\n"
" .replace(FS, '\\\\/')\n"
" .replace(DQ, '\\\\\"')\n"
" .replace(SQ, '\\\\\\'')\n"
" .replace(CR, '\\\\r')\n"
" .replace(LS, '\\\\u2028')\n"
" .replace(PS, '\\\\u2029')\n"
" .replace(NL, '\\\\n')\n"
" .replace(LF, '\\\\f')\n"
" .replace(TB, '\\\\t');\n"
" }\n"
" return s;\n"
" };\n\n"
" dust.escapeJSON = function(o) {\n"
" if (!JSON) {\n"
" dust.log('JSON is undefined; could not escape `' + o + '`', WARN);\n"
" return o;\n"
" } else {\n"
" return JSON.stringify(o)\n"
" .replace(LS, '\\\\u2028')\n"
" .replace(PS, '\\\\u2029')\n"
" .replace(LT, '\\\\u003c');\n"
" }\n"
" };\n\n"
" return dust;\n\n"
"}));\n\n"
"if (typeof define === \"function\" && define.amd && define.amd.dust === true) {\n"
" define([\"require\", \"dust.core\"], function(require, dust) {\n"
" dust.onLoad = function(name, cb) {\n"
" require([name], function() {\n"
" cb();\n"
" });\n"
" };\n"
" return dust;\n"
" });\n"
"}\n")
matches = re.finditer(regex, test_str, re.DOTALL)
for matchNum, match in enumerate(matches, start=1):
print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))
for groupNum in range(0, len(match.groups())):
groupNum = groupNum + 1
print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))
# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Python, please visit: https://docs.python.org/3/library/re.html