Files
liquidjs/dist/shopify-liquid.js
T

3858 lines
125 KiB
JavaScript

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Liquid = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var strftime = require('strftime').timezone(-new Date().getTimezoneOffset());
module.exports = function (liquid) {
liquid.registerFilter('abs', function (v) {
return Math.abs(v);
});
liquid.registerFilter('append', function (v, arg) {
return v + arg;
});
liquid.registerFilter('capitalize', function (str) {
return (str || '').charAt(0).toUpperCase() + str.slice(1);
});
liquid.registerFilter('ceil', function (v) {
return Math.ceil(v);
});
liquid.registerFilter('date', function (v, arg) {
return strftime(arg, v);
});
liquid.registerFilter('default', function (v, arg) {
return arg || v;
});
liquid.registerFilter('divided_by', function (v, arg) {
return Math.floor(v / arg);
});
liquid.registerFilter('downcase', function (v) {
return v.toLowerCase();
});
var escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
"'": '&#39;'
};
function escape(str) {
return (str || '').replace(/&|<|>|"|'/g, function (m) {
return escapeMap[m];
});
}
liquid.registerFilter('escape', escape);
var unescapeMap = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&#34;': '"',
'&#39;': "'"
};
function unescape(str) {
return (str || '').replace(/&(amp|lt|gt|#34|#39);/g, function (m) {
return unescapeMap[m];
});
}
liquid.registerFilter('escape_once', function (str) {
return escape(unescape(str));
});
liquid.registerFilter('first', function (v) {
return v[0];
});
liquid.registerFilter('floor', function (v) {
return Math.floor(v);
});
liquid.registerFilter('join', function (v, arg) {
return v.join(arg);
});
liquid.registerFilter('last', function (v) {
return v[v.length - 1];
});
liquid.registerFilter('lstrip', function (v) {
return (v || '').replace(/^\s+/, '');
});
liquid.registerFilter('map', function (arr, arg) {
return arr.map(function (v) {
return v[arg];
});
});
liquid.registerFilter('minus', bindFixed(function (v, arg) {
return v - arg;
}));
liquid.registerFilter('modulo', bindFixed(function (v, arg) {
return v % arg;
}));
liquid.registerFilter('newline_to_br', function (v) {
return v.replace(/\n/g, '<br />');
});
liquid.registerFilter('plus', bindFixed(function (v, arg) {
return v + arg;
}));
liquid.registerFilter('prepend', function (v, arg) {
return arg + v;
});
liquid.registerFilter('remove', function (v, arg) {
return v.split(arg).join('');
});
liquid.registerFilter('remove_first', function (v, l) {
return v.replace(l, '');
});
liquid.registerFilter('replace', function (v, pattern, replacement) {
return (v || '').split(pattern).join(replacement);
});
liquid.registerFilter('replace_first', function (v, arg1, arg2) {
return (v || '').replace(arg1, arg2);
});
liquid.registerFilter('reverse', function (v) {
return (v || '').reverse();
});
liquid.registerFilter('round', function (v, arg) {
var amp = Math.pow(10, arg || 0);
return Math.round(v * amp, arg) / amp;
});
liquid.registerFilter('rstrip', function (str) {
return (str || '').replace(/\s+$/, '');
});
liquid.registerFilter('size', function (v) {
return v.length;
});
liquid.registerFilter('slice', function (v, begin, length) {
return v.substr(begin, length === undefined ? 1 : length);
});
liquid.registerFilter('sort', function (v, arg) {
return (v || '').sort(arg);
});
liquid.registerFilter('split', function (v, arg) {
return (v || '').split(arg);
});
liquid.registerFilter('strip', function (v) {
return (v || '').trim();
});
liquid.registerFilter('strip_html', function (v) {
return (v || '').replace(/<\/?\s*\w+\s*\/?>/g, '');
});
liquid.registerFilter('strip_newlines', function (v) {
return (v || '').replace(/\n/g, '');
});
liquid.registerFilter('times', function (v, arg) {
return v * arg;
});
liquid.registerFilter('truncate', function (v, l, o) {
v = v || '';
o = o === undefined ? '...' : o;
l = l || 16;
if (v.length <= l) return v;
return v.substr(0, l - o.length) + o;
});
liquid.registerFilter('truncatewords', function (v, l, o) {
if (o === undefined) o = '...';
var arr = v.split(' ');
var ret = arr.slice(0, l).join(' ');
if (arr.length > l) ret += o;
return ret;
});
liquid.registerFilter('uniq', function (arr) {
var u = {};
return (arr || []).filter(function (val) {
if (u.hasOwnProperty(val)) {
return false;
}
u[val] = true;
return true;
});
});
liquid.registerFilter('upcase', function (str) {
return (str || '').toUpperCase();
});
liquid.registerFilter('url_encode', encodeURIComponent);
};
function getFixed(v) {
var p = (v + "").split(".");
return p.length > 1 ? p[1].length : 0;
}
function getMaxFixed(l, r) {
return Math.max(getFixed(l), getFixed(r));
}
function bindFixed(cb) {
return function (l, r) {
var f = getMaxFixed(l, r);
return cb(l, r).toFixed(f);
};
}
},{"strftime":10}],2:[function(require,module,exports){
'use strict';
var Scope = require('./src/scope');
var assert = require('assert');
var tokenizer = require('./src/tokenizer.js');
var Render = require('./src/render.js');
var lexical = require('./src/lexical.js');
var path = require("path");
var fs = require('fs');
var Tag = require('./src/tag.js');
var Filter = require('./src/filter.js');
var Template = require('./src/parser');
var Expression = require('./src/expression.js');
var tags = require('./tags');
var filters = require('./filters');
var Promise = require('any-promise');
var _engine = {
init: function init(tag, filter, options) {
if (options.cache) {
this.cache = {};
}
this.options = options;
this.tag = tag;
this.filter = filter;
this.parser = Template(tag, filter);
this.renderer = Render();
tags(this);
filters(this);
return this;
},
parse: function parse(html) {
var tokens = tokenizer.parse(html);
return this.parser.parse(tokens);
},
render: function render(tpl, ctx, opts) {
opts = opts || {};
opts.strict_variables = opts.strict_variables || false;
opts.strict_filters = opts.strict_filters || false;
this.renderer.resetRegisters();
var scope = Scope.factory(ctx, {
strict: opts.strict_variables
});
return this.renderer.renderTemplates(tpl, scope, opts);
},
parseAndRender: function parseAndRender(html, ctx, opts) {
try {
var tpl = this.parse(html);
return this.render(tpl, ctx, opts);
} catch (error) {
// A throw inside of a then or catch of a Promise automatically rejects, but since we mix a sync call
// with an async call, we need to do this in case the sync call throws.
return Promise.reject(error);
}
},
renderFile: function renderFile(filepath, ctx, opts) {
var _this = this;
return this.handleCache(filepath).then(function (templates) {
return _this.render(templates, ctx, opts);
}).catch(function (e) {
e.file = filepath;
throw e;
});
},
evalOutput: function evalOutput(str, scope) {
var tpl = this.parser.parseOutput(str.trim());
return this.renderer.evalOutput(tpl, scope);
},
registerFilter: function registerFilter(name, filter) {
return this.filter.register(name, filter);
},
registerTag: function registerTag(name, tag) {
return this.tag.register(name, tag);
},
handleCache: function handleCache(filepath) {
var _this2 = this;
assert(filepath, 'filepath cannot be null');
filepath = path.resolve(this.options.root, filepath);
if (path.extname(filepath) === '') {
filepath += this.options.extname;
}
return this.getTemplate(filepath).then(function (html) {
var tpl = _this2.options.cache && _this2.cache[filepath] || _this2.parse(html);
return _this2.options.cache ? _this2.cache[filepath] = tpl : tpl;
});
},
getTemplate: function getTemplate(filepath) {
return new Promise(function (resolve, reject) {
fs.readFile(filepath, 'utf8', function (err, html) {
err ? reject(err) : resolve(html);
});
});
},
express: function express() {
var _this3 = this;
return function (filePath, options, callback) {
_this3.renderFile(filePath, options).then(function (html) {
return callback(null, html);
}).catch(function (e) {
return callback(e);
});
};
}
};
function factory(options) {
options = options || {};
options.root = options.root || '';
options.extname = options.extname || '.liquid';
var engine = Object.create(_engine);
engine.init(Tag(), Filter(), options);
return engine;
}
factory.lexical = lexical;
factory.isTruthy = Expression.isTruthy;
factory.isFalsy = Expression.isFalsy;
factory.evalExp = Expression.evalExp;
factory.evalValue = Expression.evalValue;
module.exports = factory;
},{"./filters":1,"./src/expression.js":15,"./src/filter.js":16,"./src/lexical.js":17,"./src/parser":18,"./src/render.js":19,"./src/scope":20,"./src/tag.js":22,"./src/tokenizer.js":23,"./tags":34,"any-promise":3,"assert":6,"fs":7,"path":8}],3:[function(require,module,exports){
'use strict';
module.exports = require('./register')().Promise;
},{"./register":5}],4:[function(require,module,exports){
"use strict";
// global key for user preferred registration
var REGISTRATION_KEY = '@@any-promise/REGISTRATION',
// Prior registration (preferred or detected)
registered = null;
/**
* Registers the given implementation. An implementation must
* be registered prior to any call to `require("any-promise")`,
* typically on application load.
*
* If called with no arguments, will return registration in
* following priority:
*
* For Node.js:
*
* 1. Previous registration
* 2. global.Promise if node.js version >= 0.12
* 3. Auto detected promise based on first sucessful require of
* known promise libraries. Note this is a last resort, as the
* loaded library is non-deterministic. node.js >= 0.12 will
* always use global.Promise over this priority list.
* 4. Throws error.
*
* For Browser:
*
* 1. Previous registration
* 2. window.Promise
* 3. Throws error.
*
* Options:
*
* Promise: Desired Promise constructor
* global: Boolean - Should the registration be cached in a global variable to
* allow cross dependency/bundle registration? (default true)
*/
module.exports = function (root, loadImplementation) {
return function register(implementation, opts) {
implementation = implementation || null;
opts = opts || {};
// global registration unless explicitly {global: false} in options (default true)
var registerGlobal = opts.global !== false;
// load any previous global registration
if (registered === null && registerGlobal) {
registered = root[REGISTRATION_KEY] || null;
}
if (registered !== null && implementation !== null && registered.implementation !== implementation) {
// Throw error if attempting to redefine implementation
throw new Error('any-promise already defined as "' + registered.implementation + '". You can only register an implementation before the first ' + ' call to require("any-promise") and an implementation cannot be changed');
}
if (registered === null) {
// use provided implementation
if (implementation !== null && typeof opts.Promise !== 'undefined') {
registered = {
Promise: opts.Promise,
implementation: implementation
};
} else {
// require implementation if implementation is specified but not provided
registered = loadImplementation(implementation);
}
if (registerGlobal) {
// register preference globally in case multiple installations
root[REGISTRATION_KEY] = registered;
}
}
return registered;
};
};
},{}],5:[function(require,module,exports){
"use strict";
module.exports = require('./loader')(window, loadImplementation);
/**
* Browser specific loadImplementation. Always uses `window.Promise`
*
* To register a custom implementation, must register with `Promise` option.
*/
function loadImplementation() {
if (typeof window.Promise === 'undefined') {
throw new Error("any-promise browser requires a polyfill or explicit registration" + " e.g: require('any-promise/register/bluebird')");
}
return {
Promise: window.Promise,
implementation: 'window.Promise'
};
}
},{"./loader":4}],6:[function(require,module,exports){
'use strict';
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// 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 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.
// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var util = require('util/');
var pSlice = Array.prototype.slice;
var hasOwn = Object.prototype.hasOwnProperty;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
if (options.message) {
this.message = options.message;
this.generatedMessage = false;
} else {
this.message = getMessage(this);
this.generatedMessage = true;
}
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
} else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = stackStartFunction.name;
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (util.isUndefined(value)) {
return '' + value;
}
if (util.isNumber(value) && !isFinite(value)) {
return value.toString();
}
if (util.isFunction(value) || util.isRegExp(value)) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (util.isString(s)) {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function getMessage(self) {
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + self.operator + ' ' + truncate(JSON.stringify(self.expected, replacer), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (!util.isObject(actual) && !util.isObject(expected)) {
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b)) {
return a === b;
}
var aIsArgs = isArguments(a),
bIsArgs = isArguments(b);
if (aIsArgs && !bIsArgs || !aIsArgs && bIsArgs) return false;
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
var ka = objectKeys(a),
kb = objectKeys(b),
key,
i;
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length) return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i]) return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (util.isString(expected)) {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if (shouldThrow && actual && expected && !expectedException(actual, expected) || !shouldThrow && actual) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function (block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function (block, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function (err) {
if (err) {
throw err;
}
};
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
},{"util/":13}],7:[function(require,module,exports){
"use strict";
},{}],8:[function(require,module,exports){
(function (process){
'use strict';
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function splitPath(filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function () {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = i >= 0 ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string') {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function (p) {
return !!p;
}), !resolvedAbsolute).join('/');
return (resolvedAbsolute ? '/' : '') + resolvedPath || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function (path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function (p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function (path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function () {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function (p, index) {
if (typeof p !== 'string') {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function (from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function (path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function (path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function (path) {
return splitPath(path)[3];
};
function filter(xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) {
return str.substr(start, len);
} : function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
};
}).call(this,require('_process'))
},{"_process":9}],9:[function(require,module,exports){
'use strict';
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout() {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
})();
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () {
return '/';
};
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function () {
return 0;
};
},{}],10:[function(require,module,exports){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
//
// strftime
// github.com/samsonjs/strftime
// @_sjs
//
// Copyright 2010 - 2015 Sami Samhuri <[email protected]>
//
// MIT License
// http://sjs.mit-license.org
//
;(function () {
var DefaultLocale = {
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
AM: 'AM',
PM: 'PM',
am: 'am',
pm: 'pm',
formats: {
D: '%m/%d/%y',
F: '%Y-%m-%d',
R: '%H:%M',
T: '%H:%M:%S',
X: '%T',
c: '%a %b %d %X %Y',
r: '%I:%M:%S %p',
v: '%e-%b-%Y',
x: '%D'
}
},
defaultStrftime = new Strftime(DefaultLocale, 0, false),
isCommonJS = typeof module !== 'undefined',
namespace;
// CommonJS / Node module
if (isCommonJS) {
namespace = module.exports = adaptedStrftime;
namespace.strftime = deprecatedStrftime;
}
// Browsers and other environments
else {
// Get the global object. Works in ES3, ES5, and ES5 strict mode.
namespace = function () {
return this || (1, eval)('this');
}();
namespace.strftime = adaptedStrftime;
}
// Deprecated API, to be removed in v1.0
var _require = isCommonJS ? "require('strftime')" : "strftime";
var _deprecationWarnings = {};
function deprecationWarning(name, instead) {
if (!_deprecationWarnings[name]) {
if (typeof console !== 'undefined' && typeof console.warn == 'function') {
console.warn("[WARNING] " + name + " is deprecated and will be removed in version 1.0. Instead, use `" + instead + "`.");
}
_deprecationWarnings[name] = true;
}
}
namespace.strftimeTZ = deprecatedStrftimeTZ;
namespace.strftimeUTC = deprecatedStrftimeUTC;
namespace.localizedStrftime = deprecatedStrftimeLocalized;
// Adapt the old API while preserving the new API.
function adaptForwards(fn) {
fn.localize = defaultStrftime.localize.bind(defaultStrftime);
fn.timezone = defaultStrftime.timezone.bind(defaultStrftime);
fn.utc = defaultStrftime.utc.bind(defaultStrftime);
}
adaptForwards(adaptedStrftime);
function adaptedStrftime(fmt, d, locale) {
// d and locale are optional, check if this is (format, locale)
if (d && d.days) {
locale = d;
d = undefined;
}
if (locale) {
deprecationWarning("`" + _require + "(format, [date], [locale])`", "var s = " + _require + ".localize(locale); s(format, [date])");
}
var strftime = locale ? defaultStrftime.localize(locale) : defaultStrftime;
return strftime(fmt, d);
}
adaptForwards(deprecatedStrftime);
function deprecatedStrftime(fmt, d, locale) {
if (locale) {
deprecationWarning("`" + _require + ".strftime(format, [date], [locale])`", "var s = " + _require + ".localize(locale); s(format, [date])");
} else {
deprecationWarning("`" + _require + ".strftime(format, [date])`", _require + "(format, [date])");
}
var strftime = locale ? defaultStrftime.localize(locale) : defaultStrftime;
return strftime(fmt, d);
}
function deprecatedStrftimeTZ(fmt, d, locale, timezone) {
// locale is optional, check if this is (format, date, timezone)
if ((typeof locale == 'number' || typeof locale == 'string') && timezone == null) {
timezone = locale;
locale = undefined;
}
if (locale) {
deprecationWarning("`" + _require + ".strftimeTZ(format, date, locale, tz)`", "var s = " + _require + ".localize(locale).timezone(tz); s(format, [date])` or `var s = " + _require + ".localize(locale); s.timezone(tz)(format, [date])");
} else {
deprecationWarning("`" + _require + ".strftimeTZ(format, date, tz)`", "var s = " + _require + ".timezone(tz); s(format, [date])` or `" + _require + ".timezone(tz)(format, [date])");
}
var strftime = (locale ? defaultStrftime.localize(locale) : defaultStrftime).timezone(timezone);
return strftime(fmt, d);
}
var utcStrftime = defaultStrftime.utc();
function deprecatedStrftimeUTC(fmt, d, locale) {
if (locale) {
deprecationWarning("`" + _require + ".strftimeUTC(format, date, locale)`", "var s = " + _require + ".localize(locale).utc(); s(format, [date])");
} else {
deprecationWarning("`" + _require + ".strftimeUTC(format, [date])`", "var s = " + _require + ".utc(); s(format, [date])");
}
var strftime = locale ? utcStrftime.localize(locale) : utcStrftime;
return strftime(fmt, d);
}
function deprecatedStrftimeLocalized(locale) {
deprecationWarning("`" + _require + ".localizedStrftime(locale)`", _require + ".localize(locale)");
return defaultStrftime.localize(locale);
}
// End of deprecated API
// Polyfill Date.now for old browsers.
if (typeof Date.now !== 'function') {
Date.now = function () {
return +new Date();
};
}
function Strftime(locale, customTimezoneOffset, useUtcTimezone) {
var _locale = locale || DefaultLocale,
_customTimezoneOffset = customTimezoneOffset || 0,
_useUtcBasedDate = useUtcTimezone || false,
// we store unix timestamp value here to not create new Date() each iteration (each millisecond)
// Date.now() is 2 times faster than new Date()
// while millisecond precise is enough here
// this could be very helpful when strftime triggered a lot of times one by one
_cachedDateTimestamp = 0,
_cachedDate;
function _strftime(format, date) {
var timestamp;
if (!date) {
var currentTimestamp = Date.now();
if (currentTimestamp > _cachedDateTimestamp) {
_cachedDateTimestamp = currentTimestamp;
_cachedDate = new Date(_cachedDateTimestamp);
timestamp = _cachedDateTimestamp;
if (_useUtcBasedDate) {
// how to avoid duplication of date instantiation for utc here?
// we tied to getTimezoneOffset of the current date
_cachedDate = new Date(_cachedDateTimestamp + getTimestampToUtcOffsetFor(_cachedDate) + _customTimezoneOffset);
}
} else {
timestamp = _cachedDateTimestamp;
}
date = _cachedDate;
} else {
timestamp = date.getTime();
if (_useUtcBasedDate) {
date = new Date(date.getTime() + getTimestampToUtcOffsetFor(date) + _customTimezoneOffset);
}
}
return _processFormat(format, date, _locale, timestamp);
}
function _processFormat(format, date, locale, timestamp) {
var resultString = '',
padding = null,
isInScope = false,
length = format.length,
extendedTZ = false;
for (var i = 0; i < length; i++) {
var currentCharCode = format.charCodeAt(i);
if (isInScope === true) {
// '-'
if (currentCharCode === 45) {
padding = '';
continue;
}
// '_'
else if (currentCharCode === 95) {
padding = ' ';
continue;
}
// '0'
else if (currentCharCode === 48) {
padding = '0';
continue;
}
// ':'
else if (currentCharCode === 58) {
if (extendedTZ) {
if (typeof console !== 'undefined' && typeof console.warn == 'function') {
console.warn("[WARNING] detected use of unsupported %:: or %::: modifiers to strftime");
}
}
extendedTZ = true;
continue;
}
switch (currentCharCode) {
// Examples for new Date(0) in GMT
// 'Thursday'
// case 'A':
case 65:
resultString += locale.days[date.getDay()];
break;
// 'January'
// case 'B':
case 66:
resultString += locale.months[date.getMonth()];
break;
// '19'
// case 'C':
case 67:
resultString += padTill2(Math.floor(date.getFullYear() / 100), padding);
break;
// '01/01/70'
// case 'D':
case 68:
resultString += _processFormat(locale.formats.D, date, locale, timestamp);
break;
// '1970-01-01'
// case 'F':
case 70:
resultString += _processFormat(locale.formats.F, date, locale, timestamp);
break;
// '00'
// case 'H':
case 72:
resultString += padTill2(date.getHours(), padding);
break;
// '12'
// case 'I':
case 73:
resultString += padTill2(hours12(date.getHours()), padding);
break;
// '000'
// case 'L':
case 76:
resultString += padTill3(Math.floor(timestamp % 1000));
break;
// '00'
// case 'M':
case 77:
resultString += padTill2(date.getMinutes(), padding);
break;
// 'am'
// case 'P':
case 80:
resultString += date.getHours() < 12 ? locale.am : locale.pm;
break;
// '00:00'
// case 'R':
case 82:
resultString += _processFormat(locale.formats.R, date, locale, timestamp);
break;
// '00'
// case 'S':
case 83:
resultString += padTill2(date.getSeconds(), padding);
break;
// '00:00:00'
// case 'T':
case 84:
resultString += _processFormat(locale.formats.T, date, locale, timestamp);
break;
// '00'
// case 'U':
case 85:
resultString += padTill2(weekNumber(date, 'sunday'), padding);
break;
// '00'
// case 'W':
case 87:
resultString += padTill2(weekNumber(date, 'monday'), padding);
break;
// '16:00:00'
// case 'X':
case 88:
resultString += _processFormat(locale.formats.X, date, locale, timestamp);
break;
// '1970'
// case 'Y':
case 89:
resultString += date.getFullYear();
break;
// 'GMT'
// case 'Z':
case 90:
if (_useUtcBasedDate && _customTimezoneOffset === 0) {
resultString += "GMT";
} else {
// fixme optimize
var tzString = date.toString().match(/\(([\w\s]+)\)/);
resultString += tzString && tzString[1] || '';
}
break;
// 'Thu'
// case 'a':
case 97:
resultString += locale.shortDays[date.getDay()];
break;
// 'Jan'
// case 'b':
case 98:
resultString += locale.shortMonths[date.getMonth()];
break;
// ''
// case 'c':
case 99:
resultString += _processFormat(locale.formats.c, date, locale, timestamp);
break;
// '01'
// case 'd':
case 100:
resultString += padTill2(date.getDate(), padding);
break;
// ' 1'
// case 'e':
case 101:
resultString += padTill2(date.getDate(), padding == null ? ' ' : padding);
break;
// 'Jan'
// case 'h':
case 104:
resultString += locale.shortMonths[date.getMonth()];
break;
// '000'
// case 'j':
case 106:
var y = new Date(date.getFullYear(), 0, 1);
var day = Math.ceil((date.getTime() - y.getTime()) / (1000 * 60 * 60 * 24));
resultString += padTill3(day);
break;
// ' 0'
// case 'k':
case 107:
resultString += padTill2(date.getHours(), padding == null ? ' ' : padding);
break;
// '12'
// case 'l':
case 108:
resultString += padTill2(hours12(date.getHours()), padding == null ? ' ' : padding);
break;
// '01'
// case 'm':
case 109:
resultString += padTill2(date.getMonth() + 1, padding);
break;
// '\n'
// case 'n':
case 110:
resultString += '\n';
break;
// '1st'
// case 'o':
case 111:
resultString += String(date.getDate()) + ordinal(date.getDate());
break;
// 'AM'
// case 'p':
case 112:
resultString += date.getHours() < 12 ? locale.AM : locale.PM;
break;
// '12:00:00 AM'
// case 'r':
case 114:
resultString += _processFormat(locale.formats.r, date, locale, timestamp);
break;
// '0'
// case 's':
case 115:
resultString += Math.floor(timestamp / 1000);
break;
// '\t'
// case 't':
case 116:
resultString += '\t';
break;
// '4'
// case 'u':
case 117:
var day = date.getDay();
resultString += day === 0 ? 7 : day;
break; // 1 - 7, Monday is first day of the week
// ' 1-Jan-1970'
// case 'v':
case 118:
resultString += _processFormat(locale.formats.v, date, locale, timestamp);
break;
// '4'
// case 'w':
case 119:
resultString += date.getDay();
break; // 0 - 6, Sunday is first day of the week
// '12/31/69'
// case 'x':
case 120:
resultString += _processFormat(locale.formats.x, date, locale, timestamp);
break;
// '70'
// case 'y':
case 121:
resultString += ('' + date.getFullYear()).slice(2);
break;
// '+0000'
// case 'z':
case 122:
if (_useUtcBasedDate && _customTimezoneOffset === 0) {
resultString += extendedTZ ? "+00:00" : "+0000";
} else {
var off;
if (_customTimezoneOffset !== 0) {
off = _customTimezoneOffset / (60 * 1000);
} else {
off = -date.getTimezoneOffset();
}
var sign = off < 0 ? '-' : '+';
var sep = extendedTZ ? ':' : '';
var hours = Math.floor(Math.abs(off / 60));
var mins = Math.abs(off % 60);
resultString += sign + padTill2(hours) + sep + padTill2(mins);
}
break;
default:
resultString += format[i];
break;
}
padding = null;
isInScope = false;
continue;
}
// '%'
if (currentCharCode === 37) {
isInScope = true;
continue;
}
resultString += format[i];
}
return resultString;
}
var strftime = _strftime;
strftime.localize = function (locale) {
return new Strftime(locale || _locale, _customTimezoneOffset, _useUtcBasedDate);
};
strftime.timezone = function (timezone) {
var customTimezoneOffset = _customTimezoneOffset;
var useUtcBasedDate = _useUtcBasedDate;
var timezoneType = typeof timezone === 'undefined' ? 'undefined' : _typeof(timezone);
if (timezoneType === 'number' || timezoneType === 'string') {
useUtcBasedDate = true;
// ISO 8601 format timezone string, [-+]HHMM
if (timezoneType === 'string') {
var sign = timezone[0] === '-' ? -1 : 1,
hours = parseInt(timezone.slice(1, 3), 10),
minutes = parseInt(timezone.slice(3, 5), 10);
customTimezoneOffset = sign * (60 * hours + minutes) * 60 * 1000;
// in minutes: 420
} else if (timezoneType === 'number') {
customTimezoneOffset = timezone * 60 * 1000;
}
}
return new Strftime(_locale, customTimezoneOffset, useUtcBasedDate);
};
strftime.utc = function () {
return new Strftime(_locale, _customTimezoneOffset, true);
};
return strftime;
}
function padTill2(numberToPad, paddingChar) {
if (paddingChar === '' || numberToPad > 9) {
return numberToPad;
}
if (paddingChar == null) {
paddingChar = '0';
}
return paddingChar + numberToPad;
}
function padTill3(numberToPad) {
if (numberToPad > 99) {
return numberToPad;
}
if (numberToPad > 9) {
return '0' + numberToPad;
}
return '00' + numberToPad;
}
function hours12(hour) {
if (hour === 0) {
return 12;
} else if (hour > 12) {
return hour - 12;
}
return hour;
}
// firstWeekday: 'sunday' or 'monday', default is 'sunday'
//
// Pilfered & ported from Ruby's strftime implementation.
function weekNumber(date, firstWeekday) {
firstWeekday = firstWeekday || 'sunday';
// This works by shifting the weekday back by one day if we
// are treating Monday as the first day of the week.
var weekday = date.getDay();
if (firstWeekday === 'monday') {
if (weekday === 0) // Sunday
weekday = 6;else weekday--;
}
var firstDayOfYearUtc = Date.UTC(date.getFullYear(), 0, 1),
dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),
yday = Math.floor((dateUtc - firstDayOfYearUtc) / 86400000),
weekNum = (yday + 7 - weekday) / 7;
return Math.floor(weekNum);
}
// Get the ordinal suffix for a number: st, nd, rd, or th
function ordinal(number) {
var i = number % 10;
var ii = number % 100;
if (ii >= 11 && ii <= 13 || i === 0 || i >= 4) {
return 'th';
}
switch (i) {
case 1:
return 'st';
case 2:
return 'nd';
case 3:
return 'rd';
}
}
function getTimestampToUtcOffsetFor(date) {
return (date.getTimezoneOffset() || 0) * 60000;
}
})();
},{}],11:[function(require,module,exports){
'use strict';
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function TempCtor() {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
};
}
},{}],12:[function(require,module,exports){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
module.exports = function isBuffer(arg) {
return arg && (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function';
};
},{}],13:[function(require,module,exports){
(function (process,global){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.
var formatRegExp = /%[sdj%]/g;
exports.format = function (f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function (x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function (fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function () {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function (set) {
if (isUndefined(debugEnviron)) debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function () {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function () {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold': [1, 22],
'italic': [3, 23],
'underline': [4, 24],
'inverse': [7, 27],
'white': [37, 39],
'grey': [90, 39],
'black': [30, 39],
'blue': [34, 39],
'cyan': [36, 39],
'green': [32, 39],
'magenta': [35, 39],
'red': [31, 39],
'yellow': [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function (val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect && value && isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '',
array = false,
braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value)) return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '').replace(/'/g, "\\'").replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value)) return ctx.stylize('' + value, 'number');
if (isBoolean(value)) return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value)) return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true));
} else {
output.push('');
}
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function (prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function () {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function (origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":12,"_process":9,"inherits":11}],14:[function(require,module,exports){
"use strict";
var util = require('util');
function TokenizationError(message, input, line) {
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message || "";
this.input = input;
this.line = line;
}
util.inherits(TokenizationError, Error);
function ParseError(message, input, line) {
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message || "";
this.input = input;
this.line = line;
}
util.inherits(ParseError, Error);
module.exports = {
TokenizationError: TokenizationError, ParseError: ParseError
};
},{"util":13}],15:[function(require,module,exports){
'use strict';
var syntax = require('./syntax.js');
var Exp = require('./expression.js');
var lexical = require('./lexical.js');
function evalExp(exp, scope) {
if (!scope) throw new Error('unable to evalExp: scope undefined');
var operatorREs = lexical.operators,
match;
for (var i = 0; i < operatorREs.length; i++) {
var operatorRE = operatorREs[i];
var expRE = new RegExp('^(' + lexical.quoteBalanced.source + ')(' + operatorRE.source + ')(' + lexical.quoteBalanced.source + ')$');
if (match = exp.match(expRE)) {
var l = evalExp(match[1], scope);
var op = syntax.operators[match[2].trim()];
var r = evalExp(match[3], scope);
return op(l, r);
}
}
if (match = exp.match(lexical.rangeLine)) {
var low = evalValue(match[1], scope),
high = evalValue(match[2], scope);
var range = [];
for (var j = low; j <= high; j++) {
range.push(j);
}
return range;
}
return evalValue(exp, scope);
}
function evalValue(str, scope) {
str = str && str.trim();
if (!str) return undefined;
if (lexical.isLiteral(str)) {
var a = lexical.parseLiteral(str);
return lexical.parseLiteral(str);
}
if (lexical.isVariable(str)) {
return scope.get(str);
}
}
function isTruthy(val) {
if (val instanceof Array) return !!val.length;
return !!val;
}
function isFalsy(val) {
return !isTruthy(val);
}
module.exports = {
evalExp: evalExp, evalValue: evalValue, isTruthy: isTruthy, isFalsy: isFalsy
};
},{"./expression.js":15,"./lexical.js":17,"./syntax.js":21}],16:[function(require,module,exports){
'use strict';
var lexical = require('./lexical.js');
var Exp = require('./expression.js');
var valueRE = new RegExp('' + lexical.value.source, 'g');
module.exports = function () {
var filters = {};
var _filterInstance = {
render: function render(output, scope) {
var args = this.args.map(function (arg) {
return Exp.evalValue(arg, scope);
});
args.unshift(output);
return this.filter.apply(null, args);
},
parse: function parse(str) {
var match = lexical.filterLine.exec(str);
if (!match) throw new Error('illegal filter: ' + str);
var name = match[1],
argList = match[2] || '',
filter = filters[name];
if (typeof filter !== 'function') {
return {
name: name,
error: new Error('undefined filter: ' + name)
};
}
var args = [];
while (match = valueRE.exec(argList.trim())) {
args.push(match[0]);
}
this.name = name;
this.filter = filter;
this.args = args;
return this;
}
};
function construct(str) {
var instance = Object.create(_filterInstance);
return instance.parse(str);
}
function register(name, filter) {
filters[name] = filter;
}
function clear() {
filters = {};
}
return {
construct: construct, register: register, clear: clear
};
};
},{"./expression.js":15,"./lexical.js":17}],17:[function(require,module,exports){
'use strict';
// quote related
var singleQuoted = /'[^']*'/;
var doubleQuoted = /"[^"]*"/;
var quoteBalanced = new RegExp('(?:' + singleQuoted.source + '|' + doubleQuoted.source + '|[^\'"])*');
var number = /(?:-?\d+\.?\d*|\.?\d+)/;
var bool = /true|false/;
var identifier = /[a-zA-Z_$][a-zA-Z_$0-9]*/;
var subscript = /\[\d+\]/;
var quoted = new RegExp('(?:' + singleQuoted.source + '|' + doubleQuoted.source + ')');
var literal = new RegExp('(?:' + quoted.source + '|' + bool.source + '|' + number.source + ')');
var variable = new RegExp(identifier.source + '(?:\\.' + identifier.source + '|' + subscript.source + ')*');
// range related
var rangeLimit = new RegExp('(?:' + variable.source + '|' + number.source + ')');
var range = new RegExp('\\(' + rangeLimit.source + '\\.\\.' + rangeLimit.source + '\\)');
var rangeCapture = new RegExp('\\((' + rangeLimit.source + ')\\.\\.(' + rangeLimit.source + ')\\)');
var value = new RegExp('(?:' + literal.source + '|' + variable.source + '|' + range.source + ')');
// hash related
var hash = new RegExp('(?:' + identifier.source + ')\\s*:\\s*(?:' + value.source + ')');
var hashCapture = new RegExp('(' + identifier.source + ')\\s*:\\s*(' + value.source + ')', 'g');
var tagLine = new RegExp('^\\s*(' + identifier.source + ')\\s*(.*)\\s*$');
var literalLine = new RegExp('^' + literal.source + '$', 'i');
var variableLine = new RegExp('^' + variable.source + '$');
var numberLine = new RegExp('^' + number.source + '$');
var boolLine = new RegExp('^' + bool.source + '$', 'i');
var quotedLine = new RegExp('^' + quoted.source + '$');
var rangeLine = new RegExp('^' + rangeCapture.source + '$');
// filter related
var valueList = new RegExp(value.source + '(\\s*,\\s*' + value.source + ')*');
var filter = new RegExp(identifier.source + '(?:\\s*:\\s*' + valueList.source + ')?', 'g');
var filterCapture = new RegExp('(' + identifier.source + ')(?:\\s*:\\s*(' + valueList.source + '))?');
var filterLine = new RegExp('^' + filterCapture.source + '$');
var operators = [/\s+or\s+/, /\s+and\s+/, /==|!=|<=|>=|<|>|\s+contains\s+/];
function isLiteral(str) {
return literalLine.test(str);
}
function isRange(str) {
return rangeLine.test(str);
}
function isVariable(str) {
return variableLine.test(str);
}
function parseLiteral(str) {
var res;
if (res = str.match(numberLine)) {
return Number(str);
}
if (res = str.match(boolLine)) {
return str.toLowerCase() === 'true';
}
if (res = str.match(quotedLine)) {
return str.slice(1, -1);
}
}
module.exports = {
quoted: quoted, number: number, bool: bool, literal: literal, filter: filter,
hash: hash, hashCapture: hashCapture,
range: range, rangeCapture: rangeCapture,
identifier: identifier, value: value, quoteBalanced: quoteBalanced, operators: operators,
quotedLine: quotedLine, numberLine: numberLine, boolLine: boolLine, rangeLine: rangeLine, literalLine: literalLine, filterLine: filterLine, tagLine: tagLine,
isLiteral: isLiteral, isVariable: isVariable, parseLiteral: parseLiteral, isRange: isRange
};
},{}],18:[function(require,module,exports){
'use strict';
var lexical = require('./lexical.js');
var ParseError = require('./error.js').ParseError;
module.exports = function (Tag, Filter) {
var stream = {
init: function init(tokens) {
this.tokens = tokens;
this.handlers = {};
return this;
},
on: function on(name, cb) {
this.handlers[name] = cb;
return this;
},
trigger: function trigger(event, arg) {
var h = this.handlers[event];
if (typeof h === 'function') {
h(arg);
return true;
}
},
start: function start() {
this.trigger('start');
while (!this.stopRequested && (token = this.tokens.shift())) {
if (this.trigger('token', token)) continue;
if (token.type == 'tag' && this.trigger('tag:' + token.name, token)) {
continue;
}
var template = parseToken(token, this.tokens);
this.trigger('template', template);
}
if (!this.stopRequested) this.trigger('end');
return this;
},
stop: function stop() {
this.stopRequested = true;
return this;
}
};
function parse(tokens) {
var token,
templates = [];
while (token = tokens.shift()) {
templates.push(parseToken(token, tokens));
}
return templates;
}
function parseToken(token, tokens) {
try {
switch (token.type) {
case 'tag':
return parseTag(token, tokens);
case 'output':
return parseOutput(token.value);
case 'html':
return token;
}
} catch (e) {
throw new ParseError(e.message, token.input, token.line);
}
}
function parseTag(token, tokens) {
if (token.name === 'continue' || token.name === 'break') return token;
return Tag.construct(token, tokens);
}
function parseOutput(str) {
var match = lexical.value.exec(str);
if (!match) throw new Error('illegal output string: ' + str);
var initial = match[0];
str = str.substr(match.index + match[0].length);
var filters = [];
while (match = lexical.filter.exec(str)) {
filters.push([match[0].trim()]);
}
return {
type: 'output',
initial: initial,
filters: filters.map(function (str) {
return Filter.construct(str);
})
};
}
function parseStream(tokens) {
var s = Object.create(stream);
return s.init(tokens);
}
return {
parse: parse, parseTag: parseTag, parseStream: parseStream, parseOutput: parseOutput
};
};
},{"./error.js":14,"./lexical.js":17}],19:[function(require,module,exports){
'use strict';
var error = require('./error.js');
var Exp = require('./expression.js');
var assert = require('assert');
var Promise = require('any-promise');
var render = {
renderTemplates: function renderTemplates(templates, scope, opts) {
var _this = this;
assert(scope, 'unable to evalTemplates: scope undefined');
opts = opts || {};
opts.strict_filters = opts.strict_filters || false;
var html = '';
// This executes an array of promises sequentially for every template in the templates array - http://webcache.googleusercontent.com/search?q=cache:rNbMUn9TPtkJ:joost.vunderink.net/blog/2014/12/15/processing-an-array-of-promises-sequentially-in-node-js/+&cd=5&hl=en&ct=clnk&gl=us
// It's fundamentally equivalent to the following...
// emptyPromise.then(renderTag(template0).then(renderTag(template1).then(renderTag(template2)...
var lastPromise = templates.reduce(function (promise, template) {
return promise.then(function (partial) {
if (scope.safeGet('forloop.skip')) {
return Promise.resolve('');
}
if (scope.safeGet('forloop.stop')) {
throw new Error('forloop.stop'); // this will stop/break the sequential promise chain and go to the catch
}
var promiseLink = Promise.resolve('');
switch (template.type) {
case 'tag':
// Add Promises to the chain
promiseLink = _this.renderTag(template, scope, _this.register).then(function (partial) {
if (partial === undefined) {
return true; // basically a noop (do nothing)
}
return html += partial;
});
break;
case 'html':
promiseLink = Promise.resolve(template.value).then(function (partial) {
return html += partial;
});
break;
case 'output':
var val = _this.evalOutput(template, scope, opts);
promiseLink = Promise.resolve(val === undefined ? '' : stringify(val)).then(function (partial) {
return html += partial;
});
break;
}
return promiseLink;
}).catch(function (error) {
if (error.message === 'forloop.skip') {
// the error is a controlled, purposeful stop. so just return the html that we have up to this point
return html;
} else {
// rethrow actual error
throw error;
}
});
}, Promise.resolve('')); // start the reduce chain with a resolved Promise. After first run, the "promise" argument
// in our reduce callback will be the returned promise from our "then" above. In this
// case, that's the promise returned from this.renderTag or a resolved promise with raw html.
return lastPromise.then(function (renderedHtml) {
return renderedHtml;
}).catch(function (error) {
throw error;
});
},
renderTag: function renderTag(template, scope, register) {
if (template.name === 'continue') {
scope.set('forloop.skip', true);
return Promise.resolve('');
}
if (template.name === 'break') {
scope.set('forloop.stop', true);
scope.set('forloop.skip', true);
return Promise.reject(new Error('forloop.stop')); // this will stop the sequential promise chain
}
return template.render(scope, register);
},
evalOutput: function evalOutput(template, scope, opts) {
assert(scope, 'unable to evalOutput: scope undefined');
var val = Exp.evalExp(template.initial, scope);
template.filters.some(function (filter) {
if (filter.error) {
if (opts.strict_filters) {
throw filter.error;
} else {
// render as null
val = '';
return true;
}
}
val = filter.render(val, scope);
});
return val;
},
resetRegisters: function resetRegisters() {
return this.register = {};
}
};
function factory() {
var instance = Object.create(render);
instance.register = {};
return instance;
}
function stringify(val) {
if (typeof val === 'string') return val;
return JSON.stringify(val);
}
module.exports = factory;
},{"./error.js":14,"./expression.js":15,"any-promise":3,"assert":6}],20:[function(require,module,exports){
'use strict';
var lexical = require('./lexical.js');
var Scope = {
safeGet: function safeGet(str) {
var i;
// get all
if (str === undefined) {
var ctx = {};
for (i = this.scopes.length - 1; i >= 0; i--) {
var scp = this.scopes[i];
for (var k in scp) {
if (scp.hasOwnProperty(k)) {
ctx[k] = scp[k];
}
}
}
return ctx;
}
// get one path
for (i = this.scopes.length - 1; i >= 0; i--) {
var v = getPropertyByPath(this.scopes[i], str);
if (v !== undefined) return v;
}
},
get: function get(str) {
var val = this.safeGet(str);
if (val === undefined && this.opts.strict) {
throw new Error('[strict_variables] undefined variable: ' + str);
}
return val;
},
set: function set(k, v) {
setPropertyByPath(this.scopes[this.scopes.length - 1], k, v);
return this;
},
push: function push(ctx) {
if (!ctx) throw new Error('trying to push ' + ctx + ' into scopes');
return this.scopes.push(ctx);
},
pop: function pop() {
return this.scopes.pop();
}
};
function setPropertyByPath(obj, path, val) {
if (path instanceof String || typeof path === 'string') {
var paths = path.replace(/\[/g, '.').replace(/\]/g, '').split('.');
for (var i = 0; i < paths.length; i++) {
var key = paths[i];
if (i === paths.length - 1) {
return obj[key] = val;
}
if (undefined === obj[key]) obj[key] = {};
// case for readonly objects
obj = obj[key] || {};
}
return obj;
}
return obj[path] = val;
}
function getPropertyByPath(obj, path) {
if (path instanceof String || typeof path === 'string') {
var paths = path.replace(/\[/g, '.').replace(/\]/g, '').split('.');
paths.forEach(function (p) {
return obj = obj && obj[p];
});
return obj;
}
return obj[path];
}
exports.factory = function (_ctx, opts) {
opts = opts || {};
opts.strict = opts.strict || false;
var scope = Object.create(Scope);
scope.opts = opts;
scope.scopes = [_ctx || {}];
return scope;
};
},{"./lexical.js":17}],21:[function(require,module,exports){
'use strict';
var operators = {
'==': function _(l, r) {
return l == r;
},
'!=': function _(l, r) {
return l != r;
},
'>': function _(l, r) {
return l > r;
},
'<': function _(l, r) {
return l < r;
},
'>=': function _(l, r) {
return l >= r;
},
'<=': function _(l, r) {
return l <= r;
},
'contains': function contains(l, r) {
return l.indexOf(r) > -1;
},
'and': function and(l, r) {
return l && r;
},
'or': function or(l, r) {
return l || r;
}
};
exports.operators = operators;
},{}],22:[function(require,module,exports){
'use strict';
var lexical = require('./lexical.js');
var Promise = require('any-promise');
var Exp = require('./expression.js');
var TokenizationError = require('./error.js').TokenizationError;
function hash(markup, scope) {
var obj = {};
lexical.hashCapture.lastIndex = 0;
while (match = lexical.hashCapture.exec(markup)) {
var k = match[1],
v = match[2];
obj[k] = Exp.evalValue(v, scope);
}
return obj;
}
module.exports = function () {
var tagImpls = {};
var _tagInstance = {
render: function render(scope, register) {
var reg = register[this.name];
if (!reg) reg = register[this.name] = {};
var obj = hash(this.token.args, scope);
return this.tagImpl.render && this.tagImpl.render(scope, obj, reg) || Promise.resolve('');
},
parse: function parse(token, tokens) {
this.type = 'tag';
this.token = token;
this.name = token.name;
var tagImpl = tagImpls[this.name];
if (!tagImpl) throw new Error('tag ' + this.name + ' not found');
this.tagImpl = Object.create(tagImpl);
if (this.tagImpl.parse) {
this.tagImpl.parse(token, tokens);
}
}
};
function register(name, tag) {
tagImpls[name] = tag;
}
function construct(token, tokens) {
var instance = Object.create(_tagInstance);
instance.parse(token, tokens);
return instance;
}
function clear() {
tagImpls = {};
}
return {
construct: construct, register: register, clear: clear
};
};
},{"./error.js":14,"./expression.js":15,"./lexical.js":17,"any-promise":3}],23:[function(require,module,exports){
'use strict';
var lexical = require('./lexical.js');
var TokenizationError = require('./error.js').TokenizationError;
function parse(html) {
var tokens = [];
if (!html) return tokens;
var syntax = /({%(.*?)%})|({{(.*?)}})/g;
var result, htmlFragment, token;
var lastMatchEnd = 0,
lastMatchBegin = -1,
parsedLinesCount = 0;
while ((result = syntax.exec(html)) !== null) {
// passed html fragments
if (result.index > lastMatchEnd) {
htmlFragment = html.slice(lastMatchEnd, result.index);
tokens.push({
type: 'html',
raw: htmlFragment,
value: htmlFragment
});
}
// tag appeared
if (result[1]) {
token = factory('tag', 1, result);
var match = token.value.match(lexical.tagLine);
if (!match) {
throw new TokenizationError('illegal tag: ' + token.raw, token.input, token.line);
}
token.name = match[1];
token.args = match[2];
tokens.push(token);
}
// output
else {
token = factory('output', 3, result);
tokens.push(token);
}
lastMatchEnd = syntax.lastIndex;
}
// remaining html
if (html.length > lastMatchEnd) {
htmlFragment = html.slice(lastMatchEnd, html.length);
tokens.push({
type: 'html',
raw: htmlFragment,
value: htmlFragment
});
}
return tokens;
function factory(type, offset, match) {
return {
type: type,
raw: match[offset],
value: match[offset + 1].trim(),
line: getLineNum(match),
input: getLineContent(match)
};
}
function getLineContent(match) {
var idx1 = match.input.lastIndexOf('\n', match.index);
var idx2 = match.input.indexOf('\n', match.index);
if (idx2 === -1) idx2 = match.input.length;
return match.input.slice(idx1 + 1, idx2);
}
function getLineNum(match) {
var lines = match.input.slice(lastMatchBegin + 1, match.index).split('\n');
parsedLinesCount += lines.length - 1;
lastMatchBegin = match.index;
return parsedLinesCount + 1;
}
}
exports.parse = parse;
},{"./error.js":14,"./lexical.js":17}],24:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var re = new RegExp('(' + lexical.identifier.source + ')\\s*=(.*)');
module.exports = function (liquid) {
liquid.registerTag('assign', {
parse: function parse(token) {
var match = token.args.match(re);
if (!match) throw new Error('illegal token ' + token.raw);
this.key = match[1];
this.value = match[2];
},
render: function render(scope, hash) {
scope.set(this.key, liquid.evalOutput(this.value, scope));
return Promise.resolve('');
}
});
};
},{"..":2,"any-promise":3}],25:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
var re = new RegExp('(' + lexical.identifier.source + ')');
module.exports = function (liquid) {
liquid.registerTag('capture', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
var match = tagToken.args.match(re);
if (!match) throw new Error(tagToken.args + ' not valid identifier');
this.variable = match[1];
this.templates = [];
var stream = liquid.parser.parseStream(remainTokens);
stream.on('tag:endcapture', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return _this.templates.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var _this2 = this;
return liquid.renderer.renderTemplates(this.templates, scope).then(function (html) {
scope.set(_this2.variable, html);
});
}
});
};
},{"..":2}],26:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
module.exports = function (liquid) {
liquid.registerTag('case', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
this.cond = tagToken.args;
this.cases = [];
this.elseTemplates = [];
var p = [],
stream = liquid.parser.parseStream(remainTokens).on('tag:when', function (token) {
if (!_this.cases[token.args]) {
_this.cases.push({
val: token.args,
templates: p = []
});
}
}).on('tag:else', function (token) {
return p = _this.elseTemplates;
}).on('tag:endcase', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return p.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
for (var i = 0; i < this.cases.length; i++) {
var branch = this.cases[i];
var val = Liquid.evalExp(branch.val, scope);
var cond = Liquid.evalExp(this.cond, scope);
if (val === cond) {
return liquid.renderer.renderTemplates(branch.templates, scope);
}
}
return liquid.renderer.renderTemplates(this.elseTemplates, scope);
}
});
};
},{"..":2}],27:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
var re = new RegExp('(' + lexical.identifier.source + ')');
module.exports = function (liquid) {
liquid.registerTag('comment', {
parse: function parse(tagToken, remainTokens) {
var stream = liquid.parser.parseStream(remainTokens);
stream.on('token', function (token) {
if (token.name === 'endcomment') stream.stop();
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
}
});
};
},{"..":2}],28:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var groupRE = new RegExp('^(?:(' + lexical.value.source + ')\\s*:\\s*)?(.*)$');
var candidatesRE = new RegExp(lexical.value.source, 'g');
module.exports = function (liquid) {
liquid.registerTag('cycle', {
parse: function parse(tagToken, remainTokens) {
var match = groupRE.exec(tagToken.args);
if (!match) throw new Error('illegal tag: ' + tagToken.raw);
this.group = match[1] || '';
var candidates = match[2];
this.candidates = [];
while (match = candidatesRE.exec(candidates)) {
this.candidates.push(match[0]);
}
if (!this.candidates.length) {
throw new Error('empty candidates: ' + tagToken.raw);
}
},
render: function render(scope, hash, register) {
var fingerprint = Liquid.evalValue(this.group, scope) + ':' + this.candidates.join(',');
var idx = register[fingerprint];
if (idx === undefined) {
idx = register[fingerprint] = 0;
}
var candidate = this.candidates[idx];
idx = (idx + 1) % this.candidates.length;
register[fingerprint] = idx;
return Promise.resolve(Liquid.evalValue(candidate, scope));
}
});
};
},{"..":2,"any-promise":3}],29:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
var error = Liquid.error;
module.exports = function (liquid) {
liquid.registerTag('decrement', {
parse: function parse(token) {
var match = token.args.match(lexical.identifier);
if (!match) throw new Error('illegal identifier ' + token.args);
this.variable = match[0];
},
render: function render(scope, hash) {
var v = scope.get(this.variable);
if (typeof v !== 'number') v = 0;
scope.set(this.variable, v - 1);
}
});
};
},{"..":2}],30:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var re = new RegExp('^(' + lexical.identifier.source + ')\\s+in\\s+' + ('(' + lexical.value.source + ')') + ('(?:\\s+' + lexical.hash.source + ')*') + '(?:\\s+(reversed))?$');
module.exports = function (liquid) {
liquid.registerTag('for', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
var match = re.exec(tagToken.args);
if (!match) throw new Error('illegal tag: ' + tagToken.raw);
this.variable = match[1];
this.collection = match[2];
this.reversed = !!match[3];
this.templates = [];
this.elseTemplates = [];
var p,
stream = liquid.parser.parseStream(remainTokens).on('start', function (x) {
return p = _this.templates;
}).on('tag:else', function (token) {
return p = _this.elseTemplates;
}).on('tag:endfor', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return p.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var _this2 = this;
var collection = Liquid.evalExp(this.collection, scope);
if (Liquid.isFalsy(collection)) {
return liquid.renderer.renderTemplates(this.elseTemplates, scope);
}
var html = '';
var length = collection.length;
var offset = hash.offset || 0;
var limit = hash.limit === undefined ? collection.length : hash.limit;
collection = collection.slice(offset, offset + limit);
if (this.reversed) collection.reverse();
// for needs to execute the promises sequentially, not just resolve them sequentially, due to break and continue.
// We can't just loop through executing everything then resolve them all sequentially like we do for render.renderTemplates
// First, we build the array of parameters we are going to use for each call to renderTemplates
var contexts = [];
collection.some(function (item, i) {
var ctx = {};
ctx[_this2.variable] = item;
ctx.forloop = {
first: i === 0,
index: i + 1,
index0: i,
last: i === length - 1,
length: length,
rindex: length - i,
rindex0: length - i - 1,
stop: false,
skip: false
};
// We are just putting together an array of the arguments we will be passing to our sequential promises
contexts.push(ctx);
});
// This is some pretty tricksy javascript, at least to me.
// This executes an array of promises sequentially for every argument in the contexts array - http://webcache.googleusercontent.com/search?q=cache:rNbMUn9TPtkJ:joost.vunderink.net/blog/2014/12/15/processing-an-array-of-promises-sequentially-in-node-js/+&cd=5&hl=en&ct=clnk&gl=us
// It's fundamentally equivalent to the following...
// emptyPromise.then(renderTemplates(args0).then(renderTemplates(args1).then(renderTemplates(args2)...
var lastPromise = contexts.reduce(function (promise, context) {
return promise.then(function (partial) {
if (scope.get('forloop.stop')) {
throw new Error('forloop.stop'); // this will stop the sequential promise chain
}
return html += partial;
}).then(function (partial) {
// todo: Make sure our scope management is sound here. Create some tests that revolve around loops
// with sections that take differing amounts of time to complete. Make sure the order is maintained
// and scope doesn't bleed over into other renderTemplate calls.
scope.push(context);
return liquid.renderer.renderTemplates(_this2.templates, scope);
}).then(function (partial) {
scope.pop(context);
return partial;
});
}, Promise.resolve('')); // start the reduce chain with a resolved Promise. After first run, the "promise" argument
// in our reduce callback will be the returned promise from our "then" above. In this
// case, the promise returned from liquid.renderer.renderTemplates.
return lastPromise.then(function (partial) {
return html += partial;
}).catch(function (error) {
if (error.message === 'forloop.stop') {
// the error is a controlled, purposeful stop. so just return the html that we have up to this point
return html;
} else {
// rethrow actual error
throw error;
}
});
}
});
};
},{"..":2,"any-promise":3}],31:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
module.exports = function (liquid) {
liquid.registerTag('if', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
this.branches = [];
this.elseTemplates = [];
var p,
stream = liquid.parser.parseStream(remainTokens).on('start', function (x) {
return _this.branches.push({
cond: tagToken.args,
templates: p = []
});
}).on('tag:elsif', function (token) {
if (!_this.branches[token.args]) {
_this.branches.push({
cond: token.args,
templates: p = []
});
}
}).on('tag:else', function (token) {
return p = _this.elseTemplates;
}).on('tag:endif', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return p.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
for (var i = 0; i < this.branches.length; i++) {
var branch = this.branches[i];
var cond = Liquid.evalExp(branch.cond, scope);
if (Liquid.isTruthy(cond)) {
return liquid.renderer.renderTemplates(branch.templates, scope);
}
}
return liquid.renderer.renderTemplates(this.elseTemplates, scope);
}
});
};
},{"..":2}],32:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var withRE = new RegExp('with\\s+(' + lexical.value.source + ')');
module.exports = function (liquid) {
liquid.registerTag('include', {
parse: function parse(token) {
var match = lexical.value.exec(token.args);
if (!match) throw new Error('illegal token ' + token.raw);
this.value = match[0];
match = withRE.exec(token.args);
if (match) {
this.with = match[1];
}
},
render: function render(scope, hash) {
var filepath = Liquid.evalValue(this.value, scope);
if (this.with) {
hash[filepath] = Liquid.evalValue(this.with, scope);
}
return liquid.handleCache(filepath).then(function (templates) {
scope.push(hash);
return liquid.renderer.renderTemplates(templates, scope);
}).then(function (html) {
scope.pop();
return html;
});
}
});
};
},{"..":2,"any-promise":3}],33:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
module.exports = function (liquid) {
liquid.registerTag('increment', {
parse: function parse(token) {
var match = token.args.match(lexical.identifier);
if (!match) throw new Error('illegal identifier ' + token.args);
this.variable = match[0];
},
render: function render(scope, hash) {
var v = scope.get(this.variable);
if (typeof v !== 'number') v = 0;
scope.set(this.variable, v + 1);
}
});
};
},{"..":2}],34:[function(require,module,exports){
"use strict";
module.exports = function (engine) {
require("./assign.js")(engine);
require("./capture.js")(engine);
require("./case.js")(engine);
require("./comment.js")(engine);
require("./cycle.js")(engine);
require("./decrement.js")(engine);
require("./for.js")(engine);
require("./if.js")(engine);
require("./include.js")(engine);
require("./increment.js")(engine);
require("./layout.js")(engine);
require("./raw.js")(engine);
require("./tablerow.js")(engine);
require("./unless.js")(engine);
};
},{"./assign.js":24,"./capture.js":25,"./case.js":26,"./comment.js":27,"./cycle.js":28,"./decrement.js":29,"./for.js":30,"./if.js":31,"./include.js":32,"./increment.js":33,"./layout.js":35,"./raw.js":36,"./tablerow.js":37,"./unless.js":38}],35:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var withRE = new RegExp('with\\s+(' + lexical.value.source + ')');
module.exports = function (liquid) {
liquid.registerTag('layout', {
parse: function parse(token, remainTokens) {
var match = lexical.value.exec(token.args);
if (!match) throw new Error('illegal token ' + token.raw);
this.layout = match[0];
this.tpls = liquid.parser.parse(remainTokens);
},
render: function render(scope, hash) {
var layout = Liquid.evalValue(this.layout, scope);
var html = '';
scope.push({});
// not sure if this first one is needed, since the results are ignored
return liquid.renderer.renderTemplates(this.tpls, scope).then(function (partial) {
html += partial;
return liquid.handleCache(layout);
}).then(function (templates) {
return liquid.renderer.renderTemplates(templates, scope);
}).then(function (partial) {
scope.pop();
return partial;
}).catch(function (e) {
e.file = layout;
throw e;
});
// var tpl = liquid.handleCache(layout);
//
// scope.push({});
// liquid.renderer.renderTemplates(this.tpls, scope); // what's the point of this line?
// var html = liquid.renderer.renderTemplates(tpl, scope);
// scope.pop();
// return html;
}
});
liquid.registerTag('block', {
parse: function parse(token, remainTokens) {
var _this = this;
var match = /\w+/.exec(token.args);
this.block = match ? match[0] : '';
this.tpls = [];
var p,
stream = liquid.parser.parseStream(remainTokens).on('tag:endblock', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return _this.tpls.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + token.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var _this2 = this;
var html = scope.get('_liquid.blocks.' + this.block);
var promise = Promise.resolve('');
if (html === undefined) {
promise = liquid.renderer.renderTemplates(this.tpls, scope).then(function (partial) {
scope.set('_liquid.blocks.' + _this2.block, partial);
return partial;
});
} else {
scope.set('_liquid.blocks.' + this.block, html);
promise = Promise.resolve(html);
}
return promise;
// if(html === undefined){
// html = liquid.renderer.renderTemplates(this.tpls, scope);
// }
// scope.set(`_liquid.blocks.${this.block}`, html);
// return html;
}
});
};
},{"..":2,"any-promise":3}],36:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var re = new RegExp('(' + lexical.identifier.source + ')');
module.exports = function (liquid) {
liquid.registerTag('raw', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
this.tokens = [];
var stream = liquid.parser.parseStream(remainTokens);
stream.on('token', function (token) {
if (token.name === 'endraw') stream.stop();else _this.tokens.push(token);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var tokens = this.tokens.map(function (token) {
return token.raw;
}).join('');
return Promise.resolve(tokens);
}
});
};
},{"..":2,"any-promise":3}],37:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var Promise = require('any-promise');
var lexical = Liquid.lexical;
var re = new RegExp('^(' + lexical.identifier.source + ')\\s+in\\s+' + ('(' + lexical.value.source + ')') + ('(?:\\s+' + lexical.hash.source + ')*$'));
module.exports = function (liquid) {
liquid.registerTag('tablerow', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
var match = re.exec(tagToken.args);
if (!match) throw new Error('illegal tag: ' + tagToken.raw);
this.variable = match[1];
this.collection = match[2];
this.templates = [];
var p,
stream = liquid.parser.parseStream(remainTokens).on('start', function (x) {
return p = _this.templates;
}).on('tag:endtablerow', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return p.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var _this2 = this;
var collection = Liquid.evalExp(this.collection, scope) || [];
var html = '<table>',
promiseChain = Promise.resolve(''); // create an empty promise to begin the chain
length = collection.length;
var offset = hash.offset || 0;
var limit = hash.limit === undefined ? collection.length : hash.limit;
var cols = hash.cols,
row,
col;
if (!cols) throw new Error('illegal cols: ' + cols);
// build array of arguments to pass to sequential promises...
collection = collection.slice(offset, offset + limit);
var contexts = [];
collection.some(function (item, i) {
var ctx = {};
ctx[_this2.variable] = item;
// We are just putting together an array of the arguments we will be passing to our sequential promises
contexts.push(ctx);
});
// This executes an array of promises sequentially for every argument in the contexts array - http://webcache.googleusercontent.com/search?q=cache:rNbMUn9TPtkJ:joost.vunderink.net/blog/2014/12/15/processing-an-array-of-promises-sequentially-in-node-js/+&cd=5&hl=en&ct=clnk&gl=us
// It's fundamentally equivalent to the following...
// emptyPromise.then(renderTemplates(args0).then(renderTemplates(args1).then(renderTemplates(args2)...
var lastPromise = contexts.reduce(function (promise, context, currentIndex) {
return promise.then(function (partial) {
row = Math.floor(currentIndex / cols) + 1;
col = currentIndex % cols + 1;
if (col === 1) {
if (row !== 1) {
html += '</tr>';
}
html += '<tr class="row' + row + '">';
}
//ctx[this.variable] = context;
return html += '<td class="col' + col + '">';
}).then(function (partial) {
scope.push(context);
return liquid.renderer.renderTemplates(_this2.templates, scope);
}).then(function (partial) {
scope.pop(context);
html += partial;
return html += '</td>';
});
}, Promise.resolve('')); // start the reduce chain with a resolved Promise. After first run, the "promise" argument
// in our reduce callback will be the returned promise from our "then" above. In this
// case, the promise returned from liquid.renderer.renderTemplates.
return lastPromise.then(function () {
if (row > 0) {
html += '</tr>';
}
html += '</table>';
return html;
}).catch(function (error) {
throw error;
});
}
});
};
},{"..":2,"any-promise":3}],38:[function(require,module,exports){
'use strict';
var Liquid = require('..');
var lexical = Liquid.lexical;
module.exports = function (liquid) {
liquid.registerTag('unless', {
parse: function parse(tagToken, remainTokens) {
var _this = this;
this.templates = [];
this.elseTemplates = [];
var p,
stream = liquid.parser.parseStream(remainTokens).on('start', function (x) {
p = _this.templates;
_this.cond = tagToken.args;
}).on('tag:else', function (token) {
return p = _this.elseTemplates;
}).on('tag:endunless', function (token) {
return stream.stop();
}).on('template', function (tpl) {
return p.push(tpl);
}).on('end', function (x) {
throw new Error('tag ' + tagToken.raw + ' not closed');
});
stream.start();
},
render: function render(scope, hash) {
var cond = Liquid.evalExp(this.cond, scope);
return Liquid.isFalsy(cond) ? liquid.renderer.renderTemplates(this.templates, scope) : liquid.renderer.renderTemplates(this.elseTemplates, scope);
}
});
};
},{"..":2}]},{},[2])(2)
});