Skip to content

Instantly share code, notes, and snippets.

@damoclark
Last active August 4, 2020 01:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damoclark/bcd19ac1b16ece3ee84147ae1ee46fe3 to your computer and use it in GitHub Desktop.
Save damoclark/bcd19ac1b16ece3ee84147ae1ee46fe3 to your computer and use it in GitHub Desktop.
Bedifferent Renumbering
This file has been truncated, but you can view the full file.
// ==UserScript==
// @name bedifferent-editing-toolkit
// @description Editing toolkit for designers working on the CQUni BeDifferent Moodle Platform
// @version 1.0.3
// @grant none
// @noframes
// @include https://bedifferent.cqu.edu.au/*
// @include https://u-bedifferent.catalyst-au.net/*
// @include https://staging-bedifferent.catalyst-au.net/*
// ==/UserScript==
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports = "span.diff span:last-of-type {background-color: yellow;}\nspan.diff ins {background-color: aqua;}\nspan.diff del {background-color: #f3908a;}\n.diff-hidden {display: none;}";
},{}],2:[function(require,module,exports){
(function (global){
'use strict';
var objectAssign = require('object-assign');
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
// original notice:
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
function compare(a, b) {
if (a === b) {
return 0;
}
var x = a.length;
var y = b.length;
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i];
y = b[i];
break;
}
}
if (x < y) {
return -1;
}
if (y < x) {
return 1;
}
return 0;
}
function isBuffer(b) {
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
return global.Buffer.isBuffer(b);
}
return !!(b != null && b._isBuffer);
}
// based on node assert, original notice:
// NB: The URL to the CommonJS spec is kept just for tradition.
// node-assert has evolved a lot since then, both in API and behavior.
// 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.
var util = require('util/');
var hasOwn = Object.prototype.hasOwnProperty;
var pSlice = Array.prototype.slice;
var functionsHaveNames = (function () {
return function foo() {}.name === 'foo';
}());
function pToString (obj) {
return Object.prototype.toString.call(obj);
}
function isView(arrbuf) {
if (isBuffer(arrbuf)) {
return false;
}
if (typeof global.ArrayBuffer !== 'function') {
return false;
}
if (typeof ArrayBuffer.isView === 'function') {
return ArrayBuffer.isView(arrbuf);
}
if (!arrbuf) {
return false;
}
if (arrbuf instanceof DataView) {
return true;
}
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
return true;
}
return false;
}
// 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 })
var regex = /\s*function\s+([^\(\s]*)\s*/;
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
function getName(func) {
if (!util.isFunction(func)) {
return;
}
if (functionsHaveNames) {
return func.name;
}
var str = func.toString();
var match = str.match(regex);
return match && match[1];
}
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 = getName(stackStartFunction);
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 truncate(s, n) {
if (typeof s === 'string') {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function inspect(something) {
if (functionsHaveNames || !util.isFunction(something)) {
return util.inspect(something);
}
var rawname = getName(something);
var name = rawname ? ': ' + rawname : '';
return '[Function' + name + ']';
}
function getMessage(self) {
return truncate(inspect(self.actual), 128) + ' ' +
self.operator + ' ' +
truncate(inspect(self.expected), 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, false)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
}
};
function _deepEqual(actual, expected, strict, memos) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (isBuffer(actual) && isBuffer(expected)) {
return compare(actual, expected) === 0;
// 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 ((actual === null || typeof actual !== 'object') &&
(expected === null || typeof expected !== 'object')) {
return strict ? actual === expected : actual == expected;
// If both values are instances of typed arrays, wrap their underlying
// ArrayBuffers in a Buffer each to increase performance
// This optimization requires the arrays to have the same type as checked by
// Object.prototype.toString (aka pToString). Never perform binary
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
// bit patterns are not identical.
} else if (isView(actual) && isView(expected) &&
pToString(actual) === pToString(expected) &&
!(actual instanceof Float32Array ||
actual instanceof Float64Array)) {
return compare(new Uint8Array(actual.buffer),
new Uint8Array(expected.buffer)) === 0;
// 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 if (isBuffer(actual) !== isBuffer(expected)) {
return false;
} else {
memos = memos || {actual: [], expected: []};
var actualIndex = memos.actual.indexOf(actual);
if (actualIndex !== -1) {
if (actualIndex === memos.expected.indexOf(expected)) {
return true;
}
}
memos.actual.push(actual);
memos.expected.push(expected);
return objEquiv(actual, expected, strict, memos);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b, strict, actualVisitedObjects) {
if (a === null || a === undefined || b === null || b === undefined)
return false;
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b))
return a === b;
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
return false;
var aIsArgs = isArguments(a);
var bIsArgs = isArguments(b);
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
return false;
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b, strict);
}
var ka = objectKeys(a);
var kb = objectKeys(b);
var 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], strict, actualVisitedObjects))
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, false)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
assert.notDeepStrictEqual = notDeepStrictEqual;
function notDeepStrictEqual(actual, expected, message) {
if (_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
}
}
// 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);
}
try {
if (actual instanceof expected) {
return true;
}
} catch (e) {
// Ignore. The instanceof check doesn't work for arrow functions.
}
if (Error.isPrototypeOf(expected)) {
return false;
}
return expected.call({}, actual) === true;
}
function _tryBlock(block) {
var error;
try {
block();
} catch (e) {
error = e;
}
return error;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (typeof block !== 'function') {
throw new TypeError('"block" argument must be a function');
}
if (typeof expected === 'string') {
message = expected;
expected = null;
}
actual = _tryBlock(block);
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
var userProvidedMessage = typeof message === 'string';
var isUnwantedException = !shouldThrow && util.isError(actual);
var isUnexpectedException = !shouldThrow && actual && !expected;
if ((isUnwantedException &&
userProvidedMessage &&
expectedException(actual, expected)) ||
isUnexpectedException) {
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(true, block, error, message);
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws(false, block, error, message);
};
assert.ifError = function(err) { if (err) throw err; };
// Expose a strict only variant of assert
function strict(value, message) {
if (!value) fail(value, true, message, '==', strict);
}
assert.strict = objectAssign(strict, assert, {
equal: assert.strictEqual,
deepEqual: assert.deepStrictEqual,
notEqual: assert.notStrictEqual,
notDeepEqual: assert.notDeepStrictEqual
});
assert.strict.strict = assert.strict;
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"object-assign":64,"util/":5}],3:[function(require,module,exports){
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.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],4:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],5:[function(require,module,exports){
(function (process,global){
// 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 === '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 === '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 === '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":4,"_process":65,"inherits":3}],6:[function(require,module,exports){
'use strict'
exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray
var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i]
revLookup[code.charCodeAt(i)] = i
}
// Support decoding URL-safe base64 strings, as Node.js does.
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
function getLens (b64) {
var len = b64.length
if (len % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// Trim off extra bytes after placeholder bytes are found
// See: https://github.com/beatgammit/base64-js/issues/42
var validLen = b64.indexOf('=')
if (validLen === -1) validLen = len
var placeHoldersLen = validLen === len
? 0
: 4 - (validLen % 4)
return [validLen, placeHoldersLen]
}
// base64 is 4/3 + up to two characters of the original data
function byteLength (b64) {
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function _byteLength (b64, validLen, placeHoldersLen) {
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function toByteArray (b64) {
var tmp
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
var curByte = 0
// if there are placeholders, only get up to the last complete 4 chars
var len = placeHoldersLen > 0
? validLen - 4
: validLen
var i
for (i = 0; i < len; i += 4) {
tmp =
(revLookup[b64.charCodeAt(i)] << 18) |
(revLookup[b64.charCodeAt(i + 1)] << 12) |
(revLookup[b64.charCodeAt(i + 2)] << 6) |
revLookup[b64.charCodeAt(i + 3)]
arr[curByte++] = (tmp >> 16) & 0xFF
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 2) {
tmp =
(revLookup[b64.charCodeAt(i)] << 2) |
(revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 1) {
tmp =
(revLookup[b64.charCodeAt(i)] << 10) |
(revLookup[b64.charCodeAt(i + 1)] << 4) |
(revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
return arr
}
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] +
lookup[num >> 12 & 0x3F] +
lookup[num >> 6 & 0x3F] +
lookup[num & 0x3F]
}
function encodeChunk (uint8, start, end) {
var tmp
var output = []
for (var i = start; i < end; i += 3) {
tmp =
((uint8[i] << 16) & 0xFF0000) +
((uint8[i + 1] << 8) & 0xFF00) +
(uint8[i + 2] & 0xFF)
output.push(tripletToBase64(tmp))
}
return output.join('')
}
function fromByteArray (uint8) {
var tmp
var len = uint8.length
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
var parts = []
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(
uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
))
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1]
parts.push(
lookup[tmp >> 2] +
lookup[(tmp << 4) & 0x3F] +
'=='
)
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
parts.push(
lookup[tmp >> 10] +
lookup[(tmp >> 4) & 0x3F] +
lookup[(tmp << 2) & 0x3F] +
'='
)
}
return parts.join('')
}
},{}],7:[function(require,module,exports){
var uuid = 0;
function stableSort(arr, compare) {
var wrapper = arr.map(function (item, idx) {
return { item: item, idx: idx };
});
wrapper.sort(function (a, b) {
return compare(a.item, b.item) || (a.idx - b.idx);
});
return wrapper.map(function (w) { return w.item });
}
function MemoryStore() {
this._queue = []; // Array of taskIds
this._tasks = {}; // Map of taskId => task
this._priorities = {}; // Map of taskId => priority
this._running = {}; // Map of lockId => taskIds
}
MemoryStore.prototype.connect = function (cb) {
cb(null, this._queue.length);
}
MemoryStore.prototype.getTask = function (taskId, cb) {
return cb(null, this._tasks[taskId]);
}
MemoryStore.prototype.deleteTask = function (taskId, cb) {
var self = this;
var hadTask = self._tasks[taskId];
delete self._tasks[taskId];
delete self._priorities[taskId];
if (hadTask) {
self._queue.splice(self._queue.indexOf(taskId), 1);
}
cb();
}
MemoryStore.prototype.putTask = function (taskId, task, priority, cb) {
var self = this;
var hadTask = self._tasks[taskId];
self._tasks[taskId] = task;
if (!hadTask) {
self._queue.push(taskId);
}
if (priority !== undefined) {
self._priorities[taskId] = priority;
self._queue = stableSort(self._queue, function (a, b) {
if (self._priorities[a] < self._priorities[b]) return 1;
if (self._priorities[a] > self._priorities[b]) return -1;
return 0;
})
}
cb();
}
MemoryStore.prototype.takeFirstN = function (n, cb) {
var self = this;
var lockId = uuid++;;
var taskIds = self._queue.splice(0, n);
var tasks = {};
taskIds.forEach(function (taskId) {
tasks[taskId] = self._tasks[taskId];
delete self._tasks[taskId];
})
if (taskIds.length > 0) {
self._running[lockId] = tasks;
}
cb(null, lockId);
}
MemoryStore.prototype.takeLastN = function (n, cb) {
var self = this;
var lockId = uuid++;
var taskIds = self._queue.splice(-n).reverse();
var tasks = {};
taskIds.forEach(function (taskId) {
tasks[taskId] = self._tasks[taskId];
delete self._tasks[taskId];
})
if (taskIds.length > 0) {
self._running[lockId] = tasks;
}
cb(null, lockId);
}
MemoryStore.prototype.getLock = function (lockId, cb) {
var self = this;
cb(null, self._running[lockId]);
}
MemoryStore.prototype.getRunningTasks = function (cb) {
var self = this;
cb(null, self._running);
}
MemoryStore.prototype.releaseLock = function (lockId, cb) {
var self = this;
delete self._running[lockId];
cb();
}
module.exports = MemoryStore;
},{}],8:[function(require,module,exports){
(function (setImmediate){
var uuid = require('uuid');
var util = require('util');
var EE = require('events').EventEmitter;
var Ticket = require('./ticket');
var Worker = require('./worker');
var Tickets = require('./tickets');
function Queue(process, opts) {
var self = this;
opts = opts || {};
if (typeof process === 'object') {
opts = process || {};
}
if (typeof process === 'function') {
opts.process = process;
}
if (!opts.process) {
throw new Error("Queue has no process function.");
}
opts = opts || {};
self.process = opts.process || function (task, cb) { cb(null, {}) };
self.filter = opts.filter || function (input, cb) { cb(null, input) };
self.merge = opts.merge || function (oldTask, newTask, cb) { cb(null, newTask) };
self.precondition = opts.precondition || function (cb) { cb(null, true) };
self.setImmediate = opts.setImmediate || setImmediate;
self.id = opts.id || 'id';
self.priority = opts.priority || null;
self.cancelIfRunning = (opts.cancelIfRunning === undefined ? false : !!opts.cancelIfRunning);
self.autoResume = (opts.autoResume === undefined ? true : !!opts.autoResume);
self.failTaskOnProcessException = (opts.failTaskOnProcessException === undefined ? true : !!opts.failTaskOnProcessException);
self.filo = opts.filo || false;
self.batchSize = opts.batchSize || 1;
self.batchDelay = opts.batchDelay || 0;
self.batchDelayTimeout = opts.batchDelayTimeout || Infinity;
self.afterProcessDelay = opts.afterProcessDelay || 0;
self.concurrent = opts.concurrent || 1;
self.maxTimeout = opts.maxTimeout || Infinity;
self.maxRetries = opts.maxRetries || 0;
self.retryDelay = opts.retryDelay || 0;
self.storeMaxRetries = opts.storeMaxRetries || Infinity;
self.storeRetryTimeout = opts.storeRetryTimeout || 1000;
self.preconditionRetryTimeout = opts.preconditionRetryTimeout || 1000;
// Statuses
self._queuedPeak = 0;
self._queuedTime = {};
self._processedTotalElapsed = 0;
self._processedAverage = 0;
self._processedTotal = 0;
self._failedTotal = 0;
self.length = 0;
self._stopped = false;
self._saturated = false;
self._preconditionRetryTimeoutId = null;
self._batchTimeoutId = null;
self._batchDelayTimeoutId = null;
self._connected = false;
self._storeRetries = 0;
// Locks
self._hasMore = false;
self._isWriting = false;
self._writeQueue = [];
self._writing = {};
self._tasksWaitingForConnect = [];
self._calledDrain = true;
self._calledEmpty = true;
self._fetching = 0;
self._running = 0; // Active running tasks
self._retries = {}; // Map of taskId => retries
self._workers = {}; // Map of taskId => active job
self._tickets = {}; // Map of taskId => tickets
// Initialize Storage
self.use(opts.store || 'memory');
if (!self._store) {
throw new Error('Queue cannot continue without a valid store.')
}
}
util.inherits(Queue, EE);
Queue.prototype.destroy = function (cb) {
cb = cb || function () {};
var self = this;
// Statuses
self._hasMore = false;
self._isWriting = false;
self._writeQueue = [];
self._writing = {};
self._tasksWaitingForConnect = [];
// Clear internals
self._tickets = {};
self._workers = {};
self._fetching = 0;
self._running = {};
self._retries = {};
self._calledEmpty = true;
self._calledDrain = true;
self._connected = false;
self.pause();
if (typeof self._store.close === 'function') {
self._store.close(cb);
} else {
cb();
}
}
Queue.prototype.resetStats = function () {
this._queuedPeak = 0;
this._processedTotalElapsed = 0;
this._processedAverage = 0;
this._processedTotal = 0;
this._failedTotal = 0;
}
Queue.prototype.getStats = function () {
var successRate = this._processedTotal === 0 ? 0 : (1 - (this._failedTotal / this._processedTotal));
return {
successRate: successRate,
peak: this._queuedPeak,
average: this._processedAverage,
total: this._processedTotal
}
}
Queue.prototype.use = function (store, opts) {
var self = this;
var loadStore = function (store) {
var Store;
try {
Store = require('better-queue-' + store);
} catch (e) {
throw new Error('Attempting to require better-queue-' + store + ', but failed.\nPlease ensure you have this store installed via npm install --save better-queue-' + store)
}
return Store;
}
if (typeof store === 'string') {
var Store = loadStore(store);
self._store = new Store(opts);
} else if (typeof store === 'object' && typeof store.type === 'string') {
var Store = loadStore(store.type);
self._store = new Store(store);
} else if (typeof store === 'object' && store.putTask && store.getTask && ((self.filo && store.takeLastN) || (!self.filo && store.takeFirstN))) {
self._store = store;
} else {
throw new Error('unknown_store');
}
self._connected = false;
self._tasksWaitingForConnect = [];
self._connectToStore();
}
Queue.prototype._connectToStore = function () {
var self = this;
if (self._connected) return;
if (self._storeRetries >= self.storeMaxRetries) {
return self.emit('error', new Error('failed_connect_to_store'));
}
self._storeRetries++;
self._store.connect(function (err, len) {
if (err) return setTimeout(function () {
self._connectToStore();
}, self.storeRetryTimeout);
if (len === undefined || len === null) throw new Error("store_not_returning_length");
self.length = parseInt(len);
if (isNaN(self.length)) throw new Error("length_is_not_a_number");
if (self.length) self._calledDrain = false;
self._connected = true;
self._storeRetries = 0;
self._store.getRunningTasks(function (err, running) {
if (!self._stopped && self.autoResume) {
Object.keys(running).forEach(function (lockId) {
self._running++;
self._startBatch(running[lockId], {}, lockId);
})
self.resume();
}
for (var i = 0; i < self._tasksWaitingForConnect.length; i++) {
self.push(self._tasksWaitingForConnect[i].input, self._tasksWaitingForConnect[i].ticket);
}
})
})
}
Queue.prototype.resume = function () {
var self = this;
self._stopped = false;
self._getWorkers().forEach(function (worker) {
if (typeof worker.resume === 'function') {
worker.resume();
}
})
setTimeout(function () {
self._processNextAfterTimeout();
}, 0)
}
Queue.prototype.pause = function () {
this._stopped = true;
this._getWorkers().forEach(function (worker) {
if (typeof worker.pause === 'function') {
worker.pause();
}
})
}
Queue.prototype.cancel = function (taskId, cb) {
cb = cb || function(){};
var self = this;
var worker = self._workers[taskId];
if (worker) {
worker.cancel();
}
self._store.deleteTask(taskId, cb);
}
Queue.prototype.push = function (input, cb) {
var self = this;
var ticket = new Ticket();
if (cb instanceof Ticket) {
ticket = cb;
} else if (cb) {
ticket
.on('finish', function (result) { cb(null, result) })
.on('failed', function (err) { cb(err) })
}
if (!self._connected) {
self._tasksWaitingForConnect.push({ input: input, ticket: ticket });
return ticket;
}
self.filter(input, function (err, task) {
if (err || task === undefined || task === false || task === null) {
return ticket.failed('input_rejected');
}
var acceptTask = function (taskId) {
setTimeout(function () {
self._queueTask(taskId, task, ticket);
}, 0)
}
if (typeof self.id === 'function') {
self.id(task, function (err, id) {
if (err) return ticket.failed('id_error');
acceptTask(id);
})
} else if (typeof self.id === 'string' && typeof task === 'object') {
acceptTask(task[self.id])
} else {
acceptTask();
}
})
return ticket;
}
Queue.prototype._getWorkers = function () {
var self = this;
var workers = [];
Object.keys(self._workers).forEach(function (taskId) {
var worker = self._workers[taskId];
if (worker && workers.indexOf(worker) === -1) {
workers.push(worker);
}
})
return workers;
}
Queue.prototype._writeNextTask = function () {
var self = this;
if (self._isWriting) return;
if (!self._writeQueue.length) return;
self._isWriting = true;
var taskId = self._writeQueue.shift();
var finishedWrite = function () {
self._isWriting = false;
self.setImmediate(function () {
self._writeNextTask();
})
}
if (!self._writing[taskId]) {
delete self._writing[taskId];
return finishedWrite();
}
var task = self._writing[taskId].task;
var priority = self._writing[taskId].priority;
var isNew = self._writing[taskId].isNew;
var writeId = self._writing[taskId].id;
var tickets = self._writing[taskId].tickets;
self._store.putTask(taskId, task, priority, function (err) {
// Check if task has changed since put
if (self._writing[taskId] && self._writing[taskId].id !== writeId) {
self._writeQueue.unshift(taskId);
return finishedWrite();
}
delete self._writing[taskId];
// If something else has written to taskId, then wait.
if (err) {
tickets.failed('failed_to_put_task');
return finishedWrite();
}
// Task is in the queue -- update stats
if (isNew) {
self.length++;
if (self._queuedPeak < self.length) {
self._queuedPeak = self.length;
}
self._queuedTime[taskId] = new Date().getTime();
}
// Notify the ticket
if (self._tickets[taskId]) {
self._tickets[taskId].push(tickets);
} else {
self._tickets[taskId] = tickets;
}
self.emit('task_queued', taskId, task);
tickets.queued();
// If it's a new task, make sure to call drain after.
if (isNew) {
self._calledDrain = false;
self._calledEmpty = false;
}
// If already fetching, mark that there are additions to the queue
if (self._fetching > 0) {
self._hasMore = true;
}
// Clear batchDelayTimeout
if (self.batchDelayTimeout < Infinity) {
if (self._batchDelayTimeoutId) clearTimeout(self._batchDelayTimeoutId)
self._batchDelayTimeoutId = setTimeout(function () {
self._batchDelayTimeoutId = null;
if (self._batchTimeoutId) clearTimeout(self._batchTimeoutId);
self._batchTimeoutId = null;
self._processNextIfAllowed();
}, self.batchDelayTimeout)
}
// Finish writing
finishedWrite();
self._processNextAfterTimeout();
})
}
Queue.prototype._queueTask = function (taskId, newTask, ticket) {
var self = this;
var emptyTicket = new Ticket();
ticket = ticket || emptyTicket;
var isUUID = false;
if (!taskId) {
taskId = uuid.v4();
isUUID = true;
}
var priority;
var oldTask = null;
var isNew = true;
var putTask = function () {
if (!self._connected) return;
// Save ticket
var tickets = (self._writing[taskId] && self._writing[taskId].tickets) || new Tickets();
if (ticket !== emptyTicket) {
tickets.push(ticket);
}
// Add to queue
var alreadyQueued = !!self._writing[taskId];
self._writing[taskId] = {
id: uuid.v4(),
isNew: isNew,
task: newTask,
priority: priority,
tickets: tickets
};
if (!alreadyQueued) {
self._writeQueue.push(taskId);
}
self._writeNextTask();
}
var updateTask = function () {
ticket.accept();
self.emit('task_accepted', taskId, newTask);
if (!self.priority) return putTask();
self.priority(newTask, function (err, p) {
if (err) return ticket.failed('failed_to_prioritize');
priority = p;
putTask();
})
}
var mergeTask = function () {
if (!oldTask) return updateTask();
self.merge(oldTask, newTask, function (err, mergedTask) {
if (err) return ticket.failed('failed_task_merge');
if (mergedTask === undefined) return;
newTask = mergedTask;
updateTask();
})
}
if (isUUID) {
return updateTask();
}
var worker = self._workers[taskId];
if (self.cancelIfRunning && worker) {
worker.cancel();
}
// Check if task is writing
if (self._writing[taskId]) {
oldTask = self._writing[taskId].task;
return mergeTask();
}
// Check store for task
self._store.getTask(taskId, function (err, savedTask) {
if (err) return ticket.failed('failed_to_get');
// Check if it's already in the store
if (savedTask !== undefined) {
isNew = false;
}
// Check if task is writing
if (self._writing[taskId]) {
oldTask = self._writing[taskId].task;
return mergeTask();
}
// No task before
if (savedTask === undefined) {
return updateTask();
}
oldTask = savedTask;
mergeTask();
})
}
Queue.prototype._emptied = function () {
if (this._calledEmpty) return;
this._calledEmpty = true;
this.emit('empty');
}
Queue.prototype._drained = function () {
if (this._calledDrain) return;
this._calledDrain = true;
this.emit('drain');
}
Queue.prototype._getNextBatch = function (cb) {
this._store[this.filo ? 'takeLastN' : 'takeFirstN'](this.batchSize, cb)
}
Queue.prototype._processNextAfterTimeout = function () {
var self = this;
if (self.length >= self.batchSize) {
if (self._batchTimeoutId) {
clearTimeout(self._batchTimeoutId);
self._batchTimeoutId = null;
}
self.setImmediate(function () {
self._processNextIfAllowed();
})
} else if (!self._batchTimeoutId && self.batchDelay < Infinity) {
self._batchTimeoutId = setTimeout(function () {
self._batchTimeoutId = null;
self._processNextIfAllowed();
}, self.batchDelay)
}
}
Queue.prototype._processNextIfAllowed = function () {
var self = this;
if (!self._connected) return;
if (self._stopped) return;
self._saturated = (self._running + self._fetching >= self.concurrent);
if (self._saturated) return;
if (!self.length) {
if (!self._hasMore) {
self._emptied();
if (!self._running) {
self._drained();
}
}
return;
}
self.precondition(function (err, pass) {
if (err || !pass) {
if (!self._preconditionRetryTimeoutId && self.preconditionRetryTimeout) {
self._preconditionRetryTimeoutId = setTimeout(function () {
self._preconditionRetryTimeoutId = null;
self._processNextIfAllowed();
}, self.preconditionRetryTimeout)
}
} else {
self._processNext();
}
})
}
Queue.prototype._processNext = function () {
var self = this;
// FIXME: There may still be things writing
self._hasMore = false;
self._fetching++;
self._getNextBatch(function (err, lockId) {
self._fetching--;
if (err || lockId === undefined) return;
self._store.getLock(lockId, function (err, batch) {
if (err || !batch) return;
var batchSize = Object.keys(batch).length;
var isEmpty = (batchSize === 0);
if (self.length < batchSize) {
self.length = batchSize;
}
if (!self._hasMore && isEmpty) {
self._emptied();
if (!self._running) {
self._drained();
}
return;
}
// The write queue wasn't empty on fetch, so we should fetch more.
if (self._hasMore && isEmpty) {
return self._processNextAfterTimeout()
}
var tickets = {};
Object.keys(batch).forEach(function (taskId) {
var ticket = self._tickets[taskId];
if (ticket) {
ticket.started();
tickets[taskId] = ticket;
delete self._tickets[taskId];
}
})
// Acquire lock on process
self._running++;
self._startBatch(batch, tickets, lockId);
if (self.concurrent - self._running > 1) {
// Continue processing until saturated
self._processNextIfAllowed();
}
});
});
}
Queue.prototype._startBatch = function (batch, tickets, lockId) {
var self = this;
var taskIds = Object.keys(batch);
var timeout = null;
var worker = new Worker({
fn: self.process,
batch: batch,
single: (self.batchSize === 1),
failTaskOnProcessException: self.failTaskOnProcessException
})
var updateStatsForEndedTask = function (taskId) {
self._processedTotal++;
var stats = {};
if (!self._queuedTime[taskId]) return stats;
var elapsed = (new Date().getTime() - self._queuedTime[taskId]);
delete self._queuedTime[taskId];
if (elapsed > 0) {
stats.elapsed = elapsed;
self._processedTotalElapsed += elapsed;
self._processedAverage = self._processedTotalElapsed/self._processedTotal;
}
return stats;
}
if (self.maxTimeout < Infinity) {
timeout = setTimeout(function () {
worker.failedBatch('task_timeout');
}, self.maxTimeout);
}
worker.on('task_failed', function (id, msg) {
var taskId = taskIds[id];
self._retries[taskId] = self._retries[taskId] || 0;
self._retries[taskId]++;
if (worker.cancelled || self._retries[taskId] >= self.maxRetries) {
var stats = updateStatsForEndedTask(taskId);
if (tickets[taskId]) {
// Mark as a failure
tickets[taskId].failed(msg);
delete tickets[taskId];
}
self._failedTotal++;
self.emit('task_failed', taskId, msg, stats);
} else {
if (self.retryDelay) {
// Pop back onto queue and retry
setTimeout(function () {
self.emit('task_retry', taskId, self._retries[taskId]);
self._queueTask(taskId, batch[taskId], tickets[taskId]);
}, self.retryDelay)
} else {
self.setImmediate(function () {
self.emit('task_retry', taskId, self._retries[taskId]);
self._queueTask(taskId, batch[taskId], tickets[taskId]);
});
}
}
})
worker.on('task_finish', function (id, result) {
var taskId = taskIds[id];
var stats = updateStatsForEndedTask(taskId);
if (tickets[taskId]) {
tickets[taskId].finish(result);
delete tickets[taskId];
}
self.emit('task_finish', taskId, result, stats);
})
worker.on('task_progress', function (id, progress) {
var taskId = taskIds[id];
if (tickets[taskId]) {
tickets[taskId].progress(progress);
delete tickets[taskId];
}
self.emit('task_progress', taskId, progress);
})
worker.on('progress', function (progress) {
self.emit('batch_progress', progress);
})
worker.on('finish', function (result) {
self.emit('batch_finish', result);
})
worker.on('failed', function (err) {
self.emit('batch_failed', err);
})
worker.on('end', function () {
self.length -= Object.keys(batch).length;
if (timeout) {
clearTimeout(timeout);
}
var finishAndGetNext = function () {
if (!self._connected) return;
self._store.releaseLock(lockId, function (err) {
if (err) {
// If we cannot release the lock then retry
return setTimeout(function () {
finishAndGetNext();
}, 1)
}
self._running--;
taskIds.forEach(function (taskId) {
if (self._workers[taskId] && !self._workers[taskId].active) {
delete self._workers[taskId];
}
});
self._processNextAfterTimeout();
})
}
if (self.afterProcessDelay) {
setTimeout(function () {
finishAndGetNext()
}, self.afterProcessDelay);
} else {
self.setImmediate(function () {
finishAndGetNext()
})
}
})
taskIds.forEach(function (taskId) {
self._workers[taskId] = worker;
});
try {
worker.start();
taskIds.forEach(function (taskId) {
self.emit('task_started', taskId, batch[taskId])
});
} catch (e) {
self.emit('error', e);
}
}
module.exports = Queue;
}).call(this,require("timers").setImmediate)
},{"./ticket":9,"./tickets":10,"./worker":11,"events":15,"timers":73,"util":75,"uuid":76}],9:[function(require,module,exports){
var util = require('util');
var EE = require('events').EventEmitter;
var ETA = require('node-eta');
function Ticket(opts) {
this.isAccepted = false;
this.isQueued = false;
this.isStarted = false;
this.isFailed = false;
this.isFinished = false;
this.result = null;
this.status = 'created';
this.eta = new ETA();
}
util.inherits(Ticket, EE);
Ticket.prototype.accept = function () {
this.status = 'accepted';
this.isAccepted = true;
this.emit('accepted');
}
Ticket.prototype.queued = function () {
this.status = 'queued';
this.isQueued = true;
this.emit('queued');
}
Ticket.prototype.unqueued = function () {
this.status = 'accepted';
this.isQueued = false;
this.emit('unqueued');
}
Ticket.prototype.started = function () {
this.eta.count = 1;
this.eta.start();
this.isStarted = true;
this.status = 'in-progress';
this.emit('started');
}
Ticket.prototype.failed = function (msg) {
this.isFailed = true;
this.isFinished = true;
this.status = 'failed';
this.emit('failed', msg);
}
Ticket.prototype.finish = function (result) {
this.eta.done = this.eta.count;
this.isFinished = true;
this.status = 'finished';
this.result = result;
this.emit('finish', this.result);
}
Ticket.prototype.stopped = function () {
this.eta = new ETA();
this.isFinished = false;
this.isStarted = false;
this.status = 'queued';
this.result = null;
this.emit('stopped');
}
Ticket.prototype.progress = function (progress) {
this.eta.done = progress.complete;
this.eta.count = progress.total;
this.emit('progress', {
complete: this.eta.done,
total: this.eta.count,
pct: (this.eta.done/this.eta.count)*100,
eta: this.eta.format('{{etah}}'),
message: progress.message
});
}
module.exports = Ticket;
},{"events":15,"node-eta":63,"util":75}],10:[function(require,module,exports){
var Ticket = require('./ticket');
function Tickets() {
this.tickets = [];
}
Tickets.prototype._apply = function (fn, args) {
this.tickets.forEach(function (ticket) {
ticket[fn].apply(ticket, args);
})
}
Tickets.prototype.push = function (ticket) {
var self = this;
if (ticket instanceof Tickets) {
return ticket.tickets.forEach(function (ticket) {
self.push(ticket)
})
}
if (ticket instanceof Ticket) {
if (self.tickets.indexOf(ticket) === -1) {
self.tickets.push(ticket);
}
}
}
Object.keys(Ticket.prototype).forEach(function (method) {
Tickets.prototype[method] = function () {
this._apply(method, arguments);
}
})
module.exports = Tickets;
},{"./ticket":9}],11:[function(require,module,exports){
var util = require('util');
var EE = require('events').EventEmitter;
var ETA = require('node-eta');
function Worker(opts) {
this.fn = opts.fn;
this.batch = opts.batch;
this.single = opts.single;
this.active = false;
this.cancelled = false;
this.failTaskOnProcessException = opts.failTaskOnProcessException;
}
util.inherits(Worker, EE);
Worker.prototype.setup = function () {
var self = this;
// Internal
self._taskIds = Object.keys(self.batch);
self._process = {};
self._waiting = {};
self._eta = new ETA();
// Task counts
self.counts = {
finished: 0,
failed: 0,
completed: 0,
total: self._taskIds.length,
};
// Progress
self.status = 'ready';
self.progress = {
tasks: {},
complete: 0,
total: self._taskIds.length,
eta: '',
};
// Setup
self._taskIds.forEach(function (taskId, id) {
self._waiting[id] = true;
self.progress.tasks[id] = {
pct: 0,
complete: 0,
total: 1,
}
})
}
Worker.prototype.start = function () {
var self = this;
if (self.active) return;
self.setup();
self._eta.count = self.progress.total;
self._eta.start();
self.active = true;
self.status = 'in-progress';
var tasks = self._taskIds.map(function (taskId) { return self.batch[taskId] });
if (self.single) {
tasks = tasks[0]
}
try {
self._process = self.fn.call(self, tasks, function (err, result) {
if (!self.active) return;
if (err) {
self.failedBatch(err);
} else {
self.finishBatch(result);
}
})
} catch (err) {
if (self.failTaskOnProcessException) {
self.failedBatch(err);
} else {
throw new Error(err);
}
}
self._process = self._process || {};
}
Worker.prototype.end = function () {
if (!this.active) return;
this.status = 'finished';
this.active = false;
this.emit('end');
}
Worker.prototype.resume = function () {
if (typeof this._process.resume === 'function') {
this._process.resume();
}
this.status = 'in-progress';
}
Worker.prototype.pause = function () {
if (typeof this._process.pause === 'function') {
this._process.pause();
}
this.status = 'paused';
}
Worker.prototype.cancel = function () {
this.cancelled = true;
if (typeof this._process.cancel === 'function') {
this._process.cancel();
}
if (typeof this._process.abort === 'function') {
this._process.abort();
}
this.failedBatch('cancelled');
}
Worker.prototype.failedBatch = function (msg) {
var self = this;
if (!self.active) return;
Object.keys(self._waiting).forEach(function (id) {
if (!self._waiting[id]) return;
self.failedTask(id, msg);
})
self.emit('failed', msg);
self.end();
}
Worker.prototype.failedTask = function (id, msg) {
var self = this;
if (!self.active) return;
if (self._waiting[id]) {
self._waiting[id] = false;
self.counts.failed++;
self.counts.completed++;
self.emit('task_failed', id, msg);
}
}
Worker.prototype.finishBatch = function (result) {
var self = this;
if (!self.active) return;
Object.keys(self._waiting).forEach(function (id) {
if (!self._waiting[id]) return;
self.finishTask(id, result);
})
self.emit('finish', result);
self.end();
}
Worker.prototype.finishTask = function (id, result) {
var self = this;
if (!self.active) return;
if (self._waiting[id]) {
self._waiting[id] = false;
self.counts.finished++;
self.counts.completed++;
self.emit('task_finish', id, result);
}
}
Worker.prototype.progressBatch = function (complete, total, msg) {
var self = this;
if (!self.active) return;
Object.keys(self._waiting).forEach(function (id) {
if (!self._waiting[id]) return;
self.progressTask(id, complete, total, msg);
})
self.progress.complete = 0;
self._taskIds.forEach(function (taskId, id) {
self.progress.complete += self.progress.tasks[id].pct;
})
self._eta.done = self.progress.complete;
self.progress.eta = self._eta.format('{{etah}}')
self.progress.message = msg || '';
self.emit('progress', self.progress);
}
Worker.prototype.progressTask = function (id, complete, total, msg) {
var self = this;
if (!self.active) return;
if (self._waiting[id]) {
self.progress.tasks[id].complete = complete;
self.progress.tasks[id].total = self.progress.tasks[id].total || total;
self.progress.tasks[id].message = self.progress.tasks[id].message || msg;
self.progress.tasks[id].pct = Math.max(0, Math.min(1, complete/total));
self.emit('task_progress', id, self.progress.tasks[id]);
}
}
module.exports = Worker;
},{"events":15,"node-eta":63,"util":75}],12:[function(require,module,exports){
},{}],13:[function(require,module,exports){
(function (Buffer){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
'use strict'
var base64 = require('base64-js')
var ieee754 = require('ieee754')
var customInspectSymbol =
(typeof Symbol === 'function' && typeof Symbol.for === 'function')
? Symbol.for('nodejs.util.inspect.custom')
: null
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
var K_MAX_LENGTH = 0x7fffffff
exports.kMaxLength = K_MAX_LENGTH
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Print warning and recommend using `buffer` v4.x which has an Object
* implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* We report that the browser does not support typed arrays if the are not subclassable
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
* for __proto__ and has a buggy typed array implementation.
*/
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
typeof console.error === 'function') {
console.error(
'This browser lacks typed array (Uint8Array) support which is required by ' +
'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
)
}
function typedArraySupport () {
// Can typed array instances can be augmented?
try {
var arr = new Uint8Array(1)
var proto = { foo: function () { return 42 } }
Object.setPrototypeOf(proto, Uint8Array.prototype)
Object.setPrototypeOf(arr, proto)
return arr.foo() === 42
} catch (e) {
return false
}
}
Object.defineProperty(Buffer.prototype, 'parent', {
enumerable: true,
get: function () {
if (!Buffer.isBuffer(this)) return undefined
return this.buffer
}
})
Object.defineProperty(Buffer.prototype, 'offset', {
enumerable: true,
get: function () {
if (!Buffer.isBuffer(this)) return undefined
return this.byteOffset
}
})
function createBuffer (length) {
if (length > K_MAX_LENGTH) {
throw new RangeError('The value "' + length + '" is invalid for option "size"')
}
// Return an augmented `Uint8Array` instance
var buf = new Uint8Array(length)
Object.setPrototypeOf(buf, Buffer.prototype)
return buf
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer (arg, encodingOrOffset, length) {
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new TypeError(
'The "string" argument must be of type string. Received type number'
)
}
return allocUnsafe(arg)
}
return from(arg, encodingOrOffset, length)
}
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
if (typeof Symbol !== 'undefined' && Symbol.species != null &&
Buffer[Symbol.species] === Buffer) {
Object.defineProperty(Buffer, Symbol.species, {
value: null,
configurable: true,
enumerable: false,
writable: false
})
}
Buffer.poolSize = 8192 // not used by this implementation
function from (value, encodingOrOffset, length) {
if (typeof value === 'string') {
return fromString(value, encodingOrOffset)
}
if (ArrayBuffer.isView(value)) {
return fromArrayLike(value)
}
if (value == null) {
throw new TypeError(
'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
'or Array-like Object. Received type ' + (typeof value)
)
}
if (isInstance(value, ArrayBuffer) ||
(value && isInstance(value.buffer, ArrayBuffer))) {
return fromArrayBuffer(value, encodingOrOffset, length)
}
if (typeof SharedArrayBuffer !== 'undefined' &&
(isInstance(value, SharedArrayBuffer) ||
(value && isInstance(value.buffer, SharedArrayBuffer)))) {
return fromArrayBuffer(value, encodingOrOffset, length)
}
if (typeof value === 'number') {
throw new TypeError(
'The "value" argument must not be of type number. Received type number'
)
}
var valueOf = value.valueOf && value.valueOf()
if (valueOf != null && valueOf !== value) {
return Buffer.from(valueOf, encodingOrOffset, length)
}
var b = fromObject(value)
if (b) return b
if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&
typeof value[Symbol.toPrimitive] === 'function') {
return Buffer.from(
value[Symbol.toPrimitive]('string'), encodingOrOffset, length
)
}
throw new TypeError(
'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
'or Array-like Object. Received type ' + (typeof value)
)
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(value, encodingOrOffset, length)
}
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
// https://github.com/feross/buffer/pull/148
Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype)
Object.setPrototypeOf(Buffer, Uint8Array)
function assertSize (size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be of type number')
} else if (size < 0) {
throw new RangeError('The value "' + size + '" is invalid for option "size"')
}
}
function alloc (size, fill, encoding) {
assertSize(size)
if (size <= 0) {
return createBuffer(size)
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpretted as a start offset.
return typeof encoding === 'string'
? createBuffer(size).fill(fill, encoding)
: createBuffer(size).fill(fill)
}
return createBuffer(size)
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(size, fill, encoding)
}
function allocUnsafe (size) {
assertSize(size)
return createBuffer(size < 0 ? 0 : checked(size) | 0)
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(size)
}
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(size)
}
function fromString (string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
var length = byteLength(string, encoding) | 0
var buf = createBuffer(length)
var actual = buf.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
buf = buf.slice(0, actual)
}
return buf
}
function fromArrayLike (array) {
var length = array.length < 0 ? 0 : checked(array.length) | 0
var buf = createBuffer(length)
for (var i = 0; i < length; i += 1) {
buf[i] = array[i] & 255
}
return buf
}
function fromArrayBuffer (array, byteOffset, length) {
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('"offset" is outside of buffer bounds')
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('"length" is outside of buffer bounds')
}
var buf
if (byteOffset === undefined && length === undefined) {
buf = new Uint8Array(array)
} else if (length === undefined) {
buf = new Uint8Array(array, byteOffset)
} else {
buf = new Uint8Array(array, byteOffset, length)
}
// Return an augmented `Uint8Array` instance
Object.setPrototypeOf(buf, Buffer.prototype)
return buf
}
function fromObject (obj) {
if (Buffer.isBuffer(obj)) {
var len = checked(obj.length) | 0
var buf = createBuffer(len)
if (buf.length === 0) {
return buf
}
obj.copy(buf, 0, 0, len)
return buf
}
if (obj.length !== undefined) {
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
return createBuffer(0)
}
return fromArrayLike(obj)
}
if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
return fromArrayLike(obj.data)
}
}
function checked (length) {
// Note: cannot use `length < K_MAX_LENGTH` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= K_MAX_LENGTH) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (length) {
if (+length != length) { // eslint-disable-line eqeqeq
length = 0
}
return Buffer.alloc(+length)
}
Buffer.isBuffer = function isBuffer (b) {
return b != null && b._isBuffer === true &&
b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false
}
Buffer.compare = function compare (a, b) {
if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)
if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError(
'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
)
}
if (a === b) return 0
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i]
y = b[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!Array.isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
if (list.length === 0) {
return Buffer.alloc(0)
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; ++i) {
length += list[i].length
}
}
var buffer = Buffer.allocUnsafe(length)
var pos = 0
for (i = 0; i < list.length; ++i) {
var buf = list[i]
if (isInstance(buf, Uint8Array)) {
buf = Buffer.from(buf)
}
if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
buf.copy(buffer, pos)
pos += buf.length
}
return buffer
}
function byteLength (string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length
}
if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
return string.byteLength
}
if (typeof string !== 'string') {
throw new TypeError(
'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
'Received type ' + typeof string
)
}
var len = string.length
var mustMatch = (arguments.length > 2 && arguments[2] === true)
if (!mustMatch && len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len
case 'utf8':
case 'utf-8':
return utf8ToBytes(string).length
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2
case 'hex':
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) {
return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8
}
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.byteLength = byteLength
function slowToString (encoding, start, end) {
var loweredCase = false
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
// This behaves neither like String nor Uint8Array in that we set start/end
// to their upper/lower bounds if the value passed is out of range.
// undefined is handled specially as per ECMA-262 6th Edition,
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
if (start === undefined || start < 0) {
start = 0
}
// Return early if start > this.length. Done here to prevent potential uint32
// coercion fail below.
if (start > this.length) {
return ''
}
if (end === undefined || end > this.length) {
end = this.length
}
if (end <= 0) {
return ''
}
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
end >>>= 0
start >>>= 0
if (end <= start) {
return ''
}
if (!encoding) encoding = 'utf8'
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end)
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end)
case 'ascii':
return asciiSlice(this, start, end)
case 'latin1':
case 'binary':
return latin1Slice(this, start, end)
case 'base64':
return base64Slice(this, start, end)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = (encoding + '').toLowerCase()
loweredCase = true
}
}
}
// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
// reliably in a browserify context because there could be multiple different
// copies of the 'buffer' package in use. This method works even for Buffer
// instances that were created from another copy of the `buffer` package.
// See: https://github.com/feross/buffer/issues/154
Buffer.prototype._isBuffer = true
function swap (b, n, m) {
var i = b[n]
b[n] = b[m]
b[m] = i
}
Buffer.prototype.swap16 = function swap16 () {
var len = this.length
if (len % 2 !== 0) {
throw new RangeError('Buffer size must be a multiple of 16-bits')
}
for (var i = 0; i < len; i += 2) {
swap(this, i, i + 1)
}
return this
}
Buffer.prototype.swap32 = function swap32 () {
var len = this.length
if (len % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits')
}
for (var i = 0; i < len; i += 4) {
swap(this, i, i + 3)
swap(this, i + 1, i + 2)
}
return this
}
Buffer.prototype.swap64 = function swap64 () {
var len = this.length
if (len % 8 !== 0) {
throw new RangeError('Buffer size must be a multiple of 64-bits')
}
for (var i = 0; i < len; i += 8) {
swap(this, i, i + 7)
swap(this, i + 1, i + 6)
swap(this, i + 2, i + 5)
swap(this, i + 3, i + 4)
}
return this
}
Buffer.prototype.toString = function toString () {
var length = this.length
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.toLocaleString = Buffer.prototype.toString
Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function inspect () {
var str = ''
var max = exports.INSPECT_MAX_BYTES
str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()
if (this.length > max) str += ' ... '
return '<Buffer ' + str + '>'
}
if (customInspectSymbol) {
Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect
}
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
if (isInstance(target, Uint8Array)) {
target = Buffer.from(target, target.offset, target.byteLength)
}
if (!Buffer.isBuffer(target)) {
throw new TypeError(
'The "target" argument must be one of type Buffer or Uint8Array. ' +
'Received type ' + (typeof target)
)
}
if (start === undefined) {
start = 0
}
if (end === undefined) {
end = target ? target.length : 0
}
if (thisStart === undefined) {
thisStart = 0
}
if (thisEnd === undefined) {
thisEnd = this.length
}
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
throw new RangeError('out of range index')
}
if (thisStart >= thisEnd && start >= end) {
return 0
}
if (thisStart >= thisEnd) {
return -1
}
if (start >= end) {
return 1
}
start >>>= 0
end >>>= 0
thisStart >>>= 0
thisEnd >>>= 0
if (this === target) return 0
var x = thisEnd - thisStart
var y = end - start
var len = Math.min(x, y)
var thisCopy = this.slice(thisStart, thisEnd)
var targetCopy = target.slice(start, end)
for (var i = 0; i < len; ++i) {
if (thisCopy[i] !== targetCopy[i]) {
x = thisCopy[i]
y = targetCopy[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
// Empty buffer means no match
if (buffer.length === 0) return -1
// Normalize byteOffset
if (typeof byteOffset === 'string') {
encoding = byteOffset
byteOffset = 0
} else if (byteOffset > 0x7fffffff) {
byteOffset = 0x7fffffff
} else if (byteOffset < -0x80000000) {
byteOffset = -0x80000000
}
byteOffset = +byteOffset // Coerce to Number.
if (numberIsNaN(byteOffset)) {
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
byteOffset = dir ? 0 : (buffer.length - 1)
}
// Normalize byteOffset: negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = buffer.length + byteOffset
if (byteOffset >= buffer.length) {
if (dir) return -1
else byteOffset = buffer.length - 1
} else if (byteOffset < 0) {
if (dir) byteOffset = 0
else return -1
}
// Normalize val
if (typeof val === 'string') {
val = Buffer.from(val, encoding)
}
// Finally, search either indexOf (if dir is true) or lastIndexOf
if (Buffer.isBuffer(val)) {
// Special case: looking for empty string/buffer always fails
if (val.length === 0) {
return -1
}
return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
} else if (typeof val === 'number') {
val = val & 0xFF // Search for a byte value [0-255]
if (typeof Uint8Array.prototype.indexOf === 'function') {
if (dir) {
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
} else {
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
}
}
return arrayIndexOf(buffer, [val], byteOffset, encoding, dir)
}
throw new TypeError('val must be string, number or Buffer')
}
function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
var indexSize = 1
var arrLength = arr.length
var valLength = val.length
if (encoding !== undefined) {
encoding = String(encoding).toLowerCase()
if (encoding === 'ucs2' || encoding === 'ucs-2' ||
encoding === 'utf16le' || encoding === 'utf-16le') {
if (arr.length < 2 || val.length < 2) {
return -1
}
indexSize = 2
arrLength /= 2
valLength /= 2
byteOffset /= 2
}
}
function read (buf, i) {
if (indexSize === 1) {
return buf[i]
} else {
return buf.readUInt16BE(i * indexSize)
}
}
var i
if (dir) {
var foundIndex = -1
for (i = byteOffset; i < arrLength; i++) {
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
if (foundIndex === -1) foundIndex = i
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
} else {
if (foundIndex !== -1) i -= i - foundIndex
foundIndex = -1
}
}
} else {
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
for (i = byteOffset; i >= 0; i--) {
var found = true
for (var j = 0; j < valLength; j++) {
if (read(arr, i + j) !== read(val, j)) {
found = false
break
}
}
if (found) return i
}
}
return -1
}
Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
return this.indexOf(val, byteOffset, encoding) !== -1
}
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}
function hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
var strLen = string.length
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; ++i) {
var parsed = parseInt(string.substr(i * 2, 2), 16)
if (numberIsNaN(parsed)) return i
buf[offset + i] = parsed
}
return i
}
function utf8Write (buf, string, offset, length) {
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}
function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}
function latin1Write (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
}
function ucs2Write (buf, string, offset, length) {
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}
Buffer.prototype.write = function write (string, offset, length, encoding) {
// Buffer#write(string)
if (offset === undefined) {
encoding = 'utf8'
length = this.length
offset = 0
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
encoding = offset
length = this.length
offset = 0
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset >>> 0
if (isFinite(length)) {
length = length >>> 0
if (encoding === undefined) encoding = 'utf8'
} else {
encoding = length
length = undefined
}
} else {
throw new Error(
'Buffer.write(string, encoding, offset[, length]) is no longer supported'
)
}
var remaining = this.length - offset
if (length === undefined || length > remaining) length = remaining
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
throw new RangeError('Attempt to write outside buffer bounds')
}
if (!encoding) encoding = 'utf8'
var loweredCase = false
for (;;) {
switch (encoding) {
case 'hex':
return hexWrite(this, string, offset, length)
case 'utf8':
case 'utf-8':
return utf8Write(this, string, offset, length)
case 'ascii':
return asciiWrite(this, string, offset, length)
case 'latin1':
case 'binary':
return latin1Write(this, string, offset, length)
case 'base64':
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return ucs2Write(this, string, offset, length)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toJSON = function toJSON () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
function base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function utf8Slice (buf, start, end) {
end = Math.min(buf.length, end)
var res = []
var i = start
while (i < end) {
var firstByte = buf[i]
var codePoint = null
var bytesPerSequence = (firstByte > 0xEF) ? 4
: (firstByte > 0xDF) ? 3
: (firstByte > 0xBF) ? 2
: 1
if (i + bytesPerSequence <= end) {
var secondByte, thirdByte, fourthByte, tempCodePoint
switch (bytesPerSequence) {
case 1:
if (firstByte < 0x80) {
codePoint = firstByte
}
break
case 2:
secondByte = buf[i + 1]
if ((secondByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
if (tempCodePoint > 0x7F) {
codePoint = tempCodePoint
}
}
break
case 3:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
codePoint = tempCodePoint
}
}
break
case 4:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
fourthByte = buf[i + 3]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
codePoint = tempCodePoint
}
}
}
}
if (codePoint === null) {
// we did not generate a valid codePoint so insert a
// replacement char (U+FFFD) and advance only 1 byte
codePoint = 0xFFFD
bytesPerSequence = 1
} else if (codePoint > 0xFFFF) {
// encode to utf16 (surrogate pair dance)
codePoint -= 0x10000
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
codePoint = 0xDC00 | codePoint & 0x3FF
}
res.push(codePoint)
i += bytesPerSequence
}
return decodeCodePointsArray(res)
}
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000
function decodeCodePointsArray (codePoints) {
var len = codePoints.length
if (len <= MAX_ARGUMENTS_LENGTH) {
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
}
// Decode in chunks to avoid "call stack size exceeded".
var res = ''
var i = 0
while (i < len) {
res += String.fromCharCode.apply(
String,
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
)
}
return res
}
function asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i] & 0x7F)
}
return ret
}
function latin1Slice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i])
}
return ret
}
function hexSlice (buf, start, end) {
var len = buf.length
if (!start || start < 0) start = 0
if (!end || end < 0 || end > len) end = len
var out = ''
for (var i = start; i < end; ++i) {
out += hexSliceLookupTable[buf[i]]
}
return out
}
function utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
}
return res
}
Buffer.prototype.slice = function slice (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len
if (start < 0) start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0) end = 0
} else if (end > len) {
end = len
}
if (end < start) end = start
var newBuf = this.subarray(start, end)
// Return an augmented `Uint8Array` instance
Object.setPrototypeOf(newBuf, Buffer.prototype)
return newBuf
}
/*
* Need to make sure that buffer isn't trying to write out of bounds.
*/
function checkOffset (offset, ext, length) {
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
return val
}
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) {
checkOffset(offset, byteLength, this.length)
}
var val = this[offset + --byteLength]
var mul = 1
while (byteLength > 0 && (mul *= 0x100)) {
val += this[offset + --byteLength] * mul
}
return val
}
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[offset + 2] << 8) |
this[offset + 3])
}
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var i = byteLength
var mul = 1
var val = this[offset + --i]
while (i > 0 && (mul *= 0x100)) {
val += this[offset + --i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 1, this.length)
if (!(this[offset] & 0x80)) return (this[offset])
return ((0xff - this[offset] + 1) * -1)
}
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset] | (this[offset + 1] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset + 1] | (this[offset] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16) |
(this[offset + 3] << 24)
}
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] << 24) |
(this[offset + 1] << 16) |
(this[offset + 2] << 8) |
(this[offset + 3])
}
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, true, 23, 4)
}
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, false, 23, 4)
}
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, true, 52, 8)
}
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
offset = offset >>> 0
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, false, 52, 8)
}
function checkInt (buf, value, offset, ext, max, min) {
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
if (offset + ext > buf.length) throw new RangeError('Index out of range')
}
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var mul = 1
var i = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var i = byteLength - 1
var mul = 1
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
this[offset] = (value & 0xff)
return offset + 1
}
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
return offset + 2
}
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
return offset + 2
}
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
this[offset + 3] = (value >>> 24)
this[offset + 2] = (value >>> 16)
this[offset + 1] = (value >>> 8)
this[offset] = (value & 0xff)
return offset + 4
}
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
return offset + 4
}
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
var limit = Math.pow(2, (8 * byteLength) - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = 0
var mul = 1
var sub = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
var limit = Math.pow(2, (8 * byteLength) - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = byteLength - 1
var mul = 1
var sub = 0
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
if (value < 0) value = 0xff + value + 1
this[offset] = (value & 0xff)
return offset + 1
}
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
return offset + 2
}
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
return offset + 2
}
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
this[offset + 2] = (value >>> 16)
this[offset + 3] = (value >>> 24)
return offset + 4
}
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (value < 0) value = 0xffffffff + value + 1
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
return offset + 4
}
function checkIEEE754 (buf, value, offset, ext, max, min) {
if (offset + ext > buf.length) throw new RangeError('Index out of range')
if (offset < 0) throw new RangeError('Index out of range')
}
function writeFloat (buf, value, offset, littleEndian, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
}
ieee754.write(buf, value, offset, littleEndian, 23, 4)
return offset + 4
}
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
return writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
return writeFloat(this, value, offset, false, noAssert)
}
function writeDouble (buf, value, offset, littleEndian, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
}
ieee754.write(buf, value, offset, littleEndian, 52, 8)
return offset + 8
}
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
return writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
return writeDouble(this, value, offset, false, noAssert)
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (targetStart >= target.length) targetStart = target.length
if (!targetStart) targetStart = 0
if (end > 0 && end < start) end = start
// Copy 0 bytes; we're done
if (end === start) return 0
if (target.length === 0 || this.length === 0) return 0
// Fatal error conditions
if (targetStart < 0) {
throw new RangeError('targetStart out of bounds')
}
if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
if (end < 0) throw new RangeError('sourceEnd out of bounds')
// Are we oob?
if (end > this.length) end = this.length
if (target.length - targetStart < end - start) {
end = target.length - targetStart + start
}
var len = end - start
if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
// Use built-in when available, missing from IE11
this.copyWithin(targetStart, start, end)
} else if (this === target && start < targetStart && targetStart < end) {
// descending copy from end
for (var i = len - 1; i >= 0; --i) {
target[i + targetStart] = this[i + start]
}
} else {
Uint8Array.prototype.set.call(
target,
this.subarray(start, end),
targetStart
)
}
return len
}
// Usage:
// buffer.fill(number[, offset[, end]])
// buffer.fill(buffer[, offset[, end]])
// buffer.fill(string[, offset[, end]][, encoding])
Buffer.prototype.fill = function fill (val, start, end, encoding) {
// Handle string cases:
if (typeof val === 'string') {
if (typeof start === 'string') {
encoding = start
start = 0
end = this.length
} else if (typeof end === 'string') {
encoding = end
end = this.length
}
if (encoding !== undefined && typeof encoding !== 'string') {
throw new TypeError('encoding must be a string')
}
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
if (val.length === 1) {
var code = val.charCodeAt(0)
if ((encoding === 'utf8' && code < 128) ||
encoding === 'latin1') {
// Fast path: If `val` fits into a single byte, use that numeric value.
val = code
}
}
} else if (typeof val === 'number') {
val = val & 255
} else if (typeof val === 'boolean') {
val = Number(val)
}
// Invalid ranges are not set to a default, so can range check early.
if (start < 0 || this.length < start || this.length < end) {
throw new RangeError('Out of range index')
}
if (end <= start) {
return this
}
start = start >>> 0
end = end === undefined ? this.length : end >>> 0
if (!val) val = 0
var i
if (typeof val === 'number') {
for (i = start; i < end; ++i) {
this[i] = val
}
} else {
var bytes = Buffer.isBuffer(val)
? val
: Buffer.from(val, encoding)
var len = bytes.length
if (len === 0) {
throw new TypeError('The value "' + val +
'" is invalid for argument "value"')
}
for (i = 0; i < end - start; ++i) {
this[i + start] = bytes[i % len]
}
}
return this
}
// HELPER FUNCTIONS
// ================
var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
function base64clean (str) {
// Node takes equal signs as end of the Base64 encoding
str = str.split('=')[0]
// Node strips out invalid characters like \n and \t from the string, base64-js does not
str = str.trim().replace(INVALID_BASE64_RE, '')
// Node converts strings with length < 2 to ''
if (str.length < 2) return ''
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
while (str.length % 4 !== 0) {
str = str + '='
}
return str
}
function utf8ToBytes (string, units) {
units = units || Infinity
var codePoint
var length = string.length
var leadSurrogate = null
var bytes = []
for (var i = 0; i < length; ++i) {
codePoint = string.charCodeAt(i)
// is surrogate component
if (codePoint > 0xD7FF && codePoint < 0xE000) {
// last char was a lead
if (!leadSurrogate) {
// no lead yet
if (codePoint > 0xDBFF) {
// unexpected trail
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
} else if (i + 1 === length) {
// unpaired lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
}
// valid lead
leadSurrogate = codePoint
continue
}
// 2 leads in a row
if (codePoint < 0xDC00) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = codePoint
continue
}
// valid surrogate pair
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
} else if (leadSurrogate) {
// valid bmp char, but last char was a lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
}
leadSurrogate = null
// encode utf8
if (codePoint < 0x80) {
if ((units -= 1) < 0) break
bytes.push(codePoint)
} else if (codePoint < 0x800) {
if ((units -= 2) < 0) break
bytes.push(
codePoint >> 0x6 | 0xC0,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x10000) {
if ((units -= 3) < 0) break
bytes.push(
codePoint >> 0xC | 0xE0,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x110000) {
if ((units -= 4) < 0) break
bytes.push(
codePoint >> 0x12 | 0xF0,
codePoint >> 0xC & 0x3F | 0x80,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else {
throw new Error('Invalid code point')
}
}
return bytes
}
function asciiToBytes (str) {
var byteArray = []
for (var i = 0; i < str.length; ++i) {
// Node's code seems to be doing this and not & 0x7F..
byteArray.push(str.charCodeAt(i) & 0xFF)
}
return byteArray
}
function utf16leToBytes (str, units) {
var c, hi, lo
var byteArray = []
for (var i = 0; i < str.length; ++i) {
if ((units -= 2) < 0) break
c = str.charCodeAt(i)
hi = c >> 8
lo = c % 256
byteArray.push(lo)
byteArray.push(hi)
}
return byteArray
}
function base64ToBytes (str) {
return base64.toByteArray(base64clean(str))
}
function blitBuffer (src, dst, offset, length) {
for (var i = 0; i < length; ++i) {
if ((i + offset >= dst.length) || (i >= src.length)) break
dst[i + offset] = src[i]
}
return i
}
// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
// the `instanceof` check but they should be treated as of that type.
// See: https://github.com/feross/buffer/issues/166
function isInstance (obj, type) {
return obj instanceof type ||
(obj != null && obj.constructor != null && obj.constructor.name != null &&
obj.constructor.name === type.name)
}
function numberIsNaN (obj) {
// For IE11 support
return obj !== obj // eslint-disable-line no-self-compare
}
// Create lookup table for `toString('hex')`
// See: https://github.com/feross/buffer/issues/219
var hexSliceLookupTable = (function () {
var alphabet = '0123456789abcdef'
var table = new Array(256)
for (var i = 0; i < 16; ++i) {
var i16 = i * 16
for (var j = 0; j < 16; ++j) {
table[i16 + j] = alphabet[i] + alphabet[j]
}
}
return table
})()
}).call(this,require("buffer").Buffer)
},{"base64-js":6,"buffer":13,"ieee754":61}],14:[function(require,module,exports){
/**
* Expose `Emitter`.
*/
if (typeof module !== 'undefined') {
module.exports = Emitter;
}
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
};
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
function on() {
this.off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
// all
if (0 == arguments.length) {
this._callbacks = {};
return this;
}
// specific event
var callbacks = this._callbacks['$' + event];
if (!callbacks) return this;
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks['$' + event];
return this;
}
// remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
// Remove event specific arrays for event types that no
// one is subscribed for to avoid memory leak.
if (callbacks.length === 0) {
delete this._callbacks['$' + event];
}
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = new Array(arguments.length - 1)
, callbacks = this._callbacks['$' + event];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks['$' + event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};
},{}],15:[function(require,module,exports){
// 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 objectCreate = Object.create || objectCreatePolyfill
var objectKeys = Object.keys || objectKeysPolyfill
var bind = Function.prototype.bind || functionBindPolyfill
function EventEmitter() {
if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) {
this._events = objectCreate(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10;
var hasDefineProperty;
try {
var o = {};
if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 });
hasDefineProperty = o.x === 0;
} catch (err) { hasDefineProperty = false }
if (hasDefineProperty) {
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function() {
return defaultMaxListeners;
},
set: function(arg) {
// check whether the input is a positive number (whose value is zero or
// greater and not a NaN).
if (typeof arg !== 'number' || arg < 0 || arg !== arg)
throw new TypeError('"defaultMaxListeners" must be a positive number');
defaultMaxListeners = arg;
}
});
} else {
EventEmitter.defaultMaxListeners = defaultMaxListeners;
}
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== 'number' || n < 0 || isNaN(n))
throw new TypeError('"n" argument must be a positive number');
this._maxListeners = n;
return this;
};
function $getMaxListeners(that) {
if (that._maxListeners === undefined)
return EventEmitter.defaultMaxListeners;
return that._maxListeners;
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return $getMaxListeners(this);
};
// These standalone emit* functions are used to optimize calling of event
// handlers for fast cases because emit() itself often has a variable number of
// arguments and can be deoptimized because of that. These functions always have
// the same number of arguments and thus do not get deoptimized, so the code
// inside them can execute faster.
function emitNone(handler, isFn, self) {
if (isFn)
handler.call(self);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self);
}
}
function emitOne(handler, isFn, self, arg1) {
if (isFn)
handler.call(self, arg1);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1);
}
}
function emitTwo(handler, isFn, self, arg1, arg2) {
if (isFn)
handler.call(self, arg1, arg2);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2);
}
}
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
if (isFn)
handler.call(self, arg1, arg2, arg3);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2, arg3);
}
}
function emitMany(handler, isFn, self, args) {
if (isFn)
handler.apply(self, args);
else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
listeners[i].apply(self, args);
}
}
EventEmitter.prototype.emit = function emit(type) {
var er, handler, len, args, i, events;
var doError = (type === 'error');
events = this._events;
if (events)
doError = (doError && events.error == null);
else if (!doError)
return false;
// If there is no 'error' event listener then throw.
if (doError) {
if (arguments.length > 1)
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
// At least give some kind of context to the user
var err = new Error('Unhandled "error" event. (' + er + ')');
err.context = er;
throw err;
}
return false;
}
handler = events[type];
if (!handler)
return false;
var isFn = typeof handler === 'function';
len = arguments.length;
switch (len) {
// fast cases
case 1:
emitNone(handler, isFn, this);
break;
case 2:
emitOne(handler, isFn, this, arguments[1]);
break;
case 3:
emitTwo(handler, isFn, this, arguments[1], arguments[2]);
break;
case 4:
emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
break;
// slower
default:
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
emitMany(handler, isFn, this, args);
}
return true;
};
function _addListener(target, type, listener, prepend) {
var m;
var events;
var existing;
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
events = target._events;
if (!events) {
events = target._events = objectCreate(null);
target._eventsCount = 0;
} else {
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (events.newListener) {
target.emit('newListener', type,
listener.listener ? listener.listener : listener);
// Re-assign `events` because a newListener handler could have caused the
// this._events to be assigned to a new object
events = target._events;
}
existing = events[type];
}
if (!existing) {
// Optimize the case of one listener. Don't need the extra array object.
existing = events[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === 'function') {
// Adding the second element, need to change to array.
existing = events[type] =
prepend ? [listener, existing] : [existing, listener];
} else {
// If we've already got an array, just append.
if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
}
// Check for listener leak
if (!existing.warned) {
m = $getMaxListeners(target);
if (m && m > 0 && existing.length > m) {
existing.warned = true;
var w = new Error('Possible EventEmitter memory leak detected. ' +
existing.length + ' "' + String(type) + '" listeners ' +
'added. Use emitter.setMaxListeners() to ' +
'increase limit.');
w.name = 'MaxListenersExceededWarning';
w.emitter = target;
w.type = type;
w.count = existing.length;
if (typeof console === 'object' && console.warn) {
console.warn('%s: %s', w.name, w.message);
}
}
}
}
return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener, false);
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.prependListener =
function prependListener(type, listener) {
return _addListener(this, type, listener, true);
};
function onceWrapper() {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn);
this.fired = true;
switch (arguments.length) {
case 0:
return this.listener.call(this.target);
case 1:
return this.listener.call(this.target, arguments[0]);
case 2:
return this.listener.call(this.target, arguments[0], arguments[1]);
case 3:
return this.listener.call(this.target, arguments[0], arguments[1],
arguments[2]);
default:
var args = new Array(arguments.length);
for (var i = 0; i < args.length; ++i)
args[i] = arguments[i];
this.listener.apply(this.target, args);
}
}
}
function _onceWrap(target, type, listener) {
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
var wrapped = bind.call(onceWrapper, state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) {
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
// Emits a 'removeListener' event if and only if the listener was removed.
EventEmitter.prototype.removeListener =
function removeListener(type, listener) {
var list, events, position, i, originalListener;
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
events = this._events;
if (!events)
return this;
list = events[type];
if (!list)
return this;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0)
this._events = objectCreate(null);
else {
delete events[type];
if (events.removeListener)
this.emit('removeListener', type, list.listener || listener);
}
} else if (typeof list !== 'function') {
position = -1;
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0)
return this;
if (position === 0)
list.shift();
else
spliceOne(list, position);
if (list.length === 1)
events[type] = list[0];
if (events.removeListener)
this.emit('removeListener', type, originalListener || listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners =
function removeAllListeners(type) {
var listeners, events, i;
events = this._events;
if (!events)
return this;
// not listening for removeListener, no need to emit
if (!events.removeListener) {
if (arguments.length === 0) {
this._events = objectCreate(null);
this._eventsCount = 0;
} else if (events[type]) {
if (--this._eventsCount === 0)
this._events = objectCreate(null);
else
delete events[type];
}
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
var keys = objectKeys(events);
var key;
for (i = 0; i < keys.length; ++i) {
key = keys[i];
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = objectCreate(null);
this._eventsCount = 0;
return this;
}
listeners = events[type];
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
} else if (listeners) {
// LIFO order
for (i = listeners.length - 1; i >= 0; i--) {
this.removeListener(type, listeners[i]);
}
}
return this;
};
function _listeners(target, type, unwrap) {
var events = target._events;
if (!events)
return [];
var evlistener = events[type];
if (!evlistener)
return [];
if (typeof evlistener === 'function')
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
return _listeners(this, type, true);
};
EventEmitter.prototype.rawListeners = function rawListeners(type) {
return _listeners(this, type, false);
};
EventEmitter.listenerCount = function(emitter, type) {
if (typeof emitter.listenerCount === 'function') {
return emitter.listenerCount(type);
} else {
return listenerCount.call(emitter, type);
}
};
EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
var events = this._events;
if (events) {
var evlistener = events[type];
if (typeof evlistener === 'function') {
return 1;
} else if (evlistener) {
return evlistener.length;
}
}
return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
};
// About 1.5x faster than the two-arg version of Array#splice().
function spliceOne(list, index) {
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
list[i] = list[k];
list.pop();
}
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
function unwrapListeners(arr) {
var ret = new Array(arr.length);
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i];
}
return ret;
}
function objectCreatePolyfill(proto) {
var F = function() {};
F.prototype = proto;
return new F;
}
function objectKeysPolyfill(obj) {
var keys = [];
for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
return k;
}
function functionBindPolyfill(context) {
var fn = this;
return function () {
return fn.apply(context, arguments);
};
}
},{}],16:[function(require,module,exports){
module.exports = stringify
stringify.default = stringify
stringify.stable = deterministicStringify
stringify.stableStringify = deterministicStringify
var arr = []
var replacerStack = []
// Regular stringify
function stringify (obj, replacer, spacer) {
decirc(obj, '', [], undefined)
var res
if (replacerStack.length === 0) {
res = JSON.stringify(obj, replacer, spacer)
} else {
res = JSON.stringify(obj, replaceGetterValues(replacer), spacer)
}
while (arr.length !== 0) {
var part = arr.pop()
if (part.length === 4) {
Object.defineProperty(part[0], part[1], part[3])
} else {
part[0][part[1]] = part[2]
}
}
return res
}
function decirc (val, k, stack, parent) {
var i
if (typeof val === 'object' && val !== null) {
for (i = 0; i < stack.length; i++) {
if (stack[i] === val) {
var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k)
if (propertyDescriptor.get !== undefined) {
if (propertyDescriptor.configurable) {
Object.defineProperty(parent, k, { value: '[Circular]' })
arr.push([parent, k, val, propertyDescriptor])
} else {
replacerStack.push([val, k])
}
} else {
parent[k] = '[Circular]'
arr.push([parent, k, val])
}
return
}
}
stack.push(val)
// Optimize for Arrays. Big arrays could kill the performance otherwise!
if (Array.isArray(val)) {
for (i = 0; i < val.length; i++) {
decirc(val[i], i, stack, val)
}
} else {
var keys = Object.keys(val)
for (i = 0; i < keys.length; i++) {
var key = keys[i]
decirc(val[key], key, stack, val)
}
}
stack.pop()
}
}
// Stable-stringify
function compareFunction (a, b) {
if (a < b) {
return -1
}
if (a > b) {
return 1
}
return 0
}
function deterministicStringify (obj, replacer, spacer) {
var tmp = deterministicDecirc(obj, '', [], undefined) || obj
var res
if (replacerStack.length === 0) {
res = JSON.stringify(tmp, replacer, spacer)
} else {
res = JSON.stringify(tmp, replaceGetterValues(replacer), spacer)
}
while (arr.length !== 0) {
var part = arr.pop()
if (part.length === 4) {
Object.defineProperty(part[0], part[1], part[3])
} else {
part[0][part[1]] = part[2]
}
}
return res
}
function deterministicDecirc (val, k, stack, parent) {
var i
if (typeof val === 'object' && val !== null) {
for (i = 0; i < stack.length; i++) {
if (stack[i] === val) {
var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k)
if (propertyDescriptor.get !== undefined) {
if (propertyDescriptor.configurable) {
Object.defineProperty(parent, k, { value: '[Circular]' })
arr.push([parent, k, val, propertyDescriptor])
} else {
replacerStack.push([val, k])
}
} else {
parent[k] = '[Circular]'
arr.push([parent, k, val])
}
return
}
}
if (typeof val.toJSON === 'function') {
return
}
stack.push(val)
// Optimize for Arrays. Big arrays could kill the performance otherwise!
if (Array.isArray(val)) {
for (i = 0; i < val.length; i++) {
deterministicDecirc(val[i], i, stack, val)
}
} else {
// Create a temporary object in the required way
var tmp = {}
var keys = Object.keys(val).sort(compareFunction)
for (i = 0; i < keys.length; i++) {
var key = keys[i]
deterministicDecirc(val[key], key, stack, val)
tmp[key] = val[key]
}
if (parent !== undefined) {
arr.push([parent, k, val])
parent[k] = tmp
} else {
return tmp
}
}
stack.pop()
}
}
// wraps replacer function to handle values we couldn't replace
// and mark them as [Circular]
function replaceGetterValues (replacer) {
replacer = replacer !== undefined ? replacer : function (k, v) { return v }
return function (key, val) {
if (replacerStack.length > 0) {
for (var i = 0; i < replacerStack.length; i++) {
var part = replacerStack[i]
if (part[1] === key && part[0] === val) {
val = '[Circular]'
replacerStack.splice(i, 1)
break
}
}
}
return replacer.call(this, key, val)
}
}
},{}],17:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _handlebarsRuntime = require('./handlebars.runtime');
var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime);
// Compiler imports
var _handlebarsCompilerAst = require('./handlebars/compiler/ast');
var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst);
var _handlebarsCompilerBase = require('./handlebars/compiler/base');
var _handlebarsCompilerCompiler = require('./handlebars/compiler/compiler');
var _handlebarsCompilerJavascriptCompiler = require('./handlebars/compiler/javascript-compiler');
var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler);
var _handlebarsCompilerVisitor = require('./handlebars/compiler/visitor');
var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor);
var _handlebarsNoConflict = require('./handlebars/no-conflict');
var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
var _create = _handlebarsRuntime2['default'].create;
function create() {
var hb = _create();
hb.compile = function (input, options) {
return _handlebarsCompilerCompiler.compile(input, options, hb);
};
hb.precompile = function (input, options) {
return _handlebarsCompilerCompiler.precompile(input, options, hb);
};
hb.AST = _handlebarsCompilerAst2['default'];
hb.Compiler = _handlebarsCompilerCompiler.Compiler;
hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default'];
hb.Parser = _handlebarsCompilerBase.parser;
hb.parse = _handlebarsCompilerBase.parse;
hb.parseWithoutProcessing = _handlebarsCompilerBase.parseWithoutProcessing;
return hb;
}
var inst = create();
inst.create = create;
_handlebarsNoConflict2['default'](inst);
inst.Visitor = _handlebarsCompilerVisitor2['default'];
inst['default'] = inst;
exports['default'] = inst;
module.exports = exports['default'];
},{"./handlebars.runtime":18,"./handlebars/compiler/ast":20,"./handlebars/compiler/base":21,"./handlebars/compiler/compiler":23,"./handlebars/compiler/javascript-compiler":25,"./handlebars/compiler/visitor":28,"./handlebars/no-conflict":45}],18:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
// istanbul ignore next
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
var _handlebarsBase = require('./handlebars/base');
var base = _interopRequireWildcard(_handlebarsBase);
// Each of these augment the Handlebars object. No need to setup here.
// (This is done to easily share code between commonjs and browse envs)
var _handlebarsSafeString = require('./handlebars/safe-string');
var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString);
var _handlebarsException = require('./handlebars/exception');
var _handlebarsException2 = _interopRequireDefault(_handlebarsException);
var _handlebarsUtils = require('./handlebars/utils');
var Utils = _interopRequireWildcard(_handlebarsUtils);
var _handlebarsRuntime = require('./handlebars/runtime');
var runtime = _interopRequireWildcard(_handlebarsRuntime);
var _handlebarsNoConflict = require('./handlebars/no-conflict');
var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
function create() {
var hb = new base.HandlebarsEnvironment();
Utils.extend(hb, base);
hb.SafeString = _handlebarsSafeString2['default'];
hb.Exception = _handlebarsException2['default'];
hb.Utils = Utils;
hb.escapeExpression = Utils.escapeExpression;
hb.VM = runtime;
hb.template = function (spec) {
return runtime.template(spec, hb);
};
return hb;
}
var inst = create();
inst.create = create;
_handlebarsNoConflict2['default'](inst);
inst['default'] = inst;
exports['default'] = inst;
module.exports = exports['default'];
},{"./handlebars/base":19,"./handlebars/exception":32,"./handlebars/no-conflict":45,"./handlebars/runtime":46,"./handlebars/safe-string":47,"./handlebars/utils":48}],19:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.HandlebarsEnvironment = HandlebarsEnvironment;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _utils = require('./utils');
var _exception = require('./exception');
var _exception2 = _interopRequireDefault(_exception);
var _helpers = require('./helpers');
var _decorators = require('./decorators');
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
var _internalProtoAccess = require('./internal/proto-access');
var VERSION = '4.7.6';
exports.VERSION = VERSION;
var COMPILER_REVISION = 8;
exports.COMPILER_REVISION = COMPILER_REVISION;
var LAST_COMPATIBLE_COMPILER_REVISION = 7;
exports.LAST_COMPATIBLE_COMPILER_REVISION = LAST_COMPATIBLE_COMPILER_REVISION;
var REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
2: '== 1.0.0-rc.3',
3: '== 1.0.0-rc.4',
4: '== 1.x.x',
5: '== 2.0.0-alpha.x',
6: '>= 2.0.0-beta.1',
7: '>= 4.0.0 <4.3.0',
8: '>= 4.3.0'
};
exports.REVISION_CHANGES = REVISION_CHANGES;
var objectType = '[object Object]';
function HandlebarsEnvironment(helpers, partials, decorators) {
this.helpers = helpers || {};
this.partials = partials || {};
this.decorators = decorators || {};
_helpers.registerDefaultHelpers(this);
_decorators.registerDefaultDecorators(this);
}
HandlebarsEnvironment.prototype = {
constructor: HandlebarsEnvironment,
logger: _logger2['default'],
log: _logger2['default'].log,
registerHelper: function registerHelper(name, fn) {
if (_utils.toString.call(name) === objectType) {
if (fn) {
throw new _exception2['default']('Arg not supported with multiple helpers');
}
_utils.extend(this.helpers, name);
} else {
this.helpers[name] = fn;
}
},
unregisterHelper: function unregisterHelper(name) {
delete this.helpers[name];
},
registerPartial: function registerPartial(name, partial) {
if (_utils.toString.call(name) === objectType) {
_utils.extend(this.partials, name);
} else {
if (typeof partial === 'undefined') {
throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined');
}
this.partials[name] = partial;
}
},
unregisterPartial: function unregisterPartial(name) {
delete this.partials[name];
},
registerDecorator: function registerDecorator(name, fn) {
if (_utils.toString.call(name) === objectType) {
if (fn) {
throw new _exception2['default']('Arg not supported with multiple decorators');
}
_utils.extend(this.decorators, name);
} else {
this.decorators[name] = fn;
}
},
unregisterDecorator: function unregisterDecorator(name) {
delete this.decorators[name];
},
/**
* Reset the memory of illegal property accesses that have already been logged.
* @deprecated should only be used in handlebars test-cases
*/
resetLoggedPropertyAccesses: function resetLoggedPropertyAccesses() {
_internalProtoAccess.resetLoggedProperties();
}
};
var log = _logger2['default'].log;
exports.log = log;
exports.createFrame = _utils.createFrame;
exports.logger = _logger2['default'];
},{"./decorators":30,"./exception":32,"./helpers":33,"./internal/proto-access":42,"./logger":44,"./utils":48}],20:[function(require,module,exports){
'use strict';
exports.__esModule = true;
var AST = {
// Public API used to evaluate derived attributes regarding AST nodes
helpers: {
// a mustache is definitely a helper if:
// * it is an eligible helper, and
// * it has at least one parameter or hash segment
helperExpression: function helperExpression(node) {
return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash);
},
scopedId: function scopedId(path) {
return (/^\.|this\b/.test(path.original)
);
},
// an ID is simple if it only has one part, and that part is not
// `..` or `this`.
simpleId: function simpleId(path) {
return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
}
}
};
// Must be exported as an object rather than the root of the module as the jison lexer
// must modify the object to operate properly.
exports['default'] = AST;
module.exports = exports['default'];
},{}],21:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.parseWithoutProcessing = parseWithoutProcessing;
exports.parse = parse;
// istanbul ignore next
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _parser = require('./parser');
var _parser2 = _interopRequireDefault(_parser);
var _whitespaceControl = require('./whitespace-control');
var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl);
var _helpers = require('./helpers');
var Helpers = _interopRequireWildcard(_helpers);
var _utils = require('../utils');
exports.parser = _parser2['default'];
var yy = {};
_utils.extend(yy, Helpers);
function parseWithoutProcessing(input, options) {
// Just return if an already-compiled AST was passed in.
if (input.type === 'Program') {
return input;
}
_parser2['default'].yy = yy;
// Altering the shared object here, but this is ok as parser is a sync operation
yy.locInfo = function (locInfo) {
return new yy.SourceLocation(options && options.srcName, locInfo);
};
var ast = _parser2['default'].parse(input);
return ast;
}
function parse(input, options) {
var ast = parseWithoutProcessing(input, options);
var strip = new _whitespaceControl2['default'](options);
return strip.accept(ast);
}
},{"../utils":48,"./helpers":24,"./parser":26,"./whitespace-control":29}],22:[function(require,module,exports){
/* global define */
'use strict';
exports.__esModule = true;
var _utils = require('../utils');
var SourceNode = undefined;
try {
/* istanbul ignore next */
if (typeof define !== 'function' || !define.amd) {
// We don't support this in AMD environments. For these environments, we asusme that
// they are running on the browser and thus have no need for the source-map library.
var SourceMap = require('source-map');
SourceNode = SourceMap.SourceNode;
}
} catch (err) {}
/* NOP */
/* istanbul ignore if: tested but not covered in istanbul due to dist build */
if (!SourceNode) {
SourceNode = function (line, column, srcFile, chunks) {
this.src = '';
if (chunks) {
this.add(chunks);
}
};
/* istanbul ignore next */
SourceNode.prototype = {
add: function add(chunks) {
if (_utils.isArray(chunks)) {
chunks = chunks.join('');
}
this.src += chunks;
},
prepend: function prepend(chunks) {
if (_utils.isArray(chunks)) {
chunks = chunks.join('');
}
this.src = chunks + this.src;
},
toStringWithSourceMap: function toStringWithSourceMap() {
return { code: this.toString() };
},
toString: function toString() {
return this.src;
}
};
}
function castChunk(chunk, codeGen, loc) {
if (_utils.isArray(chunk)) {
var ret = [];
for (var i = 0, len = chunk.length; i < len; i++) {
ret.push(codeGen.wrap(chunk[i], loc));
}
return ret;
} else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
// Handle primitives that the SourceNode will throw up on
return chunk + '';
}
return chunk;
}
function CodeGen(srcFile) {
this.srcFile = srcFile;
this.source = [];
}
CodeGen.prototype = {
isEmpty: function isEmpty() {
return !this.source.length;
},
prepend: function prepend(source, loc) {
this.source.unshift(this.wrap(source, loc));
},
push: function push(source, loc) {
this.source.push(this.wrap(source, loc));
},
merge: function merge() {
var source = this.empty();
this.each(function (line) {
source.add([' ', line, '\n']);
});
return source;
},
each: function each(iter) {
for (var i = 0, len = this.source.length; i < len; i++) {
iter(this.source[i]);
}
},
empty: function empty() {
var loc = this.currentLocation || { start: {} };
return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
},
wrap: function wrap(chunk) {
var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];
if (chunk instanceof SourceNode) {
return chunk;
}
chunk = castChunk(chunk, this, loc);
return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
},
functionCall: function functionCall(fn, type, params) {
params = this.generateList(params);
return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
},
quotedString: function quotedString(str) {
return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
.replace(/\u2029/g, '\\u2029') + '"';
},
objectLiteral: function objectLiteral(obj) {
// istanbul ignore next
var _this = this;
var pairs = [];
Object.keys(obj).forEach(function (key) {
var value = castChunk(obj[key], _this);
if (value !== 'undefined') {
pairs.push([_this.quotedString(key), ':', value]);
}
});
var ret = this.generateList(pairs);
ret.prepend('{');
ret.add('}');
return ret;
},
generateList: function generateList(entries) {
var ret = this.empty();
for (var i = 0, len = entries.length; i < len; i++) {
if (i) {
ret.add(',');
}
ret.add(castChunk(entries[i], this));
}
return ret;
},
generateArray: function generateArray(entries) {
var ret = this.generateList(entries);
ret.prepend('[');
ret.add(']');
return ret;
}
};
exports['default'] = CodeGen;
module.exports = exports['default'];
},{"../utils":48,"source-map":60}],23:[function(require,module,exports){
/* eslint-disable new-cap */
'use strict';
exports.__esModule = true;
exports.Compiler = Compiler;
exports.precompile = precompile;
exports.compile = compile;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
var _utils = require('../utils');
var _ast = require('./ast');
var _ast2 = _interopRequireDefault(_ast);
var slice = [].slice;
function Compiler() {}
// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.
Compiler.prototype = {
compiler: Compiler,
equals: function equals(other) {
var len = this.opcodes.length;
if (other.opcodes.length !== len) {
return false;
}
for (var i = 0; i < len; i++) {
var opcode = this.opcodes[i],
otherOpcode = other.opcodes[i];
if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
return false;
}
}
// We know that length is the same between the two arrays because they are directly tied
// to the opcode behavior above.
len = this.children.length;
for (var i = 0; i < len; i++) {
if (!this.children[i].equals(other.children[i])) {
return false;
}
}
return true;
},
guid: 0,
compile: function compile(program, options) {
this.sourceNode = [];
this.opcodes = [];
this.children = [];
this.options = options;
this.stringParams = options.stringParams;
this.trackIds = options.trackIds;
options.blockParams = options.blockParams || [];
options.knownHelpers = _utils.extend(Object.create(null), {
helperMissing: true,
blockHelperMissing: true,
each: true,
'if': true,
unless: true,
'with': true,
log: true,
lookup: true
}, options.knownHelpers);
return this.accept(program);
},
compileProgram: function compileProgram(program) {
var childCompiler = new this.compiler(),
// eslint-disable-line new-cap
result = childCompiler.compile(program, this.options),
guid = this.guid++;
this.usePartial = this.usePartial || result.usePartial;
this.children[guid] = result;
this.useDepths = this.useDepths || result.useDepths;
return guid;
},
accept: function accept(node) {
/* istanbul ignore next: Sanity code */
if (!this[node.type]) {
throw new _exception2['default']('Unknown type: ' + node.type, node);
}
this.sourceNode.unshift(node);
var ret = this[node.type](node);
this.sourceNode.shift();
return ret;
},
Program: function Program(program) {
this.options.blockParams.unshift(program.blockParams);
var body = program.body,
bodyLength = body.length;
for (var i = 0; i < bodyLength; i++) {
this.accept(body[i]);
}
this.options.blockParams.shift();
this.isSimple = bodyLength === 1;
this.blockParams = program.blockParams ? program.blockParams.length : 0;
return this;
},
BlockStatement: function BlockStatement(block) {
transformLiteralToPath(block);
var program = block.program,
inverse = block.inverse;
program = program && this.compileProgram(program);
inverse = inverse && this.compileProgram(inverse);
var type = this.classifySexpr(block);
if (type === 'helper') {
this.helperSexpr(block, program, inverse);
} else if (type === 'simple') {
this.simpleSexpr(block);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('blockValue', block.path.original);
} else {
this.ambiguousSexpr(block, program, inverse);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('ambiguousBlockValue');
}
this.opcode('append');
},
DecoratorBlock: function DecoratorBlock(decorator) {
var program = decorator.program && this.compileProgram(decorator.program);
var params = this.setupFullMustacheParams(decorator, program, undefined),
path = decorator.path;
this.useDecorators = true;
this.opcode('registerDecorator', params.length, path.original);
},
PartialStatement: function PartialStatement(partial) {
this.usePartial = true;
var program = partial.program;
if (program) {
program = this.compileProgram(partial.program);
}
var params = partial.params;
if (params.length > 1) {
throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
} else if (!params.length) {
if (this.options.explicitPartialContext) {
this.opcode('pushLiteral', 'undefined');
} else {
params.push({ type: 'PathExpression', parts: [], depth: 0 });
}
}
var partialName = partial.name.original,
isDynamic = partial.name.type === 'SubExpression';
if (isDynamic) {
this.accept(partial.name);
}
this.setupFullMustacheParams(partial, program, undefined, true);
var indent = partial.indent || '';
if (this.options.preventIndent && indent) {
this.opcode('appendContent', indent);
indent = '';
}
this.opcode('invokePartial', isDynamic, partialName, indent);
this.opcode('append');
},
PartialBlockStatement: function PartialBlockStatement(partialBlock) {
this.PartialStatement(partialBlock);
},
MustacheStatement: function MustacheStatement(mustache) {
this.SubExpression(mustache);
if (mustache.escaped && !this.options.noEscape) {
this.opcode('appendEscaped');
} else {
this.opcode('append');
}
},
Decorator: function Decorator(decorator) {
this.DecoratorBlock(decorator);
},
ContentStatement: function ContentStatement(content) {
if (content.value) {
this.opcode('appendContent', content.value);
}
},
CommentStatement: function CommentStatement() {},
SubExpression: function SubExpression(sexpr) {
transformLiteralToPath(sexpr);
var type = this.classifySexpr(sexpr);
if (type === 'simple') {
this.simpleSexpr(sexpr);
} else if (type === 'helper') {
this.helperSexpr(sexpr);
} else {
this.ambiguousSexpr(sexpr);
}
},
ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
var path = sexpr.path,
name = path.parts[0],
isBlock = program != null || inverse != null;
this.opcode('getContext', path.depth);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
path.strict = true;
this.accept(path);
this.opcode('invokeAmbiguous', name, isBlock);
},
simpleSexpr: function simpleSexpr(sexpr) {
var path = sexpr.path;
path.strict = true;
this.accept(path);
this.opcode('resolvePossibleLambda');
},
helperSexpr: function helperSexpr(sexpr, program, inverse) {
var params = this.setupFullMustacheParams(sexpr, program, inverse),
path = sexpr.path,
name = path.parts[0];
if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name);
} else if (this.options.knownHelpersOnly) {
throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
} else {
path.strict = true;
path.falsy = true;
this.accept(path);
this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path));
}
},
PathExpression: function PathExpression(path) {
this.addDepth(path.depth);
this.opcode('getContext', path.depth);
var name = path.parts[0],
scoped = _ast2['default'].helpers.scopedId(path),
blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
if (blockParamId) {
this.opcode('lookupBlockParam', blockParamId, path.parts);
} else if (!name) {
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
this.opcode('pushContext');
} else if (path.data) {
this.options.data = true;
this.opcode('lookupData', path.depth, path.parts, path.strict);
} else {
this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
}
},
StringLiteral: function StringLiteral(string) {
this.opcode('pushString', string.value);
},
NumberLiteral: function NumberLiteral(number) {
this.opcode('pushLiteral', number.value);
},
BooleanLiteral: function BooleanLiteral(bool) {
this.opcode('pushLiteral', bool.value);
},
UndefinedLiteral: function UndefinedLiteral() {
this.opcode('pushLiteral', 'undefined');
},
NullLiteral: function NullLiteral() {
this.opcode('pushLiteral', 'null');
},
Hash: function Hash(hash) {
var pairs = hash.pairs,
i = 0,
l = pairs.length;
this.opcode('pushHash');
for (; i < l; i++) {
this.pushParam(pairs[i].value);
}
while (i--) {
this.opcode('assignToHash', pairs[i].key);
}
this.opcode('popHash');
},
// HELPERS
opcode: function opcode(name) {
this.opcodes.push({
opcode: name,
args: slice.call(arguments, 1),
loc: this.sourceNode[0].loc
});
},
addDepth: function addDepth(depth) {
if (!depth) {
return;
}
this.useDepths = true;
},
classifySexpr: function classifySexpr(sexpr) {
var isSimple = _ast2['default'].helpers.simpleId(sexpr.path);
var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr);
// if a mustache is an eligible helper but not a definite
// helper, it is ambiguous, and will be resolved in a later
// pass or at runtime.
var isEligible = !isBlockParam && (isHelper || isSimple);
// if ambiguous, we can possibly resolve the ambiguity now
// An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
if (isEligible && !isHelper) {
var _name = sexpr.path.parts[0],
options = this.options;
if (options.knownHelpers[_name]) {
isHelper = true;
} else if (options.knownHelpersOnly) {
isEligible = false;
}
}
if (isHelper) {
return 'helper';
} else if (isEligible) {
return 'ambiguous';
} else {
return 'simple';
}
},
pushParams: function pushParams(params) {
for (var i = 0, l = params.length; i < l; i++) {
this.pushParam(params[i]);
}
},
pushParam: function pushParam(val) {
var value = val.value != null ? val.value : val.original || '';
if (this.stringParams) {
if (value.replace) {
value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
}
if (val.depth) {
this.addDepth(val.depth);
}
this.opcode('getContext', val.depth || 0);
this.opcode('pushStringParam', value, val.type);
if (val.type === 'SubExpression') {
// SubExpressions get evaluated and passed in
// in string params mode.
this.accept(val);
}
} else {
if (this.trackIds) {
var blockParamIndex = undefined;
if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) {
blockParamIndex = this.blockParamIndex(val.parts[0]);
}
if (blockParamIndex) {
var blockParamChild = val.parts.slice(1).join('.');
this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
} else {
value = val.original || value;
if (value.replace) {
value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, '');
}
this.opcode('pushId', val.type, value);
}
}
this.accept(val);
}
},
setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
var params = sexpr.params;
this.pushParams(params);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
if (sexpr.hash) {
this.accept(sexpr.hash);
} else {
this.opcode('emptyHash', omitEmpty);
}
return params;
},
blockParamIndex: function blockParamIndex(name) {
for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
var blockParams = this.options.blockParams[depth],
param = blockParams && _utils.indexOf(blockParams, name);
if (blockParams && param >= 0) {
return [depth, param];
}
}
}
};
function precompile(input, options, env) {
if (input == null || typeof input !== 'string' && input.type !== 'Program') {
throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
if (options.compat) {
options.useDepths = true;
}
var ast = env.parse(input, options),
environment = new env.Compiler().compile(ast, options);
return new env.JavaScriptCompiler().compile(environment, options);
}
function compile(input, options, env) {
if (options === undefined) options = {};
if (input == null || typeof input !== 'string' && input.type !== 'Program') {
throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
}
options = _utils.extend({}, options);
if (!('data' in options)) {
options.data = true;
}
if (options.compat) {
options.useDepths = true;
}
var compiled = undefined;
function compileInput() {
var ast = env.parse(input, options),
environment = new env.Compiler().compile(ast, options),
templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
return env.template(templateSpec);
}
// Template is only compiled on first use and cached after that point.
function ret(context, execOptions) {
if (!compiled) {
compiled = compileInput();
}
return compiled.call(this, context, execOptions);
}
ret._setup = function (setupOptions) {
if (!compiled) {
compiled = compileInput();
}
return compiled._setup(setupOptions);
};
ret._child = function (i, data, blockParams, depths) {
if (!compiled) {
compiled = compileInput();
}
return compiled._child(i, data, blockParams, depths);
};
return ret;
}
function argEquals(a, b) {
if (a === b) {
return true;
}
if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (!argEquals(a[i], b[i])) {
return false;
}
}
return true;
}
}
function transformLiteralToPath(sexpr) {
if (!sexpr.path.parts) {
var literal = sexpr.path;
// Casting to string here to make false and 0 literal values play nicely with the rest
// of the system.
sexpr.path = {
type: 'PathExpression',
data: false,
depth: 0,
parts: [literal.original + ''],
original: literal.original + '',
loc: literal.loc
};
}
}
},{"../exception":32,"../utils":48,"./ast":20}],24:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.SourceLocation = SourceLocation;
exports.id = id;
exports.stripFlags = stripFlags;
exports.stripComment = stripComment;
exports.preparePath = preparePath;
exports.prepareMustache = prepareMustache;
exports.prepareRawBlock = prepareRawBlock;
exports.prepareBlock = prepareBlock;
exports.prepareProgram = prepareProgram;
exports.preparePartialBlock = preparePartialBlock;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
function validateClose(open, close) {
close = close.path ? close.path.original : close;
if (open.path.original !== close) {
var errorNode = { loc: open.path.loc };
throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode);
}
}
function SourceLocation(source, locInfo) {
this.source = source;
this.start = {
line: locInfo.first_line,
column: locInfo.first_column
};
this.end = {
line: locInfo.last_line,
column: locInfo.last_column
};
}
function id(token) {
if (/^\[.*\]$/.test(token)) {
return token.substring(1, token.length - 1);
} else {
return token;
}
}
function stripFlags(open, close) {
return {
open: open.charAt(2) === '~',
close: close.charAt(close.length - 3) === '~'
};
}
function stripComment(comment) {
return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, '');
}
function preparePath(data, parts, loc) {
loc = this.locInfo(loc);
var original = data ? '@' : '',
dig = [],
depth = 0;
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i].part,
// If we have [] syntax then we do not treat path references as operators,
// i.e. foo.[this] resolves to approximately context.foo['this']
isLiteral = parts[i].original !== part;
original += (parts[i].separator || '') + part;
if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
if (dig.length > 0) {
throw new _exception2['default']('Invalid path: ' + original, { loc: loc });
} else if (part === '..') {
depth++;
}
} else {
dig.push(part);
}
}
return {
type: 'PathExpression',
data: data,
depth: depth,
parts: dig,
original: original,
loc: loc
};
}
function prepareMustache(path, params, hash, open, strip, locInfo) {
// Must use charAt to support IE pre-10
var escapeFlag = open.charAt(3) || open.charAt(2),
escaped = escapeFlag !== '{' && escapeFlag !== '&';
var decorator = /\*/.test(open);
return {
type: decorator ? 'Decorator' : 'MustacheStatement',
path: path,
params: params,
hash: hash,
escaped: escaped,
strip: strip,
loc: this.locInfo(locInfo)
};
}
function prepareRawBlock(openRawBlock, contents, close, locInfo) {
validateClose(openRawBlock, close);
locInfo = this.locInfo(locInfo);
var program = {
type: 'Program',
body: contents,
strip: {},
loc: locInfo
};
return {
type: 'BlockStatement',
path: openRawBlock.path,
params: openRawBlock.params,
hash: openRawBlock.hash,
program: program,
openStrip: {},
inverseStrip: {},
closeStrip: {},
loc: locInfo
};
}
function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
if (close && close.path) {
validateClose(openBlock, close);
}
var decorator = /\*/.test(openBlock.open);
program.blockParams = openBlock.blockParams;
var inverse = undefined,
inverseStrip = undefined;
if (inverseAndProgram) {
if (decorator) {
throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram);
}
if (inverseAndProgram.chain) {
inverseAndProgram.program.body[0].closeStrip = close.strip;
}
inverseStrip = inverseAndProgram.strip;
inverse = inverseAndProgram.program;
}
if (inverted) {
inverted = inverse;
inverse = program;
program = inverted;
}
return {
type: decorator ? 'DecoratorBlock' : 'BlockStatement',
path: openBlock.path,
params: openBlock.params,
hash: openBlock.hash,
program: program,
inverse: inverse,
openStrip: openBlock.strip,
inverseStrip: inverseStrip,
closeStrip: close && close.strip,
loc: this.locInfo(locInfo)
};
}
function prepareProgram(statements, loc) {
if (!loc && statements.length) {
var firstLoc = statements[0].loc,
lastLoc = statements[statements.length - 1].loc;
/* istanbul ignore else */
if (firstLoc && lastLoc) {
loc = {
source: firstLoc.source,
start: {
line: firstLoc.start.line,
column: firstLoc.start.column
},
end: {
line: lastLoc.end.line,
column: lastLoc.end.column
}
};
}
}
return {
type: 'Program',
body: statements,
strip: {},
loc: loc
};
}
function preparePartialBlock(open, program, close, locInfo) {
validateClose(open, close);
return {
type: 'PartialBlockStatement',
name: open.path,
params: open.params,
hash: open.hash,
program: program,
openStrip: open.strip,
closeStrip: close && close.strip,
loc: this.locInfo(locInfo)
};
}
},{"../exception":32}],25:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _base = require('../base');
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
var _utils = require('../utils');
var _codeGen = require('./code-gen');
var _codeGen2 = _interopRequireDefault(_codeGen);
function Literal(value) {
this.value = value;
}
function JavaScriptCompiler() {}
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function nameLookup(parent, name /*, type */) {
return this.internalNameLookup(parent, name);
},
depthedLookup: function depthedLookup(name) {
return [this.aliasable('container.lookup'), '(depths, "', name, '")'];
},
compilerInfo: function compilerInfo() {
var revision = _base.COMPILER_REVISION,
versions = _base.REVISION_CHANGES[revision];
return [revision, versions];
},
appendToBuffer: function appendToBuffer(source, location, explicit) {
// Force a source as this simplifies the merge logic.
if (!_utils.isArray(source)) {
source = [source];
}
source = this.source.wrap(source, location);
if (this.environment.isSimple) {
return ['return ', source, ';'];
} else if (explicit) {
// This is a case where the buffer operation occurs as a child of another
// construct, generally braces. We have to explicitly output these buffer
// operations to ensure that the emitted code goes in the correct location.
return ['buffer += ', source, ';'];
} else {
source.appendToBuffer = true;
return source;
}
},
initializeBuffer: function initializeBuffer() {
return this.quotedString('');
},
// END PUBLIC API
internalNameLookup: function internalNameLookup(parent, name) {
this.lookupPropertyFunctionIsUsed = true;
return ['lookupProperty(', parent, ',', JSON.stringify(name), ')'];
},
lookupPropertyFunctionIsUsed: false,
compile: function compile(environment, options, context, asObject) {
this.environment = environment;
this.options = options;
this.stringParams = this.options.stringParams;
this.trackIds = this.options.trackIds;
this.precompile = !asObject;
this.name = this.environment.name;
this.isChild = !!context;
this.context = context || {
decorators: [],
programs: [],
environments: []
};
this.preamble();
this.stackSlot = 0;
this.stackVars = [];
this.aliases = {};
this.registers = { list: [] };
this.hashes = [];
this.compileStack = [];
this.inlineStack = [];
this.blockParams = [];
this.compileChildren(environment, options);
this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat;
this.useBlockParams = this.useBlockParams || environment.useBlockParams;
var opcodes = environment.opcodes,
opcode = undefined,
firstLoc = undefined,
i = undefined,
l = undefined;
for (i = 0, l = opcodes.length; i < l; i++) {
opcode = opcodes[i];
this.source.currentLocation = opcode.loc;
firstLoc = firstLoc || opcode.loc;
this[opcode.opcode].apply(this, opcode.args);
}
// Flush any trailing content that might be pending.
this.source.currentLocation = firstLoc;
this.pushSource('');
/* istanbul ignore next */
if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
throw new _exception2['default']('Compile completed with content left on stack');
}
if (!this.decorators.isEmpty()) {
this.useDecorators = true;
this.decorators.prepend(['var decorators = container.decorators, ', this.lookupPropertyFunctionVarDeclaration(), ';\n']);
this.decorators.push('return fn;');
if (asObject) {
this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]);
} else {
this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n');
this.decorators.push('}\n');
this.decorators = this.decorators.merge();
}
} else {
this.decorators = undefined;
}
var fn = this.createFunctionContext(asObject);
if (!this.isChild) {
var ret = {
compiler: this.compilerInfo(),
main: fn
};
if (this.decorators) {
ret.main_d = this.decorators; // eslint-disable-line camelcase
ret.useDecorators = true;
}
var _context = this.context;
var programs = _context.programs;
var decorators = _context.decorators;
for (i = 0, l = programs.length; i < l; i++) {
if (programs[i]) {
ret[i] = programs[i];
if (decorators[i]) {
ret[i + '_d'] = decorators[i];
ret.useDecorators = true;
}
}
}
if (this.environment.usePartial) {
ret.usePartial = true;
}
if (this.options.data) {
ret.useData = true;
}
if (this.useDepths) {
ret.useDepths = true;
}
if (this.useBlockParams) {
ret.useBlockParams = true;
}
if (this.options.compat) {
ret.compat = true;
}
if (!asObject) {
ret.compiler = JSON.stringify(ret.compiler);
this.source.currentLocation = { start: { line: 1, column: 0 } };
ret = this.objectLiteral(ret);
if (options.srcName) {
ret = ret.toStringWithSourceMap({ file: options.destName });
ret.map = ret.map && ret.map.toString();
} else {
ret = ret.toString();
}
} else {
ret.compilerOptions = this.options;
}
return ret;
} else {
return fn;
}
},
preamble: function preamble() {
// track the last context pushed into place to allow skipping the
// getContext opcode when it would be a noop
this.lastContext = 0;
this.source = new _codeGen2['default'](this.options.srcName);
this.decorators = new _codeGen2['default'](this.options.srcName);
},
createFunctionContext: function createFunctionContext(asObject) {
// istanbul ignore next
var _this = this;
var varDeclarations = '';
var locals = this.stackVars.concat(this.registers.list);
if (locals.length > 0) {
varDeclarations += ', ' + locals.join(', ');
}
// Generate minimizer alias mappings
//
// When using true SourceNodes, this will update all references to the given alias
// as the source nodes are reused in situ. For the non-source node compilation mode,
// aliases will not be used, but this case is already being run on the client and
// we aren't concern about minimizing the template size.
var aliasCount = 0;
Object.keys(this.aliases).forEach(function (alias) {
var node = _this.aliases[alias];
if (node.children && node.referenceCount > 1) {
varDeclarations += ', alias' + ++aliasCount + '=' + alias;
node.children[0] = 'alias' + aliasCount;
}
});
if (this.lookupPropertyFunctionIsUsed) {
varDeclarations += ', ' + this.lookupPropertyFunctionVarDeclaration();
}
var params = ['container', 'depth0', 'helpers', 'partials', 'data'];
if (this.useBlockParams || this.useDepths) {
params.push('blockParams');
}
if (this.useDepths) {
params.push('depths');
}
// Perform a second pass over the output to merge content when possible
var source = this.mergeSource(varDeclarations);
if (asObject) {
params.push(source);
return Function.apply(this, params);
} else {
return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']);
}
},
mergeSource: function mergeSource(varDeclarations) {
var isSimple = this.environment.isSimple,
appendOnly = !this.forceBuffer,
appendFirst = undefined,
sourceSeen = undefined,
bufferStart = undefined,
bufferEnd = undefined;
this.source.each(function (line) {
if (line.appendToBuffer) {
if (bufferStart) {
line.prepend(' + ');
} else {
bufferStart = line;
}
bufferEnd = line;
} else {
if (bufferStart) {
if (!sourceSeen) {
appendFirst = true;
} else {
bufferStart.prepend('buffer += ');
}
bufferEnd.add(';');
bufferStart = bufferEnd = undefined;
}
sourceSeen = true;
if (!isSimple) {
appendOnly = false;
}
}
});
if (appendOnly) {
if (bufferStart) {
bufferStart.prepend('return ');
bufferEnd.add(';');
} else if (!sourceSeen) {
this.source.push('return "";');
}
} else {
varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());
if (bufferStart) {
bufferStart.prepend('return buffer + ');
bufferEnd.add(';');
} else {
this.source.push('return buffer;');
}
}
if (varDeclarations) {
this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
}
return this.source.merge();
},
lookupPropertyFunctionVarDeclaration: function lookupPropertyFunctionVarDeclaration() {
return '\n lookupProperty = container.lookupProperty || function(parent, propertyName) {\n if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {\n return parent[propertyName];\n }\n return undefined\n }\n '.trim();
},
// [blockValue]
//
// On stack, before: hash, inverse, program, value
// On stack, after: return value of blockHelperMissing
//
// The purpose of this opcode is to take a block of the form
// `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function blockValue(name) {
var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs(name, 0, params);
var blockName = this.popStack();
params.splice(1, 0, blockName);
this.push(this.source.functionCall(blockHelperMissing, 'call', params));
},
// [ambiguousBlockValue]
//
// On stack, before: hash, inverse, program, value
// Compiler value, before: lastHelper=value of last found helper, if any
// On stack, after, if no lastHelper: same as [blockValue]
// On stack, after, if lastHelper: value
ambiguousBlockValue: function ambiguousBlockValue() {
// We're being a bit cheeky and reusing the options value from the prior exec
var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs('', 0, params, true);
this.flushInline();
var current = this.topStack();
params.splice(1, 0, current);
this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
},
// [appendContent]
//
// On stack, before: ...
// On stack, after: ...
//
// Appends the string value of `content` to the current buffer
appendContent: function appendContent(content) {
if (this.pendingContent) {
content = this.pendingContent + content;
} else {
this.pendingLocation = this.source.currentLocation;
}
this.pendingContent = content;
},
// [append]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Coerces `value` to a String and appends it to the current buffer.
//
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function append() {
if (this.isInline()) {
this.replaceStack(function (current) {
return [' != null ? ', current, ' : ""'];
});
this.pushSource(this.appendToBuffer(this.popStack()));
} else {
var local = this.popStack();
this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
if (this.environment.isSimple) {
this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
}
}
},
// [appendEscaped]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Escape `value` and append it to the buffer
appendEscaped: function appendEscaped() {
this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')']));
},
// [getContext]
//
// On stack, before: ...
// On stack, after: ...
// Compiler value, after: lastContext=depth
//
// Set the value of the `lastContext` compiler value to the depth
getContext: function getContext(depth) {
this.lastContext = depth;
},
// [pushContext]
//
// On stack, before: ...
// On stack, after: currentContext, ...
//
// Pushes the value of the current context onto the stack.
pushContext: function pushContext() {
this.pushStackLiteral(this.contextName(this.lastContext));
},
// [lookupOnContext]
//
// On stack, before: ...
// On stack, after: currentContext[name], ...
//
// Looks up the value of `name` on the current context and pushes
// it onto the stack.
lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) {
var i = 0;
if (!scoped && this.options.compat && !this.lastContext) {
// The depthed query is expected to handle the undefined logic for the root level that
// is implemented below, so we evaluate that directly in compat mode
this.push(this.depthedLookup(parts[i++]));
} else {
this.pushContext();
}
this.resolvePath('context', parts, i, falsy, strict);
},
// [lookupBlockParam]
//
// On stack, before: ...
// On stack, after: blockParam[name], ...
//
// Looks up the value of `parts` on the given block param and pushes
// it onto the stack.
lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
this.useBlockParams = true;
this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
this.resolvePath('context', parts, 1);
},
// [lookupData]
//
// On stack, before: ...
// On stack, after: data, ...
//
// Push the data lookup operator
lookupData: function lookupData(depth, parts, strict) {
if (!depth) {
this.pushStackLiteral('data');
} else {
this.pushStackLiteral('container.data(data, ' + depth + ')');
}
this.resolvePath('data', parts, 0, true, strict);
},
resolvePath: function resolvePath(type, parts, i, falsy, strict) {
// istanbul ignore next
var _this2 = this;
if (this.options.strict || this.options.assumeObjects) {
this.push(strictLookup(this.options.strict && strict, this, parts, type));
return;
}
var len = parts.length;
for (; i < len; i++) {
/* eslint-disable no-loop-func */
this.replaceStack(function (current) {
var lookup = _this2.nameLookup(current, parts[i], type);
// We want to ensure that zero and false are handled properly if the context (falsy flag)
// needs to have the special handling for these values.
if (!falsy) {
return [' != null ? ', lookup, ' : ', current];
} else {
// Otherwise we can use generic falsy handling
return [' && ', lookup];
}
});
/* eslint-enable no-loop-func */
}
},
// [resolvePossibleLambda]
//
// On stack, before: value, ...
// On stack, after: resolved value, ...
//
// If the `value` is a lambda, replace it on the stack by
// the return value of the lambda
resolvePossibleLambda: function resolvePossibleLambda() {
this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
},
// [pushStringParam]
//
// On stack, before: ...
// On stack, after: string, currentContext, ...
//
// This opcode is designed for use in string mode, which
// provides the string value of a parameter along with its
// depth rather than resolving it immediately.
pushStringParam: function pushStringParam(string, type) {
this.pushContext();
this.pushString(type);
// If it's a subexpression, the string result
// will be pushed after this opcode.
if (type !== 'SubExpression') {
if (typeof string === 'string') {
this.pushString(string);
} else {
this.pushStackLiteral(string);
}
}
},
emptyHash: function emptyHash(omitEmpty) {
if (this.trackIds) {
this.push('{}'); // hashIds
}
if (this.stringParams) {
this.push('{}'); // hashContexts
this.push('{}'); // hashTypes
}
this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
},
pushHash: function pushHash() {
if (this.hash) {
this.hashes.push(this.hash);
}
this.hash = { values: {}, types: [], contexts: [], ids: [] };
},
popHash: function popHash() {
var hash = this.hash;
this.hash = this.hashes.pop();
if (this.trackIds) {
this.push(this.objectLiteral(hash.ids));
}
if (this.stringParams) {
this.push(this.objectLiteral(hash.contexts));
this.push(this.objectLiteral(hash.types));
}
this.push(this.objectLiteral(hash.values));
},
// [pushString]
//
// On stack, before: ...
// On stack, after: quotedString(string), ...
//
// Push a quoted version of `string` onto the stack
pushString: function pushString(string) {
this.pushStackLiteral(this.quotedString(string));
},
// [pushLiteral]
//
// On stack, before: ...
// On stack, after: value, ...
//
// Pushes a value onto the stack. This operation prevents
// the compiler from creating a temporary variable to hold
// it.
pushLiteral: function pushLiteral(value) {
this.pushStackLiteral(value);
},
// [pushProgram]
//
// On stack, before: ...
// On stack, after: program(guid), ...
//
// Push a program expression onto the stack. This takes
// a compile-time guid and converts it into a runtime-accessible
// expression.
pushProgram: function pushProgram(guid) {
if (guid != null) {
this.pushStackLiteral(this.programExpression(guid));
} else {
this.pushStackLiteral(null);
}
},
// [registerDecorator]
//
// On stack, before: hash, program, params..., ...
// On stack, after: ...
//
// Pops off the decorator's parameters, invokes the decorator,
// and inserts the decorator into the decorators list.
registerDecorator: function registerDecorator(paramSize, name) {
var foundDecorator = this.nameLookup('decorators', name, 'decorator'),
options = this.setupHelperArgs(name, paramSize);
this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']);
},
// [invokeHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// Pops off the helper's parameters, invokes the helper,
// and pushes the helper's return value onto the stack.
//
// If the helper is not found, `helperMissing` is called.
invokeHelper: function invokeHelper(paramSize, name, isSimple) {
var nonHelper = this.popStack(),
helper = this.setupHelper(paramSize, name);
var possibleFunctionCalls = [];
if (isSimple) {
// direct call to helper
possibleFunctionCalls.push(helper.name);
}
// call a function from the input object
possibleFunctionCalls.push(nonHelper);
if (!this.options.strict) {
possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
}
var functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
var functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
this.push(functionCall);
},
itemsSeparatedBy: function itemsSeparatedBy(items, separator) {
var result = [];
result.push(items[0]);
for (var i = 1; i < items.length; i++) {
result.push(separator, items[i]);
}
return result;
},
// [invokeKnownHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// This operation is used when the helper is known to exist,
// so a `helperMissing` fallback is not required.
invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
var helper = this.setupHelper(paramSize, name);
this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
},
// [invokeAmbiguous]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of disambiguation
//
// This operation is used when an expression like `{{foo}}`
// is provided, but we don't know at compile-time whether it
// is a helper or a path.
//
// This operation emits more code than the other options,
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
this.useRegister('helper');
var nonHelper = this.popStack();
this.emptyHash();
var helper = this.setupHelper(0, name, helperCall);
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
if (!this.options.strict) {
lookup[0] = '(helper = ';
lookup.push(' != null ? helper : ', this.aliasable('container.hooks.helperMissing'));
}
this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
},
// [invokePartial]
//
// On stack, before: context, ...
// On stack after: result of partial invocation
//
// This operation pops off a context, invokes a partial with that context,
// and pushes the result of the invocation back.
invokePartial: function invokePartial(isDynamic, name, indent) {
var params = [],
options = this.setupParams(name, 1, params);
if (isDynamic) {
name = this.popStack();
delete options.name;
}
if (indent) {
options.indent = JSON.stringify(indent);
}
options.helpers = 'helpers';
options.partials = 'partials';
options.decorators = 'container.decorators';
if (!isDynamic) {
params.unshift(this.nameLookup('partials', name, 'partial'));
} else {
params.unshift(name);
}
if (this.options.compat) {
options.depths = 'depths';
}
options = this.objectLiteral(options);
params.push(options);
this.push(this.source.functionCall('container.invokePartial', '', params));
},
// [assignToHash]
//
// On stack, before: value, ..., hash, ...
// On stack, after: ..., hash, ...
//
// Pops a value off the stack and assigns it to the current hash
assignToHash: function assignToHash(key) {
var value = this.popStack(),
context = undefined,
type = undefined,
id = undefined;
if (this.trackIds) {
id = this.popStack();
}
if (this.stringParams) {
type = this.popStack();
context = this.popStack();
}
var hash = this.hash;
if (context) {
hash.contexts[key] = context;
}
if (type) {
hash.types[key] = type;
}
if (id) {
hash.ids[key] = id;
}
hash.values[key] = value;
},
pushId: function pushId(type, name, child) {
if (type === 'BlockParam') {
this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
} else if (type === 'PathExpression') {
this.pushString(name);
} else if (type === 'SubExpression') {
this.pushStackLiteral('true');
} else {
this.pushStackLiteral('null');
}
},
// HELPERS
compiler: JavaScriptCompiler,
compileChildren: function compileChildren(environment, options) {
var children = environment.children,
child = undefined,
compiler = undefined;
for (var i = 0, l = children.length; i < l; i++) {
child = children[i];
compiler = new this.compiler(); // eslint-disable-line new-cap
var existing = this.matchExistingProgram(child);
if (existing == null) {
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
var index = this.context.programs.length;
child.index = index;
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
this.context.decorators[index] = compiler.decorators;
this.context.environments[index] = child;
this.useDepths = this.useDepths || compiler.useDepths;
this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
child.useDepths = this.useDepths;
child.useBlockParams = this.useBlockParams;
} else {
child.index = existing.index;
child.name = 'program' + existing.index;
this.useDepths = this.useDepths || existing.useDepths;
this.useBlockParams = this.useBlockParams || existing.useBlockParams;
}
}
},
matchExistingProgram: function matchExistingProgram(child) {
for (var i = 0, len = this.context.environments.length; i < len; i++) {
var environment = this.context.environments[i];
if (environment && environment.equals(child)) {
return environment;
}
}
},
programExpression: function programExpression(guid) {
var child = this.environment.children[guid],
programParams = [child.index, 'data', child.blockParams];
if (this.useBlockParams || this.useDepths) {
programParams.push('blockParams');
}
if (this.useDepths) {
programParams.push('depths');
}
return 'container.program(' + programParams.join(', ') + ')';
},
useRegister: function useRegister(name) {
if (!this.registers[name]) {
this.registers[name] = true;
this.registers.list.push(name);
}
},
push: function push(expr) {
if (!(expr instanceof Literal)) {
expr = this.source.wrap(expr);
}
this.inlineStack.push(expr);
return expr;
},
pushStackLiteral: function pushStackLiteral(item) {
this.push(new Literal(item));
},
pushSource: function pushSource(source) {
if (this.pendingContent) {
this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
this.pendingContent = undefined;
}
if (source) {
this.source.push(source);
}
},
replaceStack: function replaceStack(callback) {
var prefix = ['('],
stack = undefined,
createdStack = undefined,
usedLiteral = undefined;
/* istanbul ignore next */
if (!this.isInline()) {
throw new _exception2['default']('replaceStack on non-inline');
}
// We want to merge the inline statement into the replacement statement via ','
var top = this.popStack(true);
if (top instanceof Literal) {
// Literals do not need to be inlined
stack = [top.value];
prefix = ['(', stack];
usedLiteral = true;
} else {
// Get or create the current stack name for use by the inline
createdStack = true;
var _name = this.incrStack();
prefix = ['((', this.push(_name), ' = ', top, ')'];
stack = this.topStack();
}
var item = callback.call(this, stack);
if (!usedLiteral) {
this.popStack();
}
if (createdStack) {
this.stackSlot--;
}
this.push(prefix.concat(item, ')'));
},
incrStack: function incrStack() {
this.stackSlot++;
if (this.stackSlot > this.stackVars.length) {
this.stackVars.push('stack' + this.stackSlot);
}
return this.topStackName();
},
topStackName: function topStackName() {
return 'stack' + this.stackSlot;
},
flushInline: function flushInline() {
var inlineStack = this.inlineStack;
this.inlineStack = [];
for (var i = 0, len = inlineStack.length; i < len; i++) {
var entry = inlineStack[i];
/* istanbul ignore if */
if (entry instanceof Literal) {
this.compileStack.push(entry);
} else {
var stack = this.incrStack();
this.pushSource([stack, ' = ', entry, ';']);
this.compileStack.push(stack);
}
}
},
isInline: function isInline() {
return this.inlineStack.length;
},
popStack: function popStack(wrapped) {
var inline = this.isInline(),
item = (inline ? this.inlineStack : this.compileStack).pop();
if (!wrapped && item instanceof Literal) {
return item.value;
} else {
if (!inline) {
/* istanbul ignore next */
if (!this.stackSlot) {
throw new _exception2['default']('Invalid stack pop');
}
this.stackSlot--;
}
return item;
}
},
topStack: function topStack() {
var stack = this.isInline() ? this.inlineStack : this.compileStack,
item = stack[stack.length - 1];
/* istanbul ignore if */
if (item instanceof Literal) {
return item.value;
} else {
return item;
}
},
contextName: function contextName(context) {
if (this.useDepths && context) {
return 'depths[' + context + ']';
} else {
return 'depth' + context;
}
},
quotedString: function quotedString(str) {
return this.source.quotedString(str);
},
objectLiteral: function objectLiteral(obj) {
return this.source.objectLiteral(obj);
},
aliasable: function aliasable(name) {
var ret = this.aliases[name];
if (ret) {
ret.referenceCount++;
return ret;
}
ret = this.aliases[name] = this.source.wrap(name);
ret.aliasable = true;
ret.referenceCount = 1;
return ret;
},
setupHelper: function setupHelper(paramSize, name, blockHelper) {
var params = [],
paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
var foundHelper = this.nameLookup('helpers', name, 'helper'),
callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})');
return {
params: params,
paramsInit: paramsInit,
name: foundHelper,
callParams: [callContext].concat(params)
};
},
setupParams: function setupParams(helper, paramSize, params) {
var options = {},
contexts = [],
types = [],
ids = [],
objectArgs = !params,
param = undefined;
if (objectArgs) {
params = [];
}
options.name = this.quotedString(helper);
options.hash = this.popStack();
if (this.trackIds) {
options.hashIds = this.popStack();
}
if (this.stringParams) {
options.hashTypes = this.popStack();
options.hashContexts = this.popStack();
}
var inverse = this.popStack(),
program = this.popStack();
// Avoid setting fn and inverse if neither are set. This allows
// helpers to do a check for `if (options.fn)`
if (program || inverse) {
options.fn = program || 'container.noop';
options.inverse = inverse || 'container.noop';
}
// The parameters go on to the stack in order (making sure that they are evaluated in order)
// so we need to pop them off the stack in reverse order
var i = paramSize;
while (i--) {
param = this.popStack();
params[i] = param;
if (this.trackIds) {
ids[i] = this.popStack();
}
if (this.stringParams) {
types[i] = this.popStack();
contexts[i] = this.popStack();
}
}
if (objectArgs) {
options.args = this.source.generateArray(params);
}
if (this.trackIds) {
options.ids = this.source.generateArray(ids);
}
if (this.stringParams) {
options.types = this.source.generateArray(types);
options.contexts = this.source.generateArray(contexts);
}
if (this.options.data) {
options.data = 'data';
}
if (this.useBlockParams) {
options.blockParams = 'blockParams';
}
return options;
},
setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
var options = this.setupParams(helper, paramSize, params);
options.loc = JSON.stringify(this.source.currentLocation);
options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
params.push('options');
return ['options=', options];
} else if (params) {
params.push(options);
return '';
} else {
return options;
}
}
};
(function () {
var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' ');
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
for (var i = 0, l = reservedWords.length; i < l; i++) {
compilerWords[reservedWords[i]] = true;
}
})();
/**
* @deprecated May be removed in the next major version
*/
JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
};
function strictLookup(requireTerminal, compiler, parts, type) {
var stack = compiler.popStack(),
i = 0,
len = parts.length;
if (requireTerminal) {
len--;
}
for (; i < len; i++) {
stack = compiler.nameLookup(stack, parts[i], type);
}
if (requireTerminal) {
return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ', ', JSON.stringify(compiler.source.currentLocation), ' )'];
} else {
return stack;
}
}
exports['default'] = JavaScriptCompiler;
module.exports = exports['default'];
},{"../base":19,"../exception":32,"../utils":48,"./code-gen":22}],26:[function(require,module,exports){
// File ignored in coverage tests via setting in .istanbul.yml
/* Jison generated parser */
"use strict";
exports.__esModule = true;
var handlebars = (function () {
var parser = { trace: function trace() {},
yy: {},
symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 },
terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" },
productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 0], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
var $0 = $$.length - 1;
switch (yystate) {
case 1:
return $$[$0 - 1];
break;
case 2:
this.$ = yy.prepareProgram($$[$0]);
break;
case 3:
this.$ = $$[$0];
break;
case 4:
this.$ = $$[$0];
break;
case 5:
this.$ = $$[$0];
break;
case 6:
this.$ = $$[$0];
break;
case 7:
this.$ = $$[$0];
break;
case 8:
this.$ = $$[$0];
break;
case 9:
this.$ = {
type: 'CommentStatement',
value: yy.stripComment($$[$0]),
strip: yy.stripFlags($$[$0], $$[$0]),
loc: yy.locInfo(this._$)
};
break;
case 10:
this.$ = {
type: 'ContentStatement',
original: $$[$0],
value: $$[$0],
loc: yy.locInfo(this._$)
};
break;
case 11:
this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
break;
case 12:
this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
break;
case 13:
this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
break;
case 14:
this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
break;
case 15:
this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 16:
this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 17:
this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 18:
this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
break;
case 19:
var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
program = yy.prepareProgram([inverse], $$[$0 - 1].loc);
program.chained = true;
this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };
break;
case 20:
this.$ = $$[$0];
break;
case 21:
this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
break;
case 22:
this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
break;
case 23:
this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
break;
case 24:
this.$ = {
type: 'PartialStatement',
name: $$[$0 - 3],
params: $$[$0 - 2],
hash: $$[$0 - 1],
indent: '',
strip: yy.stripFlags($$[$0 - 4], $$[$0]),
loc: yy.locInfo(this._$)
};
break;
case 25:
this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
break;
case 26:
this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) };
break;
case 27:
this.$ = $$[$0];
break;
case 28:
this.$ = $$[$0];
break;
case 29:
this.$ = {
type: 'SubExpression',
path: $$[$0 - 3],
params: $$[$0 - 2],
hash: $$[$0 - 1],
loc: yy.locInfo(this._$)
};
break;
case 30:
this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) };
break;
case 31:
this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) };
break;
case 32:
this.$ = yy.id($$[$0 - 1]);
break;
case 33:
this.$ = $$[$0];
break;
case 34:
this.$ = $$[$0];
break;
case 35:
this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) };
break;
case 36:
this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) };
break;
case 37:
this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) };
break;
case 38:
this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) };
break;
case 39:
this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) };
break;
case 40:
this.$ = $$[$0];
break;
case 41:
this.$ = $$[$0];
break;
case 42:
this.$ = yy.preparePath(true, $$[$0], this._$);
break;
case 43:
this.$ = yy.preparePath(false, $$[$0], this._$);
break;
case 44:
$$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2];
break;
case 45:
this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
break;
case 46:
this.$ = [];
break;
case 47:
$$[$0 - 1].push($$[$0]);
break;
case 48:
this.$ = [];
break;
case 49:
$$[$0 - 1].push($$[$0]);
break;
case 50:
this.$ = [];
break;
case 51:
$$[$0 - 1].push($$[$0]);
break;
case 58:
this.$ = [];
break;
case 59:
$$[$0 - 1].push($$[$0]);
break;
case 64:
this.$ = [];
break;
case 65:
$$[$0 - 1].push($$[$0]);
break;
case 70:
this.$ = [];
break;
case 71:
$$[$0 - 1].push($$[$0]);
break;
case 78:
this.$ = [];
break;
case 79:
$$[$0 - 1].push($$[$0]);
break;
case 82:
this.$ = [];
break;
case 83:
$$[$0 - 1].push($$[$0]);
break;
case 86:
this.$ = [];
break;
case 87:
$$[$0 - 1].push($$[$0]);
break;
case 90:
this.$ = [];
break;
case 91:
$$[$0 - 1].push($$[$0]);
break;
case 94:
this.$ = [];
break;
case 95:
$$[$0 - 1].push($$[$0]);
break;
case 98:
this.$ = [$$[$0]];
break;
case 99:
$$[$0 - 1].push($$[$0]);
break;
case 100:
this.$ = [$$[$0]];
break;
case 101:
$$[$0 - 1].push($$[$0]);
break;
}
},
table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 15: [2, 48], 17: 39, 18: [2, 48] }, { 20: 41, 56: 40, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 44, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 45, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 41, 56: 48, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 49, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 50] }, { 72: [1, 35], 86: 51 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 52, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 53, 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 54, 47: [2, 54] }, { 28: 59, 43: 60, 44: [1, 58], 47: [2, 56] }, { 13: 62, 15: [1, 20], 18: [1, 61] }, { 33: [2, 86], 57: 63, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 64, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 65, 47: [1, 66] }, { 30: 67, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 68, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 69, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 70, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 74, 33: [2, 80], 50: 71, 63: 72, 64: 75, 65: [1, 43], 69: 73, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 79] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 50] }, { 20: 74, 53: 80, 54: [2, 84], 63: 81, 64: 75, 65: [1, 43], 69: 82, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 83, 47: [1, 66] }, { 47: [2, 55] }, { 4: 84, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 85, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 86, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 87, 47: [1, 66] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 74, 33: [2, 88], 58: 88, 63: 89, 64: 75, 65: [1, 43], 69: 90, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 91, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 92, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 31: 93, 33: [2, 60], 63: 94, 64: 75, 65: [1, 43], 69: 95, 70: 76, 71: 77, 72: [1, 78], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 66], 36: 96, 63: 97, 64: 75, 65: [1, 43], 69: 98, 70: 76, 71: 77, 72: [1, 78], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 22: 99, 23: [2, 52], 63: 100, 64: 75, 65: [1, 43], 69: 101, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 92], 62: 102, 63: 103, 64: 75, 65: [1, 43], 69: 104, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 105] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 106, 72: [1, 107], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 108], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 109] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 111, 46: 110, 47: [2, 76] }, { 33: [2, 70], 40: 112, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 113] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 74, 63: 115, 64: 75, 65: [1, 43], 67: 114, 68: [2, 96], 69: 116, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 117] }, { 32: 118, 33: [2, 62], 74: 119, 75: [1, 120] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 121, 74: 122, 75: [1, 120] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 123] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 124] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 108] }, { 20: 74, 63: 125, 64: 75, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 74, 33: [2, 72], 41: 126, 63: 127, 64: 75, 65: [1, 43], 69: 128, 70: 76, 71: 77, 72: [1, 78], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 129] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 130] }, { 33: [2, 63] }, { 72: [1, 132], 76: 131 }, { 33: [1, 133] }, { 33: [2, 69] }, { 15: [2, 12], 18: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 134, 74: 135, 75: [1, 120] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 137], 77: [1, 136] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 138] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }],
defaultActions: { 4: [2, 1], 54: [2, 55], 56: [2, 20], 60: [2, 57], 73: [2, 81], 82: [2, 85], 86: [2, 18], 90: [2, 89], 101: [2, 53], 104: [2, 93], 110: [2, 19], 111: [2, 77], 116: [2, 97], 119: [2, 63], 122: [2, 69], 135: [2, 75], 136: [2, 32] },
parseError: function parseError(str, hash) {
throw new Error(str);
},
parse: function parse(input) {
var self = this,
stack = [0],
vstack = [null],
lstack = [],
table = this.table,
yytext = "",
yylineno = 0,
yyleng = 0,
recovering = 0,
TERROR = 2,
EOF = 1;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || 1;
if (typeof token !== "number") {
token = self.symbols_[token] || token;
}
return token;
}
var symbol,
preErrorSymbol,
state,
action,
a,
r,
yyval = {},
p,
len,
newState,
expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == "undefined") {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === "undefined" || !action.length || !action[0]) {
var errStr = "";
if (!recovering) {
expected = [];
for (p in table[state]) if (this.terminals_[p] && p > 2) {
expected.push("'" + this.terminals_[p] + "'");
}
if (this.lexer.showPosition) {
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
} else {
errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
}
this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
}
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0) recovering--;
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
if (ranges) {
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
}
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
if (typeof r !== "undefined") {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}
};
/* Jison generated lexer */
var lexer = (function () {
var lexer = { EOF: 1,
parseError: function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
setInput: function setInput(input) {
this._input = input;
this._more = this._less = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
if (this.options.ranges) this.yylloc.range = [0, 0];
this.offset = 0;
return this;
},
input: function input() {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) this.yylloc.range[1]++;
this._input = this._input.slice(1);
return ch;
},
unput: function unput(ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) this.yylineno -= lines.length - 1;
var r = this.yylloc.range;
this.yylloc = { first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
return this;
},
more: function more() {
this._more = true;
return this;
},
less: function less(n) {
this.unput(this.match.slice(n));
},
pastInput: function pastInput() {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
},
upcomingInput: function upcomingInput() {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20 - next.length);
}
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
showPosition: function showPosition() {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
next: function next() {
if (this.done) {
return this.EOF;
}
if (!this._input) this.done = true;
var token, match, tempMatch, index, col, lines;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (!this.options.flex) break;
}
}
if (match) {
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) this.yylineno += lines.length;
this.yylloc = { first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length };
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) this.done = false;
if (token) return token;else return;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno });
}
},
lex: function lex() {
var r = this.next();
if (typeof r !== 'undefined') {
return r;
} else {
return this.lex();
}
},
begin: function begin(condition) {
this.conditionStack.push(condition);
},
popState: function popState() {
return this.conditionStack.pop();
},
_currentRules: function _currentRules() {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
},
topState: function topState() {
return this.conditionStack[this.conditionStack.length - 2];
},
pushState: function begin(condition) {
this.begin(condition);
} };
lexer.options = {};
lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
function strip(start, end) {
return yy_.yytext = yy_.yytext.substring(start, yy_.yyleng - end + start);
}
var YYSTATE = YY_START;
switch ($avoiding_name_collisions) {
case 0:
if (yy_.yytext.slice(-2) === "\\\\") {
strip(0, 1);
this.begin("mu");
} else if (yy_.yytext.slice(-1) === "\\") {
strip(0, 1);
this.begin("emu");
} else {
this.begin("mu");
}
if (yy_.yytext) return 15;
break;
case 1:
return 15;
break;
case 2:
this.popState();
return 15;
break;
case 3:
this.begin('raw');return 15;
break;
case 4:
this.popState();
// Should be using `this.topState()` below, but it currently
// returns the second top instead of the first top. Opened an
// issue about it at https://github.com/zaach/jison/issues/291
if (this.conditionStack[this.conditionStack.length - 1] === 'raw') {
return 15;
} else {
strip(5, 9);
return 'END_RAW_BLOCK';
}
break;
case 5:
return 15;
break;
case 6:
this.popState();
return 14;
break;
case 7:
return 65;
break;
case 8:
return 68;
break;
case 9:
return 19;
break;
case 10:
this.popState();
this.begin('raw');
return 23;
break;
case 11:
return 55;
break;
case 12:
return 60;
break;
case 13:
return 29;
break;
case 14:
return 47;
break;
case 15:
this.popState();return 44;
break;
case 16:
this.popState();return 44;
break;
case 17:
return 34;
break;
case 18:
return 39;
break;
case 19:
return 51;
break;
case 20:
return 48;
break;
case 21:
this.unput(yy_.yytext);
this.popState();
this.begin('com');
break;
case 22:
this.popState();
return 14;
break;
case 23:
return 48;
break;
case 24:
return 73;
break;
case 25:
return 72;
break;
case 26:
return 72;
break;
case 27:
return 87;
break;
case 28:
// ignore whitespace
break;
case 29:
this.popState();return 54;
break;
case 30:
this.popState();return 33;
break;
case 31:
yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80;
break;
case 32:
yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80;
break;
case 33:
return 85;
break;
case 34:
return 82;
break;
case 35:
return 82;
break;
case 36:
return 83;
break;
case 37:
return 84;
break;
case 38:
return 81;
break;
case 39:
return 75;
break;
case 40:
return 77;
break;
case 41:
return 72;
break;
case 42:
yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72;
break;
case 43:
return 'INVALID';
break;
case 44:
return 5;
break;
}
};
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]+?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/];
lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } };
return lexer;
})();
parser.lexer = lexer;
function Parser() {
this.yy = {};
}Parser.prototype = parser;parser.Parser = Parser;
return new Parser();
})();exports["default"] = handlebars;
module.exports = exports["default"];
},{}],27:[function(require,module,exports){
/* eslint-disable new-cap */
'use strict';
exports.__esModule = true;
exports.print = print;
exports.PrintVisitor = PrintVisitor;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _visitor = require('./visitor');
var _visitor2 = _interopRequireDefault(_visitor);
function print(ast) {
return new PrintVisitor().accept(ast);
}
function PrintVisitor() {
this.padding = 0;
}
PrintVisitor.prototype = new _visitor2['default']();
PrintVisitor.prototype.pad = function (string) {
var out = '';
for (var i = 0, l = this.padding; i < l; i++) {
out += ' ';
}
out += string + '\n';
return out;
};
PrintVisitor.prototype.Program = function (program) {
var out = '',
body = program.body,
i = undefined,
l = undefined;
if (program.blockParams) {
var blockParams = 'BLOCK PARAMS: [';
for (i = 0, l = program.blockParams.length; i < l; i++) {
blockParams += ' ' + program.blockParams[i];
}
blockParams += ' ]';
out += this.pad(blockParams);
}
for (i = 0, l = body.length; i < l; i++) {
out += this.accept(body[i]);
}
this.padding--;
return out;
};
PrintVisitor.prototype.MustacheStatement = function (mustache) {
return this.pad('{{ ' + this.SubExpression(mustache) + ' }}');
};
PrintVisitor.prototype.Decorator = function (mustache) {
return this.pad('{{ DIRECTIVE ' + this.SubExpression(mustache) + ' }}');
};
PrintVisitor.prototype.BlockStatement = PrintVisitor.prototype.DecoratorBlock = function (block) {
var out = '';
out += this.pad((block.type === 'DecoratorBlock' ? 'DIRECTIVE ' : '') + 'BLOCK:');
this.padding++;
out += this.pad(this.SubExpression(block));
if (block.program) {
out += this.pad('PROGRAM:');
this.padding++;
out += this.accept(block.program);
this.padding--;
}
if (block.inverse) {
if (block.program) {
this.padding++;
}
out += this.pad('{{^}}');
this.padding++;
out += this.accept(block.inverse);
this.padding--;
if (block.program) {
this.padding--;
}
}
this.padding--;
return out;
};
PrintVisitor.prototype.PartialStatement = function (partial) {
var content = 'PARTIAL:' + partial.name.original;
if (partial.params[0]) {
content += ' ' + this.accept(partial.params[0]);
}
if (partial.hash) {
content += ' ' + this.accept(partial.hash);
}
return this.pad('{{> ' + content + ' }}');
};
PrintVisitor.prototype.PartialBlockStatement = function (partial) {
var content = 'PARTIAL BLOCK:' + partial.name.original;
if (partial.params[0]) {
content += ' ' + this.accept(partial.params[0]);
}
if (partial.hash) {
content += ' ' + this.accept(partial.hash);
}
content += ' ' + this.pad('PROGRAM:');
this.padding++;
content += this.accept(partial.program);
this.padding--;
return this.pad('{{> ' + content + ' }}');
};
PrintVisitor.prototype.ContentStatement = function (content) {
return this.pad("CONTENT[ '" + content.value + "' ]");
};
PrintVisitor.prototype.CommentStatement = function (comment) {
return this.pad("{{! '" + comment.value + "' }}");
};
PrintVisitor.prototype.SubExpression = function (sexpr) {
var params = sexpr.params,
paramStrings = [],
hash = undefined;
for (var i = 0, l = params.length; i < l; i++) {
paramStrings.push(this.accept(params[i]));
}
params = '[' + paramStrings.join(', ') + ']';
hash = sexpr.hash ? ' ' + this.accept(sexpr.hash) : '';
return this.accept(sexpr.path) + ' ' + params + hash;
};
PrintVisitor.prototype.PathExpression = function (id) {
var path = id.parts.join('/');
return (id.data ? '@' : '') + 'PATH:' + path;
};
PrintVisitor.prototype.StringLiteral = function (string) {
return '"' + string.value + '"';
};
PrintVisitor.prototype.NumberLiteral = function (number) {
return 'NUMBER{' + number.value + '}';
};
PrintVisitor.prototype.BooleanLiteral = function (bool) {
return 'BOOLEAN{' + bool.value + '}';
};
PrintVisitor.prototype.UndefinedLiteral = function () {
return 'UNDEFINED';
};
PrintVisitor.prototype.NullLiteral = function () {
return 'NULL';
};
PrintVisitor.prototype.Hash = function (hash) {
var pairs = hash.pairs,
joinedPairs = [];
for (var i = 0, l = pairs.length; i < l; i++) {
joinedPairs.push(this.accept(pairs[i]));
}
return 'HASH{' + joinedPairs.join(', ') + '}';
};
PrintVisitor.prototype.HashPair = function (pair) {
return pair.key + '=' + this.accept(pair.value);
};
/* eslint-enable new-cap */
},{"./visitor":28}],28:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
function Visitor() {
this.parents = [];
}
Visitor.prototype = {
constructor: Visitor,
mutating: false,
// Visits a given value. If mutating, will replace the value if necessary.
acceptKey: function acceptKey(node, name) {
var value = this.accept(node[name]);
if (this.mutating) {
// Hacky sanity check: This may have a few false positives for type for the helper
// methods but will generally do the right thing without a lot of overhead.
if (value && !Visitor.prototype[value.type]) {
throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
}
node[name] = value;
}
},
// Performs an accept operation with added sanity check to ensure
// required keys are not removed.
acceptRequired: function acceptRequired(node, name) {
this.acceptKey(node, name);
if (!node[name]) {
throw new _exception2['default'](node.type + ' requires ' + name);
}
},
// Traverses a given array. If mutating, empty respnses will be removed
// for child elements.
acceptArray: function acceptArray(array) {
for (var i = 0, l = array.length; i < l; i++) {
this.acceptKey(array, i);
if (!array[i]) {
array.splice(i, 1);
i--;
l--;
}
}
},
accept: function accept(object) {
if (!object) {
return;
}
/* istanbul ignore next: Sanity code */
if (!this[object.type]) {
throw new _exception2['default']('Unknown type: ' + object.type, object);
}
if (this.current) {
this.parents.unshift(this.current);
}
this.current = object;
var ret = this[object.type](object);
this.current = this.parents.shift();
if (!this.mutating || ret) {
return ret;
} else if (ret !== false) {
return object;
}
},
Program: function Program(program) {
this.acceptArray(program.body);
},
MustacheStatement: visitSubExpression,
Decorator: visitSubExpression,
BlockStatement: visitBlock,
DecoratorBlock: visitBlock,
PartialStatement: visitPartial,
PartialBlockStatement: function PartialBlockStatement(partial) {
visitPartial.call(this, partial);
this.acceptKey(partial, 'program');
},
ContentStatement: function ContentStatement() /* content */{},
CommentStatement: function CommentStatement() /* comment */{},
SubExpression: visitSubExpression,
PathExpression: function PathExpression() /* path */{},
StringLiteral: function StringLiteral() /* string */{},
NumberLiteral: function NumberLiteral() /* number */{},
BooleanLiteral: function BooleanLiteral() /* bool */{},
UndefinedLiteral: function UndefinedLiteral() /* literal */{},
NullLiteral: function NullLiteral() /* literal */{},
Hash: function Hash(hash) {
this.acceptArray(hash.pairs);
},
HashPair: function HashPair(pair) {
this.acceptRequired(pair, 'value');
}
};
function visitSubExpression(mustache) {
this.acceptRequired(mustache, 'path');
this.acceptArray(mustache.params);
this.acceptKey(mustache, 'hash');
}
function visitBlock(block) {
visitSubExpression.call(this, block);
this.acceptKey(block, 'program');
this.acceptKey(block, 'inverse');
}
function visitPartial(partial) {
this.acceptRequired(partial, 'name');
this.acceptArray(partial.params);
this.acceptKey(partial, 'hash');
}
exports['default'] = Visitor;
module.exports = exports['default'];
},{"../exception":32}],29:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _visitor = require('./visitor');
var _visitor2 = _interopRequireDefault(_visitor);
function WhitespaceControl() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
this.options = options;
}
WhitespaceControl.prototype = new _visitor2['default']();
WhitespaceControl.prototype.Program = function (program) {
var doStandalone = !this.options.ignoreStandalone;
var isRoot = !this.isRootSeen;
this.isRootSeen = true;
var body = program.body;
for (var i = 0, l = body.length; i < l; i++) {
var current = body[i],
strip = this.accept(current);
if (!strip) {
continue;
}
var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
_isNextWhitespace = isNextWhitespace(body, i, isRoot),
openStandalone = strip.openStandalone && _isPrevWhitespace,
closeStandalone = strip.closeStandalone && _isNextWhitespace,
inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
if (strip.close) {
omitRight(body, i, true);
}
if (strip.open) {
omitLeft(body, i, true);
}
if (doStandalone && inlineStandalone) {
omitRight(body, i);
if (omitLeft(body, i)) {
// If we are on a standalone node, save the indent info for partials
if (current.type === 'PartialStatement') {
// Pull out the whitespace from the final line
current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
}
}
}
if (doStandalone && openStandalone) {
omitRight((current.program || current.inverse).body);
// Strip out the previous content node if it's whitespace only
omitLeft(body, i);
}
if (doStandalone && closeStandalone) {
// Always strip the next node
omitRight(body, i);
omitLeft((current.inverse || current.program).body);
}
}
return program;
};
WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) {
this.accept(block.program);
this.accept(block.inverse);
// Find the inverse program that is involed with whitespace stripping.
var program = block.program || block.inverse,
inverse = block.program && block.inverse,
firstInverse = inverse,
lastInverse = inverse;
if (inverse && inverse.chained) {
firstInverse = inverse.body[0].program;
// Walk the inverse chain to find the last inverse that is actually in the chain.
while (lastInverse.chained) {
lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
}
}
var strip = {
open: block.openStrip.open,
close: block.closeStrip.close,
// Determine the standalone candiacy. Basically flag our content as being possibly standalone
// so our parent can determine if we actually are standalone
openStandalone: isNextWhitespace(program.body),
closeStandalone: isPrevWhitespace((firstInverse || program).body)
};
if (block.openStrip.close) {
omitRight(program.body, null, true);
}
if (inverse) {
var inverseStrip = block.inverseStrip;
if (inverseStrip.open) {
omitLeft(program.body, null, true);
}
if (inverseStrip.close) {
omitRight(firstInverse.body, null, true);
}
if (block.closeStrip.open) {
omitLeft(lastInverse.body, null, true);
}
// Find standalone else statments
if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
omitLeft(program.body);
omitRight(firstInverse.body);
}
} else if (block.closeStrip.open) {
omitLeft(program.body, null, true);
}
return strip;
};
WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) {
return mustache.strip;
};
WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
/* istanbul ignore next */
var strip = node.strip || {};
return {
inlineStandalone: true,
open: strip.open,
close: strip.close
};
};
function isPrevWhitespace(body, i, isRoot) {
if (i === undefined) {
i = body.length;
}
// Nodes that end with newlines are considered whitespace (but are special
// cased for strip operations)
var prev = body[i - 1],
sibling = body[i - 2];
if (!prev) {
return isRoot;
}
if (prev.type === 'ContentStatement') {
return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
}
}
function isNextWhitespace(body, i, isRoot) {
if (i === undefined) {
i = -1;
}
var next = body[i + 1],
sibling = body[i + 2];
if (!next) {
return isRoot;
}
if (next.type === 'ContentStatement') {
return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
}
}
// Marks the node to the right of the position as omitted.
// I.e. {{foo}}' ' will mark the ' ' node as omitted.
//
// If i is undefined, then the first child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitRight(body, i, multiple) {
var current = body[i == null ? 0 : i + 1];
if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
return;
}
var original = current.value;
current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
current.rightStripped = current.value !== original;
}
// Marks the node to the left of the position as omitted.
// I.e. ' '{{foo}} will mark the ' ' node as omitted.
//
// If i is undefined then the last child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitLeft(body, i, multiple) {
var current = body[i == null ? body.length - 1 : i - 1];
if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
return;
}
// We omit the last node if it's whitespace only and not preceded by a non-content node.
var original = current.value;
current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
current.leftStripped = current.value !== original;
return current.leftStripped;
}
exports['default'] = WhitespaceControl;
module.exports = exports['default'];
},{"./visitor":28}],30:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.registerDefaultDecorators = registerDefaultDecorators;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _decoratorsInline = require('./decorators/inline');
var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline);
function registerDefaultDecorators(instance) {
_decoratorsInline2['default'](instance);
}
},{"./decorators/inline":31}],31:[function(require,module,exports){
'use strict';
exports.__esModule = true;
var _utils = require('../utils');
exports['default'] = function (instance) {
instance.registerDecorator('inline', function (fn, props, container, options) {
var ret = fn;
if (!props.partials) {
props.partials = {};
ret = function (context, options) {
// Create a new partials stack frame prior to exec.
var original = container.partials;
container.partials = _utils.extend({}, original, props.partials);
var ret = fn(context, options);
container.partials = original;
return ret;
};
}
props.partials[options.args[0]] = options.fn;
return ret;
});
};
module.exports = exports['default'];
},{"../utils":48}],32:[function(require,module,exports){
'use strict';
exports.__esModule = true;
var errorProps = ['description', 'fileName', 'lineNumber', 'endLineNumber', 'message', 'name', 'number', 'stack'];
function Exception(message, node) {
var loc = node && node.loc,
line = undefined,
endLineNumber = undefined,
column = undefined,
endColumn = undefined;
if (loc) {
line = loc.start.line;
endLineNumber = loc.end.line;
column = loc.start.column;
endColumn = loc.end.column;
message += ' - ' + line + ':' + column;
}
var tmp = Error.prototype.constructor.call(this, message);
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
for (var idx = 0; idx < errorProps.length; idx++) {
this[errorProps[idx]] = tmp[errorProps[idx]];
}
/* istanbul ignore else */
if (Error.captureStackTrace) {
Error.captureStackTrace(this, Exception);
}
try {
if (loc) {
this.lineNumber = line;
this.endLineNumber = endLineNumber;
// Work around issue under safari where we can't directly set the column value
/* istanbul ignore next */
if (Object.defineProperty) {
Object.defineProperty(this, 'column', {
value: column,
enumerable: true
});
Object.defineProperty(this, 'endColumn', {
value: endColumn,
enumerable: true
});
} else {
this.column = column;
this.endColumn = endColumn;
}
}
} catch (nop) {
/* Ignore if the browser is very particular */
}
}
Exception.prototype = new Error();
exports['default'] = Exception;
module.exports = exports['default'];
},{}],33:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.registerDefaultHelpers = registerDefaultHelpers;
exports.moveHelperToHooks = moveHelperToHooks;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _helpersBlockHelperMissing = require('./helpers/block-helper-missing');
var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing);
var _helpersEach = require('./helpers/each');
var _helpersEach2 = _interopRequireDefault(_helpersEach);
var _helpersHelperMissing = require('./helpers/helper-missing');
var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing);
var _helpersIf = require('./helpers/if');
var _helpersIf2 = _interopRequireDefault(_helpersIf);
var _helpersLog = require('./helpers/log');
var _helpersLog2 = _interopRequireDefault(_helpersLog);
var _helpersLookup = require('./helpers/lookup');
var _helpersLookup2 = _interopRequireDefault(_helpersLookup);
var _helpersWith = require('./helpers/with');
var _helpersWith2 = _interopRequireDefault(_helpersWith);
function registerDefaultHelpers(instance) {
_helpersBlockHelperMissing2['default'](instance);
_helpersEach2['default'](instance);
_helpersHelperMissing2['default'](instance);
_helpersIf2['default'](instance);
_helpersLog2['default'](instance);
_helpersLookup2['default'](instance);
_helpersWith2['default'](instance);
}
function moveHelperToHooks(instance, helperName, keepHelper) {
if (instance.helpers[helperName]) {
instance.hooks[helperName] = instance.helpers[helperName];
if (!keepHelper) {
delete instance.helpers[helperName];
}
}
}
},{"./helpers/block-helper-missing":34,"./helpers/each":35,"./helpers/helper-missing":36,"./helpers/if":37,"./helpers/log":38,"./helpers/lookup":39,"./helpers/with":40}],34:[function(require,module,exports){
'use strict';
exports.__esModule = true;
var _utils = require('../utils');
exports['default'] = function (instance) {
instance.registerHelper('blockHelperMissing', function (context, options) {
var inverse = options.inverse,
fn = options.fn;
if (context === true) {
return fn(this);
} else if (context === false || context == null) {
return inverse(this);
} else if (_utils.isArray(context)) {
if (context.length > 0) {
if (options.ids) {
options.ids = [options.name];
}
return instance.helpers.each(context, options);
} else {
return inverse(this);
}
} else {
if (options.data && options.ids) {
var data = _utils.createFrame(options.data);
data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
options = { data: data };
}
return fn(context, options);
}
});
};
module.exports = exports['default'];
},{"../utils":48}],35:[function(require,module,exports){
(function (global){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _utils = require('../utils');
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
exports['default'] = function (instance) {
instance.registerHelper('each', function (context, options) {
if (!options) {
throw new _exception2['default']('Must pass iterator to #each');
}
var fn = options.fn,
inverse = options.inverse,
i = 0,
ret = '',
data = undefined,
contextPath = undefined;
if (options.data && options.ids) {
contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
}
if (_utils.isFunction(context)) {
context = context.call(this);
}
if (options.data) {
data = _utils.createFrame(options.data);
}
function execIteration(field, index, last) {
if (data) {
data.key = field;
data.index = index;
data.first = index === 0;
data.last = !!last;
if (contextPath) {
data.contextPath = contextPath + field;
}
}
ret = ret + fn(context[field], {
data: data,
blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
});
}
if (context && typeof context === 'object') {
if (_utils.isArray(context)) {
for (var j = context.length; i < j; i++) {
if (i in context) {
execIteration(i, i, i === context.length - 1);
}
}
} else if (global.Symbol && context[global.Symbol.iterator]) {
var newContext = [];
var iterator = context[global.Symbol.iterator]();
for (var it = iterator.next(); !it.done; it = iterator.next()) {
newContext.push(it.value);
}
context = newContext;
for (var j = context.length; i < j; i++) {
execIteration(i, i, i === context.length - 1);
}
} else {
(function () {
var priorKey = undefined;
Object.keys(context).forEach(function (key) {
// We're running the iterations one step out of sync so we can detect
// the last iteration without have to scan the object twice and create
// an itermediate keys array.
if (priorKey !== undefined) {
execIteration(priorKey, i - 1);
}
priorKey = key;
i++;
});
if (priorKey !== undefined) {
execIteration(priorKey, i - 1, true);
}
})();
}
}
if (i === 0) {
ret = inverse(this);
}
return ret;
});
};
module.exports = exports['default'];
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../exception":32,"../utils":48}],36:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
exports['default'] = function (instance) {
instance.registerHelper('helperMissing', function () /* [args, ]options */{
if (arguments.length === 1) {
// A missing field in a {{foo}} construct.
return undefined;
} else {
// Someone is actually trying to call something, blow up.
throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
}
});
};
module.exports = exports['default'];
},{"../exception":32}],37:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _utils = require('../utils');
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
exports['default'] = function (instance) {
instance.registerHelper('if', function (conditional, options) {
if (arguments.length != 2) {
throw new _exception2['default']('#if requires exactly one argument');
}
if (_utils.isFunction(conditional)) {
conditional = conditional.call(this);
}
// Default behavior is to render the positive path if the value is truthy and not empty.
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
instance.registerHelper('unless', function (conditional, options) {
if (arguments.length != 2) {
throw new _exception2['default']('#unless requires exactly one argument');
}
return instance.helpers['if'].call(this, conditional, {
fn: options.inverse,
inverse: options.fn,
hash: options.hash
});
});
};
module.exports = exports['default'];
},{"../exception":32,"../utils":48}],38:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports['default'] = function (instance) {
instance.registerHelper('log', function () /* message, options */{
var args = [undefined],
options = arguments[arguments.length - 1];
for (var i = 0; i < arguments.length - 1; i++) {
args.push(arguments[i]);
}
var level = 1;
if (options.hash.level != null) {
level = options.hash.level;
} else if (options.data && options.data.level != null) {
level = options.data.level;
}
args[0] = level;
instance.log.apply(instance, args);
});
};
module.exports = exports['default'];
},{}],39:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports['default'] = function (instance) {
instance.registerHelper('lookup', function (obj, field, options) {
if (!obj) {
// Note for 5.0: Change to "obj == null" in 5.0
return obj;
}
return options.lookupProperty(obj, field);
});
};
module.exports = exports['default'];
},{}],40:[function(require,module,exports){
'use strict';
exports.__esModule = true;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _utils = require('../utils');
var _exception = require('../exception');
var _exception2 = _interopRequireDefault(_exception);
exports['default'] = function (instance) {
instance.registerHelper('with', function (context, options) {
if (arguments.length != 2) {
throw new _exception2['default']('#with requires exactly one argument');
}
if (_utils.isFunction(context)) {
context = context.call(this);
}
var fn = options.fn;
if (!_utils.isEmpty(context)) {
var data = options.data;
if (options.data && options.ids) {
data = _utils.createFrame(options.data);
data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]);
}
return fn(context, {
data: data,
blockParams: _utils.blockParams([context], [data && data.contextPath])
});
} else {
return options.inverse(this);
}
});
};
module.exports = exports['default'];
},{"../exception":32,"../utils":48}],41:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.createNewLookupObject = createNewLookupObject;
var _utils = require('../utils');
/**
* Create a new object with "null"-prototype to avoid truthy results on prototype properties.
* The resulting object can be used with "object[property]" to check if a property exists
* @param {...object} sources a varargs parameter of source objects that will be merged
* @returns {object}
*/
function createNewLookupObject() {
for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
sources[_key] = arguments[_key];
}
return _utils.extend.apply(undefined, [Object.create(null)].concat(sources));
}
},{"../utils":48}],42:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.createProtoAccessControl = createProtoAccessControl;
exports.resultIsAllowed = resultIsAllowed;
exports.resetLoggedProperties = resetLoggedProperties;
// istanbul ignore next
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
var _createNewLookupObject = require('./create-new-lookup-object');
var _logger = require('../logger');
var logger = _interopRequireWildcard(_logger);
var loggedProperties = Object.create(null);
function createProtoAccessControl(runtimeOptions) {
var defaultMethodWhiteList = Object.create(null);
defaultMethodWhiteList['constructor'] = false;
defaultMethodWhiteList['__defineGetter__'] = false;
defaultMethodWhiteList['__defineSetter__'] = false;
defaultMethodWhiteList['__lookupGetter__'] = false;
var defaultPropertyWhiteList = Object.create(null);
// eslint-disable-next-line no-proto
defaultPropertyWhiteList['__proto__'] = false;
return {
properties: {
whitelist: _createNewLookupObject.createNewLookupObject(defaultPropertyWhiteList, runtimeOptions.allowedProtoProperties),
defaultValue: runtimeOptions.allowProtoPropertiesByDefault
},
methods: {
whitelist: _createNewLookupObject.createNewLookupObject(defaultMethodWhiteList, runtimeOptions.allowedProtoMethods),
defaultValue: runtimeOptions.allowProtoMethodsByDefault
}
};
}
function resultIsAllowed(result, protoAccessControl, propertyName) {
if (typeof result === 'function') {
return checkWhiteList(protoAccessControl.methods, propertyName);
} else {
return checkWhiteList(protoAccessControl.properties, propertyName);
}
}
function checkWhiteList(protoAccessControlForType, propertyName) {
if (protoAccessControlForType.whitelist[propertyName] !== undefined) {
return protoAccessControlForType.whitelist[propertyName] === true;
}
if (protoAccessControlForType.defaultValue !== undefined) {
return protoAccessControlForType.defaultValue;
}
logUnexpecedPropertyAccessOnce(propertyName);
return false;
}
function logUnexpecedPropertyAccessOnce(propertyName) {
if (loggedProperties[propertyName] !== true) {
loggedProperties[propertyName] = true;
logger.log('error', 'Handlebars: Access has been denied to resolve the property "' + propertyName + '" because it is not an "own property" of its parent.\n' + 'You can add a runtime option to disable the check or this warning:\n' + 'See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details');
}
}
function resetLoggedProperties() {
Object.keys(loggedProperties).forEach(function (propertyName) {
delete loggedProperties[propertyName];
});
}
},{"../logger":44,"./create-new-lookup-object":41}],43:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.wrapHelper = wrapHelper;
function wrapHelper(helper, transformOptionsFn) {
if (typeof helper !== 'function') {
// This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639
// We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function.
return helper;
}
var wrapper = function wrapper() /* dynamic arguments */{
var options = arguments[arguments.length - 1];
arguments[arguments.length - 1] = transformOptionsFn(options);
return helper.apply(this, arguments);
};
return wrapper;
}
},{}],44:[function(require,module,exports){
'use strict';
exports.__esModule = true;
var _utils = require('./utils');
var logger = {
methodMap: ['debug', 'info', 'warn', 'error'],
level: 'info',
// Maps a given level value to the `methodMap` indexes above.
lookupLevel: function lookupLevel(level) {
if (typeof level === 'string') {
var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase());
if (levelMap >= 0) {
level = levelMap;
} else {
level = parseInt(level, 10);
}
}
return level;
},
// Can be overridden in the host environment
log: function log(level) {
level = logger.lookupLevel(level);
if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
var method = logger.methodMap[level];
// eslint-disable-next-line no-console
if (!console[method]) {
method = 'log';
}
for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
message[_key - 1] = arguments[_key];
}
console[method].apply(console, message); // eslint-disable-line no-console
}
}
};
exports['default'] = logger;
module.exports = exports['default'];
},{"./utils":48}],45:[function(require,module,exports){
(function (global){
'use strict';
exports.__esModule = true;
exports['default'] = function (Handlebars) {
/* istanbul ignore next */
var root = typeof global !== 'undefined' ? global : window,
$Handlebars = root.Handlebars;
/* istanbul ignore next */
Handlebars.noConflict = function () {
if (root.Handlebars === Handlebars) {
root.Handlebars = $Handlebars;
}
return Handlebars;
};
};
module.exports = exports['default'];
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],46:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.checkRevision = checkRevision;
exports.template = template;
exports.wrapProgram = wrapProgram;
exports.resolvePartial = resolvePartial;
exports.invokePartial = invokePartial;
exports.noop = noop;
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
// istanbul ignore next
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
var _utils = require('./utils');
var Utils = _interopRequireWildcard(_utils);
var _exception = require('./exception');
var _exception2 = _interopRequireDefault(_exception);
var _base = require('./base');
var _helpers = require('./helpers');
var _internalWrapHelper = require('./internal/wrapHelper');
var _internalProtoAccess = require('./internal/proto-access');
function checkRevision(compilerInfo) {
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
currentRevision = _base.COMPILER_REVISION;
if (compilerRevision >= _base.LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= _base.COMPILER_REVISION) {
return;
}
if (compilerRevision < _base.LAST_COMPATIBLE_COMPILER_REVISION) {
var runtimeVersions = _base.REVISION_CHANGES[currentRevision],
compilerVersions = _base.REVISION_CHANGES[compilerRevision];
throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
}
}
function template(templateSpec, env) {
/* istanbul ignore next */
if (!env) {
throw new _exception2['default']('No environment passed to template');
}
if (!templateSpec || !templateSpec.main) {
throw new _exception2['default']('Unknown template object: ' + typeof templateSpec);
}
templateSpec.main.decorator = templateSpec.main_d;
// Note: Using env.VM references rather than local var references throughout this section to allow
// for external users to override these as pseudo-supported APIs.
env.VM.checkRevision(templateSpec.compiler);
// backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)
var templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7;
function invokePartialWrapper(partial, context, options) {
if (options.hash) {
context = Utils.extend({}, context, options.hash);
if (options.ids) {
options.ids[0] = true;
}
}
partial = env.VM.resolvePartial.call(this, partial, context, options);
var extendedOptions = Utils.extend({}, options, {
hooks: this.hooks,
protoAccessControl: this.protoAccessControl
});
var result = env.VM.invokePartial.call(this, partial, context, extendedOptions);
if (result == null && env.compile) {
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
result = options.partials[options.name](context, extendedOptions);
}
if (result != null) {
if (options.indent) {
var lines = result.split('\n');
for (var i = 0, l = lines.length; i < l; i++) {
if (!lines[i] && i + 1 === l) {
break;
}
lines[i] = options.indent + lines[i];
}
result = lines.join('\n');
}
return result;
} else {
throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
}
}
// Just add water
var container = {
strict: function strict(obj, name, loc) {
if (!obj || !(name in obj)) {
throw new _exception2['default']('"' + name + '" not defined in ' + obj, {
loc: loc
});
}
return obj[name];
},
lookupProperty: function lookupProperty(parent, propertyName) {
var result = parent[propertyName];
if (result == null) {
return result;
}
if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
return result;
}
if (_internalProtoAccess.resultIsAllowed(result, container.protoAccessControl, propertyName)) {
return result;
}
return undefined;
},
lookup: function lookup(depths, name) {
var len = depths.length;
for (var i = 0; i < len; i++) {
var result = depths[i] && container.lookupProperty(depths[i], name);
if (result != null) {
return depths[i][name];
}
}
},
lambda: function lambda(current, context) {
return typeof current === 'function' ? current.call(context) : current;
},
escapeExpression: Utils.escapeExpression,
invokePartial: invokePartialWrapper,
fn: function fn(i) {
var ret = templateSpec[i];
ret.decorator = templateSpec[i + '_d'];
return ret;
},
programs: [],
program: function program(i, data, declaredBlockParams, blockParams, depths) {
var programWrapper = this.programs[i],
fn = this.fn(i);
if (data || depths || blockParams || declaredBlockParams) {
programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
} else if (!programWrapper) {
programWrapper = this.programs[i] = wrapProgram(this, i, fn);
}
return programWrapper;
},
data: function data(value, depth) {
while (value && depth--) {
value = value._parent;
}
return value;
},
mergeIfNeeded: function mergeIfNeeded(param, common) {
var obj = param || common;
if (param && common && param !== common) {
obj = Utils.extend({}, common, param);
}
return obj;
},
// An empty object to use as replacement for null-contexts
nullContext: Object.seal({}),
noop: env.VM.noop,
compilerInfo: templateSpec.compiler
};
function ret(context) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var data = options.data;
ret._setup(options);
if (!options.partial && templateSpec.useData) {
data = initData(context, data);
}
var depths = undefined,
blockParams = templateSpec.useBlockParams ? [] : undefined;
if (templateSpec.useDepths) {
if (options.depths) {
depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
} else {
depths = [context];
}
}
function main(context /*, options*/) {
return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
}
main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
return main(context, options);
}
ret.isTop = true;
ret._setup = function (options) {
if (!options.partial) {
var mergedHelpers = Utils.extend({}, env.helpers, options.helpers);
wrapHelpersToPassLookupProperty(mergedHelpers, container);
container.helpers = mergedHelpers;
if (templateSpec.usePartial) {
// Use mergeIfNeeded here to prevent compiling global partials multiple times
container.partials = container.mergeIfNeeded(options.partials, env.partials);
}
if (templateSpec.usePartial || templateSpec.useDecorators) {
container.decorators = Utils.extend({}, env.decorators, options.decorators);
}
container.hooks = {};
container.protoAccessControl = _internalProtoAccess.createProtoAccessControl(options);
var keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7;
_helpers.moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers);
_helpers.moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers);
} else {
container.protoAccessControl = options.protoAccessControl; // internal option
container.helpers = options.helpers;
container.partials = options.partials;
container.decorators = options.decorators;
container.hooks = options.hooks;
}
};
ret._child = function (i, data, blockParams, depths) {
if (templateSpec.useBlockParams && !blockParams) {
throw new _exception2['default']('must pass block params');
}
if (templateSpec.useDepths && !depths) {
throw new _exception2['default']('must pass parent depths');
}
return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
};
return ret;
}
function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
function prog(context) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var currentDepths = depths;
if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
currentDepths = [context].concat(depths);
}
return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
}
prog = executeDecorators(fn, prog, container, depths, data, blockParams);
prog.program = i;
prog.depth = depths ? depths.length : 0;
prog.blockParams = declaredBlockParams || 0;
return prog;
}
/**
* This is currently part of the official API, therefore implementation details should not be changed.
*/
function resolvePartial(partial, context, options) {
if (!partial) {
if (options.name === '@partial-block') {
partial = options.data['partial-block'];
} else {
partial = options.partials[options.name];
}
} else if (!partial.call && !options.name) {
// This is a dynamic partial that returned a string
options.name = partial;
partial = options.partials[partial];
}
return partial;
}
function invokePartial(partial, context, options) {
// Use the current closure context to save the partial-block if this partial
var currentPartialBlock = options.data && options.data['partial-block'];
options.partial = true;
if (options.ids) {
options.data.contextPath = options.ids[0] || options.data.contextPath;
}
var partialBlock = undefined;
if (options.fn && options.fn !== noop) {
(function () {
options.data = _base.createFrame(options.data);
// Wrapper function to get access to currentPartialBlock from the closure
var fn = options.fn;
partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
// Restore the partial-block from the closure for the execution of the block
// i.e. the part inside the block of the partial call.
options.data = _base.createFrame(options.data);
options.data['partial-block'] = currentPartialBlock;
return fn(context, options);
};
if (fn.partials) {
options.partials = Utils.extend({}, options.partials, fn.partials);
}
})();
}
if (partial === undefined && partialBlock) {
partial = partialBlock;
}
if (partial === undefined) {
throw new _exception2['default']('The partial ' + options.name + ' could not be found');
} else if (partial instanceof Function) {
return partial(context, options);
}
}
function noop() {
return '';
}
function initData(context, data) {
if (!data || !('root' in data)) {
data = data ? _base.createFrame(data) : {};
data.root = context;
}
return data;
}
function executeDecorators(fn, prog, container, depths, data, blockParams) {
if (fn.decorator) {
var props = {};
prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
Utils.extend(prog, props);
}
return prog;
}
function wrapHelpersToPassLookupProperty(mergedHelpers, container) {
Object.keys(mergedHelpers).forEach(function (helperName) {
var helper = mergedHelpers[helperName];
mergedHelpers[helperName] = passLookupPropertyOption(helper, container);
});
}
function passLookupPropertyOption(helper, container) {
var lookupProperty = container.lookupProperty;
return _internalWrapHelper.wrapHelper(helper, function (options) {
return Utils.extend({ lookupProperty: lookupProperty }, options);
});
}
},{"./base":19,"./exception":32,"./helpers":33,"./internal/proto-access":42,"./internal/wrapHelper":43,"./utils":48}],47:[function(require,module,exports){
// Build out our basic SafeString type
'use strict';
exports.__esModule = true;
function SafeString(string) {
this.string = string;
}
SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
return '' + this.string;
};
exports['default'] = SafeString;
module.exports = exports['default'];
},{}],48:[function(require,module,exports){
'use strict';
exports.__esModule = true;
exports.extend = extend;
exports.indexOf = indexOf;
exports.escapeExpression = escapeExpression;
exports.isEmpty = isEmpty;
exports.createFrame = createFrame;
exports.blockParams = blockParams;
exports.appendContextPath = appendContextPath;
var escape = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;',
'=': '&#x3D;'
};
var badChars = /[&<>"'`=]/g,
possible = /[&<>"'`=]/;
function escapeChar(chr) {
return escape[chr];
}
function extend(obj /* , ...source */) {
for (var i = 1; i < arguments.length; i++) {
for (var key in arguments[i]) {
if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
obj[key] = arguments[i][key];
}
}
}
return obj;
}
var toString = Object.prototype.toString;
exports.toString = toString;
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
/* eslint-disable func-style */
var isFunction = function isFunction(value) {
return typeof value === 'function';
};
// fallback for older versions of Chrome and Safari
/* istanbul ignore next */
if (isFunction(/x/)) {
exports.isFunction = isFunction = function (value) {
return typeof value === 'function' && toString.call(value) === '[object Function]';
};
}
exports.isFunction = isFunction;
/* eslint-enable func-style */
/* istanbul ignore next */
var isArray = Array.isArray || function (value) {
return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
};
exports.isArray = isArray;
// Older IE versions do not directly support indexOf so we must implement our own, sadly.
function indexOf(array, value) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return i;
}
}
return -1;
}
function escapeExpression(string) {
if (typeof string !== 'string') {
// don't escape SafeStrings, since they're already safe
if (string && string.toHTML) {
return string.toHTML();
} else if (string == null) {
return '';
} else if (!string) {
return string + '';
}
// Force a string conversion as this will be done by the append regardless and
// the regex test will do this transparently behind the scenes, causing issues if
// an object's to string has escaped characters in it.
string = '' + string;
}
if (!possible.test(string)) {
return string;
}
return string.replace(badChars, escapeChar);
}
function isEmpty(value) {
if (!value && value !== 0) {
return true;
} else if (isArray(value) && value.length === 0) {
return true;
} else {
return false;
}
}
function createFrame(object) {
var frame = extend({}, object);
frame._parent = object;
return frame;
}
function blockParams(params, ids) {
params.path = ids;
return params;
}
function appendContextPath(contextPath, id) {
return (contextPath ? contextPath + '.' : '') + id;
}
},{}],49:[function(require,module,exports){
// USAGE:
// var handlebars = require('handlebars');
/* eslint-disable no-var */
// var local = handlebars.create();
var handlebars = require('../dist/cjs/handlebars')['default'];
var printer = require('../dist/cjs/handlebars/compiler/printer');
handlebars.PrintVisitor = printer.PrintVisitor;
handlebars.print = printer.print;
module.exports = handlebars;
// Publish a Node.js require() handler for .handlebars and .hbs files
function extension(module, filename) {
var fs = require('fs');
var templateString = fs.readFileSync(filename, 'utf8');
module.exports = handlebars.compile(templateString);
}
/* istanbul ignore else */
if (typeof require !== 'undefined' && require.extensions) {
require.extensions['.handlebars'] = extension;
require.extensions['.hbs'] = extension;
}
},{"../dist/cjs/handlebars":17,"../dist/cjs/handlebars/compiler/printer":27,"fs":12}],50:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var util = require('./util');
var has = Object.prototype.hasOwnProperty;
var hasNativeMap = typeof Map !== "undefined";
/**
* A data structure which is a combination of an array and a set. Adding a new
* member is O(1), testing for membership is O(1), and finding the index of an
* element is O(1). Removing elements from the set is not supported. Only
* strings are supported for membership.
*/
function ArraySet() {
this._array = [];
this._set = hasNativeMap ? new Map() : Object.create(null);
}
/**
* Static method for creating ArraySet instances from an existing array.
*/
ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
var set = new ArraySet();
for (var i = 0, len = aArray.length; i < len; i++) {
set.add(aArray[i], aAllowDuplicates);
}
return set;
};
/**
* Return how many unique items are in this ArraySet. If duplicates have been
* added, than those do not count towards the size.
*
* @returns Number
*/
ArraySet.prototype.size = function ArraySet_size() {
return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;
};
/**
* Add the given string to this set.
*
* @param String aStr
*/
ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
var sStr = hasNativeMap ? aStr : util.toSetString(aStr);
var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
var idx = this._array.length;
if (!isDuplicate || aAllowDuplicates) {
this._array.push(aStr);
}
if (!isDuplicate) {
if (hasNativeMap) {
this._set.set(aStr, idx);
} else {
this._set[sStr] = idx;
}
}
};
/**
* Is the given string a member of this set?
*
* @param String aStr
*/
ArraySet.prototype.has = function ArraySet_has(aStr) {
if (hasNativeMap) {
return this._set.has(aStr);
} else {
var sStr = util.toSetString(aStr);
return has.call(this._set, sStr);
}
};
/**
* What is the index of the given string in the array?
*
* @param String aStr
*/
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
if (hasNativeMap) {
var idx = this._set.get(aStr);
if (idx >= 0) {
return idx;
}
} else {
var sStr = util.toSetString(aStr);
if (has.call(this._set, sStr)) {
return this._set[sStr];
}
}
throw new Error('"' + aStr + '" is not in the set.');
};
/**
* What is the element at the given index?
*
* @param Number aIdx
*/
ArraySet.prototype.at = function ArraySet_at(aIdx) {
if (aIdx >= 0 && aIdx < this._array.length) {
return this._array[aIdx];
}
throw new Error('No element indexed by ' + aIdx);
};
/**
* Returns the array representation of this set (which has the proper indices
* indicated by indexOf). Note that this is a copy of the internal array used
* for storing the members so that no one can mess with internal state.
*/
ArraySet.prototype.toArray = function ArraySet_toArray() {
return this._array.slice();
};
exports.ArraySet = ArraySet;
},{"./util":59}],51:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*
* Based on the Base 64 VLQ implementation in Closure Compiler:
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
*
* Copyright 2011 The Closure Compiler Authors. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var base64 = require('./base64');
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
// the next four bits are the actual value, and the 6th bit is the
// continuation bit. The continuation bit tells us whether there are more
// digits in this value following this digit.
//
// Continuation
// | Sign
// | |
// V V
// 101011
var VLQ_BASE_SHIFT = 5;
// binary: 100000
var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
// binary: 011111
var VLQ_BASE_MASK = VLQ_BASE - 1;
// binary: 100000
var VLQ_CONTINUATION_BIT = VLQ_BASE;
/**
* Converts from a two-complement value to a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
*/
function toVLQSigned(aValue) {
return aValue < 0
? ((-aValue) << 1) + 1
: (aValue << 1) + 0;
}
/**
* Converts to a two-complement value from a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
*/
function fromVLQSigned(aValue) {
var isNegative = (aValue & 1) === 1;
var shifted = aValue >> 1;
return isNegative
? -shifted
: shifted;
}
/**
* Returns the base 64 VLQ encoded value.
*/
exports.encode = function base64VLQ_encode(aValue) {
var encoded = "";
var digit;
var vlq = toVLQSigned(aValue);
do {
digit = vlq & VLQ_BASE_MASK;
vlq >>>= VLQ_BASE_SHIFT;
if (vlq > 0) {
// There are still more digits in this value, so we must make sure the
// continuation bit is marked.
digit |= VLQ_CONTINUATION_BIT;
}
encoded += base64.encode(digit);
} while (vlq > 0);
return encoded;
};
/**
* Decodes the next base 64 VLQ value from the given string and returns the
* value and the rest of the string via the out parameter.
*/
exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
var strLen = aStr.length;
var result = 0;
var shift = 0;
var continuation, digit;
do {
if (aIndex >= strLen) {
throw new Error("Expected more digits in base 64 VLQ value.");
}
digit = base64.decode(aStr.charCodeAt(aIndex++));
if (digit === -1) {
throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
}
continuation = !!(digit & VLQ_CONTINUATION_BIT);
digit &= VLQ_BASE_MASK;
result = result + (digit << shift);
shift += VLQ_BASE_SHIFT;
} while (continuation);
aOutParam.value = fromVLQSigned(result);
aOutParam.rest = aIndex;
};
},{"./base64":52}],52:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
/**
* Encode an integer in the range of 0 to 63 to a single base 64 digit.
*/
exports.encode = function (number) {
if (0 <= number && number < intToCharMap.length) {
return intToCharMap[number];
}
throw new TypeError("Must be between 0 and 63: " + number);
};
/**
* Decode a single base 64 character code digit to an integer. Returns -1 on
* failure.
*/
exports.decode = function (charCode) {
var bigA = 65; // 'A'
var bigZ = 90; // 'Z'
var littleA = 97; // 'a'
var littleZ = 122; // 'z'
var zero = 48; // '0'
var nine = 57; // '9'
var plus = 43; // '+'
var slash = 47; // '/'
var littleOffset = 26;
var numberOffset = 52;
// 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
if (bigA <= charCode && charCode <= bigZ) {
return (charCode - bigA);
}
// 26 - 51: abcdefghijklmnopqrstuvwxyz
if (littleA <= charCode && charCode <= littleZ) {
return (charCode - littleA + littleOffset);
}
// 52 - 61: 0123456789
if (zero <= charCode && charCode <= nine) {
return (charCode - zero + numberOffset);
}
// 62: +
if (charCode == plus) {
return 62;
}
// 63: /
if (charCode == slash) {
return 63;
}
// Invalid base64 digit.
return -1;
};
},{}],53:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
exports.GREATEST_LOWER_BOUND = 1;
exports.LEAST_UPPER_BOUND = 2;
/**
* Recursive implementation of binary search.
*
* @param aLow Indices here and lower do not contain the needle.
* @param aHigh Indices here and higher do not contain the needle.
* @param aNeedle The element being searched for.
* @param aHaystack The non-empty array being searched.
* @param aCompare Function which takes two elements and returns -1, 0, or 1.
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
*/
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
// This function terminates when one of the following is true:
//
// 1. We find the exact element we are looking for.
//
// 2. We did not find the exact element, but we can return the index of
// the next-closest element.
//
// 3. We did not find the exact element, and there is no next-closest
// element than the one we are searching for, so we return -1.
var mid = Math.floor((aHigh - aLow) / 2) + aLow;
var cmp = aCompare(aNeedle, aHaystack[mid], true);
if (cmp === 0) {
// Found the element we are looking for.
return mid;
}
else if (cmp > 0) {
// Our needle is greater than aHaystack[mid].
if (aHigh - mid > 1) {
// The element is in the upper half.
return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
}
// The exact needle element was not found in this haystack. Determine if
// we are in termination case (3) or (2) and return the appropriate thing.
if (aBias == exports.LEAST_UPPER_BOUND) {
return aHigh < aHaystack.length ? aHigh : -1;
} else {
return mid;
}
}
else {
// Our needle is less than aHaystack[mid].
if (mid - aLow > 1) {
// The element is in the lower half.
return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
}
// we are in termination case (3) or (2) and return the appropriate thing.
if (aBias == exports.LEAST_UPPER_BOUND) {
return mid;
} else {
return aLow < 0 ? -1 : aLow;
}
}
}
/**
* This is an implementation of binary search which will always try and return
* the index of the closest element if there is no exact hit. This is because
* mappings between original and generated line/col pairs are single points,
* and there is an implicit region between each of them, so a miss just means
* that you aren't on the very start of a region.
*
* @param aNeedle The element you are looking for.
* @param aHaystack The array that is being searched.
* @param aCompare A function which takes the needle and an element in the
* array and returns -1, 0, or 1 depending on whether the needle is less
* than, equal to, or greater than the element, respectively.
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.
*/
exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
if (aHaystack.length === 0) {
return -1;
}
var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,
aCompare, aBias || exports.GREATEST_LOWER_BOUND);
if (index < 0) {
return -1;
}
// We have found either the exact element, or the next-closest element than
// the one we are searching for. However, there may be more than one such
// element. Make sure we always return the smallest of these.
while (index - 1 >= 0) {
if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
break;
}
--index;
}
return index;
};
},{}],54:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2014 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var util = require('./util');
/**
* Determine whether mappingB is after mappingA with respect to generated
* position.
*/
function generatedPositionAfter(mappingA, mappingB) {
// Optimized for most common case
var lineA = mappingA.generatedLine;
var lineB = mappingB.generatedLine;
var columnA = mappingA.generatedColumn;
var columnB = mappingB.generatedColumn;
return lineB > lineA || lineB == lineA && columnB >= columnA ||
util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
}
/**
* A data structure to provide a sorted view of accumulated mappings in a
* performance conscious manner. It trades a neglibable overhead in general
* case for a large speedup in case of mappings being added in order.
*/
function MappingList() {
this._array = [];
this._sorted = true;
// Serves as infimum
this._last = {generatedLine: -1, generatedColumn: 0};
}
/**
* Iterate through internal items. This method takes the same arguments that
* `Array.prototype.forEach` takes.
*
* NOTE: The order of the mappings is NOT guaranteed.
*/
MappingList.prototype.unsortedForEach =
function MappingList_forEach(aCallback, aThisArg) {
this._array.forEach(aCallback, aThisArg);
};
/**
* Add the given source mapping.
*
* @param Object aMapping
*/
MappingList.prototype.add = function MappingList_add(aMapping) {
if (generatedPositionAfter(this._last, aMapping)) {
this._last = aMapping;
this._array.push(aMapping);
} else {
this._sorted = false;
this._array.push(aMapping);
}
};
/**
* Returns the flat, sorted array of mappings. The mappings are sorted by
* generated position.
*
* WARNING: This method returns internal data without copying, for
* performance. The return value must NOT be mutated, and should be treated as
* an immutable borrow. If you want to take ownership, you must make your own
* copy.
*/
MappingList.prototype.toArray = function MappingList_toArray() {
if (!this._sorted) {
this._array.sort(util.compareByGeneratedPositionsInflated);
this._sorted = true;
}
return this._array;
};
exports.MappingList = MappingList;
},{"./util":59}],55:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
// It turns out that some (most?) JavaScript engines don't self-host
// `Array.prototype.sort`. This makes sense because C++ will likely remain
// faster than JS when doing raw CPU-intensive sorting. However, when using a
// custom comparator function, calling back and forth between the VM's C++ and
// JIT'd JS is rather slow *and* loses JIT type information, resulting in
// worse generated code for the comparator function than would be optimal. In
// fact, when sorting with a comparator, these costs outweigh the benefits of
// sorting in C++. By using our own JS-implemented Quick Sort (below), we get
// a ~3500ms mean speed-up in `bench/bench.html`.
/**
* Swap the elements indexed by `x` and `y` in the array `ary`.
*
* @param {Array} ary
* The array.
* @param {Number} x
* The index of the first item.
* @param {Number} y
* The index of the second item.
*/
function swap(ary, x, y) {
var temp = ary[x];
ary[x] = ary[y];
ary[y] = temp;
}
/**
* Returns a random integer within the range `low .. high` inclusive.
*
* @param {Number} low
* The lower bound on the range.
* @param {Number} high
* The upper bound on the range.
*/
function randomIntInRange(low, high) {
return Math.round(low + (Math.random() * (high - low)));
}
/**
* The Quick Sort algorithm.
*
* @param {Array} ary
* An array to sort.
* @param {function} comparator
* Function to use to compare two items.
* @param {Number} p
* Start index of the array
* @param {Number} r
* End index of the array
*/
function doQuickSort(ary, comparator, p, r) {
// If our lower bound is less than our upper bound, we (1) partition the
// array into two pieces and (2) recurse on each half. If it is not, this is
// the empty array and our base case.
if (p < r) {
// (1) Partitioning.
//
// The partitioning chooses a pivot between `p` and `r` and moves all
// elements that are less than or equal to the pivot to the before it, and
// all the elements that are greater than it after it. The effect is that
// once partition is done, the pivot is in the exact place it will be when
// the array is put in sorted order, and it will not need to be moved
// again. This runs in O(n) time.
// Always choose a random pivot so that an input array which is reverse
// sorted does not cause O(n^2) running time.
var pivotIndex = randomIntInRange(p, r);
var i = p - 1;
swap(ary, pivotIndex, r);
var pivot = ary[r];
// Immediately after `j` is incremented in this loop, the following hold
// true:
//
// * Every element in `ary[p .. i]` is less than or equal to the pivot.
//
// * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
for (var j = p; j < r; j++) {
if (comparator(ary[j], pivot) <= 0) {
i += 1;
swap(ary, i, j);
}
}
swap(ary, i + 1, j);
var q = i + 1;
// (2) Recurse on each half.
doQuickSort(ary, comparator, p, q - 1);
doQuickSort(ary, comparator, q + 1, r);
}
}
/**
* Sort the given array in-place with the given comparator function.
*
* @param {Array} ary
* An array to sort.
* @param {function} comparator
* Function to use to compare two items.
*/
exports.quickSort = function (ary, comparator) {
doQuickSort(ary, comparator, 0, ary.length - 1);
};
},{}],56:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var util = require('./util');
var binarySearch = require('./binary-search');
var ArraySet = require('./array-set').ArraySet;
var base64VLQ = require('./base64-vlq');
var quickSort = require('./quick-sort').quickSort;
function SourceMapConsumer(aSourceMap, aSourceMapURL) {
var sourceMap = aSourceMap;
if (typeof aSourceMap === 'string') {
sourceMap = util.parseSourceMapInput(aSourceMap);
}
return sourceMap.sections != null
? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL)
: new BasicSourceMapConsumer(sourceMap, aSourceMapURL);
}
SourceMapConsumer.fromSourceMap = function(aSourceMap, aSourceMapURL) {
return BasicSourceMapConsumer.fromSourceMap(aSourceMap, aSourceMapURL);
}
/**
* The version of the source mapping spec that we are consuming.
*/
SourceMapConsumer.prototype._version = 3;
// `__generatedMappings` and `__originalMappings` are arrays that hold the
// parsed mapping coordinates from the source map's "mappings" attribute. They
// are lazily instantiated, accessed via the `_generatedMappings` and
// `_originalMappings` getters respectively, and we only parse the mappings
// and create these arrays once queried for a source location. We jump through
// these hoops because there can be many thousands of mappings, and parsing
// them is expensive, so we only want to do it if we must.
//
// Each object in the arrays is of the form:
//
// {
// generatedLine: The line number in the generated code,
// generatedColumn: The column number in the generated code,
// source: The path to the original source file that generated this
// chunk of code,
// originalLine: The line number in the original source that
// corresponds to this chunk of generated code,
// originalColumn: The column number in the original source that
// corresponds to this chunk of generated code,
// name: The name of the original symbol which generated this chunk of
// code.
// }
//
// All properties except for `generatedLine` and `generatedColumn` can be
// `null`.
//
// `_generatedMappings` is ordered by the generated positions.
//
// `_originalMappings` is ordered by the original positions.
SourceMapConsumer.prototype.__generatedMappings = null;
Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
configurable: true,
enumerable: true,
get: function () {
if (!this.__generatedMappings) {
this._parseMappings(this._mappings, this.sourceRoot);
}
return this.__generatedMappings;
}
});
SourceMapConsumer.prototype.__originalMappings = null;
Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
configurable: true,
enumerable: true,
get: function () {
if (!this.__originalMappings) {
this._parseMappings(this._mappings, this.sourceRoot);
}
return this.__originalMappings;
}
});
SourceMapConsumer.prototype._charIsMappingSeparator =
function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
var c = aStr.charAt(index);
return c === ";" || c === ",";
};
/**
* Parse the mappings in a string in to a data structure which we can easily
* query (the ordered arrays in the `this.__generatedMappings` and
* `this.__originalMappings` properties).
*/
SourceMapConsumer.prototype._parseMappings =
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
throw new Error("Subclasses must implement _parseMappings");
};
SourceMapConsumer.GENERATED_ORDER = 1;
SourceMapConsumer.ORIGINAL_ORDER = 2;
SourceMapConsumer.GREATEST_LOWER_BOUND = 1;
SourceMapConsumer.LEAST_UPPER_BOUND = 2;
/**
* Iterate over each mapping between an original source/line/column and a
* generated line/column in this source map.
*
* @param Function aCallback
* The function that is called with each mapping.
* @param Object aContext
* Optional. If specified, this object will be the value of `this` every
* time that `aCallback` is called.
* @param aOrder
* Either `SourceMapConsumer.GENERATED_ORDER` or
* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
* iterate over the mappings sorted by the generated file's line/column
* order or the original's source/line/column order, respectively. Defaults to
* `SourceMapConsumer.GENERATED_ORDER`.
*/
SourceMapConsumer.prototype.eachMapping =
function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
var context = aContext || null;
var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
var mappings;
switch (order) {
case SourceMapConsumer.GENERATED_ORDER:
mappings = this._generatedMappings;
break;
case SourceMapConsumer.ORIGINAL_ORDER:
mappings = this._originalMappings;
break;
default:
throw new Error("Unknown order of iteration.");
}
var sourceRoot = this.sourceRoot;
mappings.map(function (mapping) {
var source = mapping.source === null ? null : this._sources.at(mapping.source);
source = util.computeSourceURL(sourceRoot, source, this._sourceMapURL);
return {
source: source,
generatedLine: mapping.generatedLine,
generatedColumn: mapping.generatedColumn,
originalLine: mapping.originalLine,
originalColumn: mapping.originalColumn,
name: mapping.name === null ? null : this._names.at(mapping.name)
};
}, this).forEach(aCallback, context);
};
/**
* Returns all generated line and column information for the original source,
* line, and column provided. If no column is provided, returns all mappings
* corresponding to a either the line we are searching for or the next
* closest line that has any mappings. Otherwise, returns all mappings
* corresponding to the given line and either the column we are searching for
* or the next closest column that has any offsets.
*
* The only argument is an object with the following properties:
*
* - source: The filename of the original source.
* - line: The line number in the original source. The line number is 1-based.
* - column: Optional. the column number in the original source.
* The column number is 0-based.
*
* and an array of objects is returned, each with the following properties:
*
* - line: The line number in the generated source, or null. The
* line number is 1-based.
* - column: The column number in the generated source, or null.
* The column number is 0-based.
*/
SourceMapConsumer.prototype.allGeneratedPositionsFor =
function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
var line = util.getArg(aArgs, 'line');
// When there is no exact match, BasicSourceMapConsumer.prototype._findMapping
// returns the index of the closest mapping less than the needle. By
// setting needle.originalColumn to 0, we thus find the last mapping for
// the given line, provided such a mapping exists.
var needle = {
source: util.getArg(aArgs, 'source'),
originalLine: line,
originalColumn: util.getArg(aArgs, 'column', 0)
};
needle.source = this._findSourceIndex(needle.source);
if (needle.source < 0) {
return [];
}
var mappings = [];
var index = this._findMapping(needle,
this._originalMappings,
"originalLine",
"originalColumn",
util.compareByOriginalPositions,
binarySearch.LEAST_UPPER_BOUND);
if (index >= 0) {
var mapping = this._originalMappings[index];
if (aArgs.column === undefined) {
var originalLine = mapping.originalLine;
// Iterate until either we run out of mappings, or we run into
// a mapping for a different line than the one we found. Since
// mappings are sorted, this is guaranteed to find all mappings for
// the line we found.
while (mapping && mapping.originalLine === originalLine) {
mappings.push({
line: util.getArg(mapping, 'generatedLine', null),
column: util.getArg(mapping, 'generatedColumn', null),
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
});
mapping = this._originalMappings[++index];
}
} else {
var originalColumn = mapping.originalColumn;
// Iterate until either we run out of mappings, or we run into
// a mapping for a different line than the one we were searching for.
// Since mappings are sorted, this is guaranteed to find all mappings for
// the line we are searching for.
while (mapping &&
mapping.originalLine === line &&
mapping.originalColumn == originalColumn) {
mappings.push({
line: util.getArg(mapping, 'generatedLine', null),
column: util.getArg(mapping, 'generatedColumn', null),
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
});
mapping = this._originalMappings[++index];
}
}
}
return mappings;
};
exports.SourceMapConsumer = SourceMapConsumer;
/**
* A BasicSourceMapConsumer instance represents a parsed source map which we can
* query for information about the original file positions by giving it a file
* position in the generated source.
*
* The first parameter is the raw source map (either as a JSON string, or
* already parsed to an object). According to the spec, source maps have the
* following attributes:
*
* - version: Which version of the source map spec this map is following.
* - sources: An array of URLs to the original source files.
* - names: An array of identifiers which can be referrenced by individual mappings.
* - sourceRoot: Optional. The URL root from which all sources are relative.
* - sourcesContent: Optional. An array of contents of the original source files.
* - mappings: A string of base64 VLQs which contain the actual mappings.
* - file: Optional. The generated file this source map is associated with.
*
* Here is an example source map, taken from the source map spec[0]:
*
* {
* version : 3,
* file: "out.js",
* sourceRoot : "",
* sources: ["foo.js", "bar.js"],
* names: ["src", "maps", "are", "fun"],
* mappings: "AA,AB;;ABCDE;"
* }
*
* The second parameter, if given, is a string whose value is the URL
* at which the source map was found. This URL is used to compute the
* sources array.
*
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
*/
function BasicSourceMapConsumer(aSourceMap, aSourceMapURL) {
var sourceMap = aSourceMap;
if (typeof aSourceMap === 'string') {
sourceMap = util.parseSourceMapInput(aSourceMap);
}
var version = util.getArg(sourceMap, 'version');
var sources = util.getArg(sourceMap, 'sources');
// Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
// requires the array) to play nice here.
var names = util.getArg(sourceMap, 'names', []);
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
var mappings = util.getArg(sourceMap, 'mappings');
var file = util.getArg(sourceMap, 'file', null);
// Once again, Sass deviates from the spec and supplies the version as a
// string rather than a number, so we use loose equality checking here.
if (version != this._version) {
throw new Error('Unsupported version: ' + version);
}
if (sourceRoot) {
sourceRoot = util.normalize(sourceRoot);
}
sources = sources
.map(String)
// Some source maps produce relative source paths like "./foo.js" instead of
// "foo.js". Normalize these first so that future comparisons will succeed.
// See bugzil.la/1090768.
.map(util.normalize)
// Always ensure that absolute sources are internally stored relative to
// the source root, if the source root is absolute. Not doing this would
// be particularly problematic when the source root is a prefix of the
// source (valid, but why??). See github issue #199 and bugzil.la/1188982.
.map(function (source) {
return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
? util.relative(sourceRoot, source)
: source;
});
// Pass `true` below to allow duplicate names and sources. While source maps
// are intended to be compressed and deduplicated, the TypeScript compiler
// sometimes generates source maps with duplicates in them. See Github issue
// #72 and bugzil.la/889492.
this._names = ArraySet.fromArray(names.map(String), true);
this._sources = ArraySet.fromArray(sources, true);
this._absoluteSources = this._sources.toArray().map(function (s) {
return util.computeSourceURL(sourceRoot, s, aSourceMapURL);
});
this.sourceRoot = sourceRoot;
this.sourcesContent = sourcesContent;
this._mappings = mappings;
this._sourceMapURL = aSourceMapURL;
this.file = file;
}
BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
/**
* Utility function to find the index of a source. Returns -1 if not
* found.
*/
BasicSourceMapConsumer.prototype._findSourceIndex = function(aSource) {
var relativeSource = aSource;
if (this.sourceRoot != null) {
relativeSource = util.relative(this.sourceRoot, relativeSource);
}
if (this._sources.has(relativeSource)) {
return this._sources.indexOf(relativeSource);
}
// Maybe aSource is an absolute URL as returned by |sources|. In
// this case we can't simply undo the transform.
var i;
for (i = 0; i < this._absoluteSources.length; ++i) {
if (this._absoluteSources[i] == aSource) {
return i;
}
}
return -1;
};
/**
* Create a BasicSourceMapConsumer from a SourceMapGenerator.
*
* @param SourceMapGenerator aSourceMap
* The source map that will be consumed.
* @param String aSourceMapURL
* The URL at which the source map can be found (optional)
* @returns BasicSourceMapConsumer
*/
BasicSourceMapConsumer.fromSourceMap =
function SourceMapConsumer_fromSourceMap(aSourceMap, aSourceMapURL) {
var smc = Object.create(BasicSourceMapConsumer.prototype);
var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
smc.sourceRoot = aSourceMap._sourceRoot;
smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
smc.sourceRoot);
smc.file = aSourceMap._file;
smc._sourceMapURL = aSourceMapURL;
smc._absoluteSources = smc._sources.toArray().map(function (s) {
return util.computeSourceURL(smc.sourceRoot, s, aSourceMapURL);
});
// Because we are modifying the entries (by converting string sources and
// names to indices into the sources and names ArraySets), we have to make
// a copy of the entry or else bad things happen. Shared mutable state
// strikes again! See github issue #191.
var generatedMappings = aSourceMap._mappings.toArray().slice();
var destGeneratedMappings = smc.__generatedMappings = [];
var destOriginalMappings = smc.__originalMappings = [];
for (var i = 0, length = generatedMappings.length; i < length; i++) {
var srcMapping = generatedMappings[i];
var destMapping = new Mapping;
destMapping.generatedLine = srcMapping.generatedLine;
destMapping.generatedColumn = srcMapping.generatedColumn;
if (srcMapping.source) {
destMapping.source = sources.indexOf(srcMapping.source);
destMapping.originalLine = srcMapping.originalLine;
destMapping.originalColumn = srcMapping.originalColumn;
if (srcMapping.name) {
destMapping.name = names.indexOf(srcMapping.name);
}
destOriginalMappings.push(destMapping);
}
destGeneratedMappings.push(destMapping);
}
quickSort(smc.__originalMappings, util.compareByOriginalPositions);
return smc;
};
/**
* The version of the source mapping spec that we are consuming.
*/
BasicSourceMapConsumer.prototype._version = 3;
/**
* The list of original sources.
*/
Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
get: function () {
return this._absoluteSources.slice();
}
});
/**
* Provide the JIT with a nice shape / hidden class.
*/
function Mapping() {
this.generatedLine = 0;
this.generatedColumn = 0;
this.source = null;
this.originalLine = null;
this.originalColumn = null;
this.name = null;
}
/**
* Parse the mappings in a string in to a data structure which we can easily
* query (the ordered arrays in the `this.__generatedMappings` and
* `this.__originalMappings` properties).
*/
BasicSourceMapConsumer.prototype._parseMappings =
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
var generatedLine = 1;
var previousGeneratedColumn = 0;
var previousOriginalLine = 0;
var previousOriginalColumn = 0;
var previousSource = 0;
var previousName = 0;
var length = aStr.length;
var index = 0;
var cachedSegments = {};
var temp = {};
var originalMappings = [];
var generatedMappings = [];
var mapping, str, segment, end, value;
while (index < length) {
if (aStr.charAt(index) === ';') {
generatedLine++;
index++;
previousGeneratedColumn = 0;
}
else if (aStr.charAt(index) === ',') {
index++;
}
else {
mapping = new Mapping();
mapping.generatedLine = generatedLine;
// Because each offset is encoded relative to the previous one,
// many segments often have the same encoding. We can exploit this
// fact by caching the parsed variable length fields of each segment,
// allowing us to avoid a second parse if we encounter the same
// segment again.
for (end = index; end < length; end++) {
if (this._charIsMappingSeparator(aStr, end)) {
break;
}
}
str = aStr.slice(index, end);
segment = cachedSegments[str];
if (segment) {
index += str.length;
} else {
segment = [];
while (index < end) {
base64VLQ.decode(aStr, index, temp);
value = temp.value;
index = temp.rest;
segment.push(value);
}
if (segment.length === 2) {
throw new Error('Found a source, but no line and column');
}
if (segment.length === 3) {
throw new Error('Found a source and line, but no column');
}
cachedSegments[str] = segment;
}
// Generated column.
mapping.generatedColumn = previousGeneratedColumn + segment[0];
previousGeneratedColumn = mapping.generatedColumn;
if (segment.length > 1) {
// Original source.
mapping.source = previousSource + segment[1];
previousSource += segment[1];
// Original line.
mapping.originalLine = previousOriginalLine + segment[2];
previousOriginalLine = mapping.originalLine;
// Lines are stored 0-based
mapping.originalLine += 1;
// Original column.
mapping.originalColumn = previousOriginalColumn + segment[3];
previousOriginalColumn = mapping.originalColumn;
if (segment.length > 4) {
// Original name.
mapping.name = previousName + segment[4];
previousName += segment[4];
}
}
generatedMappings.push(mapping);
if (typeof mapping.originalLine === 'number') {
originalMappings.push(mapping);
}
}
}
quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);
this.__generatedMappings = generatedMappings;
quickSort(originalMappings, util.compareByOriginalPositions);
this.__originalMappings = originalMappings;
};
/**
* Find the mapping that best matches the hypothetical "needle" mapping that
* we are searching for in the given "haystack" of mappings.
*/
BasicSourceMapConsumer.prototype._findMapping =
function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
aColumnName, aComparator, aBias) {
// To return the position we are searching for, we must first find the
// mapping for the given position and then return the opposite position it
// points to. Because the mappings are sorted, we can use binary search to
// find the best mapping.
if (aNeedle[aLineName] <= 0) {
throw new TypeError('Line must be greater than or equal to 1, got '
+ aNeedle[aLineName]);
}
if (aNeedle[aColumnName] < 0) {
throw new TypeError('Column must be greater than or equal to 0, got '
+ aNeedle[aColumnName]);
}
return binarySearch.search(aNeedle, aMappings, aComparator, aBias);
};
/**
* Compute the last column for each generated mapping. The last column is
* inclusive.
*/
BasicSourceMapConsumer.prototype.computeColumnSpans =
function SourceMapConsumer_computeColumnSpans() {
for (var index = 0; index < this._generatedMappings.length; ++index) {
var mapping = this._generatedMappings[index];
// Mappings do not contain a field for the last generated columnt. We
// can come up with an optimistic estimate, however, by assuming that
// mappings are contiguous (i.e. given two consecutive mappings, the
// first mapping ends where the second one starts).
if (index + 1 < this._generatedMappings.length) {
var nextMapping = this._generatedMappings[index + 1];
if (mapping.generatedLine === nextMapping.generatedLine) {
mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
continue;
}
}
// The last mapping for each line spans the entire line.
mapping.lastGeneratedColumn = Infinity;
}
};
/**
* Returns the original source, line, and column information for the generated
* source's line and column positions provided. The only argument is an object
* with the following properties:
*
* - line: The line number in the generated source. The line number
* is 1-based.
* - column: The column number in the generated source. The column
* number is 0-based.
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
*
* and an object is returned with the following properties:
*
* - source: The original source file, or null.
* - line: The line number in the original source, or null. The
* line number is 1-based.
* - column: The column number in the original source, or null. The
* column number is 0-based.
* - name: The original identifier, or null.
*/
BasicSourceMapConsumer.prototype.originalPositionFor =
function SourceMapConsumer_originalPositionFor(aArgs) {
var needle = {
generatedLine: util.getArg(aArgs, 'line'),
generatedColumn: util.getArg(aArgs, 'column')
};
var index = this._findMapping(
needle,
this._generatedMappings,
"generatedLine",
"generatedColumn",
util.compareByGeneratedPositionsDeflated,
util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)
);
if (index >= 0) {
var mapping = this._generatedMappings[index];
if (mapping.generatedLine === needle.generatedLine) {
var source = util.getArg(mapping, 'source', null);
if (source !== null) {
source = this._sources.at(source);
source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL);
}
var name = util.getArg(mapping, 'name', null);
if (name !== null) {
name = this._names.at(name);
}
return {
source: source,
line: util.getArg(mapping, 'originalLine', null),
column: util.getArg(mapping, 'originalColumn', null),
name: name
};
}
}
return {
source: null,
line: null,
column: null,
name: null
};
};
/**
* Return true if we have the source content for every source in the source
* map, false otherwise.
*/
BasicSourceMapConsumer.prototype.hasContentsOfAllSources =
function BasicSourceMapConsumer_hasContentsOfAllSources() {
if (!this.sourcesContent) {
return false;
}
return this.sourcesContent.length >= this._sources.size() &&
!this.sourcesContent.some(function (sc) { return sc == null; });
};
/**
* Returns the original source content. The only argument is the url of the
* original source file. Returns null if no original source content is
* available.
*/
BasicSourceMapConsumer.prototype.sourceContentFor =
function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
if (!this.sourcesContent) {
return null;
}
var index = this._findSourceIndex(aSource);
if (index >= 0) {
return this.sourcesContent[index];
}
var relativeSource = aSource;
if (this.sourceRoot != null) {
relativeSource = util.relative(this.sourceRoot, relativeSource);
}
var url;
if (this.sourceRoot != null
&& (url = util.urlParse(this.sourceRoot))) {
// XXX: file:// URIs and absolute paths lead to unexpected behavior for
// many users. We can help them out when they expect file:// URIs to
// behave like it would if they were running a local HTTP server. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
var fileUriAbsPath = relativeSource.replace(/^file:\/\//, "");
if (url.scheme == "file"
&& this._sources.has(fileUriAbsPath)) {
return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
}
if ((!url.path || url.path == "/")
&& this._sources.has("/" + relativeSource)) {
return this.sourcesContent[this._sources.indexOf("/" + relativeSource)];
}
}
// This function is used recursively from
// IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
// don't want to throw if we can't find the source - we just want to
// return null, so we provide a flag to exit gracefully.
if (nullOnMissing) {
return null;
}
else {
throw new Error('"' + relativeSource + '" is not in the SourceMap.');
}
};
/**
* Returns the generated line and column information for the original source,
* line, and column positions provided. The only argument is an object with
* the following properties:
*
* - source: The filename of the original source.
* - line: The line number in the original source. The line number
* is 1-based.
* - column: The column number in the original source. The column
* number is 0-based.
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
*
* and an object is returned with the following properties:
*
* - line: The line number in the generated source, or null. The
* line number is 1-based.
* - column: The column number in the generated source, or null.
* The column number is 0-based.
*/
BasicSourceMapConsumer.prototype.generatedPositionFor =
function SourceMapConsumer_generatedPositionFor(aArgs) {
var source = util.getArg(aArgs, 'source');
source = this._findSourceIndex(source);
if (source < 0) {
return {
line: null,
column: null,
lastColumn: null
};
}
var needle = {
source: source,
originalLine: util.getArg(aArgs, 'line'),
originalColumn: util.getArg(aArgs, 'column')
};
var index = this._findMapping(
needle,
this._originalMappings,
"originalLine",
"originalColumn",
util.compareByOriginalPositions,
util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)
);
if (index >= 0) {
var mapping = this._originalMappings[index];
if (mapping.source === needle.source) {
return {
line: util.getArg(mapping, 'generatedLine', null),
column: util.getArg(mapping, 'generatedColumn', null),
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
};
}
}
return {
line: null,
column: null,
lastColumn: null
};
};
exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
/**
* An IndexedSourceMapConsumer instance represents a parsed source map which
* we can query for information. It differs from BasicSourceMapConsumer in
* that it takes "indexed" source maps (i.e. ones with a "sections" field) as
* input.
*
* The first parameter is a raw source map (either as a JSON string, or already
* parsed to an object). According to the spec for indexed source maps, they
* have the following attributes:
*
* - version: Which version of the source map spec this map is following.
* - file: Optional. The generated file this source map is associated with.
* - sections: A list of section definitions.
*
* Each value under the "sections" field has two fields:
* - offset: The offset into the original specified at which this section
* begins to apply, defined as an object with a "line" and "column"
* field.
* - map: A source map definition. This source map could also be indexed,
* but doesn't have to be.
*
* Instead of the "map" field, it's also possible to have a "url" field
* specifying a URL to retrieve a source map from, but that's currently
* unsupported.
*
* Here's an example source map, taken from the source map spec[0], but
* modified to omit a section which uses the "url" field.
*
* {
* version : 3,
* file: "app.js",
* sections: [{
* offset: {line:100, column:10},
* map: {
* version : 3,
* file: "section.js",
* sources: ["foo.js", "bar.js"],
* names: ["src", "maps", "are", "fun"],
* mappings: "AAAA,E;;ABCDE;"
* }
* }],
* }
*
* The second parameter, if given, is a string whose value is the URL
* at which the source map was found. This URL is used to compute the
* sources array.
*
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt
*/
function IndexedSourceMapConsumer(aSourceMap, aSourceMapURL) {
var sourceMap = aSourceMap;
if (typeof aSourceMap === 'string') {
sourceMap = util.parseSourceMapInput(aSourceMap);
}
var version = util.getArg(sourceMap, 'version');
var sections = util.getArg(sourceMap, 'sections');
if (version != this._version) {
throw new Error('Unsupported version: ' + version);
}
this._sources = new ArraySet();
this._names = new ArraySet();
var lastOffset = {
line: -1,
column: 0
};
this._sections = sections.map(function (s) {
if (s.url) {
// The url field will require support for asynchronicity.
// See https://github.com/mozilla/source-map/issues/16
throw new Error('Support for url field in sections not implemented.');
}
var offset = util.getArg(s, 'offset');
var offsetLine = util.getArg(offset, 'line');
var offsetColumn = util.getArg(offset, 'column');
if (offsetLine < lastOffset.line ||
(offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {
throw new Error('Section offsets must be ordered and non-overlapping.');
}
lastOffset = offset;
return {
generatedOffset: {
// The offset fields are 0-based, but we use 1-based indices when
// encoding/decoding from VLQ.
generatedLine: offsetLine + 1,
generatedColumn: offsetColumn + 1
},
consumer: new SourceMapConsumer(util.getArg(s, 'map'), aSourceMapURL)
}
});
}
IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;
/**
* The version of the source mapping spec that we are consuming.
*/
IndexedSourceMapConsumer.prototype._version = 3;
/**
* The list of original sources.
*/
Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {
get: function () {
var sources = [];
for (var i = 0; i < this._sections.length; i++) {
for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
sources.push(this._sections[i].consumer.sources[j]);
}
}
return sources;
}
});
/**
* Returns the original source, line, and column information for the generated
* source's line and column positions provided. The only argument is an object
* with the following properties:
*
* - line: The line number in the generated source. The line number
* is 1-based.
* - column: The column number in the generated source. The column
* number is 0-based.
*
* and an object is returned with the following properties:
*
* - source: The original source file, or null.
* - line: The line number in the original source, or null. The
* line number is 1-based.
* - column: The column number in the original source, or null. The
* column number is 0-based.
* - name: The original identifier, or null.
*/
IndexedSourceMapConsumer.prototype.originalPositionFor =
function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
var needle = {
generatedLine: util.getArg(aArgs, 'line'),
generatedColumn: util.getArg(aArgs, 'column')
};
// Find the section containing the generated position we're trying to map
// to an original position.
var sectionIndex = binarySearch.search(needle, this._sections,
function(needle, section) {
var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
if (cmp) {
return cmp;
}
return (needle.generatedColumn -
section.generatedOffset.generatedColumn);
});
var section = this._sections[sectionIndex];
if (!section) {
return {
source: null,
line: null,
column: null,
name: null
};
}
return section.consumer.originalPositionFor({
line: needle.generatedLine -
(section.generatedOffset.generatedLine - 1),
column: needle.generatedColumn -
(section.generatedOffset.generatedLine === needle.generatedLine
? section.generatedOffset.generatedColumn - 1
: 0),
bias: aArgs.bias
});
};
/**
* Return true if we have the source content for every source in the source
* map, false otherwise.
*/
IndexedSourceMapConsumer.prototype.hasContentsOfAllSources =
function IndexedSourceMapConsumer_hasContentsOfAllSources() {
return this._sections.every(function (s) {
return s.consumer.hasContentsOfAllSources();
});
};
/**
* Returns the original source content. The only argument is the url of the
* original source file. Returns null if no original source content is
* available.
*/
IndexedSourceMapConsumer.prototype.sourceContentFor =
function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
for (var i = 0; i < this._sections.length; i++) {
var section = this._sections[i];
var content = section.consumer.sourceContentFor(aSource, true);
if (content) {
return content;
}
}
if (nullOnMissing) {
return null;
}
else {
throw new Error('"' + aSource + '" is not in the SourceMap.');
}
};
/**
* Returns the generated line and column information for the original source,
* line, and column positions provided. The only argument is an object with
* the following properties:
*
* - source: The filename of the original source.
* - line: The line number in the original source. The line number
* is 1-based.
* - column: The column number in the original source. The column
* number is 0-based.
*
* and an object is returned with the following properties:
*
* - line: The line number in the generated source, or null. The
* line number is 1-based.
* - column: The column number in the generated source, or null.
* The column number is 0-based.
*/
IndexedSourceMapConsumer.prototype.generatedPositionFor =
function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
for (var i = 0; i < this._sections.length; i++) {
var section = this._sections[i];
// Only consider this section if the requested source is in the list of
// sources of the consumer.
if (section.consumer._findSourceIndex(util.getArg(aArgs, 'source')) === -1) {
continue;
}
var generatedPosition = section.consumer.generatedPositionFor(aArgs);
if (generatedPosition) {
var ret = {
line: generatedPosition.line +
(section.generatedOffset.generatedLine - 1),
column: generatedPosition.column +
(section.generatedOffset.generatedLine === generatedPosition.line
? section.generatedOffset.generatedColumn - 1
: 0)
};
return ret;
}
}
return {
line: null,
column: null
};
};
/**
* Parse the mappings in a string in to a data structure which we can easily
* query (the ordered arrays in the `this.__generatedMappings` and
* `this.__originalMappings` properties).
*/
IndexedSourceMapConsumer.prototype._parseMappings =
function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
this.__generatedMappings = [];
this.__originalMappings = [];
for (var i = 0; i < this._sections.length; i++) {
var section = this._sections[i];
var sectionMappings = section.consumer._generatedMappings;
for (var j = 0; j < sectionMappings.length; j++) {
var mapping = sectionMappings[j];
var source = section.consumer._sources.at(mapping.source);
source = util.computeSourceURL(section.consumer.sourceRoot, source, this._sourceMapURL);
this._sources.add(source);
source = this._sources.indexOf(source);
var name = null;
if (mapping.name) {
name = section.consumer._names.at(mapping.name);
this._names.add(name);
name = this._names.indexOf(name);
}
// The mappings coming from the consumer for the section have
// generated positions relative to the start of the section, so we
// need to offset them to be relative to the start of the concatenated
// generated file.
var adjustedMapping = {
source: source,
generatedLine: mapping.generatedLine +
(section.generatedOffset.generatedLine - 1),
generatedColumn: mapping.generatedColumn +
(section.generatedOffset.generatedLine === mapping.generatedLine
? section.generatedOffset.generatedColumn - 1
: 0),
originalLine: mapping.originalLine,
originalColumn: mapping.originalColumn,
name: name
};
this.__generatedMappings.push(adjustedMapping);
if (typeof adjustedMapping.originalLine === 'number') {
this.__originalMappings.push(adjustedMapping);
}
}
}
quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
quickSort(this.__originalMappings, util.compareByOriginalPositions);
};
exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
},{"./array-set":50,"./base64-vlq":51,"./binary-search":53,"./quick-sort":55,"./util":59}],57:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var base64VLQ = require('./base64-vlq');
var util = require('./util');
var ArraySet = require('./array-set').ArraySet;
var MappingList = require('./mapping-list').MappingList;
/**
* An instance of the SourceMapGenerator represents a source map which is
* being built incrementally. You may pass an object with the following
* properties:
*
* - file: The filename of the generated source.
* - sourceRoot: A root for all relative URLs in this source map.
*/
function SourceMapGenerator(aArgs) {
if (!aArgs) {
aArgs = {};
}
this._file = util.getArg(aArgs, 'file', null);
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
this._sources = new ArraySet();
this._names = new ArraySet();
this._mappings = new MappingList();
this._sourcesContents = null;
}
SourceMapGenerator.prototype._version = 3;
/**
* Creates a new SourceMapGenerator based on a SourceMapConsumer
*
* @param aSourceMapConsumer The SourceMap.
*/
SourceMapGenerator.fromSourceMap =
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
var sourceRoot = aSourceMapConsumer.sourceRoot;
var generator = new SourceMapGenerator({
file: aSourceMapConsumer.file,
sourceRoot: sourceRoot
});
aSourceMapConsumer.eachMapping(function (mapping) {
var newMapping = {
generated: {
line: mapping.generatedLine,
column: mapping.generatedColumn
}
};
if (mapping.source != null) {
newMapping.source = mapping.source;
if (sourceRoot != null) {
newMapping.source = util.relative(sourceRoot, newMapping.source);
}
newMapping.original = {
line: mapping.originalLine,
column: mapping.originalColumn
};
if (mapping.name != null) {
newMapping.name = mapping.name;
}
}
generator.addMapping(newMapping);
});
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var sourceRelative = sourceFile;
if (sourceRoot !== null) {
sourceRelative = util.relative(sourceRoot, sourceFile);
}
if (!generator._sources.has(sourceRelative)) {
generator._sources.add(sourceRelative);
}
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
generator.setSourceContent(sourceFile, content);
}
});
return generator;
};
/**
* Add a single mapping from original source line and column to the generated
* source's line and column for this source map being created. The mapping
* object should have the following properties:
*
* - generated: An object with the generated line and column positions.
* - original: An object with the original line and column positions.
* - source: The original source file (relative to the sourceRoot).
* - name: An optional original token name for this mapping.
*/
SourceMapGenerator.prototype.addMapping =
function SourceMapGenerator_addMapping(aArgs) {
var generated = util.getArg(aArgs, 'generated');
var original = util.getArg(aArgs, 'original', null);
var source = util.getArg(aArgs, 'source', null);
var name = util.getArg(aArgs, 'name', null);
if (!this._skipValidation) {
this._validateMapping(generated, original, source, name);
}
if (source != null) {
source = String(source);
if (!this._sources.has(source)) {
this._sources.add(source);
}
}
if (name != null) {
name = String(name);
if (!this._names.has(name)) {
this._names.add(name);
}
}
this._mappings.add({
generatedLine: generated.line,
generatedColumn: generated.column,
originalLine: original != null && original.line,
originalColumn: original != null && original.column,
source: source,
name: name
});
};
/**
* Set the source content for a source file.
*/
SourceMapGenerator.prototype.setSourceContent =
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
var source = aSourceFile;
if (this._sourceRoot != null) {
source = util.relative(this._sourceRoot, source);
}
if (aSourceContent != null) {
// Add the source content to the _sourcesContents map.
// Create a new _sourcesContents map if the property is null.
if (!this._sourcesContents) {
this._sourcesContents = Object.create(null);
}
this._sourcesContents[util.toSetString(source)] = aSourceContent;
} else if (this._sourcesContents) {
// Remove the source file from the _sourcesContents map.
// If the _sourcesContents map is empty, set the property to null.
delete this._sourcesContents[util.toSetString(source)];
if (Object.keys(this._sourcesContents).length === 0) {
this._sourcesContents = null;
}
}
};
/**
* Applies the mappings of a sub-source-map for a specific source file to the
* source map being generated. Each mapping to the supplied source file is
* rewritten using the supplied source map. Note: The resolution for the
* resulting mappings is the minimium of this map and the supplied map.
*
* @param aSourceMapConsumer The source map to be applied.
* @param aSourceFile Optional. The filename of the source file.
* If omitted, SourceMapConsumer's file property will be used.
* @param aSourceMapPath Optional. The dirname of the path to the source map
* to be applied. If relative, it is relative to the SourceMapConsumer.
* This parameter is needed when the two source maps aren't in the same
* directory, and the source map to be applied contains relative source
* paths. If so, those relative source paths need to be rewritten
* relative to the SourceMapGenerator.
*/
SourceMapGenerator.prototype.applySourceMap =
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
var sourceFile = aSourceFile;
// If aSourceFile is omitted, we will use the file property of the SourceMap
if (aSourceFile == null) {
if (aSourceMapConsumer.file == null) {
throw new Error(
'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
'or the source map\'s "file" property. Both were omitted.'
);
}
sourceFile = aSourceMapConsumer.file;
}
var sourceRoot = this._sourceRoot;
// Make "sourceFile" relative if an absolute Url is passed.
if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
// Applying the SourceMap can add and remove items from the sources and
// the names array.
var newSources = new ArraySet();
var newNames = new ArraySet();
// Find mappings for the "sourceFile"
this._mappings.unsortedForEach(function (mapping) {
if (mapping.source === sourceFile && mapping.originalLine != null) {
// Check if it can be mapped by the source map, then update the mapping.
var original = aSourceMapConsumer.originalPositionFor({
line: mapping.originalLine,
column: mapping.originalColumn
});
if (original.source != null) {
// Copy mapping
mapping.source = original.source;
if (aSourceMapPath != null) {
mapping.source = util.join(aSourceMapPath, mapping.source)
}
if (sourceRoot != null) {
mapping.source = util.relative(sourceRoot, mapping.source);
}
mapping.originalLine = original.line;
mapping.originalColumn = original.column;
if (original.name != null) {
mapping.name = original.name;
}
}
}
var source = mapping.source;
if (source != null && !newSources.has(source)) {
newSources.add(source);
}
var name = mapping.name;
if (name != null && !newNames.has(name)) {
newNames.add(name);
}
}, this);
this._sources = newSources;
this._names = newNames;
// Copy sourcesContents of applied map.
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
if (aSourceMapPath != null) {
sourceFile = util.join(aSourceMapPath, sourceFile);
}
if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
this.setSourceContent(sourceFile, content);
}
}, this);
};
/**
* A mapping can have one of the three levels of data:
*
* 1. Just the generated position.
* 2. The Generated position, original position, and original source.
* 3. Generated and original position, original source, as well as a name
* token.
*
* To maintain consistency, we validate that any new mapping being added falls
* in to one of these categories.
*/
SourceMapGenerator.prototype._validateMapping =
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
aName) {
// When aOriginal is truthy but has empty values for .line and .column,
// it is most likely a programmer error. In this case we throw a very
// specific error message to try to guide them the right way.
// For example: https://github.com/Polymer/polymer-bundler/pull/519
if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
throw new Error(
'original.line and original.column are not numbers -- you probably meant to omit ' +
'the original mapping entirely and only map the generated position. If so, pass ' +
'null for the original mapping instead of an object with empty or null values.'
);
}
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
&& aGenerated.line > 0 && aGenerated.column >= 0
&& !aOriginal && !aSource && !aName) {
// Case 1.
return;
}
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal
&& aGenerated.line > 0 && aGenerated.column >= 0
&& aOriginal.line > 0 && aOriginal.column >= 0
&& aSource) {
// Cases 2 and 3.
return;
}
else {
throw new Error('Invalid mapping: ' + JSON.stringify({
generated: aGenerated,
source: aSource,
original: aOriginal,
name: aName
}));
}
};
/**
* Serialize the accumulated mappings in to the stream of base 64 VLQs
* specified by the source map format.
*/
SourceMapGenerator.prototype._serializeMappings =
function SourceMapGenerator_serializeMappings() {
var previousGeneratedColumn = 0;
var previousGeneratedLine = 1;
var previousOriginalColumn = 0;
var previousOriginalLine = 0;
var previousName = 0;
var previousSource = 0;
var result = '';
var next;
var mapping;
var nameIdx;
var sourceIdx;
var mappings = this._mappings.toArray();
for (var i = 0, len = mappings.length; i < len; i++) {
mapping = mappings[i];
next = ''
if (mapping.generatedLine !== previousGeneratedLine) {
previousGeneratedColumn = 0;
while (mapping.generatedLine !== previousGeneratedLine) {
next += ';';
previousGeneratedLine++;
}
}
else {
if (i > 0) {
if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
continue;
}
next += ',';
}
}
next += base64VLQ.encode(mapping.generatedColumn
- previousGeneratedColumn);
previousGeneratedColumn = mapping.generatedColumn;
if (mapping.source != null) {
sourceIdx = this._sources.indexOf(mapping.source);
next += base64VLQ.encode(sourceIdx - previousSource);
previousSource = sourceIdx;
// lines are stored 0-based in SourceMap spec version 3
next += base64VLQ.encode(mapping.originalLine - 1
- previousOriginalLine);
previousOriginalLine = mapping.originalLine - 1;
next += base64VLQ.encode(mapping.originalColumn
- previousOriginalColumn);
previousOriginalColumn = mapping.originalColumn;
if (mapping.name != null) {
nameIdx = this._names.indexOf(mapping.name);
next += base64VLQ.encode(nameIdx - previousName);
previousName = nameIdx;
}
}
result += next;
}
return result;
};
SourceMapGenerator.prototype._generateSourcesContent =
function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
return aSources.map(function (source) {
if (!this._sourcesContents) {
return null;
}
if (aSourceRoot != null) {
source = util.relative(aSourceRoot, source);
}
var key = util.toSetString(source);
return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
? this._sourcesContents[key]
: null;
}, this);
};
/**
* Externalize the source map.
*/
SourceMapGenerator.prototype.toJSON =
function SourceMapGenerator_toJSON() {
var map = {
version: this._version,
sources: this._sources.toArray(),
names: this._names.toArray(),
mappings: this._serializeMappings()
};
if (this._file != null) {
map.file = this._file;
}
if (this._sourceRoot != null) {
map.sourceRoot = this._sourceRoot;
}
if (this._sourcesContents) {
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
}
return map;
};
/**
* Render the source map being generated to a string.
*/
SourceMapGenerator.prototype.toString =
function SourceMapGenerator_toString() {
return JSON.stringify(this.toJSON());
};
exports.SourceMapGenerator = SourceMapGenerator;
},{"./array-set":50,"./base64-vlq":51,"./mapping-list":54,"./util":59}],58:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
var util = require('./util');
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
// operating systems these days (capturing the result).
var REGEX_NEWLINE = /(\r?\n)/;
// Newline character code for charCodeAt() comparisons
var NEWLINE_CODE = 10;
// Private symbol for identifying `SourceNode`s when multiple versions of
// the source-map library are loaded. This MUST NOT CHANGE across
// versions!
var isSourceNode = "$$$isSourceNode$$$";
/**
* SourceNodes provide a way to abstract over interpolating/concatenating
* snippets of generated JavaScript source code while maintaining the line and
* column information associated with the original source code.
*
* @param aLine The original line number.
* @param aColumn The original column number.
* @param aSource The original source's filename.
* @param aChunks Optional. An array of strings which are snippets of
* generated JS, or other SourceNodes.
* @param aName The original identifier.
*/
function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
this.children = [];
this.sourceContents = {};
this.line = aLine == null ? null : aLine;
this.column = aColumn == null ? null : aColumn;
this.source = aSource == null ? null : aSource;
this.name = aName == null ? null : aName;
this[isSourceNode] = true;
if (aChunks != null) this.add(aChunks);
}
/**
* Creates a SourceNode from generated code and a SourceMapConsumer.
*
* @param aGeneratedCode The generated code
* @param aSourceMapConsumer The SourceMap for the generated code
* @param aRelativePath Optional. The path that relative sources in the
* SourceMapConsumer should be relative to.
*/
SourceNode.fromStringWithSourceMap =
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
// The SourceNode we want to fill with the generated code
// and the SourceMap
var node = new SourceNode();
// All even indices of this array are one line of the generated code,
// while all odd indices are the newlines between two adjacent lines
// (since `REGEX_NEWLINE` captures its match).
// Processed fragments are accessed by calling `shiftNextLine`.
var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
var remainingLinesIndex = 0;
var shiftNextLine = function() {
var lineContents = getNextLine();
// The last line of a file might not have a newline.
var newLine = getNextLine() || "";
return lineContents + newLine;
function getNextLine() {
return remainingLinesIndex < remainingLines.length ?
remainingLines[remainingLinesIndex++] : undefined;
}
};
// We need to remember the position of "remainingLines"
var lastGeneratedLine = 1, lastGeneratedColumn = 0;
// The generate SourceNodes we need a code range.
// To extract it current and last mapping is used.
// Here we store the last mapping.
var lastMapping = null;
aSourceMapConsumer.eachMapping(function (mapping) {
if (lastMapping !== null) {
// We add the code from "lastMapping" to "mapping":
// First check if there is a new line in between.
if (lastGeneratedLine < mapping.generatedLine) {
// Associate first line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
lastGeneratedLine++;
lastGeneratedColumn = 0;
// The remaining code is added without mapping
} else {
// There is no new line in between.
// Associate the code between "lastGeneratedColumn" and
// "mapping.generatedColumn" with "lastMapping"
var nextLine = remainingLines[remainingLinesIndex] || '';
var code = nextLine.substr(0, mapping.generatedColumn -
lastGeneratedColumn);
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -
lastGeneratedColumn);
lastGeneratedColumn = mapping.generatedColumn;
addMappingWithCode(lastMapping, code);
// No more remaining code, continue
lastMapping = mapping;
return;
}
}
// We add the generated code until the first mapping
// to the SourceNode without any mapping.
// Each line is added as separate string.
while (lastGeneratedLine < mapping.generatedLine) {
node.add(shiftNextLine());
lastGeneratedLine++;
}
if (lastGeneratedColumn < mapping.generatedColumn) {
var nextLine = remainingLines[remainingLinesIndex] || '';
node.add(nextLine.substr(0, mapping.generatedColumn));
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);
lastGeneratedColumn = mapping.generatedColumn;
}
lastMapping = mapping;
}, this);
// We have processed all mappings.
if (remainingLinesIndex < remainingLines.length) {
if (lastMapping) {
// Associate the remaining code in the current line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
}
// and add the remaining lines without any mapping
node.add(remainingLines.splice(remainingLinesIndex).join(""));
}
// Copy sourcesContent into SourceNode
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
if (aRelativePath != null) {
sourceFile = util.join(aRelativePath, sourceFile);
}
node.setSourceContent(sourceFile, content);
}
});
return node;
function addMappingWithCode(mapping, code) {
if (mapping === null || mapping.source === undefined) {
node.add(code);
} else {
var source = aRelativePath
? util.join(aRelativePath, mapping.source)
: mapping.source;
node.add(new SourceNode(mapping.originalLine,
mapping.originalColumn,
source,
code,
mapping.name));
}
}
};
/**
* Add a chunk of generated JS to this source node.
*
* @param aChunk A string snippet of generated JS code, another instance of
* SourceNode, or an array where each member is one of those things.
*/
SourceNode.prototype.add = function SourceNode_add(aChunk) {
if (Array.isArray(aChunk)) {
aChunk.forEach(function (chunk) {
this.add(chunk);
}, this);
}
else if (aChunk[isSourceNode] || typeof aChunk === "string") {
if (aChunk) {
this.children.push(aChunk);
}
}
else {
throw new TypeError(
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
);
}
return this;
};
/**
* Add a chunk of generated JS to the beginning of this source node.
*
* @param aChunk A string snippet of generated JS code, another instance of
* SourceNode, or an array where each member is one of those things.
*/
SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
if (Array.isArray(aChunk)) {
for (var i = aChunk.length-1; i >= 0; i--) {
this.prepend(aChunk[i]);
}
}
else if (aChunk[isSourceNode] || typeof aChunk === "string") {
this.children.unshift(aChunk);
}
else {
throw new TypeError(
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
);
}
return this;
};
/**
* Walk over the tree of JS snippets in this node and its children. The
* walking function is called once for each snippet of JS and is passed that
* snippet and the its original associated source's line/column location.
*
* @param aFn The traversal function.
*/
SourceNode.prototype.walk = function SourceNode_walk(aFn) {
var chunk;
for (var i = 0, len = this.children.length; i < len; i++) {
chunk = this.children[i];
if (chunk[isSourceNode]) {
chunk.walk(aFn);
}
else {
if (chunk !== '') {
aFn(chunk, { source: this.source,
line: this.line,
column: this.column,
name: this.name });
}
}
}
};
/**
* Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
* each of `this.children`.
*
* @param aSep The separator.
*/
SourceNode.prototype.join = function SourceNode_join(aSep) {
var newChildren;
var i;
var len = this.children.length;
if (len > 0) {
newChildren = [];
for (i = 0; i < len-1; i++) {
newChildren.push(this.children[i]);
newChildren.push(aSep);
}
newChildren.push(this.children[i]);
this.children = newChildren;
}
return this;
};
/**
* Call String.prototype.replace on the very right-most source snippet. Useful
* for trimming whitespace from the end of a source node, etc.
*
* @param aPattern The pattern to replace.
* @param aReplacement The thing to replace the pattern with.
*/
SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
var lastChild = this.children[this.children.length - 1];
if (lastChild[isSourceNode]) {
lastChild.replaceRight(aPattern, aReplacement);
}
else if (typeof lastChild === 'string') {
this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
}
else {
this.children.push(''.replace(aPattern, aReplacement));
}
return this;
};
/**
* Set the source content for a source file. This will be added to the SourceMapGenerator
* in the sourcesContent field.
*
* @param aSourceFile The filename of the source file
* @param aSourceContent The content of the source file
*/
SourceNode.prototype.setSourceContent =
function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
};
/**
* Walk over the tree of SourceNodes. The walking function is called for each
* source file content and is passed the filename and source content.
*
* @param aFn The traversal function.
*/
SourceNode.prototype.walkSourceContents =
function SourceNode_walkSourceContents(aFn) {
for (var i = 0, len = this.children.length; i < len; i++) {
if (this.children[i][isSourceNode]) {
this.children[i].walkSourceContents(aFn);
}
}
var sources = Object.keys(this.sourceContents);
for (var i = 0, len = sources.length; i < len; i++) {
aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
}
};
/**
* Return the string representation of this source node. Walks over the tree
* and concatenates all the various snippets together to one string.
*/
SourceNode.prototype.toString = function SourceNode_toString() {
var str = "";
this.walk(function (chunk) {
str += chunk;
});
return str;
};
/**
* Returns the string representation of this source node along with a source
* map.
*/
SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
var generated = {
code: "",
line: 1,
column: 0
};
var map = new SourceMapGenerator(aArgs);
var sourceMappingActive = false;
var lastOriginalSource = null;
var lastOriginalLine = null;
var lastOriginalColumn = null;
var lastOriginalName = null;
this.walk(function (chunk, original) {
generated.code += chunk;
if (original.source !== null
&& original.line !== null
&& original.column !== null) {
if(lastOriginalSource !== original.source
|| lastOriginalLine !== original.line
|| lastOriginalColumn !== original.column
|| lastOriginalName !== original.name) {
map.addMapping({
source: original.source,
original: {
line: original.line,
column: original.column
},
generated: {
line: generated.line,
column: generated.column
},
name: original.name
});
}
lastOriginalSource = original.source;
lastOriginalLine = original.line;
lastOriginalColumn = original.column;
lastOriginalName = original.name;
sourceMappingActive = true;
} else if (sourceMappingActive) {
map.addMapping({
generated: {
line: generated.line,
column: generated.column
}
});
lastOriginalSource = null;
sourceMappingActive = false;
}
for (var idx = 0, length = chunk.length; idx < length; idx++) {
if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
generated.line++;
generated.column = 0;
// Mappings end at eol
if (idx + 1 === length) {
lastOriginalSource = null;
sourceMappingActive = false;
} else if (sourceMappingActive) {
map.addMapping({
source: original.source,
original: {
line: original.line,
column: original.column
},
generated: {
line: generated.line,
column: generated.column
},
name: original.name
});
}
} else {
generated.column++;
}
}
});
this.walkSourceContents(function (sourceFile, sourceContent) {
map.setSourceContent(sourceFile, sourceContent);
});
return { code: generated.code, map: map };
};
exports.SourceNode = SourceNode;
},{"./source-map-generator":57,"./util":59}],59:[function(require,module,exports){
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
/**
* This is a helper function for getting values from parameter/options
* objects.
*
* @param args The object we are extracting values from
* @param name The name of the property we are getting.
* @param defaultValue An optional value to return if the property is missing
* from the object. If this is not specified and the property is missing, an
* error will be thrown.
*/
function getArg(aArgs, aName, aDefaultValue) {
if (aName in aArgs) {
return aArgs[aName];
} else if (arguments.length === 3) {
return aDefaultValue;
} else {
throw new Error('"' + aName + '" is a required argument.');
}
}
exports.getArg = getArg;
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
var dataUrlRegexp = /^data:.+\,.+$/;
function urlParse(aUrl) {
var match = aUrl.match(urlRegexp);
if (!match) {
return null;
}
return {
scheme: match[1],
auth: match[2],
host: match[3],
port: match[4],
path: match[5]
};
}
exports.urlParse = urlParse;
function urlGenerate(aParsedUrl) {
var url = '';
if (aParsedUrl.scheme) {
url += aParsedUrl.scheme + ':';
}
url += '//';
if (aParsedUrl.auth) {
url += aParsedUrl.auth + '@';
}
if (aParsedUrl.host) {
url += aParsedUrl.host;
}
if (aParsedUrl.port) {
url += ":" + aParsedUrl.port
}
if (aParsedUrl.path) {
url += aParsedUrl.path;
}
return url;
}
exports.urlGenerate = urlGenerate;
/**
* Normalizes a path, or the path portion of a URL:
*
* - Replaces consecutive slashes with one slash.
* - Removes unnecessary '.' parts.
* - Removes unnecessary '<dir>/..' parts.
*
* Based on code in the Node.js 'path' core module.
*
* @param aPath The path or url to normalize.
*/
function normalize(aPath) {
var path = aPath;
var url = urlParse(aPath);
if (url) {
if (!url.path) {
return aPath;
}
path = url.path;
}
var isAbsolute = exports.isAbsolute(path);
var parts = path.split(/\/+/);
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
part = parts[i];
if (part === '.') {
parts.splice(i, 1);
} else if (part === '..') {
up++;
} else if (up > 0) {
if (part === '') {
// The first part is blank if the path is absolute. Trying to go
// above the root is a no-op. Therefore we can remove all '..' parts
// directly after the root.
parts.splice(i + 1, up);
up = 0;
} else {
parts.splice(i, 2);
up--;
}
}
}
path = parts.join('/');
if (path === '') {
path = isAbsolute ? '/' : '.';
}
if (url) {
url.path = path;
return urlGenerate(url);
}
return path;
}
exports.normalize = normalize;
/**
* Joins two paths/URLs.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be joined with the root.
*
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended
* first.
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion
* is updated with the result and aRoot is returned. Otherwise the result
* is returned.
* - If aPath is absolute, the result is aPath.
* - Otherwise the two paths are joined with a slash.
* - Joining for example 'http://' and 'www.example.com' is also supported.
*/
function join(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
if (aPath === "") {
aPath = ".";
}
var aPathUrl = urlParse(aPath);
var aRootUrl = urlParse(aRoot);
if (aRootUrl) {
aRoot = aRootUrl.path || '/';
}
// `join(foo, '//www.example.org')`
if (aPathUrl && !aPathUrl.scheme) {
if (aRootUrl) {
aPathUrl.scheme = aRootUrl.scheme;
}
return urlGenerate(aPathUrl);
}
if (aPathUrl || aPath.match(dataUrlRegexp)) {
return aPath;
}
// `join('http://', 'www.example.com')`
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
aRootUrl.host = aPath;
return urlGenerate(aRootUrl);
}
var joined = aPath.charAt(0) === '/'
? aPath
: normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
if (aRootUrl) {
aRootUrl.path = joined;
return urlGenerate(aRootUrl);
}
return joined;
}
exports.join = join;
exports.isAbsolute = function (aPath) {
return aPath.charAt(0) === '/' || urlRegexp.test(aPath);
};
/**
* Make a path relative to a URL or another path.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be made relative to aRoot.
*/
function relative(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
aRoot = aRoot.replace(/\/$/, '');
// It is possible for the path to be above the root. In this case, simply
// checking whether the root is a prefix of the path won't work. Instead, we
// need to remove components from the root one by one, until either we find
// a prefix that fits, or we run out of components to remove.
var level = 0;
while (aPath.indexOf(aRoot + '/') !== 0) {
var index = aRoot.lastIndexOf("/");
if (index < 0) {
return aPath;
}
// If the only part of the root that is left is the scheme (i.e. http://,
// file:///, etc.), one or more slashes (/), or simply nothing at all, we
// have exhausted all components, so the path is not relative to the root.
aRoot = aRoot.slice(0, index);
if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
return aPath;
}
++level;
}
// Make sure we add a "../" for each component we removed from the root.
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
}
exports.relative = relative;
var supportsNullProto = (function () {
var obj = Object.create(null);
return !('__proto__' in obj);
}());
function identity (s) {
return s;
}
/**
* Because behavior goes wacky when you set `__proto__` on objects, we
* have to prefix all the strings in our set with an arbitrary character.
*
* See https://github.com/mozilla/source-map/pull/31 and
* https://github.com/mozilla/source-map/issues/30
*
* @param String aStr
*/
function toSetString(aStr) {
if (isProtoString(aStr)) {
return '$' + aStr;
}
return aStr;
}
exports.toSetString = supportsNullProto ? identity : toSetString;
function fromSetString(aStr) {
if (isProtoString(aStr)) {
return aStr.slice(1);
}
return aStr;
}
exports.fromSetString = supportsNullProto ? identity : fromSetString;
function isProtoString(s) {
if (!s) {
return false;
}
var length = s.length;
if (length < 9 /* "__proto__".length */) {
return false;
}
if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
s.charCodeAt(length - 2) !== 95 /* '_' */ ||
s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
s.charCodeAt(length - 4) !== 116 /* 't' */ ||
s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
s.charCodeAt(length - 8) !== 95 /* '_' */ ||
s.charCodeAt(length - 9) !== 95 /* '_' */) {
return false;
}
for (var i = length - 10; i >= 0; i--) {
if (s.charCodeAt(i) !== 36 /* '$' */) {
return false;
}
}
return true;
}
/**
* Comparator between two mappings where the original positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same original source/line/column, but different generated
* line and column the same. Useful when searching for a mapping with a
* stubbed out mapping.
*/
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
var cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0 || onlyCompareOriginal) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByOriginalPositions = compareByOriginalPositions;
/**
* Comparator between two mappings with deflated source and name indices where
* the generated positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same generated line and column, but different
* source/name/original line and column the same. Useful when searching for a
* mapping with a stubbed out mapping.
*/
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
var cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0 || onlyCompareGenerated) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
function strcmp(aStr1, aStr2) {
if (aStr1 === aStr2) {
return 0;
}
if (aStr1 === null) {
return 1; // aStr2 !== null
}
if (aStr2 === null) {
return -1; // aStr1 !== null
}
if (aStr1 > aStr2) {
return 1;
}
return -1;
}
/**
* Comparator between two mappings with inflated source and name strings where
* the generated positions are compared.
*/
function compareByGeneratedPositionsInflated(mappingA, mappingB) {
var cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
/**
* Strip any JSON XSSI avoidance prefix from the string (as documented
* in the source maps specification), and then parse the string as
* JSON.
*/
function parseSourceMapInput(str) {
return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));
}
exports.parseSourceMapInput = parseSourceMapInput;
/**
* Compute the URL of a source given the the source root, the source's
* URL, and the source map's URL.
*/
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
sourceURL = sourceURL || '';
if (sourceRoot) {
// This follows what Chrome does.
if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
sourceRoot += '/';
}
// The spec says:
// Line 4: An optional source root, useful for relocating source
// files on a server or removing repeated values in the
// “sources” entry. This value is prepended to the individual
// entries in the “source” field.
sourceURL = sourceRoot + sourceURL;
}
// Historically, SourceMapConsumer did not take the sourceMapURL as
// a parameter. This mode is still somewhat supported, which is why
// this code block is conditional. However, it's preferable to pass
// the source map URL to SourceMapConsumer, so that this function
// can implement the source URL resolution algorithm as outlined in
// the spec. This block is basically the equivalent of:
// new URL(sourceURL, sourceMapURL).toString()
// ... except it avoids using URL, which wasn't available in the
// older releases of node still supported by this library.
//
// The spec says:
// If the sources are not absolute URLs after prepending of the
// “sourceRoot”, the sources are resolved relative to the
// SourceMap (like resolving script src in a html document).
if (sourceMapURL) {
var parsed = urlParse(sourceMapURL);
if (!parsed) {
throw new Error("sourceMapURL could not be parsed");
}
if (parsed.path) {
// Strip the last path component, but keep the "/".
var index = parsed.path.lastIndexOf('/');
if (index >= 0) {
parsed.path = parsed.path.substring(0, index + 1);
}
}
sourceURL = join(urlGenerate(parsed), sourceURL);
}
return normalize(sourceURL);
}
exports.computeSourceURL = computeSourceURL;
},{}],60:[function(require,module,exports){
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
exports.SourceMapGenerator = require('./lib/source-map-generator').SourceMapGenerator;
exports.SourceMapConsumer = require('./lib/source-map-consumer').SourceMapConsumer;
exports.SourceNode = require('./lib/source-node').SourceNode;
},{"./lib/source-map-consumer":56,"./lib/source-map-generator":57,"./lib/source-node":58}],61:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m
var eLen = (nBytes * 8) - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var nBits = -7
var i = isLE ? (nBytes - 1) : 0
var d = isLE ? -1 : 1
var s = buffer[offset + i]
i += d
e = s & ((1 << (-nBits)) - 1)
s >>= (-nBits)
nBits += eLen
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
m = e & ((1 << (-nBits)) - 1)
e >>= (-nBits)
nBits += mLen
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
if (e === 0) {
e = 1 - eBias
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity)
} else {
m = m + Math.pow(2, mLen)
e = e - eBias
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c
var eLen = (nBytes * 8) - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
var i = isLE ? 0 : (nBytes - 1)
var d = isLE ? 1 : -1
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
value = Math.abs(value)
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0
e = eMax
} else {
e = Math.floor(Math.log(value) / Math.LN2)
if (value * (c = Math.pow(2, -e)) < 1) {
e--
c *= 2
}
if (e + eBias >= 1) {
value += rt / c
} else {
value += rt * Math.pow(2, 1 - eBias)
}
if (value * c >= 2) {
e++
c /= 2
}
if (e + eBias >= eMax) {
m = 0
e = eMax
} else if (e + eBias >= 1) {
m = ((value * c) - 1) * Math.pow(2, mLen)
e = e + eBias
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
e = 0
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
e = (e << mLen) | m
eLen += mLen
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
buffer[offset + i - d] |= s * 128
}
},{}],62:[function(require,module,exports){
arguments[4][3][0].apply(exports,arguments)
},{"dup":3}],63:[function(require,module,exports){
var util = require('util');
module.exports = Eta;
function Eta (count, options) {
this.count = count;
var optionsNumberFormatter = options && options.numberFormatter;
this.numberFormatter = typeof optionsNumberFormatter == 'function' ? optionsNumberFormatter : formatNumber;
if (options && options.autoStart || options === true) {
this.start();
}
}
Eta.prototype.start = function () {
this.done = 0;
this.startedAt = new Date();
};
Eta.prototype.iterate = function (anything) {
this.done++;
if (anything) {
this.last = util.format.apply(this, arguments);
}
};
Eta.prototype.format = function () {
var layout = util.format.apply(this, arguments);
var elapsed = (new Date() - this.startedAt)/1000;
var rate = this.done/elapsed;
var estimated = this.count/rate;
var progress = this.done/this.count;
var eta = estimated - elapsed;
var etah = secondsToStr(eta);
var fields = {
elapsed: elapsed,
rate: rate,
estimated: estimated,
progress: progress,
eta: eta,
etah: etah,
last: this.last
};
return layout.replace(/{{\S+?}}/g, function (match) {
var key = match.slice(2, match.length - 2);
var value = fields[key] || '';
return typeof value == 'number' ? value.toPrecision(4) : value;
});
};
function secondsToStr (seconds) {
return millisecondsToStr(seconds*1000);
}
// http://stackoverflow.com/a/8212878
function millisecondsToStr (milliseconds) {
// TIP: to find current time in milliseconds, use:
// var current_time_milliseconds = new Date().getTime();
function numberEnding (number) {
return (number > 1) ? 's' : '';
}
var temp = Math.floor(milliseconds / 1000);
var years = Math.floor(temp / 31536000);
if (years) {
return years + ' year' + numberEnding(years);
}
//TODO: Months! Maybe weeks?
var days = Math.floor((temp %= 31536000) / 86400);
if (days) {
return days + ' day' + numberEnding(days);
}
var hours = Math.floor((temp %= 86400) / 3600);
if (hours) {
return hours + ' hour' + numberEnding(hours);
}
var minutes = Math.floor((temp %= 3600) / 60);
if (minutes) {
return minutes + ' minute' + numberEnding(minutes);
}
var seconds = temp % 60;
if (seconds) {
return seconds + ' second' + numberEnding(seconds);
}
return 'less than a second'; //'just now' //or other string you like;
}
function formatNumber (it) {
return it.toPrecision(4);
}
},{"util":75}],64:[function(require,module,exports){
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
'use strict';
/* eslint-disable no-unused-vars */
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
// Detect buggy property enumeration order in older V8 versions.
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
test1[5] = 'de';
if (Object.getOwnPropertyNames(test1)[0] === '5') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test2 = {};
for (var i = 0; i < 10; i++) {
test2['_' + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
return test2[n];
});
if (order2.join('') !== '0123456789') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test3 = {};
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join('') !==
'abcdefghijklmnopqrst') {
return false;
}
return true;
} catch (err) {
// We don't expect any of the above to throw, but better to be safe.
return false;
}
}
module.exports = shouldUseNative() ? Object.assign : function (target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
},{}],65:[function(require,module,exports){
// 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.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
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; };
},{}],66:[function(require,module,exports){
"use strict";
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
function Agent() {
this._defaults = [];
}
['use', 'on', 'once', 'set', 'query', 'type', 'accept', 'auth', 'withCredentials', 'sortQuery', 'retry', 'ok', 'redirects', 'timeout', 'buffer', 'serialize', 'parse', 'ca', 'key', 'pfx', 'cert', 'disableTLSCerts'].forEach(function (fn) {
// Default setting for all requests from this agent
Agent.prototype[fn] = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
this._defaults.push({
fn: fn,
args: args
});
return this;
};
});
Agent.prototype._setDefaults = function (req) {
this._defaults.forEach(function (def) {
req[def.fn].apply(req, _toConsumableArray(def.args));
});
};
module.exports = Agent;
},{}],67:[function(require,module,exports){
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
/**
* Root reference for iframes.
*/
var root;
if (typeof window !== 'undefined') {
// Browser window
root = window;
} else if (typeof self === 'undefined') {
// Other environments
console.warn('Using browser-only version of superagent in non-browser environment');
root = void 0;
} else {
// Web Worker
root = self;
}
var Emitter = require('component-emitter');
var safeStringify = require('fast-safe-stringify');
var RequestBase = require('./request-base');
var isObject = require('./is-object');
var ResponseBase = require('./response-base');
var Agent = require('./agent-base');
/**
* Noop.
*/
function noop() {}
/**
* Expose `request`.
*/
module.exports = function (method, url) {
// callback
if (typeof url === 'function') {
return new exports.Request('GET', method).end(url);
} // url first
if (arguments.length === 1) {
return new exports.Request('GET', method);
}
return new exports.Request(method, url);
};
exports = module.exports;
var request = exports;
exports.Request = Request;
/**
* Determine XHR.
*/
request.getXHR = function () {
if (root.XMLHttpRequest && (!root.location || root.location.protocol !== 'file:' || !root.ActiveXObject)) {
return new XMLHttpRequest();
}
try {
return new ActiveXObject('Microsoft.XMLHTTP');
} catch (_unused) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP.6.0');
} catch (_unused2) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP.3.0');
} catch (_unused3) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP');
} catch (_unused4) {}
throw new Error('Browser-only version of superagent could not find XHR');
};
/**
* Removes leading and trailing whitespace, added to support IE.
*
* @param {String} s
* @return {String}
* @api private
*/
var trim = ''.trim ? function (s) {
return s.trim();
} : function (s) {
return s.replace(/(^\s*|\s*$)/g, '');
};
/**
* Serialize the given `obj`.
*
* @param {Object} obj
* @return {String}
* @api private
*/
function serialize(obj) {
if (!isObject(obj)) return obj;
var pairs = [];
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) pushEncodedKeyValuePair(pairs, key, obj[key]);
}
return pairs.join('&');
}
/**
* Helps 'serialize' with serializing arrays.
* Mutates the pairs array.
*
* @param {Array} pairs
* @param {String} key
* @param {Mixed} val
*/
function pushEncodedKeyValuePair(pairs, key, val) {
if (val === undefined) return;
if (val === null) {
pairs.push(encodeURI(key));
return;
}
if (Array.isArray(val)) {
val.forEach(function (v) {
pushEncodedKeyValuePair(pairs, key, v);
});
} else if (isObject(val)) {
for (var subkey in val) {
if (Object.prototype.hasOwnProperty.call(val, subkey)) pushEncodedKeyValuePair(pairs, "".concat(key, "[").concat(subkey, "]"), val[subkey]);
}
} else {
pairs.push(encodeURI(key) + '=' + encodeURIComponent(val));
}
}
/**
* Expose serialization method.
*/
request.serializeObject = serialize;
/**
* Parse the given x-www-form-urlencoded `str`.
*
* @param {String} str
* @return {Object}
* @api private
*/
function parseString(str) {
var obj = {};
var pairs = str.split('&');
var pair;
var pos;
for (var i = 0, len = pairs.length; i < len; ++i) {
pair = pairs[i];
pos = pair.indexOf('=');
if (pos === -1) {
obj[decodeURIComponent(pair)] = '';
} else {
obj[decodeURIComponent(pair.slice(0, pos))] = decodeURIComponent(pair.slice(pos + 1));
}
}
return obj;
}
/**
* Expose parser.
*/
request.parseString = parseString;
/**
* Default MIME type map.
*
* superagent.types.xml = 'application/xml';
*
*/
request.types = {
html: 'text/html',
json: 'application/json',
xml: 'text/xml',
urlencoded: 'application/x-www-form-urlencoded',
form: 'application/x-www-form-urlencoded',
'form-data': 'application/x-www-form-urlencoded'
};
/**
* Default serialization map.
*
* superagent.serialize['application/xml'] = function(obj){
* return 'generated xml here';
* };
*
*/
request.serialize = {
'application/x-www-form-urlencoded': serialize,
'application/json': safeStringify
};
/**
* Default parsers.
*
* superagent.parse['application/xml'] = function(str){
* return { object parsed from str };
* };
*
*/
request.parse = {
'application/x-www-form-urlencoded': parseString,
'application/json': JSON.parse
};
/**
* Parse the given header `str` into
* an object containing the mapped fields.
*
* @param {String} str
* @return {Object}
* @api private
*/
function parseHeader(str) {
var lines = str.split(/\r?\n/);
var fields = {};
var index;
var line;
var field;
var val;
for (var i = 0, len = lines.length; i < len; ++i) {
line = lines[i];
index = line.indexOf(':');
if (index === -1) {
// could be empty line, just skip it
continue;
}
field = line.slice(0, index).toLowerCase();
val = trim(line.slice(index + 1));
fields[field] = val;
}
return fields;
}
/**
* Check if `mime` is json or has +json structured syntax suffix.
*
* @param {String} mime
* @return {Boolean}
* @api private
*/
function isJSON(mime) {
// should match /json or +json
// but not /json-seq
return /[/+]json($|[^-\w])/.test(mime);
}
/**
* Initialize a new `Response` with the given `xhr`.
*
* - set flags (.ok, .error, etc)
* - parse header
*
* Examples:
*
* Aliasing `superagent` as `request` is nice:
*
* request = superagent;
*
* We can use the promise-like API, or pass callbacks:
*
* request.get('/').end(function(res){});
* request.get('/', function(res){});
*
* Sending data can be chained:
*
* request
* .post('/user')
* .send({ name: 'tj' })
* .end(function(res){});
*
* Or passed to `.send()`:
*
* request
* .post('/user')
* .send({ name: 'tj' }, function(res){});
*
* Or passed to `.post()`:
*
* request
* .post('/user', { name: 'tj' })
* .end(function(res){});
*
* Or further reduced to a single call for simple cases:
*
* request
* .post('/user', { name: 'tj' }, function(res){});
*
* @param {XMLHTTPRequest} xhr
* @param {Object} options
* @api private
*/
function Response(req) {
this.req = req;
this.xhr = this.req.xhr; // responseText is accessible only if responseType is '' or 'text' and on older browsers
this.text = this.req.method !== 'HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text') || typeof this.xhr.responseType === 'undefined' ? this.xhr.responseText : null;
this.statusText = this.req.xhr.statusText;
var status = this.xhr.status; // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
if (status === 1223) {
status = 204;
}
this._setStatusProperties(status);
this.headers = parseHeader(this.xhr.getAllResponseHeaders());
this.header = this.headers; // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
if (this.text === null && req._responseType) {
this.body = this.xhr.response;
} else {
this.body = this.req.method === 'HEAD' ? null : this._parseBody(this.text ? this.text : this.xhr.response);
}
} // eslint-disable-next-line new-cap
ResponseBase(Response.prototype);
/**
* Parse the given body `str`.
*
* Used for auto-parsing of bodies. Parsers
* are defined on the `superagent.parse` object.
*
* @param {String} str
* @return {Mixed}
* @api private
*/
Response.prototype._parseBody = function (str) {
var parse = request.parse[this.type];
if (this.req._parser) {
return this.req._parser(this, str);
}
if (!parse && isJSON(this.type)) {
parse = request.parse['application/json'];
}
return parse && str && (str.length > 0 || str instanceof Object) ? parse(str) : null;
};
/**
* Return an `Error` representative of this response.
*
* @return {Error}
* @api public
*/
Response.prototype.toError = function () {
var req = this.req;
var method = req.method;
var url = req.url;
var msg = "cannot ".concat(method, " ").concat(url, " (").concat(this.status, ")");
var err = new Error(msg);
err.status = this.status;
err.method = method;
err.url = url;
return err;
};
/**
* Expose `Response`.
*/
request.Response = Response;
/**
* Initialize a new `Request` with the given `method` and `url`.
*
* @param {String} method
* @param {String} url
* @api public
*/
function Request(method, url) {
var self = this;
this._query = this._query || [];
this.method = method;
this.url = url;
this.header = {}; // preserves header name case
this._header = {}; // coerces header names to lowercase
this.on('end', function () {
var err = null;
var res = null;
try {
res = new Response(self);
} catch (err_) {
err = new Error('Parser is unable to parse the response');
err.parse = true;
err.original = err_; // issue #675: return the raw response if the response parsing fails
if (self.xhr) {
// ie9 doesn't have 'response' property
err.rawResponse = typeof self.xhr.responseType === 'undefined' ? self.xhr.responseText : self.xhr.response; // issue #876: return the http status code if the response parsing fails
err.status = self.xhr.status ? self.xhr.status : null;
err.statusCode = err.status; // backwards-compat only
} else {
err.rawResponse = null;
err.status = null;
}
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
new_err = new Error(res.statusText || res.text || 'Unsuccessful HTTP response');
}
} catch (err_) {
new_err = err_; // ok() callback can throw
} // #1000 don't catch errors from the callback to avoid double calling it
if (new_err) {
new_err.original = err;
new_err.response = res;
new_err.status = res.status;
self.callback(new_err, res);
} else {
self.callback(null, res);
}
});
}
/**
* Mixin `Emitter` and `RequestBase`.
*/
// eslint-disable-next-line new-cap
Emitter(Request.prototype); // eslint-disable-next-line new-cap
RequestBase(Request.prototype);
/**
* Set Content-Type to `type`, mapping values from `request.types`.
*
* Examples:
*
* superagent.types.xml = 'application/xml';
*
* request.post('/')
* .type('xml')
* .send(xmlstring)
* .end(callback);
*
* request.post('/')
* .type('application/xml')
* .send(xmlstring)
* .end(callback);
*
* @param {String} type
* @return {Request} for chaining
* @api public
*/
Request.prototype.type = function (type) {
this.set('Content-Type', request.types[type] || type);
return this;
};
/**
* Set Accept to `type`, mapping values from `request.types`.
*
* Examples:
*
* superagent.types.json = 'application/json';
*
* request.get('/agent')
* .accept('json')
* .end(callback);
*
* request.get('/agent')
* .accept('application/json')
* .end(callback);
*
* @param {String} accept
* @return {Request} for chaining
* @api public
*/
Request.prototype.accept = function (type) {
this.set('Accept', request.types[type] || type);
return this;
};
/**
* Set Authorization field value with `user` and `pass`.
*
* @param {String} user
* @param {String} [pass] optional in case of using 'bearer' as type
* @param {Object} options with 'type' property 'auto', 'basic' or 'bearer' (default 'basic')
* @return {Request} for chaining
* @api public
*/
Request.prototype.auth = function (user, pass, options) {
if (arguments.length === 1) pass = '';
if (_typeof(pass) === 'object' && pass !== null) {
// pass is optional and can be replaced with options
options = pass;
pass = '';
}
if (!options) {
options = {
type: typeof btoa === 'function' ? 'basic' : 'auto'
};
}
var encoder = function encoder(string) {
if (typeof btoa === 'function') {
return btoa(string);
}
throw new Error('Cannot use basic auth, btoa is not a function');
};
return this._auth(user, pass, options, encoder);
};
/**
* Add query-string `val`.
*
* Examples:
*
* request.get('/shoes')
* .query('size=10')
* .query({ color: 'blue' })
*
* @param {Object|String} val
* @return {Request} for chaining
* @api public
*/
Request.prototype.query = function (val) {
if (typeof val !== 'string') val = serialize(val);
if (val) this._query.push(val);
return this;
};
/**
* Queue the given `file` as an attachment to the specified `field`,
* with optional `options` (or filename).
*
* ``` js
* request.post('/upload')
* .attach('content', new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"}))
* .end(callback);
* ```
*
* @param {String} field
* @param {Blob|File} file
* @param {String|Object} options
* @return {Request} for chaining
* @api public
*/
Request.prototype.attach = function (field, file, options) {
if (file) {
if (this._data) {
throw new Error("superagent can't mix .send() and .attach()");
}
this._getFormData().append(field, file, options || file.name);
}
return this;
};
Request.prototype._getFormData = function () {
if (!this._formData) {
this._formData = new root.FormData();
}
return this._formData;
};
/**
* Invoke the callback with `err` and `res`
* and handle arity check.
*
* @param {Error} err
* @param {Response} res
* @api private
*/
Request.prototype.callback = function (err, res) {
if (this._shouldRetry(err, res)) {
return this._retry();
}
var fn = this._callback;
this.clearTimeout();
if (err) {
if (this._maxRetries) err.retries = this._retries - 1;
this.emit('error', err);
}
fn(err, res);
};
/**
* Invoke callback with x-domain error.
*
* @api private
*/
Request.prototype.crossDomainError = function () {
var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.');
err.crossDomain = true;
err.status = this.status;
err.method = this.method;
err.url = this.url;
this.callback(err);
}; // This only warns, because the request is still likely to work
Request.prototype.agent = function () {
console.warn('This is not supported in browser version of superagent');
return this;
};
Request.prototype.ca = Request.prototype.agent;
Request.prototype.buffer = Request.prototype.ca; // This throws, because it can't send/receive data as expected
Request.prototype.write = function () {
throw new Error('Streaming is not supported in browser version of superagent');
};
Request.prototype.pipe = Request.prototype.write;
/**
* Check if `obj` is a host object,
* we don't want to serialize these :)
*
* @param {Object} obj host object
* @return {Boolean} is a host object
* @api private
*/
Request.prototype._isHost = function (obj) {
// Native objects stringify to [object File], [object Blob], [object FormData], etc.
return obj && _typeof(obj) === 'object' && !Array.isArray(obj) && Object.prototype.toString.call(obj) !== '[object Object]';
};
/**
* Initiate request, invoking callback `fn(res)`
* with an instanceof `Response`.
*
* @param {Function} fn
* @return {Request} for chaining
* @api public
*/
Request.prototype.end = function (fn) {
if (this._endCalled) {
console.warn('Warning: .end() was called twice. This is not supported in superagent');
}
this._endCalled = true; // store callback
this._callback = fn || noop; // querystring
this._finalizeQueryString();
this._end();
};
Request.prototype._setUploadTimeout = function () {
var self = this; // upload timeout it's wokrs only if deadline timeout is off
if (this._uploadTimeout && !this._uploadTimeoutTimer) {
this._uploadTimeoutTimer = setTimeout(function () {
self._timeoutError('Upload timeout of ', self._uploadTimeout, 'ETIMEDOUT');
}, this._uploadTimeout);
}
}; // eslint-disable-next-line complexity
Request.prototype._end = function () {
if (this._aborted) return this.callback(new Error('The request has been aborted even before .end() was called'));
var self = this;
this.xhr = request.getXHR();
var xhr = this.xhr;
var data = this._formData || this._data;
this._setTimeouts(); // state change
xhr.onreadystatechange = function () {
var readyState = xhr.readyState;
if (readyState >= 2 && self._responseTimeoutTimer) {
clearTimeout(self._responseTimeoutTimer);
}
if (readyState !== 4) {
return;
} // In IE9, reads to any property (e.g. status) off of an aborted XHR will
// result in the error "Could not complete the operation due to error c00c023f"
var status;
try {
status = xhr.status;
} catch (_unused5) {
status = 0;
}
if (!status) {
if (self.timedout || self._aborted) return;
return self.crossDomainError();
}
self.emit('end');
}; // progress
var handleProgress = function handleProgress(direction, e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100;
if (e.percent === 100) {
clearTimeout(self._uploadTimeoutTimer);
}
}
e.direction = direction;
self.emit('progress', e);
};
if (this.hasListeners('progress')) {
try {
xhr.addEventListener('progress', handleProgress.bind(null, 'download'));
if (xhr.upload) {
xhr.upload.addEventListener('progress', handleProgress.bind(null, 'upload'));
}
} catch (_unused6) {// Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist.
// Reported here:
// https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context
}
}
if (xhr.upload) {
this._setUploadTimeout();
} // initiate request
try {
if (this.username && this.password) {
xhr.open(this.method, this.url, true, this.username, this.password);
} else {
xhr.open(this.method, this.url, true);
}
} catch (err) {
// see #1149
return this.callback(err);
} // CORS
if (this._withCredentials) xhr.withCredentials = true; // body
if (!this._formData && this.method !== 'GET' && this.method !== 'HEAD' && typeof data !== 'string' && !this._isHost(data)) {
// serialize stuff
var contentType = this._header['content-type'];
var _serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : ''];
if (!_serialize && isJSON(contentType)) {
_serialize = request.serialize['application/json'];
}
if (_serialize) data = _serialize(data);
} // set header fields
for (var field in this.header) {
if (this.header[field] === null) continue;
if (Object.prototype.hasOwnProperty.call(this.header, field)) xhr.setRequestHeader(field, this.header[field]);
}
if (this._responseType) {
xhr.responseType = this._responseType;
} // send stuff
this.emit('request', this); // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing)
// We need null here if data is undefined
xhr.send(typeof data === 'undefined' ? null : data);
};
request.agent = function () {
return new Agent();
};
['GET', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE'].forEach(function (method) {
Agent.prototype[method.toLowerCase()] = function (url, fn) {
var req = new request.Request(method, url);
this._setDefaults(req);
if (fn) {
req.end(fn);
}
return req;
};
});
Agent.prototype.del = Agent.prototype.delete;
/**
* GET `url` with optional callback `fn(res)`.
*
* @param {String} url
* @param {Mixed|Function} [data] or fn
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.get = function (url, data, fn) {
var req = request('GET', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.query(data);
if (fn) req.end(fn);
return req;
};
/**
* HEAD `url` with optional callback `fn(res)`.
*
* @param {String} url
* @param {Mixed|Function} [data] or fn
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.head = function (url, data, fn) {
var req = request('HEAD', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.query(data);
if (fn) req.end(fn);
return req;
};
/**
* OPTIONS query to `url` with optional callback `fn(res)`.
*
* @param {String} url
* @param {Mixed|Function} [data] or fn
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.options = function (url, data, fn) {
var req = request('OPTIONS', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.send(data);
if (fn) req.end(fn);
return req;
};
/**
* DELETE `url` with optional `data` and callback `fn(res)`.
*
* @param {String} url
* @param {Mixed} [data]
* @param {Function} [fn]
* @return {Request}
* @api public
*/
function del(url, data, fn) {
var req = request('DELETE', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}
request.del = del;
request.delete = del;
/**
* PATCH `url` with optional `data` and callback `fn(res)`.
*
* @param {String} url
* @param {Mixed} [data]
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.patch = function (url, data, fn) {
var req = request('PATCH', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.send(data);
if (fn) req.end(fn);
return req;
};
/**
* POST `url` with optional `data` and callback `fn(res)`.
*
* @param {String} url
* @param {Mixed} [data]
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.post = function (url, data, fn) {
var req = request('POST', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.send(data);
if (fn) req.end(fn);
return req;
};
/**
* PUT `url` with optional `data` and callback `fn(res)`.
*
* @param {String} url
* @param {Mixed|Function} [data] or fn
* @param {Function} [fn]
* @return {Request}
* @api public
*/
request.put = function (url, data, fn) {
var req = request('PUT', url);
if (typeof data === 'function') {
fn = data;
data = null;
}
if (data) req.send(data);
if (fn) req.end(fn);
return req;
};
},{"./agent-base":66,"./is-object":68,"./request-base":69,"./response-base":70,"component-emitter":14,"fast-safe-stringify":16}],68:[function(require,module,exports){
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
/**
* Check if `obj` is an object.
*
* @param {Object} obj
* @return {Boolean}
* @api private
*/
function isObject(obj) {
return obj !== null && _typeof(obj) === 'object';
}
module.exports = isObject;
},{}],69:[function(require,module,exports){
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
/**
* Module of mixed-in functions shared between node and client code
*/
var isObject = require('./is-object');
/**
* Expose `RequestBase`.
*/
module.exports = RequestBase;
/**
* Initialize a new `RequestBase`.
*
* @api public
*/
function RequestBase(obj) {
if (obj) return mixin(obj);
}
/**
* Mixin the prototype properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in RequestBase.prototype) {
if (Object.prototype.hasOwnProperty.call(RequestBase.prototype, key)) obj[key] = RequestBase.prototype[key];
}
return obj;
}
/**
* Clear previous timeout.
*
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.clearTimeout = function () {
clearTimeout(this._timer);
clearTimeout(this._responseTimeoutTimer);
clearTimeout(this._uploadTimeoutTimer);
delete this._timer;
delete this._responseTimeoutTimer;
delete this._uploadTimeoutTimer;
return this;
};
/**
* Override default response body parser
*
* This function will be called to convert incoming data into request.body
*
* @param {Function}
* @api public
*/
RequestBase.prototype.parse = function (fn) {
this._parser = fn;
return this;
};
/**
* Set format of binary response body.
* In browser valid formats are 'blob' and 'arraybuffer',
* which return Blob and ArrayBuffer, respectively.
*
* In Node all values result in Buffer.
*
* Examples:
*
* req.get('/')
* .responseType('blob')
* .end(callback);
*
* @param {String} val
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.responseType = function (val) {
this._responseType = val;
return this;
};
/**
* Override default request body serializer
*
* This function will be called to convert data set via .send or .attach into payload to send
*
* @param {Function}
* @api public
*/
RequestBase.prototype.serialize = function (fn) {
this._serializer = fn;
return this;
};
/**
* Set timeouts.
*
* - response timeout is time between sending request and receiving the first byte of the response. Includes DNS and connection time.
* - deadline is the time from start of the request to receiving response body in full. If the deadline is too short large files may not load at all on slow connections.
* - upload is the time since last bit of data was sent or received. This timeout works only if deadline timeout is off
*
* Value of 0 or false means no timeout.
*
* @param {Number|Object} ms or {response, deadline}
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.timeout = function (options) {
if (!options || _typeof(options) !== 'object') {
this._timeout = options;
this._responseTimeout = 0;
this._uploadTimeout = 0;
return this;
}
for (var option in options) {
if (Object.prototype.hasOwnProperty.call(options, option)) {
switch (option) {
case 'deadline':
this._timeout = options.deadline;
break;
case 'response':
this._responseTimeout = options.response;
break;
case 'upload':
this._uploadTimeout = options.upload;
break;
default:
console.warn('Unknown timeout option', option);
}
}
}
return this;
};
/**
* Set number of retry attempts on error.
*
* Failed requests will be retried 'count' times if timeout or err.code >= 500.
*
* @param {Number} count
* @param {Function} [fn]
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.retry = function (count, fn) {
// Default to 1 if no count passed or true
if (arguments.length === 0 || count === true) count = 1;
if (count <= 0) count = 0;
this._maxRetries = count;
this._retries = 0;
this._retryCallback = fn;
return this;
};
var ERROR_CODES = ['ECONNRESET', 'ETIMEDOUT', 'EADDRINFO', 'ESOCKETTIMEDOUT'];
/**
* Determine if a request should be retried.
* (Borrowed from segmentio/superagent-retry)
*
* @param {Error} err an error
* @param {Response} [res] response
* @returns {Boolean} if segment should be retried
*/
RequestBase.prototype._shouldRetry = function (err, res) {
if (!this._maxRetries || this._retries++ >= this._maxRetries) {
return false;
}
if (this._retryCallback) {
try {
var override = this._retryCallback(err, res);
if (override === true) return true;
if (override === false) return false; // undefined falls back to defaults
} catch (err_) {
console.error(err_);
}
}
if (res && res.status && res.status >= 500 && res.status !== 501) return true;
if (err) {
if (err.code && ERROR_CODES.includes(err.code)) return true; // Superagent timeout
if (err.timeout && err.code === 'ECONNABORTED') return true;
if (err.crossDomain) return true;
}
return false;
};
/**
* Retry request
*
* @return {Request} for chaining
* @api private
*/
RequestBase.prototype._retry = function () {
this.clearTimeout(); // node
if (this.req) {
this.req = null;
this.req = this.request();
}
this._aborted = false;
this.timedout = false;
this.timedoutError = null;
return this._end();
};
/**
* Promise support
*
* @param {Function} resolve
* @param {Function} [reject]
* @return {Request}
*/
RequestBase.prototype.then = function (resolve, reject) {
var _this = this;
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn('Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises');
}
this._fullfilledPromise = new Promise(function (resolve, reject) {
self.on('abort', function () {
if (_this.timedout && _this.timedoutError) {
reject(_this.timedoutError);
return;
}
var err = new Error('Aborted');
err.code = 'ABORTED';
err.status = _this.status;
err.method = _this.method;
err.url = _this.url;
reject(err);
});
self.end(function (err, res) {
if (err) reject(err);else resolve(res);
});
});
}
return this._fullfilledPromise.then(resolve, reject);
};
RequestBase.prototype.catch = function (cb) {
return this.then(undefined, cb);
};
/**
* Allow for extension
*/
RequestBase.prototype.use = function (fn) {
fn(this);
return this;
};
RequestBase.prototype.ok = function (cb) {
if (typeof cb !== 'function') throw new Error('Callback required');
this._okCallback = cb;
return this;
};
RequestBase.prototype._isResponseOK = function (res) {
if (!res) {
return false;
}
if (this._okCallback) {
return this._okCallback(res);
}
return res.status >= 200 && res.status < 300;
};
/**
* Get request header `field`.
* Case-insensitive.
*
* @param {String} field
* @return {String}
* @api public
*/
RequestBase.prototype.get = function (field) {
return this._header[field.toLowerCase()];
};
/**
* Get case-insensitive header `field` value.
* This is a deprecated internal API. Use `.get(field)` instead.
*
* (getHeader is no longer used internally by the superagent code base)
*
* @param {String} field
* @return {String}
* @api private
* @deprecated
*/
RequestBase.prototype.getHeader = RequestBase.prototype.get;
/**
* Set header `field` to `val`, or multiple fields with one object.
* Case-insensitive.
*
* Examples:
*
* req.get('/')
* .set('Accept', 'application/json')
* .set('X-API-Key', 'foobar')
* .end(callback);
*
* req.get('/')
* .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
* .end(callback);
*
* @param {String|Object} field
* @param {String} val
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.set = function (field, val) {
if (isObject(field)) {
for (var key in field) {
if (Object.prototype.hasOwnProperty.call(field, key)) this.set(key, field[key]);
}
return this;
}
this._header[field.toLowerCase()] = val;
this.header[field] = val;
return this;
};
/**
* Remove header `field`.
* Case-insensitive.
*
* Example:
*
* req.get('/')
* .unset('User-Agent')
* .end(callback);
*
* @param {String} field field name
*/
RequestBase.prototype.unset = function (field) {
delete this._header[field.toLowerCase()];
delete this.header[field];
return this;
};
/**
* Write the field `name` and `val`, or multiple fields with one object
* for "multipart/form-data" request bodies.
*
* ``` js
* request.post('/upload')
* .field('foo', 'bar')
* .end(callback);
*
* request.post('/upload')
* .field({ foo: 'bar', baz: 'qux' })
* .end(callback);
* ```
*
* @param {String|Object} name name of field
* @param {String|Blob|File|Buffer|fs.ReadStream} val value of field
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.field = function (name, val) {
// name should be either a string or an object.
if (name === null || undefined === name) {
throw new Error('.field(name, val) name can not be empty');
}
if (this._data) {
throw new Error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
}
if (isObject(name)) {
for (var key in name) {
if (Object.prototype.hasOwnProperty.call(name, key)) this.field(key, name[key]);
}
return this;
}
if (Array.isArray(val)) {
for (var i in val) {
if (Object.prototype.hasOwnProperty.call(val, i)) this.field(name, val[i]);
}
return this;
} // val should be defined now
if (val === null || undefined === val) {
throw new Error('.field(name, val) val can not be empty');
}
if (typeof val === 'boolean') {
val = String(val);
}
this._getFormData().append(name, val);
return this;
};
/**
* Abort the request, and clear potential timeout.
*
* @return {Request} request
* @api public
*/
RequestBase.prototype.abort = function () {
if (this._aborted) {
return this;
}
this._aborted = true;
if (this.xhr) this.xhr.abort(); // browser
if (this.req) this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
};
RequestBase.prototype._auth = function (user, pass, options, base64Encoder) {
switch (options.type) {
case 'basic':
this.set('Authorization', "Basic ".concat(base64Encoder("".concat(user, ":").concat(pass))));
break;
case 'auto':
this.username = user;
this.password = pass;
break;
case 'bearer':
// usage would be .auth(accessToken, { type: 'bearer' })
this.set('Authorization', "Bearer ".concat(user));
break;
default:
break;
}
return this;
};
/**
* Enable transmission of cookies with x-domain requests.
*
* Note that for this to work the origin must not be
* using "Access-Control-Allow-Origin" with a wildcard,
* and also must set "Access-Control-Allow-Credentials"
* to "true".
*
* @api public
*/
RequestBase.prototype.withCredentials = function (on) {
// This is browser-only functionality. Node side is no-op.
if (on === undefined) on = true;
this._withCredentials = on;
return this;
};
/**
* Set the max redirects to `n`. Does nothing in browser XHR implementation.
*
* @param {Number} n
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.redirects = function (n) {
this._maxRedirects = n;
return this;
};
/**
* Maximum size of buffered response body, in bytes. Counts uncompressed size.
* Default 200MB.
*
* @param {Number} n number of bytes
* @return {Request} for chaining
*/
RequestBase.prototype.maxResponseSize = function (n) {
if (typeof n !== 'number') {
throw new TypeError('Invalid argument');
}
this._maxResponseSize = n;
return this;
};
/**
* Convert to a plain javascript object (not JSON string) of scalar properties.
* Note as this method is designed to return a useful non-this value,
* it cannot be chained.
*
* @return {Object} describing method, url, and data of this request
* @api public
*/
RequestBase.prototype.toJSON = function () {
return {
method: this.method,
url: this.url,
data: this._data,
headers: this._header
};
};
/**
* Send `data` as the request body, defaulting the `.type()` to "json" when
* an object is given.
*
* Examples:
*
* // manual json
* request.post('/user')
* .type('json')
* .send('{"name":"tj"}')
* .end(callback)
*
* // auto json
* request.post('/user')
* .send({ name: 'tj' })
* .end(callback)
*
* // manual x-www-form-urlencoded
* request.post('/user')
* .type('form')
* .send('name=tj')
* .end(callback)
*
* // auto x-www-form-urlencoded
* request.post('/user')
* .type('form')
* .send({ name: 'tj' })
* .end(callback)
*
* // defaults to x-www-form-urlencoded
* request.post('/user')
* .send('name=tobi')
* .send('species=ferret')
* .end(callback)
*
* @param {String|Object} data
* @return {Request} for chaining
* @api public
*/
// eslint-disable-next-line complexity
RequestBase.prototype.send = function (data) {
var isObj = isObject(data);
var type = this._header['content-type'];
if (this._formData) {
throw new Error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
}
if (isObj && !this._data) {
if (Array.isArray(data)) {
this._data = [];
} else if (!this._isHost(data)) {
this._data = {};
}
} else if (data && this._data && this._isHost(this._data)) {
throw new Error("Can't merge these send calls");
} // merge
if (isObj && isObject(this._data)) {
for (var key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) this._data[key] = data[key];
}
} else if (typeof data === 'string') {
// default to x-www-form-urlencoded
if (!type) this.type('form');
type = this._header['content-type'];
if (type === 'application/x-www-form-urlencoded') {
this._data = this._data ? "".concat(this._data, "&").concat(data) : data;
} else {
this._data = (this._data || '') + data;
}
} else {
this._data = data;
}
if (!isObj || this._isHost(data)) {
return this;
} // default to json
if (!type) this.type('json');
return this;
};
/**
* Sort `querystring` by the sort function
*
*
* Examples:
*
* // default order
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery()
* .end(callback)
*
* // customized sort function
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery(function(a, b){
* return a.length - b.length;
* })
* .end(callback)
*
*
* @param {Function} sort
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.sortQuery = function (sort) {
// _sort default to true but otherwise can be a function or boolean
this._sort = typeof sort === 'undefined' ? true : sort;
return this;
};
/**
* Compose querystring to append to req.url
*
* @api private
*/
RequestBase.prototype._finalizeQueryString = function () {
var query = this._query.join('&');
if (query) {
this.url += (this.url.includes('?') ? '&' : '?') + query;
}
this._query.length = 0; // Makes the call idempotent
if (this._sort) {
var index = this.url.indexOf('?');
if (index >= 0) {
var queryArr = this.url.slice(index + 1).split('&');
if (typeof this._sort === 'function') {
queryArr.sort(this._sort);
} else {
queryArr.sort();
}
this.url = this.url.slice(0, index) + '?' + queryArr.join('&');
}
}
}; // For backwards compat only
RequestBase.prototype._appendQueryString = function () {
console.warn('Unsupported');
};
/**
* Invoke callback with timeout error.
*
* @api private
*/
RequestBase.prototype._timeoutError = function (reason, timeout, errno) {
if (this._aborted) {
return;
}
var err = new Error("".concat(reason + timeout, "ms exceeded"));
err.timeout = timeout;
err.code = 'ECONNABORTED';
err.errno = errno;
this.timedout = true;
this.timedoutError = err;
this.abort();
this.callback(err);
};
RequestBase.prototype._setTimeouts = function () {
var self = this; // deadline
if (this._timeout && !this._timer) {
this._timer = setTimeout(function () {
self._timeoutError('Timeout of ', self._timeout, 'ETIME');
}, this._timeout);
} // response timeout
if (this._responseTimeout && !this._responseTimeoutTimer) {
this._responseTimeoutTimer = setTimeout(function () {
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
}, this._responseTimeout);
}
};
},{"./is-object":68}],70:[function(require,module,exports){
"use strict";
/**
* Module dependencies.
*/
var utils = require('./utils');
/**
* Expose `ResponseBase`.
*/
module.exports = ResponseBase;
/**
* Initialize a new `ResponseBase`.
*
* @api public
*/
function ResponseBase(obj) {
if (obj) return mixin(obj);
}
/**
* Mixin the prototype properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in ResponseBase.prototype) {
if (Object.prototype.hasOwnProperty.call(ResponseBase.prototype, key)) obj[key] = ResponseBase.prototype[key];
}
return obj;
}
/**
* Get case-insensitive `field` value.
*
* @param {String} field
* @return {String}
* @api public
*/
ResponseBase.prototype.get = function (field) {
return this.header[field.toLowerCase()];
};
/**
* Set header related properties:
*
* - `.type` the content type without params
*
* A response of "Content-Type: text/plain; charset=utf-8"
* will provide you with a `.type` of "text/plain".
*
* @param {Object} header
* @api private
*/
ResponseBase.prototype._setHeaderProperties = function (header) {
// TODO: moar!
// TODO: make this a util
// content-type
var ct = header['content-type'] || '';
this.type = utils.type(ct); // params
var params = utils.params(ct);
for (var key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) this[key] = params[key];
}
this.links = {}; // links
try {
if (header.link) {
this.links = utils.parseLinks(header.link);
}
} catch (_unused) {// ignore
}
};
/**
* Set flags such as `.ok` based on `status`.
*
* For example a 2xx response will give you a `.ok` of __true__
* whereas 5xx will be __false__ and `.error` will be __true__. The
* `.clientError` and `.serverError` are also available to be more
* specific, and `.statusType` is the class of error ranging from 1..5
* sometimes useful for mapping respond colors etc.
*
* "sugar" properties are also defined for common cases. Currently providing:
*
* - .noContent
* - .badRequest
* - .unauthorized
* - .notAcceptable
* - .notFound
*
* @param {Number} status
* @api private
*/
ResponseBase.prototype._setStatusProperties = function (status) {
var type = status / 100 | 0; // status / class
this.statusCode = status;
this.status = this.statusCode;
this.statusType = type; // basics
this.info = type === 1;
this.ok = type === 2;
this.redirect = type === 3;
this.clientError = type === 4;
this.serverError = type === 5;
this.error = type === 4 || type === 5 ? this.toError() : false; // sugar
this.created = status === 201;
this.accepted = status === 202;
this.noContent = status === 204;
this.badRequest = status === 400;
this.unauthorized = status === 401;
this.notAcceptable = status === 406;
this.forbidden = status === 403;
this.notFound = status === 404;
this.unprocessableEntity = status === 422;
};
},{"./utils":71}],71:[function(require,module,exports){
"use strict";
/**
* Return the mime type for the given `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
exports.type = function (str) {
return str.split(/ *; */).shift();
};
/**
* Return header field parameters.
*
* @param {String} str
* @return {Object}
* @api private
*/
exports.params = function (str) {
return str.split(/ *; */).reduce(function (obj, str) {
var parts = str.split(/ *= */);
var key = parts.shift();
var val = parts.shift();
if (key && val) obj[key] = val;
return obj;
}, {});
};
/**
* Parse Link header fields.
*
* @param {String} str
* @return {Object}
* @api private
*/
exports.parseLinks = function (str) {
return str.split(/ *, */).reduce(function (obj, str) {
var parts = str.split(/ *; */);
var url = parts[0].slice(1, -1);
var rel = parts[1].split(/ *= */)[1].slice(1, -1);
obj[rel] = url;
return obj;
}, {});
};
/**
* Strip content related fields from `header`.
*
* @param {Object} header
* @return {Object} header
* @api private
*/
exports.cleanHeader = function (header, changesOrigin) {
delete header['content-type'];
delete header['content-length'];
delete header['transfer-encoding'];
delete header.host; // secuirty
if (changesOrigin) {
delete header.authorization;
delete header.cookie;
}
return header;
};
},{}],72:[function(require,module,exports){
/**
* This library was modified by Harrison Liddiard. The source code to this
* modified version can be found at https://github.com/liddiard/google-diff/.
* The original source code can be found at
* http://code.google.com/p/google-diff-match-patch/. This unofficial fork is
* not maintained by or affiliated with Google Inc. The original attribution
* and licensing information follows.
*/
/**
* Diff Match and Patch
*
* Copyright 2006 Google Inc.
* http://code.google.com/p/google-diff-match-patch/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Computes the difference between two texts to create a patch.
* Applies the patch onto another text, allowing for errors.
* @author fraser@google.com (Neil Fraser)
*/
/**
* Class containing the diff.
* @constructor
*/
function diff(options) {
var options = options || {};
// Defaults.
// Redefine these in your program to override the defaults.
// Number of seconds to map a diff before giving up (0 for infinity).
this.Timeout = options.timeout || 1.0;
// Cost of an empty edit operation in terms of edit characters.
this.EditCost = options.editCost || 4;
}
// DIFF FUNCTIONS
/**
* The data structure representing a diff is an array of tuples:
* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
*/
var DIFF_DELETE = -1;
var DIFF_INSERT = 1;
var DIFF_EQUAL = 0;
/** @typedef {{0: number, 1: string}} */
diff.Diff;
/**
* Find the differences between two texts. Simplifies the problem by stripping
* any common prefix or suffix off the texts before diffing.
* @param {string} text1 Old string to be diffed.
* @param {string} text2 New string to be diffed.
* @param {boolean=} opt_checklines Optional speedup flag. If present and false,
* then don't run a line-level diff first to identify the changed areas.
* Defaults to true, which does a faster, slightly less optimal diff.
* @param {number} opt_deadline Optional time when the diff should be complete
* by. Used internally for recursive calls. Users should set DiffTimeout
* instead.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
*/
diff.prototype.main = function(text1, text2, opt_checklines,
opt_deadline) {
// Set a deadline by which time the diff must be complete.
if (typeof opt_deadline == 'undefined') {
if (this.Timeout <= 0) {
opt_deadline = Number.MAX_VALUE;
} else {
opt_deadline = (new Date).getTime() + this.Timeout * 1000;
}
}
var deadline = opt_deadline;
// Check for null inputs.
if (text1 == null || text2 == null) {
throw new Error('Null input. (diff_main)');
}
// Check for equality (speedup).
if (text1 == text2) {
if (text1) {
return [[DIFF_EQUAL, text1]];
}
return [];
}
if (typeof opt_checklines == 'undefined') {
opt_checklines = true;
}
var checklines = opt_checklines;
// Trim off common prefix (speedup).
var commonlength = this.commonPrefix(text1, text2);
var commonprefix = text1.substring(0, commonlength);
text1 = text1.substring(commonlength);
text2 = text2.substring(commonlength);
// Trim off common suffix (speedup).
commonlength = this.commonSuffix(text1, text2);
var commonsuffix = text1.substring(text1.length - commonlength);
text1 = text1.substring(0, text1.length - commonlength);
text2 = text2.substring(0, text2.length - commonlength);
// Compute the diff on the middle block.
var diffs = this.compute_(text1, text2, checklines, deadline);
// Restore the prefix and suffix.
if (commonprefix) {
diffs.unshift([DIFF_EQUAL, commonprefix]);
}
if (commonsuffix) {
diffs.push([DIFF_EQUAL, commonsuffix]);
}
this.cleanupMerge(diffs);
return diffs;
};
/**
* Find the differences between two texts. Assumes that the texts do not
* have any common prefix or suffix.
* @param {string} text1 Old string to be diffed.
* @param {string} text2 New string to be diffed.
* @param {boolean} checklines Speedup flag. If false, then don't run a
* line-level diff first to identify the changed areas.
* If true, then run a faster, slightly less optimal diff.
* @param {number} deadline Time when the diff should be complete by.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
* @private
*/
diff.prototype.compute_ = function(text1, text2, checklines,
deadline) {
var diffs;
if (!text1) {
// Just add some text (speedup).
return [[DIFF_INSERT, text2]];
}
if (!text2) {
// Just delete some text (speedup).
return [[DIFF_DELETE, text1]];
}
var longtext = text1.length > text2.length ? text1 : text2;
var shorttext = text1.length > text2.length ? text2 : text1;
var i = longtext.indexOf(shorttext);
if (i != -1) {
// Shorter text is inside the longer text (speedup).
diffs = [[DIFF_INSERT, longtext.substring(0, i)],
[DIFF_EQUAL, shorttext],
[DIFF_INSERT, longtext.substring(i + shorttext.length)]];
// Swap insertions for deletions if diff is reversed.
if (text1.length > text2.length) {
diffs[0][0] = diffs[2][0] = DIFF_DELETE;
}
return diffs;
}
if (shorttext.length == 1) {
// Single character string.
// After the previous speedup, the character can't be an equality.
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
}
// Check to see if the problem can be split in two.
var hm = this.halfMatch_(text1, text2);
if (hm) {
// A half-match was found, sort out the return data.
var text1_a = hm[0];
var text1_b = hm[1];
var text2_a = hm[2];
var text2_b = hm[3];
var mid_common = hm[4];
// Send both pairs off for separate processing.
var diffs_a = this.main(text1_a, text2_a, checklines, deadline);
var diffs_b = this.main(text1_b, text2_b, checklines, deadline);
// Merge the results.
return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);
}
if (checklines && text1.length > 100 && text2.length > 100) {
return this.lineMode_(text1, text2, deadline);
}
return this.bisect_(text1, text2, deadline);
};
/**
* Do a quick line-level diff on both strings, then rediff the parts for
* greater accuracy.
* This speedup can produce non-minimal diffs.
* @param {string} text1 Old string to be diffed.
* @param {string} text2 New string to be diffed.
* @param {number} deadline Time when the diff should be complete by.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
* @private
*/
diff.prototype.lineMode_ = function(text1, text2, deadline) {
// Scan the text on a line-by-line basis first.
var a = this.linesToChars_(text1, text2);
text1 = a.chars1;
text2 = a.chars2;
var linearray = a.lineArray;
var diffs = this.main(text1, text2, false, deadline);
// Convert the diff back to original text.
this.charsToLines_(diffs, linearray);
// Eliminate freak matches (e.g. blank lines)
this.cleanupSemantic(diffs);
// Rediff any replacement blocks, this time character-by-character.
// Add a dummy entry at the end.
diffs.push([DIFF_EQUAL, '']);
var pointer = 0;
var count_delete = 0;
var count_insert = 0;
var text_delete = '';
var text_insert = '';
while (pointer < diffs.length) {
switch (diffs[pointer][0]) {
case DIFF_INSERT:
count_insert++;
text_insert += diffs[pointer][1];
break;
case DIFF_DELETE:
count_delete++;
text_delete += diffs[pointer][1];
break;
case DIFF_EQUAL:
// Upon reaching an equality, check for prior redundancies.
if (count_delete >= 1 && count_insert >= 1) {
// Delete the offending records and add the merged ones.
diffs.splice(pointer - count_delete - count_insert,
count_delete + count_insert);
pointer = pointer - count_delete - count_insert;
var a = this.main(text_delete, text_insert, false, deadline);
for (var j = a.length - 1; j >= 0; j--) {
diffs.splice(pointer, 0, a[j]);
}
pointer = pointer + a.length;
}
count_insert = 0;
count_delete = 0;
text_delete = '';
text_insert = '';
break;
}
pointer++;
}
diffs.pop(); // Remove the dummy entry at the end.
return diffs;
};
/**
* Find the 'middle snake' of a diff, split the problem in two
* and return the recursively constructed diff.
* See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
* @param {string} text1 Old string to be diffed.
* @param {string} text2 New string to be diffed.
* @param {number} deadline Time at which to bail if not yet complete.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
* @private
*/
diff.prototype.bisect_ = function(text1, text2, deadline) {
// Cache the text lengths to prevent multiple calls.
var text1_length = text1.length;
var text2_length = text2.length;
var max_d = Math.ceil((text1_length + text2_length) / 2);
var v_offset = max_d;
var v_length = 2 * max_d;
var v1 = new Array(v_length);
var v2 = new Array(v_length);
// Setting all elements to -1 is faster in Chrome & Firefox than mixing
// integers and undefined.
for (var x = 0; x < v_length; x++) {
v1[x] = -1;
v2[x] = -1;
}
v1[v_offset + 1] = 0;
v2[v_offset + 1] = 0;
var delta = text1_length - text2_length;
// If the total number of characters is odd, then the front path will collide
// with the reverse path.
var front = (delta % 2 != 0);
// Offsets for start and end of k loop.
// Prevents mapping of space beyond the grid.
var k1start = 0;
var k1end = 0;
var k2start = 0;
var k2end = 0;
for (var d = 0; d < max_d; d++) {
// Bail out if deadline is reached.
if ((new Date()).getTime() > deadline) {
break;
}
// Walk the front path one step.
for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
var k1_offset = v_offset + k1;
var x1;
if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {
x1 = v1[k1_offset + 1];
} else {
x1 = v1[k1_offset - 1] + 1;
}
var y1 = x1 - k1;
while (x1 < text1_length && y1 < text2_length &&
text1.charAt(x1) == text2.charAt(y1)) {
x1++;
y1++;
}
v1[k1_offset] = x1;
if (x1 > text1_length) {
// Ran off the right of the graph.
k1end += 2;
} else if (y1 > text2_length) {
// Ran off the bottom of the graph.
k1start += 2;
} else if (front) {
var k2_offset = v_offset + delta - k1;
if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {
// Mirror x2 onto top-left coordinate system.
var x2 = text1_length - v2[k2_offset];
if (x1 >= x2) {
// Overlap detected.
return this.bisectSplit_(text1, text2, x1, y1, deadline);
}
}
}
}
// Walk the reverse path one step.
for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
var k2_offset = v_offset + k2;
var x2;
if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {
x2 = v2[k2_offset + 1];
} else {
x2 = v2[k2_offset - 1] + 1;
}
var y2 = x2 - k2;
while (x2 < text1_length && y2 < text2_length &&
text1.charAt(text1_length - x2 - 1) ==
text2.charAt(text2_length - y2 - 1)) {
x2++;
y2++;
}
v2[k2_offset] = x2;
if (x2 > text1_length) {
// Ran off the left of the graph.
k2end += 2;
} else if (y2 > text2_length) {
// Ran off the top of the graph.
k2start += 2;
} else if (!front) {
var k1_offset = v_offset + delta - k2;
if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {
var x1 = v1[k1_offset];
var y1 = v_offset + x1 - k1_offset;
// Mirror x2 onto top-left coordinate system.
x2 = text1_length - x2;
if (x1 >= x2) {
// Overlap detected.
return this.bisectSplit_(text1, text2, x1, y1, deadline);
}
}
}
}
}
// Diff took too long and hit the deadline or
// number of diffs equals number of characters, no commonality at all.
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
};
/**
* Given the location of the 'middle snake', split the diff in two parts
* and recurse.
* @param {string} text1 Old string to be diffed.
* @param {string} text2 New string to be diffed.
* @param {number} x Index of split point in text1.
* @param {number} y Index of split point in text2.
* @param {number} deadline Time at which to bail if not yet complete.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
* @private
*/
diff.prototype.bisectSplit_ = function(text1, text2, x, y,
deadline) {
var text1a = text1.substring(0, x);
var text2a = text2.substring(0, y);
var text1b = text1.substring(x);
var text2b = text2.substring(y);
// Compute both diffs serially.
var diffs = this.main(text1a, text2a, false, deadline);
var diffsb = this.main(text1b, text2b, false, deadline);
return diffs.concat(diffsb);
};
/**
* Split two texts into an array of strings. Reduce the texts to a string of
* hashes where each Unicode character represents one line.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
* An object containing the encoded text1, the encoded text2 and
* the array of unique strings.
* The zeroth element of the array of unique strings is intentionally blank.
* @private
*/
diff.prototype.linesToChars_ = function(text1, text2) {
var lineArray = []; // e.g. lineArray[4] == 'Hello\n'
var lineHash = {}; // e.g. lineHash['Hello\n'] == 4
// '\x00' is a valid character, but various debuggers don't like it.
// So we'll insert a junk entry to avoid generating a null character.
lineArray[0] = '';
/**
* Split a text into an array of strings. Reduce the texts to a string of
* hashes where each Unicode character represents one line.
* Modifies linearray and linehash through being a closure.
* @param {string} text String to encode.
* @return {string} Encoded string.
* @private
*/
function diff_linesToCharsMunge_(text) {
var chars = '';
// Walk the text, pulling out a substring for each line.
// text.split('\n') would would temporarily double our memory footprint.
// Modifying text would create many large strings to garbage collect.
var lineStart = 0;
var lineEnd = -1;
// Keeping our own length variable is faster than looking it up.
var lineArrayLength = lineArray.length;
while (lineEnd < text.length - 1) {
lineEnd = text.indexOf('\n', lineStart);
if (lineEnd == -1) {
lineEnd = text.length - 1;
}
var line = text.substring(lineStart, lineEnd + 1);
lineStart = lineEnd + 1;
if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :
(lineHash[line] !== undefined)) {
chars += String.fromCharCode(lineHash[line]);
} else {
chars += String.fromCharCode(lineArrayLength);
lineHash[line] = lineArrayLength;
lineArray[lineArrayLength++] = line;
}
}
return chars;
}
var chars1 = diff_linesToCharsMunge_(text1);
var chars2 = diff_linesToCharsMunge_(text2);
return {chars1: chars1, chars2: chars2, lineArray: lineArray};
};
/**
* Rehydrate the text in a diff from a string of line hashes to real lines of
* text.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @param {!Array.<string>} lineArray Array of unique strings.
* @private
*/
diff.prototype.charsToLines_ = function(diffs, lineArray) {
for (var x = 0; x < diffs.length; x++) {
var chars = diffs[x][1];
var text = [];
for (var y = 0; y < chars.length; y++) {
text[y] = lineArray[chars.charCodeAt(y)];
}
diffs[x][1] = text.join('');
}
};
/**
* Determine the common prefix of two strings.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the start of each
* string.
*/
diff.prototype.commonPrefix = function(text1, text2) {
// Quick check for common null cases.
if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {
return 0;
}
// Binary search.
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
var pointermin = 0;
var pointermax = Math.min(text1.length, text2.length);
var pointermid = pointermax;
var pointerstart = 0;
while (pointermin < pointermid) {
if (text1.substring(pointerstart, pointermid) ==
text2.substring(pointerstart, pointermid)) {
pointermin = pointermid;
pointerstart = pointermin;
} else {
pointermax = pointermid;
}
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
};
/**
* Determine the common suffix of two strings.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the end of each string.
*/
diff.prototype.commonSuffix = function(text1, text2) {
// Quick check for common null cases.
if (!text1 || !text2 ||
text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {
return 0;
}
// Binary search.
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
var pointermin = 0;
var pointermax = Math.min(text1.length, text2.length);
var pointermid = pointermax;
var pointerend = 0;
while (pointermin < pointermid) {
if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==
text2.substring(text2.length - pointermid, text2.length - pointerend)) {
pointermin = pointermid;
pointerend = pointermin;
} else {
pointermax = pointermid;
}
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
};
/**
* Determine if the suffix of one string is the prefix of another.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the end of the first
* string and the start of the second string.
* @private
*/
diff.prototype.commonOverlap_ = function(text1, text2) {
// Cache the text lengths to prevent multiple calls.
var text1_length = text1.length;
var text2_length = text2.length;
// Eliminate the null case.
if (text1_length == 0 || text2_length == 0) {
return 0;
}
// Truncate the longer string.
if (text1_length > text2_length) {
text1 = text1.substring(text1_length - text2_length);
} else if (text1_length < text2_length) {
text2 = text2.substring(0, text1_length);
}
var text_length = Math.min(text1_length, text2_length);
// Quick check for the worst case.
if (text1 == text2) {
return text_length;
}
// Start by looking for a single character match
// and increase length until no match is found.
// Performance analysis: http://neil.fraser.name/news/2010/11/04/
var best = 0;
var length = 1;
while (true) {
var pattern = text1.substring(text_length - length);
var found = text2.indexOf(pattern);
if (found == -1) {
return best;
}
length += found;
if (found == 0 || text1.substring(text_length - length) ==
text2.substring(0, length)) {
best = length;
length++;
}
}
};
/**
* Do the two texts share a substring which is at least half the length of the
* longer text?
* This speedup can produce non-minimal diffs.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {Array.<string>} Five element Array, containing the prefix of
* text1, the suffix of text1, the prefix of text2, the suffix of
* text2 and the common middle. Or null if there was no match.
* @private
*/
diff.prototype.halfMatch_ = function(text1, text2) {
if (this.Timeout <= 0) {
// Don't risk returning a non-optimal diff if we have unlimited time.
return null;
}
var longtext = text1.length > text2.length ? text1 : text2;
var shorttext = text1.length > text2.length ? text2 : text1;
if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
return null; // Pointless.
}
var dmp = this; // 'this' becomes 'window' in a closure.
/**
* Does a substring of shorttext exist within longtext such that the substring
* is at least half the length of longtext?
* Closure, but does not reference any external variables.
* @param {string} longtext Longer string.
* @param {string} shorttext Shorter string.
* @param {number} i Start index of quarter length substring within longtext.
* @return {Array.<string>} Five element Array, containing the prefix of
* longtext, the suffix of longtext, the prefix of shorttext, the suffix
* of shorttext and the common middle. Or null if there was no match.
* @private
*/
function diff_halfMatchI_(longtext, shorttext, i) {
// Start with a 1/4 length substring at position i as a seed.
var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
var j = -1;
var best_common = '';
var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
while ((j = shorttext.indexOf(seed, j + 1)) != -1) {
var prefixLength = dmp.commonPrefix(longtext.substring(i),
shorttext.substring(j));
var suffixLength = dmp.commonSuffix(longtext.substring(0, i),
shorttext.substring(0, j));
if (best_common.length < suffixLength + prefixLength) {
best_common = shorttext.substring(j - suffixLength, j) +
shorttext.substring(j, j + prefixLength);
best_longtext_a = longtext.substring(0, i - suffixLength);
best_longtext_b = longtext.substring(i + prefixLength);
best_shorttext_a = shorttext.substring(0, j - suffixLength);
best_shorttext_b = shorttext.substring(j + prefixLength);
}
}
if (best_common.length * 2 >= longtext.length) {
return [best_longtext_a, best_longtext_b,
best_shorttext_a, best_shorttext_b, best_common];
} else {
return null;
}
}
// First check if the second quarter is the seed for a half-match.
var hm1 = diff_halfMatchI_(longtext, shorttext,
Math.ceil(longtext.length / 4));
// Check again based on the third quarter.
var hm2 = diff_halfMatchI_(longtext, shorttext,
Math.ceil(longtext.length / 2));
var hm;
if (!hm1 && !hm2) {
return null;
} else if (!hm2) {
hm = hm1;
} else if (!hm1) {
hm = hm2;
} else {
// Both matched. Select the longest.
hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
}
// A half-match was found, sort out the return data.
var text1_a, text1_b, text2_a, text2_b;
if (text1.length > text2.length) {
text1_a = hm[0];
text1_b = hm[1];
text2_a = hm[2];
text2_b = hm[3];
} else {
text2_a = hm[0];
text2_b = hm[1];
text1_a = hm[2];
text1_b = hm[3];
}
var mid_common = hm[4];
return [text1_a, text1_b, text2_a, text2_b, mid_common];
};
/**
* Reduce the number of edits by eliminating semantically trivial equalities.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
*/
diff.prototype.cleanupSemantic = function(diffs) {
var changes = false;
var equalities = []; // Stack of indices where equalities are found.
var equalitiesLength = 0; // Keeping our own length var is faster in JS.
/** @type {?string} */
var lastequality = null;
// Always equal to diffs[equalities[equalitiesLength - 1]][1]
var pointer = 0; // Index of current position.
// Number of characters that changed prior to the equality.
var length_insertions1 = 0;
var length_deletions1 = 0;
// Number of characters that changed after the equality.
var length_insertions2 = 0;
var length_deletions2 = 0;
while (pointer < diffs.length) {
if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.
equalities[equalitiesLength++] = pointer;
length_insertions1 = length_insertions2;
length_deletions1 = length_deletions2;
length_insertions2 = 0;
length_deletions2 = 0;
lastequality = diffs[pointer][1];
} else { // An insertion or deletion.
if (diffs[pointer][0] == DIFF_INSERT) {
length_insertions2 += diffs[pointer][1].length;
} else {
length_deletions2 += diffs[pointer][1].length;
}
// Eliminate an equality that is smaller or equal to the edits on both
// sides of it.
if (lastequality && (lastequality.length <=
Math.max(length_insertions1, length_deletions1)) &&
(lastequality.length <= Math.max(length_insertions2,
length_deletions2))) {
// Duplicate record.
diffs.splice(equalities[equalitiesLength - 1], 0,
[DIFF_DELETE, lastequality]);
// Change second copy to insert.
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
// Throw away the equality we just deleted.
equalitiesLength--;
// Throw away the previous equality (it needs to be reevaluated).
equalitiesLength--;
pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
length_insertions1 = 0; // Reset the counters.
length_deletions1 = 0;
length_insertions2 = 0;
length_deletions2 = 0;
lastequality = null;
changes = true;
}
}
pointer++;
}
// Normalize the diff.
if (changes) {
this.cleanupMerge(diffs);
}
this.cleanupSemanticLossless(diffs);
// Find any overlaps between deletions and insertions.
// e.g: <del>abcxxx</del><ins>xxxdef</ins>
// -> <del>abc</del>xxx<ins>def</ins>
// e.g: <del>xxxabc</del><ins>defxxx</ins>
// -> <ins>def</ins>xxx<del>abc</del>
// Only extract an overlap if it is as big as the edit ahead or behind it.
pointer = 1;
while (pointer < diffs.length) {
if (diffs[pointer - 1][0] == DIFF_DELETE &&
diffs[pointer][0] == DIFF_INSERT) {
var deletion = diffs[pointer - 1][1];
var insertion = diffs[pointer][1];
var overlap_length1 = this.commonOverlap_(deletion, insertion);
var overlap_length2 = this.commonOverlap_(insertion, deletion);
if (overlap_length1 >= overlap_length2) {
if (overlap_length1 >= deletion.length / 2 ||
overlap_length1 >= insertion.length / 2) {
// Overlap found. Insert an equality and trim the surrounding edits.
diffs.splice(pointer, 0,
[DIFF_EQUAL, insertion.substring(0, overlap_length1)]);
diffs[pointer - 1][1] =
deletion.substring(0, deletion.length - overlap_length1);
diffs[pointer + 1][1] = insertion.substring(overlap_length1);
pointer++;
}
} else {
if (overlap_length2 >= deletion.length / 2 ||
overlap_length2 >= insertion.length / 2) {
// Reverse overlap found.
// Insert an equality and swap and trim the surrounding edits.
diffs.splice(pointer, 0,
[DIFF_EQUAL, deletion.substring(0, overlap_length2)]);
diffs[pointer - 1][0] = DIFF_INSERT;
diffs[pointer - 1][1] =
insertion.substring(0, insertion.length - overlap_length2);
diffs[pointer + 1][0] = DIFF_DELETE;
diffs[pointer + 1][1] =
deletion.substring(overlap_length2);
pointer++;
}
}
pointer++;
}
pointer++;
}
};
/**
* Look for single edits surrounded on both sides by equalities
* which can be shifted sideways to align the edit to a word boundary.
* e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
*/
diff.prototype.cleanupSemanticLossless = function(diffs) {
/**
* Given two strings, compute a score representing whether the internal
* boundary falls on logical boundaries.
* Scores range from 6 (best) to 0 (worst).
* Closure, but does not reference any external variables.
* @param {string} one First string.
* @param {string} two Second string.
* @return {number} The score.
* @private
*/
function diff_cleanupSemanticScore_(one, two) {
if (!one || !two) {
// Edges are the best.
return 6;
}
// Each port of this function behaves slightly differently due to
// subtle differences in each language's definition of things like
// 'whitespace'. Since this function's purpose is largely cosmetic,
// the choice has been made to use each language's native features
// rather than force total conformity.
var char1 = one.charAt(one.length - 1);
var char2 = two.charAt(0);
var nonAlphaNumeric1 = char1.match(diff.nonAlphaNumericRegex_);
var nonAlphaNumeric2 = char2.match(diff.nonAlphaNumericRegex_);
var whitespace1 = nonAlphaNumeric1 &&
char1.match(diff.whitespaceRegex_);
var whitespace2 = nonAlphaNumeric2 &&
char2.match(diff.whitespaceRegex_);
var lineBreak1 = whitespace1 &&
char1.match(diff.linebreakRegex_);
var lineBreak2 = whitespace2 &&
char2.match(diff.linebreakRegex_);
var blankLine1 = lineBreak1 &&
one.match(diff.blanklineEndRegex_);
var blankLine2 = lineBreak2 &&
two.match(diff.blanklineStartRegex_);
if (blankLine1 || blankLine2) {
// Five points for blank lines.
return 5;
} else if (lineBreak1 || lineBreak2) {
// Four points for line breaks.
return 4;
} else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {
// Three points for end of sentences.
return 3;
} else if (whitespace1 || whitespace2) {
// Two points for whitespace.
return 2;
} else if (nonAlphaNumeric1 || nonAlphaNumeric2) {
// One point for non-alphanumeric.
return 1;
}
return 0;
}
var pointer = 1;
// Intentionally ignore the first and last element (don't need checking).
while (pointer < diffs.length - 1) {
if (diffs[pointer - 1][0] == DIFF_EQUAL &&
diffs[pointer + 1][0] == DIFF_EQUAL) {
// This is a single edit surrounded by equalities.
var equality1 = diffs[pointer - 1][1];
var edit = diffs[pointer][1];
var equality2 = diffs[pointer + 1][1];
// First, shift the edit as far left as possible.
var commonOffset = this.commonSuffix(equality1, edit);
if (commonOffset) {
var commonString = edit.substring(edit.length - commonOffset);
equality1 = equality1.substring(0, equality1.length - commonOffset);
edit = commonString + edit.substring(0, edit.length - commonOffset);
equality2 = commonString + equality2;
}
// Second, step character by character right, looking for the best fit.
var bestEquality1 = equality1;
var bestEdit = edit;
var bestEquality2 = equality2;
var bestScore = diff_cleanupSemanticScore_(equality1, edit) +
diff_cleanupSemanticScore_(edit, equality2);
while (edit.charAt(0) === equality2.charAt(0)) {
equality1 += edit.charAt(0);
edit = edit.substring(1) + equality2.charAt(0);
equality2 = equality2.substring(1);
var score = diff_cleanupSemanticScore_(equality1, edit) +
diff_cleanupSemanticScore_(edit, equality2);
// The >= encourages trailing rather than leading whitespace on edits.
if (score >= bestScore) {
bestScore = score;
bestEquality1 = equality1;
bestEdit = edit;
bestEquality2 = equality2;
}
}
if (diffs[pointer - 1][1] != bestEquality1) {
// We have an improvement, save it back to the diff.
if (bestEquality1) {
diffs[pointer - 1][1] = bestEquality1;
} else {
diffs.splice(pointer - 1, 1);
pointer--;
}
diffs[pointer][1] = bestEdit;
if (bestEquality2) {
diffs[pointer + 1][1] = bestEquality2;
} else {
diffs.splice(pointer + 1, 1);
pointer--;
}
}
}
pointer++;
}
};
// Define some regex patterns for matching boundaries.
diff.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;
diff.whitespaceRegex_ = /\s/;
diff.linebreakRegex_ = /[\r\n]/;
diff.blanklineEndRegex_ = /\n\r?\n$/;
diff.blanklineStartRegex_ = /^\r?\n\r?\n/;
/**
* Reduce the number of edits by eliminating operationally trivial equalities.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
*/
diff.prototype.cleanupEfficiency = function(diffs) {
var changes = false;
var equalities = []; // Stack of indices where equalities are found.
var equalitiesLength = 0; // Keeping our own length var is faster in JS.
/** @type {?string} */
var lastequality = null;
// Always equal to diffs[equalities[equalitiesLength - 1]][1]
var pointer = 0; // Index of current position.
// Is there an insertion operation before the last equality.
var pre_ins = false;
// Is there a deletion operation before the last equality.
var pre_del = false;
// Is there an insertion operation after the last equality.
var post_ins = false;
// Is there a deletion operation after the last equality.
var post_del = false;
while (pointer < diffs.length) {
if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.
if (diffs[pointer][1].length < this.EditCost &&
(post_ins || post_del)) {
// Candidate found.
equalities[equalitiesLength++] = pointer;
pre_ins = post_ins;
pre_del = post_del;
lastequality = diffs[pointer][1];
} else {
// Not a candidate, and can never become one.
equalitiesLength = 0;
lastequality = null;
}
post_ins = post_del = false;
} else { // An insertion or deletion.
if (diffs[pointer][0] == DIFF_DELETE) {
post_del = true;
} else {
post_ins = true;
}
/*
* Five types to be split:
* <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
* <ins>A</ins>X<ins>C</ins><del>D</del>
* <ins>A</ins><del>B</del>X<ins>C</ins>
* <ins>A</del>X<ins>C</ins><del>D</del>
* <ins>A</ins><del>B</del>X<del>C</del>
*/
if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||
((lastequality.length < this.EditCost / 2) &&
(pre_ins + pre_del + post_ins + post_del) == 3))) {
// Duplicate record.
diffs.splice(equalities[equalitiesLength - 1], 0,
[DIFF_DELETE, lastequality]);
// Change second copy to insert.
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
equalitiesLength--; // Throw away the equality we just deleted;
lastequality = null;
if (pre_ins && pre_del) {
// No changes made which could affect previous entry, keep going.
post_ins = post_del = true;
equalitiesLength = 0;
} else {
equalitiesLength--; // Throw away the previous equality.
pointer = equalitiesLength > 0 ?
equalities[equalitiesLength - 1] : -1;
post_ins = post_del = false;
}
changes = true;
}
}
pointer++;
}
if (changes) {
this.cleanupMerge(diffs);
}
};
/**
* Reorder and merge like edit sections. Merge equalities.
* Any edit section can move as long as it doesn't cross an equality.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
*/
diff.prototype.cleanupMerge = function(diffs) {
diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end.
var pointer = 0;
var count_delete = 0;
var count_insert = 0;
var text_delete = '';
var text_insert = '';
var commonlength;
while (pointer < diffs.length) {
switch (diffs[pointer][0]) {
case DIFF_INSERT:
count_insert++;
text_insert += diffs[pointer][1];
pointer++;
break;
case DIFF_DELETE:
count_delete++;
text_delete += diffs[pointer][1];
pointer++;
break;
case DIFF_EQUAL:
// Upon reaching an equality, check for prior redundancies.
if (count_delete + count_insert > 1) {
if (count_delete !== 0 && count_insert !== 0) {
// Factor out any common prefixies.
commonlength = this.commonPrefix(text_insert, text_delete);
if (commonlength !== 0) {
if ((pointer - count_delete - count_insert) > 0 &&
diffs[pointer - count_delete - count_insert - 1][0] ==
DIFF_EQUAL) {
diffs[pointer - count_delete - count_insert - 1][1] +=
text_insert.substring(0, commonlength);
} else {
diffs.splice(0, 0, [DIFF_EQUAL,
text_insert.substring(0, commonlength)]);
pointer++;
}
text_insert = text_insert.substring(commonlength);
text_delete = text_delete.substring(commonlength);
}
// Factor out any common suffixies.
commonlength = this.commonSuffix(text_insert, text_delete);
if (commonlength !== 0) {
diffs[pointer][1] = text_insert.substring(text_insert.length -
commonlength) + diffs[pointer][1];
text_insert = text_insert.substring(0, text_insert.length -
commonlength);
text_delete = text_delete.substring(0, text_delete.length -
commonlength);
}
}
// Delete the offending records and add the merged ones.
if (count_delete === 0) {
diffs.splice(pointer - count_insert,
count_delete + count_insert, [DIFF_INSERT, text_insert]);
} else if (count_insert === 0) {
diffs.splice(pointer - count_delete,
count_delete + count_insert, [DIFF_DELETE, text_delete]);
} else {
diffs.splice(pointer - count_delete - count_insert,
count_delete + count_insert, [DIFF_DELETE, text_delete],
[DIFF_INSERT, text_insert]);
}
pointer = pointer - count_delete - count_insert +
(count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;
} else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {
// Merge this equality with the previous one.
diffs[pointer - 1][1] += diffs[pointer][1];
diffs.splice(pointer, 1);
} else {
pointer++;
}
count_insert = 0;
count_delete = 0;
text_delete = '';
text_insert = '';
break;
}
}
if (diffs[diffs.length - 1][1] === '') {
diffs.pop(); // Remove the dummy entry at the end.
}
// Second pass: look for single edits surrounded on both sides by equalities
// which can be shifted sideways to eliminate an equality.
// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
var changes = false;
pointer = 1;
// Intentionally ignore the first and last element (don't need checking).
while (pointer < diffs.length - 1) {
if (diffs[pointer - 1][0] == DIFF_EQUAL &&
diffs[pointer + 1][0] == DIFF_EQUAL) {
// This is a single edit surrounded by equalities.
if (diffs[pointer][1].substring(diffs[pointer][1].length -
diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {
// Shift the edit over the previous equality.
diffs[pointer][1] = diffs[pointer - 1][1] +
diffs[pointer][1].substring(0, diffs[pointer][1].length -
diffs[pointer - 1][1].length);
diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
diffs.splice(pointer - 1, 1);
changes = true;
} else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==
diffs[pointer + 1][1]) {
// Shift the edit over the next equality.
diffs[pointer - 1][1] += diffs[pointer + 1][1];
diffs[pointer][1] =
diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
diffs[pointer + 1][1];
diffs.splice(pointer + 1, 1);
changes = true;
}
}
pointer++;
}
// If shifts were made, the diff needs reordering and another shift sweep.
if (changes) {
this.cleanupMerge(diffs);
}
};
/**
* loc is a location in text1, compute and return the equivalent location in
* text2.
* e.g. 'The cat' vs 'The big cat', 1->1, 5->8
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @param {number} loc Location within text1.
* @return {number} Location within text2.
*/
diff.prototype.xIndex = function(diffs, loc) {
var chars1 = 0;
var chars2 = 0;
var last_chars1 = 0;
var last_chars2 = 0;
var x;
for (x = 0; x < diffs.length; x++) {
if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion.
chars1 += diffs[x][1].length;
}
if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion.
chars2 += diffs[x][1].length;
}
if (chars1 > loc) { // Overshot the location.
break;
}
last_chars1 = chars1;
last_chars2 = chars2;
}
// Was the location was deleted?
if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {
return last_chars2;
}
// Add the remaining character length.
return last_chars2 + (loc - last_chars1);
};
/**
* Convert a diff array into a pretty HTML report.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @return {string} HTML representation.
*/
diff.prototype.prettyHtml = function(diffs) {
var html = [];
var pattern_amp = /&/g;
var pattern_lt = /</g;
var pattern_gt = />/g;
var pattern_br = /\n/g;
for (var x = 0; x < diffs.length; x++) {
var op = diffs[x][0]; // Operation (insert, delete, equal)
var data = diffs[x][1]; // Text of change.
var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')
.replace(pattern_gt, '&gt;').replace(pattern_br, '<br/>');
switch (op) {
case DIFF_INSERT:
html[x] = '<ins>' + text + '</ins>';
break;
case DIFF_DELETE:
html[x] = '<del>' + text + '</del>';
break;
case DIFF_EQUAL:
html[x] = '<span>' + text + '</span>';
break;
}
}
return html.join('');
};
/**
* Compute and return the source text (all equalities and deletions).
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @return {string} Source text.
*/
diff.prototype.text1 = function(diffs) {
var text = [];
for (var x = 0; x < diffs.length; x++) {
if (diffs[x][0] !== DIFF_INSERT) {
text[x] = diffs[x][1];
}
}
return text.join('');
};
/**
* Compute and return the destination text (all equalities and insertions).
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @return {string} Destination text.
*/
diff.prototype.text2 = function(diffs) {
var text = [];
for (var x = 0; x < diffs.length; x++) {
if (diffs[x][0] !== DIFF_DELETE) {
text[x] = diffs[x][1];
}
}
return text.join('');
};
/**
* Compute the Levenshtein distance; the number of inserted, deleted or
* substituted characters.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @return {number} Number of changes.
*/
diff.prototype.levenshtein = function(diffs) {
var levenshtein = 0;
var insertions = 0;
var deletions = 0;
for (var x = 0; x < diffs.length; x++) {
var op = diffs[x][0];
var data = diffs[x][1];
switch (op) {
case DIFF_INSERT:
insertions += data.length;
break;
case DIFF_DELETE:
deletions += data.length;
break;
case DIFF_EQUAL:
// A deletion and an insertion is one substitution.
levenshtein += Math.max(insertions, deletions);
insertions = 0;
deletions = 0;
break;
}
}
levenshtein += Math.max(insertions, deletions);
return levenshtein;
};
/**
* Crush the diff into an encoded string which describes the operations
* required to transform text1 into text2.
* E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'.
* Operations are tab-separated. Inserted text is escaped using %xx notation.
* @param {!Array.<!diff.Diff>} diffs Array of diff tuples.
* @return {string} Delta text.
*/
diff.prototype.toDelta = function(diffs) {
var text = [];
for (var x = 0; x < diffs.length; x++) {
switch (diffs[x][0]) {
case DIFF_INSERT:
text[x] = '+' + encodeURI(diffs[x][1]);
break;
case DIFF_DELETE:
text[x] = '-' + diffs[x][1].length;
break;
case DIFF_EQUAL:
text[x] = '=' + diffs[x][1].length;
break;
}
}
return text.join('\t').replace(/%20/g, ' ');
};
/**
* Given the original text1, and an encoded string which describes the
* operations required to transform text1 into text2, compute the full diff.
* @param {string} text1 Source string for the diff.
* @param {string} delta Delta text.
* @return {!Array.<!diff.Diff>} Array of diff tuples.
* @throws {!Error} If invalid input.
*/
diff.prototype.fromDelta = function(text1, delta) {
var diffs = [];
var diffsLength = 0; // Keeping our own length var is faster in JS.
var pointer = 0; // Cursor in text1
var tokens = delta.split(/\t/g);
for (var x = 0; x < tokens.length; x++) {
// Each token begins with a one character parameter which specifies the
// operation of this token (delete, insert, equality).
var param = tokens[x].substring(1);
switch (tokens[x].charAt(0)) {
case '+':
try {
diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)];
} catch (ex) {
// Malformed URI sequence.
throw new Error('Illegal escape in diff_fromDelta: ' + param);
}
break;
case '-':
// Fall through.
case '=':
var n = parseInt(param, 10);
if (isNaN(n) || n < 0) {
throw new Error('Invalid number in diff_fromDelta: ' + param);
}
var text = text1.substring(pointer, pointer += n);
if (tokens[x].charAt(0) == '=') {
diffs[diffsLength++] = [DIFF_EQUAL, text];
} else {
diffs[diffsLength++] = [DIFF_DELETE, text];
}
break;
default:
// Blank tokens are ok (from a trailing \t).
// Anything else is an error.
if (tokens[x]) {
throw new Error('Invalid diff operation in diff_fromDelta: ' +
tokens[x]);
}
}
}
if (pointer != text1.length) {
throw new Error('Delta length (' + pointer +
') does not equal source text length (' + text1.length + ').');
}
return diffs;
};
// Export these global variables so that they survive Google's JS compiler.
// In a browser, 'this' will be 'window'.
// Users of node.js should 'require' the uncompressed version since Google's
// JS compiler may break the following exports for non-browser environments.
this['diff'] = diff;
this['DIFF_DELETE'] = DIFF_DELETE;
this['DIFF_INSERT'] = DIFF_INSERT;
this['DIFF_EQUAL'] = DIFF_EQUAL;
module.exports = diff;
},{}],73:[function(require,module,exports){
(function (setImmediate,clearImmediate){
var nextTick = require('process/browser.js').nextTick;
var apply = Function.prototype.apply;
var slice = Array.prototype.slice;
var immediateIds = {};
var nextImmediateId = 0;
// DOM APIs, for completeness
exports.setTimeout = function() {
return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
};
exports.setInterval = function() {
return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
};
exports.clearTimeout =
exports.clearInterval = function(timeout) { timeout.close(); };
function Timeout(id, clearFn) {
this._id = id;
this._clearFn = clearFn;
}
Timeout.prototype.unref = Timeout.prototype.ref = function() {};
Timeout.prototype.close = function() {
this._clearFn.call(window, this._id);
};
// Does not start the time, just sets up the members needed.
exports.enroll = function(item, msecs) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = msecs;
};
exports.unenroll = function(item) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = -1;
};
exports._unrefActive = exports.active = function(item) {
clearTimeout(item._idleTimeoutId);
var msecs = item._idleTimeout;
if (msecs >= 0) {
item._idleTimeoutId = setTimeout(function onTimeout() {
if (item._onTimeout)
item._onTimeout();
}, msecs);
}
};
// That's not how node.js implements it but the exposed api is the same.
exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
var id = nextImmediateId++;
var args = arguments.length < 2 ? false : slice.call(arguments, 1);
immediateIds[id] = true;
nextTick(function onNextTick() {
if (immediateIds[id]) {
// fn.call() is faster so we optimize for the common use-case
// @see http://jsperf.com/call-apply-segu
if (args) {
fn.apply(null, args);
} else {
fn.call(null);
}
// Prevent ids from leaking
exports.clearImmediate(id);
}
});
return id;
};
exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
delete immediateIds[id];
};
}).call(this,require("timers").setImmediate,require("timers").clearImmediate)
},{"process/browser.js":65,"timers":73}],74:[function(require,module,exports){
arguments[4][4][0].apply(exports,arguments)
},{"dup":4}],75:[function(require,module,exports){
arguments[4][5][0].apply(exports,arguments)
},{"./support/isBuffer":74,"_process":65,"dup":5,"inherits":62}],76:[function(require,module,exports){
var v1 = require('./v1');
var v4 = require('./v4');
var uuid = v4;
uuid.v1 = v1;
uuid.v4 = v4;
module.exports = uuid;
},{"./v1":79,"./v4":80}],77:[function(require,module,exports){
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex[i] = (i + 0x100).toString(16).substr(1);
}
function bytesToUuid(buf, offset) {
var i = offset || 0;
var bth = byteToHex;
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return ([
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]]
]).join('');
}
module.exports = bytesToUuid;
},{}],78:[function(require,module,exports){
// Unique ID creation requires a high quality random # generator. In the
// browser this is a little complicated due to unknown quality of Math.random()
// and inconsistent support for the `crypto` API. We do the best we can via
// feature-detection
// getRandomValues needs to be invoked in a context where "this" is a Crypto
// implementation. Also, find the complete implementation of crypto on IE11.
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
(typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
if (getRandomValues) {
// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
module.exports = function whatwgRNG() {
getRandomValues(rnds8);
return rnds8;
};
} else {
// Math.random()-based (RNG)
//
// If all else fails, use Math.random(). It's fast, but is of unspecified
// quality.
var rnds = new Array(16);
module.exports = function mathRNG() {
for (var i = 0, r; i < 16; i++) {
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return rnds;
};
}
},{}],79:[function(require,module,exports){
var rng = require('./lib/rng');
var bytesToUuid = require('./lib/bytesToUuid');
// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
var _nodeId;
var _clockseq;
// Previous uuid creation time
var _lastMSecs = 0;
var _lastNSecs = 0;
// See https://github.com/uuidjs/uuid for API details
function v1(options, buf, offset) {
var i = buf && offset || 0;
var b = buf || [];
options = options || {};
var node = options.node || _nodeId;
var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
// node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if (node == null || clockseq == null) {
var seedBytes = rng();
if (node == null) {
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
node = _nodeId = [
seedBytes[0] | 0x01,
seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
];
}
if (clockseq == null) {
// Per 4.2.2, randomize (14 bit) clockseq
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
}
}
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
// Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
// Time since last uuid creation (in msecs)
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
// Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq === undefined) {
clockseq = clockseq + 1 & 0x3fff;
}
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
nsecs = 0;
}
// Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq;
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000;
// `time_low`
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff;
// `time_mid`
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff;
// `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff;
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80;
// `clock_seq_low`
b[i++] = clockseq & 0xff;
// `node`
for (var n = 0; n < 6; ++n) {
b[i + n] = node[n];
}
return buf ? buf : bytesToUuid(b);
}
module.exports = v1;
},{"./lib/bytesToUuid":77,"./lib/rng":78}],80:[function(require,module,exports){
var rng = require('./lib/rng');
var bytesToUuid = require('./lib/bytesToUuid');
function v4(options, buf, offset) {
var i = buf && offset || 0;
if (typeof(options) == 'string') {
buf = options === 'binary' ? new Array(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || rng)();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ++ii) {
buf[i + ii] = rnds[ii];
}
}
return buf || bytesToUuid(rnds);
}
module.exports = v4;
},{"./lib/bytesToUuid":77,"./lib/rng":78}],81:[function(require,module,exports){
module.exports = "<li class=\"section main\" id=\"diff-section\">\n <div class=\"controls\">\n <div id=\"diff_heading_rename\" class=\"settings\"><i class=\"icon fa fa-play fa-fw iconsmall\"\n title=\"Rename Incorrect Headings\"\n aria-label=\"Rename\"></i>\n </div>\n <div id=\"diff_heading_busy\" class=\"settings diff-hidden\"><i class=\"icon fa fa-circle-notch fa-spin fa-fw iconsmall\"\n title=\"Renaming Headings\"\n aria-label=\"Renaming Headings\"></i>\n </div>\n </div>\n <div class=\"content\">\n <div style=\"background: url('https://u-bedifferent.catalyst-au.net/pluginfile.php/347/format_unbox/background/363/Overview.jpg') no-repeat center; background-size: cover; background-color: #000;\">\n <div class=\"unbox-section-summary mo-boxitem \">\n <div class=\"mo-titledetails\">\n <div class=\"mo-shortname\">Renumbering</div>\n <div class=\"mo-fullname\">BeDifferent Renumbering Control Panel</div>\n </div>\n <div class=\"mo-bottomborder\"></div>\n </div>\n </div>\n <div class=\"section-modules-list\">\n <ul class=\"section section-modules yui3-dd-drop\"\n data-draggroups=\"resource\">\n {{#if activity.length}}\n <li class=\"activity unboxpage modtype_unboxpage yui3-dd-drop\"\n data-draggroups=\"resource\">\n <p><a href=\"javascript:Array.from(window.document.querySelectorAll('input.diff-select[type=checkbox]')).filter(c => !c.disabled).forEach(c => c.checked = true);\">Select All</a>&nbsp;/&nbsp;<a href=\"javascript:window.document.querySelectorAll('input.diff-select[type=checkbox]').forEach(c => c.checked = false)\">Select None</a> </p>\n </li>\n {{/if}}\n {{#each activity}}\n <li class=\"activity unboxpage modtype_unboxpage yui3-dd-drop\"\n data-draggroups=\"resource\">\n <div>\n <div class=\"mod-indent-outer\">\n <div class=\"mod-indent\"></div>\n <div>\n <div class=\"activityinstance\"><span class=\"inplaceeditable inplaceeditable-text\"\n data-inplaceeditable=\"1\"\n data-component=\"core_course\"\n data-itemtype=\"activityname\"\n data-value=\"What Will You Study?\"\n data-editlabel=\"New name for activity What Will You Study?\"\n data-type=\"text\" data-options=\"\">\n<span><input class=\"diff-select\" type=\"checkbox\" name=\"select-{{{id}}}\" value=\"{{{id}}}\" id=\"select-{{{id}}}\"></span>\n<a class=\" unbox-progress-incomplete\" onclick=\"\"\n href=\"#{{{id}}}\">{{{text}}}</a><i id=\"spinner-{{{id}}}\" class=\"icon fa fa-spinner fa-spin fa-fw iconsmall diff-hidden\"></i><i id=\"tick-{{{id}}}\" class=\"icon fa fa-check-circle fa-fw iconsmall diff-hidden\"></i><i id=\"cross-{{{id}}}\" class=\"icon fa fa-times-circle fa-fw iconsmall diff-hidden\"></i>\n</span></div>\n </div>\n </div>\n </div>\n </li>\n {{else}}\n <p>All numbered headings are correct!</p>\n {{/each}}\n </ul>\n </div>\n\n </div>\n</li>";
},{}],82:[function(require,module,exports){
module.exports = "<iframe width=\"0\" height=\"0\" tabindex=\"-1\"></iframe>\n{{! Using display:none wont allow .click() to work <iframe style=\"display:none\" width=\"1200\" height=\"900\"></iframe>}}\n";
},{}],83:[function(require,module,exports){
/**
* Create a heading number
* @param {number|number[]|string} number The initial number as either a string with separators or an array of numbers or as a single number
* @param {string} separator A literal separator for the numbering, defaults to period ( . )
* @param {string} trailer A literal string to append as the trailer to the heading (Default is single space ' ')
* @param {number} startingNumber When numbering a subsection, what number do you start with (default 1)
* @constructor
*/
function HeadingNumber(number, separator,trailer, startingNumber) {
if(separator === undefined)
this.separator = '.' ;
else if(typeof separator !== 'string')
throw new Error('Separator must be of type string: '+typeof separator) ;
else
this.separator = separator ;
if(number !== undefined)
this.number = parseNumber(number,this.separator) ;
if(trailer === undefined)
this.trailer = ' ' ;
else if(typeof trailer !== 'string')
throw new Error('Trailer must be of type string: '+typeof trailer) ;
else
this.trailer = trailer ;
if(startingNumber === undefined)
this.start = 0 ;
else if(typeof startingNumber !== 'number')
throw new Error('startingNumber must be of type number: '+typeof startingNumber) ;
else
this.start = startingNumber - 1;
}
/**
* Return a new instance with an additional sub-level, starting at 'number'
* @example 1.4 -> 1.4.1
* @param {number} number Number to start with in new sub-level - defaults to startingNumber
* @returns {HeadingNumber} New instance with additional sub-level
*/
HeadingNumber.prototype.down = function (number) {
if(number === undefined)
number = this.start ;
let a = this.copy() ;
a.number.push(number) ;
return a ;
} ;
/**
* Returns a new instance with the lowest sub-level removed
* @example 1.4.2 -> 1.4
* @returns {HeadingNumber} New instance with one less sub-level
*/
HeadingNumber.prototype.up = function() {
if(this.number.length === 0)
throw new Error('Cannot go up - heading number not initialised') ;
if(this.number.length === 1)
throw new Error('Cannot go up - at highest number level: '+this) ;
let a = this.copy() ;
a.number.pop() ;
return a ;
} ;
/**
* Generate a string representation of this HeadingNumber
* @return {string}
*/
HeadingNumber.prototype.toString = function () {
let v = this.number.join(this.separator) ;
v += this.trailer ;
return v ;
} ;
/**
* Increment lowest-level heading number
* @return {HeadingNumber} New instance
*/
HeadingNumber.prototype.next = function () {
let a = this.copy() ;
++a.number[a.number.length-1] ;
return a ;
} ;
/**
* Decrement lowest-level heading number
* @return {HeadingNumber} New instance
*/
HeadingNumber.prototype.previous = function () {
let a = this.copy() ;
--a.number[a.number.length-1] ;
return a ;
} ;
/**
* Create copy of this HeadingNumber instance
* @return {HeadingNumber} New instance as a copy of existing object
*/
HeadingNumber.prototype.copy = function() {
let a = Object.create(HeadingNumber.prototype) ;
a.number = Array.from(this.number) ;
a.separator = this.separator ;
a.trailer = this.trailer ;
a.start = this.start ;
return a ;
} ;
/**
* Returns the nested level number of the heading number.
* @example 1.2.1 would have level of 3, 1.2.4.1 would have a level of 4
* @returns {number}
*/
HeadingNumber.prototype.getLevel = function() {
return this.number.length ;
} ;
/**
* Given a number, parse and split it into an array of components using separator with each representing a level of depth
* @param {number|number[]|string} number The number to parse
* @param {string} separator The separator to split a string representation of the number
* @return {number[]} Returns an array of numbers representing the individual levels of the given number
*/
function parseNumber(number,separator) {
if(typeof number === 'string') {
return number.trim().split(separator).map(n => Number.parseInt(n)) ;
}
else if(typeof number === 'number')
return [ number ] ;
else if(Array.isArray(number)) {
// Make sure all numbers
if(number.some(n => typeof n !== 'number'))
throw new Error('Array type must contain all numbers',1) ;
return number ;
}
else {
throw new Error('Invalid type for number: '+number,1) ;
}
}
module.exports = HeadingNumber ;
},{}],84:[function(require,module,exports){
const ToolStore = require('./ToolStore') ;
const iframeHtml = require('../section-edit.hbs.html') ;
const htmlToElement = require('./htmlToElement') ;
/**
* IframeAgentManager provides a http agent and DOM parser
* @constructor
*/
function IframeAgentManager() {
this.iframeStore = new ToolStore(0,() => {
let iframe = htmlToElement(iframeHtml) ; // Create DOM object for iframe from template
iframe.load = IframeAgent ;
window.document.body.appendChild(iframe); // Add the iframe to the page, but not loaded any src attribute yet
return iframe ; // Return the new tool
}, tool => tool.removeAttribute('src'),
tool => {
tool.removeAttribute('src') ;
window.document.body.removeChild(tool) ;
}) ;
}
/**
* Borrow an iframe agent from the manager
* @returns {HTMLIFrameElement}
*/
IframeAgentManager.prototype.borrow = function() {
return this.iframeStore.borrow() ;
} ;
/**
* Return a borrowed iframe agent back to manager when finished with it
* @param {HTMLIFrameElement} iframe The iframe agent previously borrowed
*/
IframeAgentManager.prototype.return = function(iframe) {
this.iframeStore.return(iframe) ;
} ;
IframeAgentManager.prototype.discardAll = function() {
this.iframeStore.discardAll() ;
} ;
/**
* Wait for load action to complete
* @param {string|function} action url or function that causes iframe document to load page (like .click() form button)
*/
async function IframeAgent(action) {
if(typeof action !== 'string' && typeof action !== 'function')
reject(`Must provide url string or function as parameter to load`) ;
return new Promise((resolve,reject) => {
var loadErrorEvent = err => {
this.removeEventListener('load',loadEvent) ;
this.removeEventListener('error',loadErrorEvent) ;
reject(err) ;
} ;
var loadEvent = () => {
this.removeEventListener('load',loadEvent) ;
this.removeEventListener('error',loadErrorEvent) ;
resolve() ;
} ;
this.addEventListener('load',loadEvent) ;
this.addEventListener('error',loadErrorEvent) ;
if (typeof action === 'string') {
this.src = action;
} else if (typeof action === 'function') {
action() ; // Cause iframe to load page (like .click() form button)
}
}) ;
}
module.exports = IframeAgentManager ;
},{"../section-edit.hbs.html":82,"./ToolStore":85,"./htmlToElement":86}],85:[function(require,module,exports){
/**
* Creates a tool store which lends instances of objects for work that are spare or creates new objects when necessary
* @param {number} maxSpare Maximum number of tools that can remain spare in the store (excess will be discarded)
* @param {function} factory A function that creates new tool instances
* @param {function} reset A function that resets the state of the tool on return
* @param {function} destroy A destructor function that is called when a tool is discarded
* @constructor
*/
function ToolStore(maxSpare,factory,reset,destroy) {
this.spare = [] ;
this.maxSpare = (typeof maxSpare === 'number') ? maxSpare : 0 ;
this.used = new Set() ;
this.create = factory ;
this.reset = reset ? reset : () => {} ;
this.destroy = destroy ? destroy : () => {} ;
}
/**
* Borrow a tool from the store, creating a new one if there isn't one spare
* @returns {object}
*/
ToolStore.prototype.borrow = function() {
if(this.spare.length) {
let a = this.spare.shift() ;
this.used.add(a) ;
return a ;
}
// Create
let a = this.create() ;
this.used.add(a) ;
return a ;
} ;
/**
* Return a tool back to the store when finished so can be used by another job
* @param {object} tool The instance that was returned by borrow method
*/
ToolStore.prototype.return = function(tool) {
// Only return it to the store if it is still in the used list (i.e. dont return if already returned)
if(this.used.has(tool)) {
if(this.maxSpare && this.spare.length >= this.maxSpare) {
this.discard(tool) ;
return ;
}
this.reset(tool);
this.used.delete(tool);
this.spare.push(tool);
}
} ;
/**
* Discard all tools in the store, whether they are in use or spare
*/
ToolStore.prototype.discardAll = function() {
this.spare.forEach(tool => this.destroy(tool)) ;
this.used.forEach(tool => this.destroy(tool)) ;
this.used.clear() ;
this.spare = [] ;
} ;
/**
* Discard the given tool so that it cannot be used by the store again
* @param tool Must be a tool that is currently borrowed
*/
ToolStore.prototype.discard = function(tool) {
this.used.delete(tool) ;
this.destroy(tool) ;
} ;
module.exports = ToolStore ;
},{}],86:[function(require,module,exports){
// https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
/**
* @param {String} html representing a single element
* @return {Element}
*/
function htmlToElement(html) {
var template = window.document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
module.exports = htmlToElement ;
},{}],87:[function(require,module,exports){
(function (process){
const r = require('rummage') ;
const fs = require('fs') ;
const HeadingNumber = require('./HeadingNumber') ;
const rename_activity = require('./rename_activity') ;
const superagent = require('superagent') ;
const htmlToElement = require('./htmlToElement') ;
const Diff = require('text-diff') ;
const Handlebars = require('handlebars') ;
const panelHtml = require('../panel.hbs') ;
const Queue = require('better-queue') ;
const MemoryStore = require('better-queue-memory') ;
const IframeAgentManager = require('./IframeAgentManager') ;
const css = require('../diff.css') ;
var diff = new Diff() ;
(async () => {
try {
// Dont run inside iframes
if(window.self !== window.top)
return ;
// Check if in editing mode
let edit = r.Rummage()
.through(window.document)
.for(
r.Pipe(
r.SelectorAll('div.dropdown-item > a'), // Locate all menu items
r.Filter( // Filter looking for textContent 'Turn editing off'
r.Pipe(r.Prop('textContent'), r.Trim(), r.Match(/Turn editing off/))
)
)
)
.collect() ;
// If 'Turn editing off' edit menu item not found, then not in edit mode so don't run
if(edit.length === 0)
return ;
// Test if editing a section (not the whole unit)
let params = (new URL(document.location)).searchParams ;
if(params.has('sectionid'))
return ;
console.log('Running - inserting CSS');
const panelTemplate = Handlebars.compile(panelHtml) ;
addGlobalStyle(css) ;
var heading = r.Object() ;
heading.for({
name: r.Pipe(r.Selector('div.mo-fullname'), r.Prop('textContent')),
edit: r.Pipe(r.Selector('div.controls a.settings'),r.ParseUrl()),
div: r.Selector('div.mo-fullname'),
type: 'section',
items: r.Array([
// :scope means start relative to 'Element' with Element.querySelector(':scope ...')
r.Selector(':scope > div.content > ul.section, :scope > div.content > div.section-modules-list ul.section'),
r.SelectorAll('li.activity'),
r.Filter(r.Selector('div.activityinstance > span.inplaceeditable:first-child > a:first-child:not(.dimmed)'))
],r.Object({
// If necessary, can pull from the data-value attribute of the parent span - but pulling from UI assures we are capturing what user sees
// name: r.Pipe(r.Selector('div.activityinstance > span:first-child').setDebug(true), r.Attr('data-value').setDebug(true)),
// https://stackoverflow.com/a/49168777 (.firstChild.nodeValue) = Gets first textnode and ignores rest
name: r.Pipe(r.Selector('span.instancename'), r.Prop('firstChild'), r.Prop('nodeValue')),
span: r.Selector('span.instancename'),
div: r.Selector('div.activityinstance'),
textnode: r.Pipe(r.Selector('span.instancename'), r.Prop('firstChild')),
itemid: r.Pipe(r.Selector('span[data-itemtype="activityname"]'), r.Attr('data-itemid')),
type: 'item'
})),
sections: r.Array([r.SelectorAll(':scope > div.content > ul.format-unbox > li.section'),r.Filter(r.Selector('div.controls a.hide'))], heading)
}) ;
// div.section-modules-list ul.section-modules li.activity span.instancename
let data = r.Rummage()
.through(window.document)
.for(
r.Array(
r.SelectorAll('ul.unbox-level-1 > li.section'), heading
)
)
.collect();
// console.log('data=\n%o', data);
// Code to get the session key (need to refactor)
let sesskey = r.Rummage().through(window.document).for(r.Selector("a[data-title='logout,moodle']")).collect() ;
sesskey = sesskey.href ;
sesskey = new URL(sesskey) ;
sesskey = sesskey.searchParams.get('sesskey') ;
// console.log(`sesskey=${sesskey}`) ;
// Code to rename the activity
// let response = await rename_activity(sesskey,727,'What Will You Study?2') ;
// console.log('response=%o',response) ;
// let example = [
// {
// "diff": {
// "id": "diff-sectionid-480",
// "text": "<span class=\"diff\"><span>1.</span><del>9</del><ins>2</ins><span> Strategic Marketing</span></span>"
// },
// "rename": {
// "node": {
// "name": "1.9 Strategic Marketing",
// "edit": "https://u-bedifferent.catalyst-au.net/course/editsection.php?id=480&sr",
// "div": {},
// "type": "section",
// "items": [
// {
// "name": "1.2.1 Introduction",
// "span": {},
// "textnode": {},
// "itemid": "2792",
// "type": "item"
// }
// ],
// "sections": []
// },
// "id": "diff-sectionid-480",
// "heading": "1.2 Strategic Marketing"
// }
// },
// {
// "diff": {
// "id": "diff-itemid-11580",
// "text": "<span class=\"diff\"><ins>1.2.9 </ins><span>Strategic Marketing</span></span>"
// },
// "rename": {
// "id": "diff-itemid-11580",
// "node": {
// "name": "Strategic Marketing",
// "span": {},
// "textnode": {},
// "itemid": "11580",
// "type": "item"
// },
// "heading": "1.2.9 Strategic Marketing"
// }
// }
// ] ;
let list = [] ;
data.forEach(h => {
// console.log(`Working on heading: ${h.name}`);
let moduleNumber = /^module\s+(\d+)/i.exec(h.name) ;
// console.log(`length of moduleNumber=${moduleNumber.length}`);
// console.log('moduleNumber=%o',moduleNumber) ;
if(moduleNumber && moduleNumber.length > 1) moduleNumber = moduleNumber[1] ;
else return ;
// console.log(`Working on Module: ${h.name} with number ${moduleNumber}`);
let headingNumber = new HeadingNumber(moduleNumber,'.',' ') ;
process(h,headingNumber,list) ;
}) ;
let output = panelTemplate({activity: list.map(r => r.diff)}) ;
// console.log(output) ;
// console.log('%o', list);
window.document.querySelector('ul.format-unbox.unbox-level-1').insertAdjacentHTML('afterbegin',output) ;
const ifm = new IframeAgentManager() ;
const q = new Queue(async function worker(data, cb) {
// Display spinner
window.document.querySelector(`i#spinner-${data.id}`).classList.remove('diff-hidden');
// Disable the checkbox and set it unchecked (so can't rename again
window.document.getElementById(`select-${data.id}`).disabled = true ;
window.document.getElementById(`select-${data.id}`).checked = false ;
try {
if (data.node.type === 'section') {
// console.log(`Worker editing section: ${data.heading}`) ;
var iframe = ifm.borrow();
// console.log(`borrowed an iframe`);
await iframe.load(data.node.edit.toString());
// console.log(`loaded url from: ${data.node.edit}`);
iframe.contentWindow.document.querySelector('#id_name_value').value = data.heading;
// console.log(`set the value`);
await iframe.load(() => iframe.contentWindow.document.querySelector('#id_submitbutton').click());
// console.log('clicked submit');
ifm.return(iframe);
// console.log('returned iframe');
} else { // type === 'item'
// console.log(`Renaming activity id:'${data.node.itemid}': heading:'${data.heading}'`) ;
let response = await rename_activity(sesskey, data.node.itemid, data.heading);
// console.log(`Rename finished: response=%o`,response) ;
if(response.status !== 200 || response.body[0].error === true) {
console.error(`Rename failed: response=%o`,response) ;
throw new Error(`Error renaming itemid=${data.node.itemid} to ${data.heading}`) ;
}
}
// Display tick
window.document.querySelector(`i#tick-${data.id}`).classList.remove('diff-hidden');
} catch (e) {
window.document.querySelector(`i#cross-${data.id}`).classList.remove('diff-hidden');
console.error('Error: ' + e);
console.error('On line: ' + e.lineNumber);
console.error('Stack: ' + e.stack);
} finally {
// Hide spinner
window.document.querySelector(`i#spinner-${data.id}`).classList.add('diff-hidden');
ifm.return(iframe) ;
}
cb();
}, {store: new MemoryStore(), concurrent: 3}) ; // Explicit assignment of memory store necessary for browserify
q.on('drain',() => {
window.document.querySelector('#diff_heading_busy').classList.add('diff-hidden');
ifm.discardAll() ;
}) ;
q.on('task_accepted',() => {
window.document.querySelector('#diff_heading_busy').classList.remove('diff-hidden');
}) ;
if(list.length) { // Then we have incorrect headings, so fix them if user clicks play button
window.document.querySelector('#diff_heading_rename').onclick = () => {
// Only if at least some checkboxes are selected should we ask to rename
if(Array.from(window.document.querySelectorAll('input.diff-select[type=checkbox]')).some(t => t.checked)) {
confirm('Click OK to Rename all incorrectly numbered headings') && list.filter(
l => window.document.getElementById(`select-${l.rename.id}`).checked
)
.forEach(l => q.push(l.rename));
}
else
alert('Select headings to rename first');
}
}
else { // All heads are okay, so hide the icon control panel entirely
window.document.querySelector('#diff-section div.controls').classList.add('diff-hidden') ;
}
} catch (e) {
console.error('Error: ' + e) ;
console.error('On line: ' + e.lineNumber) ;
console.error('Stack: ' + e.stack) ;
}
})() ;
/**
* Product a HTML diff of the existing heading with what the heading should be
* @param {string} name The existing heading of the form '1.2.3 Heading Text'
* @param {HeadingNumber} heading The number the heading should be of the form '1.2.4 '
* @returns {string|null} Returns a HTML formatted string showing a diff between what is and what it should be or null if heading is correct
*/
function diffHeadingString(name,heading) {
// console.log(`'${name}' Untouched`);
let n = stripHeadingNumber(name) ;
n = `${heading}${n}`;
let d = diff.main(name, n);
// console.log(`'${name}' ==> '${n}'`);
if(name === n)
return null ;
// 1.2 no indent
// 1.2.1 indent once
// 1.2.1.4 indent twice
// ...
let indent = (heading.getLevel()-2)*15 ;
return `<span title="Click to view heading within its section" style="padding-left: ${indent}px;" class="diff">${diff.prettyHtml(d)}</span>` ;
}
/**
* Return the heading without the prefixed numbers
* @param {string} heading Original heading string of form '1.2.3 Heading Text'
* @returns {string} Returns string of form 'Heading Text'
*/
function stripHeadingNumber(heading) {
return heading.replace(/^\s*[0-9\.]+\s+/, '');
}
/**
* Calculate what the correct heading should be given the existing heading name and the correct number
* @param {string} name The existing heading name of form '1.2.3 Heading Text'
* @param {HeadingNumber} heading
* @returns {string}
*/
function calculateHeadingText(name,heading) {
let n = stripHeadingNumber(name) ;
return `${heading}${n}` ;
}
/**
* Traverse recursive structure, collect list of incorrect names and update UI
* @param {Object} node
* @param {HeadingNumber} heading
* @param {Object[]} list generated list of corrections necessary
*/
function process(node,heading,list) {
// Process section heading first
if(!/^module\s+\d+/i.test(node.name)) { // Skip module headings
let html = diffHeadingString(node.name,heading) ;
if(html !== null) {
let sectionid = node.edit.searchParams ;
sectionid = sectionid.get('id') ;
let id = `diff-sectionid-${sectionid}` ;
let element = htmlToElement(html) ;
element.id = id ;
list.push({
diff: {
id,
text: html
},
rename: {
node,
id,
heading: calculateHeadingText(node.name,heading)
}
}) ;
node.div.innerHTML = '';
node.div.appendChild(element) ;
}
}
// Now process section items
heading = heading.down() ;
let observer = new MutationObserver(mutationList => {
// console.log('%o', mutationList);
mutationList.forEach(m => {
/** @type {HTMLElement} */
let target = m.target;
if (m.addedNodes.length) {
let id = target.getAttribute('diff-itemid');
/** @type {HTMLLIElement} */
// console.log(`Searching for input#select-diff-${id}`);
let e = r.Rummage().through(window.document).for(r.Pipe(r.Selector(`input#select-diff-itemid-${id}`), r.Parent('li'))).collect();
if (e) e.remove();
}
});
}) ;
node.items.forEach(i => {
heading = heading.next() ;
let html = diffHeadingString(i.name,heading) ;
if(html === null)
return ;
let correctHeading = calculateHeadingText(i.name, heading);
let id = `diff-itemid-${i.itemid}` ;
// Set attributes on the div that surrounds each activity instance because we watch for changes inside
i.div.setAttribute('diff-data-value', correctHeading);
i.div.setAttribute('diff-itemid', i.itemid);
// Observe whenever there is a change inside this div so we can remove from our changelist if its been changed manually
observer.observe(i.div,{childList:true,attributes:false,subtree:false}) ;
let element = htmlToElement(html) ;
element.id = id ;
list.push({
diff: {
id,
text: html
},
rename: {
id,
node: i,
heading: calculateHeadingText(i.name,heading)
}
}) ;
i.span.replaceChild(element,i.textnode) ;
});
// Finally, process subsections
node.sections.forEach(s => {
// console.log(`Working on section: ${s.name}`);
heading = heading.next() ;
process(s, heading, list);
}) ;
}
// http://greasemonkey.win-start.de/patterns/add-css.html
/**
* Add css source to page
* @param {string} css
*/
function addGlobalStyle(css) {
var head, style;
head = window.document.getElementsByTagName('head')[0];
if (!head) { return; }
style = window.document.createElement('style');
// style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
}
// CSS to add:
// Editing section heading text in form:
// window.document.querySelector('input#id_name_value').value = 'Before You Begin: Start Here4';
// window.document.querySelector('input#id_submitbutton').click() ;
}).call(this,require('_process'))
},{"../diff.css":1,"../panel.hbs":81,"./HeadingNumber":83,"./IframeAgentManager":84,"./htmlToElement":86,"./rename_activity":88,"_process":65,"better-queue":8,"better-queue-memory":7,"fs":12,"handlebars":49,"rummage":89,"superagent":67,"text-diff":72}],88:[function(require,module,exports){
const superagent = require('superagent') ;
// templates
/**
* Rename activityname for given itemid
* @param {string} sesskey Session Key value for the request
* @param {number} itemid The unique id number for the item being renamed
* @param {string} name The new name for the item
* @return {Object}
*/
async function rename(sesskey,itemid,name) {
let request_data = [{
"index": 0,
"methodname": "core_update_inplace_editable",
"args": {"itemid": itemid, "component": "core_course", "itemtype": "activityname", "value": name}
}];
let query_data = {sesskey, info: 'core_update_inplace_editable'} ;
// Working but commented out - it will rename an item
return superagent.post('/lib/ajax/service.php')
.set('Content-Type','application/json')
.query(query_data)
.send(request_data) ;
}
module.exports = rename ;
},{"superagent":67}],89:[function(require,module,exports){
var Rummager = require('./lib/Rummager') ;
var RummageMap = require('./lib/RummageMap') ;
var RummageError = require('./lib/RummageError') ;
var FilterRummager = require('./lib/FilterRummager') ;
var MatchRummager = require('./lib/MatchRummager') ;
var FirstOfRummager = require('./lib/FirstOfRummager') ;
var ArrayRummager = require('./lib/ArrayRummager') ;
var ObjectRummager = require('./lib/ObjectRummager') ;
var SelectorAllRummager = require('./lib/SelectorAllRummager') ;
var SelectorRummager = require('./lib/SelectorRummager') ;
var PropRummager = require('./lib/PropRummager') ;
var IndexRummager = require('./lib/IndexRummager') ;
var AttrRummager = require('./lib/AttrRummager') ;
var ReplaceRummager = require('./lib/ReplaceRummager') ;
var TrimRummager = require('./lib/TrimRummager') ;
var FuncRummager = require('./lib/FuncRummager') ;
var PipeRummager = require('./lib/PipeRummager') ;
var DateRummager = require('./lib/DateRummager') ;
var ParseFloatRummager = require('./lib/ParseFloatRummager') ;
var ParentRummager = require('./lib/ParentRummager') ;
var ParseIntRummager = require('./lib/ParseIntRummager') ;
var ParseUrlRummager = require('./lib/ParseUrlRummager') ;
var Rummage = require('./lib/Rummage') ;
var ParserDOMParser = require('./lib/parsers/DOMParserAdapter') ;
var ParserJSDom = require('./lib/parsers/JSDomAdapter') ;
var ParserCheerio = require('./lib/parsers/CheerioAdapter') ;
var AgentAxios = require('./lib/agents/AxiosAdapter') ;
var AgentSuperagent = require('./lib/agents/SuperagentAdapter') ;
var AgentXhr = require('./lib/agents/XHRAdapter') ;
var defaultAgent = null ;
var defaultParser = null ;
/**
* Helper function that will instantiate arbitrary objects, and allow passing of arbitrary constructor parameters
*
* @param {Function} object The object constructor function to instantiate
*
* @param {Array} args An array of arbitrary number of arguments to pass to constructor
*
* @returns {Object} An instance of object
*/
function create(object, args)
{
var o = Object.create(object.prototype) ;
object.apply(o,args) ;
return o ;
} ;
/**
* Rummage Module
* @module Rummage
*/
var r =
{
/**
* Rummage .through(a DOM) searching .for(data)
*
* @param {RummageParserAdapter} [parser] A parser to use to parse HTML string
* @param {RummageAgentAdapter} [agent] An agent to use to download HTML source
*
* @returns {Rummage} An instance of Rummage
*/
"Rummage": function(parser,agent)
{
if(parser === undefined)
parser = defaultParser ;
if(agent === undefined)
agent = defaultAgent ;
return create(Rummage,[parser,agent]) ;
},
"RummageMap": function()
{
var rm = create(RummageMap,arguments) ;
rm.r = r ;
return rm ;
},
/**
* RummageAgentAdapter constructors
*/
"agent":
{
/**
* Axios RummageAgentAdapter Constructor
*/
"axios": AgentAxios,
/**
* Superagent RummageAgentAdapter Constructor
*/
"superagent": AgentSuperagent,
/**
* xmlHttpRequest RummageAgentAdapter Constructor
*/
"xhr": AgentXhr
},
/**
* RummageParserAdapter constructors
*/
"parser":
{
/**
* jsdom RummageParserAdapter Constructor
*/
"jsdom": ParserJSDom,
/**
* DOMParser RummageParserAdapter Constructor
*/
"DOMParser": ParserDOMParser,
/**
* Cheerio RummageParserAdapter Constructor
*/
"Cheerio": ParserCheerio
},
/**
* Specify default useragent for all Rummage activities
*
* Can be overidden for specific Rummage by calling Rummage.usingAgent()
* @function
* @param {RummageAgentAdapter} agent The default agent to use or null to specify no default
*/
"useAgent": function(agent)
{
if(agent === undefined)
agent = null ;
defaultAgent = agent ;
},
/**
* Specify default parser for all Rummage activities
*
* Can be overidden for specific Rummage by calling Rummage.usingParser()
*
* @param {RummageParserAdapter} parser The default parser to use or null to specify no default
*/
"useParser": function(parser)
{
if(parser === undefined)
parser = null ;
defaultParser = parser ;
},
/**
* Register given object with name as a Rummager
*
* @param {String} name Name of property to access Rummager
* @param {Rummager} object A subclass of Rummager to register
*
* @returns {Rummage} Fluent interface, returns copy of itself
*/
"register": function(name,object)
{
Rummage.prototype[name] = function()
{
return create(object,arguments) ;
}
return this ;
},
/**
* Unregister given rummager by name from Rummage
*
* @param {String} Rummage The name of the Rummager to unregister
*
* @returns {Rummage} Fluent interface, returns copy of itself
*/
"unregister": function(name)
{
delete Rummage.prototype[name] ;
return this ;
},
/**
* Class for finding arrays of values within a page
*
* @param {Rummager} findList Rummager object/s that return a NodeList or Array of Node objects on which this ArrayRummager operates
* @param {Rummager} extractList Rummager object/s that extract value/s from each Node in findList. Typically an ObjectRummager to extract a record of values from each array element
*
* @returns {ArrayRummager} An instance of ArrayRummager
*/
"Array": function(findList,extractList) { return create(ArrayRummager,arguments) },
/**
* Class for finding values within a page and returning them into a given object structure
*
* @param {Object} extractList An object with keys as variable names and values as 'Rummager' objects to locate and assign values to the variables
*
* @returns {ObjectRummager} An instance of ObjectRummager
*/
"Object": function(extractList) { return create(ObjectRummager,arguments) },
/**
* Rummager object for selecting all matching Nodes/Elements from a DOM based on CSS
*
* @param {String} selector css selector string for selecting the node
*
* @returns {SelectorAllRummager} An Instance
*/
"SelectorAll": function(selector) { return create(SelectorAllRummager,arguments) },
/**
* Rummager object for returning the first option to be found in the DOM or null
*
* @param {...Rummager[]} rummagers Rummagers to test in order until a value found
*
* @returns {FirstOfRummager} An Instance
*/
"FirstOf": function(rummagers) { return create(FirstOfRummager,arguments) },
/**
* Rummager object for selecting a specific Node/Element from a DOM based on CSS
*
* @param {String} selector css selector string for selecting the node
*
* @returns {SelectorRummager} An instance
*/
"Selector": function(selector) { return create(SelectorRummager,arguments) },
/**
* Rummager object for return a property of an element, by specifying the property name
*
* @param {String} propertyName Name of the element property to return
*
* @returns {PropRummager} An instance of PropRummager
*/
"Prop": function(propertyName) { return create(PropRummager,arguments) },
/**
* Rummager object for indexing Array of Objects by given property name
*
* @param {String} propertyName Name of the object property to use to index the data
*
* @returns {IndexRummager} An instance of IndexRummager
*/
"Index": function(propertyName) { return create(IndexRummager,arguments) },
/**
* Rummager object for return an attribute of an element, by specifying the attribute name
*
* @param {String} attributeName Name of the element attribute to return
*
* @returns {AttrRummager} An instance of AttrRummager
*/
"Attr": function(attributeName) { return create(AttrRummager,arguments) },
/**
* Rummager object for extracting a value from a string using an regular expression
*
* @param {RegExp} re RE object to parse the string we are rummaging .through()
*
* @param {String} replacement String representing the replacement for re including placeholders
*
* @returns {ReplaceRummager} An instance of ReplaceRummager
*/
"Replace": function(re,replacement) { return create(ReplaceRummager,arguments) },
/**
* Rummager object for trimming whitespace from string
*
* @returns {TrimRummager} An instance of TrimRummager
*/
"Trim": function(re,replacement) { return create(TrimRummager,arguments) },
/**
* Rummager object for executing arbitrary code via func function
*
* @param {Function} func Function to execute passing in as a single parameter, what to rummage .through()
*
* @returns {FuncRummager} An instance of FuncRummager
*/
"Func": function(func) { return create(FuncRummager,arguments) },
/**
* PipeRummager object passes output from first argument as input to the next
* and so on, much like the UNIX pipe concept.
*
* @param {Array} arr Array of Rummagers where first Rummager outputs to the next and so on until the last Rummager returns the result to PipeRummager
*
* @returns {PipeRummager} An instance of PipeRummager
*/
"Pipe": function(arr) { return create(PipeRummager,arguments) },
/**
* Rummager object for parsing a date as a string (as per Date object constructor) and returning a Date object
*
* @returns {DateRummager} The Date object representing the time passed to search .through() or null if date string is invalid
*/
"Date": function() { return create(DateRummager,arguments) },
/**
* Rummager object for parsing an float value from a string (as per parseFloat function) and returning an Float primitive
*
* @returns {ParseFloatRummager} An instance of ParseFloatRummager
*/
"ParseFloat": function() { return create(ParseFloatRummager,arguments) },
/**
* Rummager object for parsing an integer value from a string (as per parseInt function) and returning an Integer primitive
*
* @param {Integer} radix The radix, if not provided defaults to base-10 numbers
*
* @returns {ParseIntRummager} An instance of ParseIntRummager
*/
"ParseInt": function(radix) { return create(ParseIntRummager,arguments) },
/**
* Rummager object for locating closest ancestor of current element by css selector
*
* @param {String} selector css Selector to match closest ancestor relative to current element
* @link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
*
* @returns {ParentRummager} An instance
*/
"Parent": function(selector) { return create(ParentRummager,arguments) },
/**
* Rummager object for testing a string value using a regular expression
*
* @param {RegExp} re Regular expression to match against
*
* @returns {MatchRummager} An instance of MatchRummager
*/
"Match": function(re) { return create(MatchRummager,arguments) },
/**
* Class for filtering an array, based on given criteria for each element
*
* @param {Rummager} criteria Rummager that ultimately returns true or false based on comparison with relative
*
* @returns {FilterRummager} An instance of FilterRummager
*/
"Filter": function(criteria) { return create(FilterRummager,arguments) },
/**
* Class for parsing URLs from strings or relevant HTMLElement objects
*
* @returns {URL} AN instance of URL or polyfill for node.js
* @link https://developer.mozilla.org/en-US/docs/Web/API/URL
*/
"ParseUrl": function() { return create(ParseUrlRummager,arguments) },
/**
* Constructor functions for all Rummagers, useful for creating your own sub-classes
*/
"constructors":
{
"Array": ArrayRummager,
"Object": ObjectRummager,
"SelectorAll": SelectorAllRummager,
"Selector": SelectorRummager,
"Prop": PropRummager,
"Index": IndexRummager,
"Attr": AttrRummager,
"Replace": ReplaceRummager,
"Func": FuncRummager,
"Pipe": PipeRummager,
"Date": DateRummager,
"ParseFloat": ParseFloatRummager,
"ParseInt": ParseIntRummager,
"Parent": ParentRummager,
"RummageMap": RummageMap,
"Rummage": Rummage,
"Match": MatchRummager,
"Trim": TrimRummager,
"Filter": FilterRummager,
"ParseUrl": ParseUrlRummager,
"Rummager": Rummager
},
/**
* Prototype properties for all Rummagers, useful for creating your own sub-classes
*/
"prototypes":
{
"Array": ArrayRummager.prototype,
"Object": ObjectRummager.prototype,
"SelectorAll": SelectorAllRummager.prototype,
"Selector": SelectorRummager.prototype,
"Prop": PropRummager.prototype,
"Index": IndexRummager.prototype,
"Attr": AttrRummager.prototype,
"Replace": ReplaceRummager.prototype,
"Func": FuncRummager.prototype,
"Pipe": PipeRummager.prototype,
"Date": DateRummager.prototype,
"ParseFloat": ParseFloatRummager.prototype,
"ParseInt": ParseIntRummager.prototype,
"Parent": ParentRummager.prototype,
"RummageMap": RummageMap.prototype,
"Rummage": Rummage.prototype,
"Match": MatchRummager.prototype,
"Trim": TrimRummager.prototype,
"Filter": FilterRummager.prototype,
"ParseUrl": ParseUrlRummager.prototype,
"Rummager": Rummager.prototype
}
} ;
module.exports = r ;
},{"./lib/ArrayRummager":92,"./lib/AttrRummager":93,"./lib/DateRummager":94,"./lib/FilterRummager":95,"./lib/FirstOfRummager":96,"./lib/FuncRummager":97,"./lib/IndexRummager":98,"./lib/MatchRummager":99,"./lib/ObjectRummager":100,"./lib/ParentRummager":101,"./lib/ParseFloatRummager":102,"./lib/ParseIntRummager":103,"./lib/ParseUrlRummager":104,"./lib/PipeRummager":105,"./lib/PropRummager":106,"./lib/ReplaceRummager":107,"./lib/Rummage":108,"./lib/RummageError":109,"./lib/RummageMap":110,"./lib/Rummager":111,"./lib/SelectorAllRummager":112,"./lib/SelectorRummager":113,"./lib/TrimRummager":114,"./lib/agents/AxiosAdapter":115,"./lib/agents/SuperagentAdapter":117,"./lib/agents/XHRAdapter":118,"./lib/parsers/CheerioAdapter":119,"./lib/parsers/DOMParserAdapter":120,"./lib/parsers/JSDomAdapter":121}],90:[function(require,module,exports){
/**
* Argument.js
*
* A RummageMap Argument
*
* rummage
*
* 19/11/17
*
* Copyright (C) 2017 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var prop = require('pope').prop ;
function Argument(path,args)
{
if(path !== undefined)
this.path = path ;
if(args !== undefined)
this.args = args ;
}
Argument.prototype.toString = function()
{
return this.path ;
} ;
Argument.prototype.resolve = function(data)
{
if(data === undefined)
data = this.args ;
return prop(data,this.path) ;
} ;
/**
* Default path argument is first argument provided to RummageMap
* @type {string}
*/
Argument.prototype.path = '0' ;
module.exports = Argument ;
},{"pope":141}],91:[function(require,module,exports){
/**
* ArgumentTemplate.js
*
* A RummageMap ArgumentTemplate
*
* rummage
*
* 19/11/17
*
* Copyright (C) 2017 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var pope = require('pope').pope ;
var Argument = require('./Argument') ;
function ArgumentTemplate(template,args)
{
if(template !== undefined)
this.template = template ;
if(args !== undefined)
this.args = args ;
}
ArgumentTemplate.prototype = Object.create(Argument.prototype) ;
ArgumentTemplate.prototype.toString = function()
{
return this.template ;
} ;
ArgumentTemplate.prototype.resolve = function(data)
{
if(data === undefined)
data = this.args ;
return pope(this.template,data) ;
} ;
/**
* Default template argument is first argument provided to RummageMap
* @type {string}
*/
ArgumentTemplate.prototype.template = '{{0}}' ;
module.exports = ArgumentTemplate ;
},{"./Argument":90,"pope":141}],92:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var ObjectRummager = require('./ObjectRummager') ;
var PipeRummager = require('./PipeRummager') ;
var RummageError = require('./RummageError') ;
/**
* Class for finding arrays of values within a page
*
* @param {Rummager} findList Rummager object/s that return a NodeList or Array of Node objects on which this ArrayRummager operates
* @param {Rummager} extractList Rummager object/s that extract value/s from each Node in findList. Typically an ObjectRummager to extract a record of values from each array element
*
* @returns {ArrayRummager} An instance of ArrayRummager
*/
function ArrayRummager(findList,extractList)
{
//Call super constructor and pass values
Rummager.call(this,findList,extractList) ;
this.run.found = [] ;
}
//A subclass of Rummager
ArrayRummager.prototype = Object.create(Rummager.prototype) ;
/**
* The retrieve method is part of the API and will initiate a complete parsing of the
* data structure and ultimately return the data found, based on extractList
* and starting element provided to the instance
*
* @returns {Object} The data found with the property names matches those in extractList
*/
ArrayRummager.prototype.retrieve = function()
{
var extractList = this.rummageFor[1] ;
//Locate and retrieve the Array elements required for this ArrayRummager
var found = this.find() ;
if (found === null)
found = [ ] ;
found = Array.from(found) ;
//If we arent given an extraction List of properties to collect, then
//just return the list of elements that we found
if (extractList === null || extractList === undefined)
return found ;
//Otherwise, extract the value/s required for each array element in found
var extractList = this.rummageFor[1] ;
//found is the root to start from
var data = [ ] ;
//Iterate over the list of found elements from findList
for(var f=0;f<found.length;f++)
{
data[f] = extractList
.through(found[f])
.collect() ;
if(data[f] === undefined)
{
data[f] = null ;
}
}
return data ;
} ;
/**
* Generate an array of Elements on which to base the extraction of value/s
*
*/
ArrayRummager.prototype.find = function()
{
//Assign our findList
if (this.rummageFor[0] === undefined || this.rummageFor[0] === null)
throw new RummageError("You must call the .for() method or pass what to search for to the constructor") ;
var findList = this.rummageFor[0] ;
//If rummageFor contains an array, pass it to PipeRummager to process
//array with a single Rummager object
if (Array.isArray(findList))
findList = new PipeRummager(findList) ;
//Go find the Array of Nodes to work on
var data = findList
.through(this.rummageThrough)
.collect() ;
return data ;
} ;
/**
* Initialise to null
*/
ArrayRummager.prototype.findList = null ;
/**
* Initialise to null
*/
ArrayRummager.prototype.extractList = null ;
ArrayRummager.prototype.name = 'ArrayRummager' ;
module.exports = ArrayRummager ;
},{"./ObjectRummager":100,"./PipeRummager":105,"./RummageError":109,"./Rummager":111}],93:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for return an attribute of an element, by specifying the attribute name
*
* @param {String} attributeName Name of the element attribute to return
*
* @returns {AttrRummager} An instance of AttrRummager
*/
function AttrRummager(attributeName)
{
//Call super constructor and pass value
Rummager.call(this,attributeName) ;
}
//A subclass of Rummager
AttrRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the property on the element provided.
*
* @returns {String} Returns the string value of the property or null
*/
AttrRummager.prototype.retrieve = function()
{
if (this.rummageThrough === undefined) {
var error = "AttrRummager: no element defined to locate attributeName: "+this.rummageFor ;
if(this.debug) console.log(error) ;
throw error ;
}
else if (this.rummageFor === undefined) {
var error = "AttrRummager: no attributeName defined for element: "+JSON.stringify(this.rummageThrough) ;
if(this.debug) console.log(error) ;
throw error ;
}
return this.rummageThrough.getAttribute(this.rummageFor) ;
}
AttrRummager.prototype.name = 'AttrRummager' ;
module.exports = AttrRummager
},{"./Rummager":111}],94:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var moment = require('moment') ;
/**
* Rummager object for parsing a date as a string (as per momentjs library) and returning a Moment object or string
*
* @returns {DateRummager} The Date object representing the time passed to search .through() or null if date string is invalid
*/
function DateRummager()
{
// Call super constructor and pass values
Rummager.apply(this,arguments) ;
// Set default for format to undefined
this.options = {format: undefined, clean: false} ;
}
//A subclass of Rummager
DateRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Specify string format output if .asString(true) is called
* @param {string} format Format for date as string
*
* @see {@link http://momentjs.com/docs/#/displaying/format/|momentjs}
* @return {DateRummager}
*/
DateRummager.prototype.format = function(format)
{
this.options.format = format ;
return this ;
}
DateRummager.prototype.setClean = function(clean)
{
this.options.clean = clean ;
return this ;
} ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using momentjs module to parse the string provided.
*
* @returns {string} Returns the Date object representing the time passed to search .through() or null if date string is invalid
*/
DateRummager.prototype.retrieve = function()
{
if(this.options.clean)
return this.cleanInput() ;
// moment(rummageThrough,[parameters passed to r.Date, ...])
var a = [this.rummageThrough].concat(this.rummageFor) ;
var date = moment.apply(null,a) ;
// 'Invalid date' is output from format() method
// return null if the date is not valid
if(date.isValid())
return (this.options.format === undefined) ? moment(date) : date.format(this.options.format) ;
return null ;
}
DateRummager.prototype.cleanInput = function()
{
var self = this ;
// moment(rummageThrough,[parameters passed to r.Date, ...])
var value = null ;
var rummageFor = this.rummageFor ;
var patterns = null ;
//No arguments
//Single argument
//Array
//Multiple arguments
//Multiple arguments and first argument is an array
// No arguments provided for moment
if(rummageFor === null)
{
// Implement straight default moment without format parameter
var date = moment(this.rummageThrough.toString()) ;
if(date.isValid())
value = (this.options.format === undefined) ? moment(date) : date.format(this.options.format) ;
return value;
}
// More than one argument provided
if(Array.isArray(rummageFor))
{
// Make a copy
rummageFor = Array.from(this.rummageFor) ;
// Get the argument for matching date patterns
patterns = rummageFor.shift() ;
// If it is a single pattern (not an array), make into an array
if(!Array.isArray(patterns))
patterns = [].concat(patterns) ;
}
else // Its just a single pattern, so make into an array
patterns = [].concat(this.rummageFor) ;
// Try each pattern until one matches
patterns.some(function(format) {
// Get copy of the format parameter
var restr = format.toString() ;
// Translate the format from moment to RegExp that matches similarly
replacements.forEach(function(tokens) {
restr = restr.replace.apply(restr,tokens) ;
}) ;
// Create the RE
var re = new RegExp(restr,'i') ;
// And apply the RE against the input
var m = self.rummageThrough.toString().match(re) ;
// If a match is found
if(Array.isArray(m))
{
// Throw away first value in returned array
m = m.shift() ;
// Build arguments list for the moment function
// (m=matched input, format=original moment format, plus any remaining arguments)
var opts = [m, format].concat( (Array.isArray(rummageFor)) ? rummageFor : [] ) ;
// Call moment with the
var date = moment.apply(null,opts) ;
// 'Invalid date' is output from format() method
// return null if the date is not valid
if(date.isValid())
{
// Set return value for cleanInput call
value = (self.options.format === undefined) ? moment(date) : date.format(self.options.format) ;
// Return true so 'some' will stop
return true ;
}
}
}) ;
return value ;
} ;
DateRummager.prototype.name = 'DateRummager' ;
module.exports = DateRummager ;
// Replace momentjs date matching tokens with generic regular expression matching, so that dates can be searched
// for in the input provided to this rummager
// Regex matches in specific order such that subsequent false matches don't occur on newly injected RE syntax
var replacements = [
// Dates
[/YYYY/,'\\d{2}(?:\\d{2})?'], // Can match 2 or 4 digit years with YYYY
[/YY/,'\\d{2}'],
[/Y/,'\\d+'],
[/DDDD/,'\\d{3}'],
[/DDD/,'\\d{1,3}'],
[/DD/,'\\d{2}'],
[/X/,'\\d{9,}'],
[/x/,'\\d{9,}\\.\\d{3}'],
// Weeks
[/gggg/,'\\d{4}'],
[/gg/,'\\d{2}'],
[/ww/,'\\d{2}'],
[/w/,'\\d\\d?'],
[/e/,'[0-6]'],
[/E/,'[1-7]'],
[/GGGG/,'\\d{4}'],
[/GG/,'\\d{2}'],
[/WW/,'\\d{2}'],
[/W/,'\\d\\d?'],
// Hours, minute, second, millisecond, and offset tokens
[/HH/,'\\d{2}'],
[/H/,'\\d\\d?'],
[/hh/,'\\d{2}'],
[/h/,'\\d\\d?'],
[/kk/,'\\d{2}'],
[/k/,'\\d\\d?'],
[/mm/,'\\d{2}'],
[/m/,'\\d\\d?'],
[/ss/,'\\d{2}'],
[/s/,'\\d\\d?'],
[/S{1,3}/,'\\d{1,3}'],
[/ZZ/,'[+-]\\d\\d?:?\\d\\d']
// Hours, minute, second, millisecond, and offset tokens
[/[aA]/,'(?:am?|pm?)'],
// Weeks
[/dddd/,'(?:sunday|monday|tuesday|wednesday|thursday|friday|saturday)'],
[/ddd/,'(?:sun|mon|tue|wed|thu|fri|sat)'],
// Dates
[/Qo/,'\\d(?:st|nd|rd|th)'], // TODO check
[/Q/,'[1-4]'],
[/MMMM/,'[:alpha:]+'],
[/MMM/, '(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'],
[/MM/,'\\d{2}'],
[/Mo/,'\\d\\d?(?:st|nd|rd|th)'], // TODO check
[/M/,'\\d\\d?'],
[/Do/,'\\d{1,2}(?:st|nd|rd|th)'],
[/D/,'\\d\\d?']
] ;
},{"./Rummager":111,"moment":140}],95:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var ObjectRummager = require('./ObjectRummager') ;
var PipeRummager = require('./PipeRummager') ;
var RummageError = require('./RummageError') ;
var isArrayLike = require('is-array-like') ;
/**
* Class for filtering a list of nodes, based on given criteria
*
* @param {Rummager} criteria Rummager that ultimately returns true or false based on each element of input
*
* @returns {FilterRummager} An instance of FilterRummager
*/
function FilterRummager(criteria)
{
// Call super constructor and pass values
Rummager.call(this,criteria) ;
// Set default for onlyOne to false
this.options = {onlyOne: false} ;
}
//A subclass of Rummager
FilterRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Specify that if a match is found, only one result (the first found) will be returned as a single value
* rather than an array with a single value
* @param {boolean} onlyOne If true, return just a single value, otherwise return all matching results
* @return {FilterRummager} An instance of FilterRummager
*/
FilterRummager.prototype.onlyOne = function(onlyOne)
{
this.options.onlyOne = new Boolean(onlyOne).valueOf() ;
return this ;
} ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
*
* @returns {(Array|*)} Returns an array of matching values, a single matching value, or an empty array
*/
FilterRummager.prototype.retrieve = function()
{
if (this.rummageFor === undefined || this.rummageFor === null)
throw new RummageError("You must call the .for() method or pass what to search for to the constructor") ;
//If rummageFor contains an array, pass it to PipeRummager to process
//array with a single Rummager object
var criteria = (Array.isArray(this.rummageFor))
? new PipeRummager(this.rummageFor)
: this.rummageFor ;
var through = (isArrayLike(this.rummageThrough))
? Array.from(this.rummageThrough)
: [ this.rummageThrough ] ;
var data = [ ] ;
through.forEach(function(e) {
// Test criteria matches for each 'e'
var match = criteria.through(e).collect() ;
if(match) // Then add to our list of elements to return if it matches
data.push(e) ;
}) ;
// If one() is called with true, then return the first record, not an array with one record
if(this.options.onlyOne) {
if(data.length > 0)
return data[0] ;
return null ;
}
return data ;
} ;
FilterRummager.prototype.name = 'FilterRummager' ;
module.exports = FilterRummager ;
},{"./ObjectRummager":100,"./PipeRummager":105,"./RummageError":109,"./Rummager":111,"is-array-like":130}],96:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* FirstOfRummager object passes output from first argument as input to the next
* and so on, much like the UNIX pipe concept.
*
* @param {Array} Array of Rummagers where first Rummager outputs to the next and so on until the last Rummager returns the result to FirstOfRummager
*
* @returns {FirstOfRummager} An instance of FirstOfRummager
*/
function FirstOfRummager()
{
//Call super constructor and pass value
Rummager.apply(this,arguments) ;
}
//A subclass of Rummager
FirstOfRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the property on the element provided.
*
* @returns {String} Returns the string value of the property or null
*/
FirstOfRummager.prototype.retrieve = function()
{
//Initialise our starting operand
var self = this ;
var rummageThrough = this.rummageThrough ;
var rummageFor = this.rummageFor ;
var data = null ;
//If by chance, only actually passed in a single rummager for pipeline
if(!Array.isArray(rummageFor))
{
rummageFor = [ rummageFor ] ;
}
//Loop through each Rummager for the given variable 'p'
rummageFor.some
(
function(rummager)
{
data = rummager.through(rummageThrough).collect() ;
return (data !== null) ;
}
) ;
return data ;
}
FirstOfRummager.prototype.name = 'FirstOfRummager' ;
module.exports = FirstOfRummager ;
},{"./Rummager":111}],97:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for executing arbitrary code via func function
*
* @param {Function} func Function to execute passing in as a single parameter, what to rummage .through()
*
* @returns {FuncRummager} An instance of FuncRummager
*/
function FuncRummager(func)
{
//Call super constructor and pass value
Rummager.call(this,func) ;
}
//A subclass of Rummager
FuncRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the func function provided through .for() to search .through()
*
* @returns {Object} Returns arbitrary results according to needs
*/
FuncRummager.prototype.retrieve = function()
{
return this.rummageFor.call(null,this.rummageThrough) ;
}
FuncRummager.prototype.name = 'FuncRummager' ;
module.exports = FuncRummager
},{"./Rummager":111}],98:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var RummageError = require('./RummageError') ;
var pope = require('pope').pope ;
/**
* Rummager object for indexing Array of Objects by given property name
*
* @param {String} indexPropertyName Name of the object property to use to index the data
* @param {String} [valueTemplate] String template using (TODO) for interpolating a value derived from other properties of the data structure
*
* @returns {IndexRummager} An instance of IndexRummager
*/
function IndexRummager(indexPropertyName,valueTemplate)
{
//Call super constructor and pass value
Rummager.call(this,indexPropertyName,valueTemplate) ;
}
//A subclass of Rummager
IndexRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the propertyName to index an Array of objects, returning an object keyed by the values of propertyName
*
* @returns {Object} Returns an object where property names are the values of propertyName for each array element in the input
*/
IndexRummager.prototype.retrieve = function()
{
var rummageThrough = this.rummageThrough ;
var indexByPropertyName = this.rummageFor[0] ;
var valueTemplate = this.rummageFor[1] ;
//@todo through should be an array - need to throw error (if told to) if not or just return null
//@todo through should be an array of objects - need to throw error (if told to) if not or just return null
//Convert data from array to object using the values r[indexByPropertyName]
//as the keys
var data = { } ;
rummageThrough.forEach
(
function(r)
{
if(!r.hasOwnProperty(indexByPropertyName))
throw new RummageError("Index '"+indexByPropertyName+"' does not exist in data") ;
if (data.hasOwnProperty(r[indexByPropertyName]))
throw new RummageError("Duplicate key value '"+r[indexByPropertyName]+"'") ;
if(valueTemplate === undefined)
data[r[indexByPropertyName]] = r ;
else
data[r[indexByPropertyName]] = pope(valueTemplate,r)
}
)
return data ;
}
IndexRummager.prototype.name = 'IndexRummager' ;
module.exports = IndexRummager
},{"./RummageError":109,"./Rummager":111,"pope":141}],99:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for return an attribute of an element, by specifying the attribute name
*
* @param {RegExp} re Regular expression to match against
*
* @returns {MatchRummager} An instance of MatchRummager
*/
function MatchRummager(re)
{
//Call super constructor and pass value
Rummager.call(this,re) ;
}
//A subclass of Rummager
MatchRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the property on the element provided.
*
* @returns {String} Returns the string value of the property or null
*/
MatchRummager.prototype.retrieve = function()
{
if (this.rummageThrough === undefined) {
var error = "MatchRummager: nothing provided to .through() method: "+this.rummageFor ;
if(this.debug) console.log(error) ;
throw error ;
}
else if (this.rummageFor === undefined) {
var error = "MatchRummager: no RegExp provided" ;
if(this.debug) console.log(error) ;
throw error ;
}
var through = this.rummageThrough ;
if(through === undefined || through === null)
return false ;
// Ensure we have a string representation to match against
return (through.toString().match(this.rummageFor) !== null) ;
}
module.exports = MatchRummager ;
},{"./Rummager":111}],100:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var PipeRummager = require('./PipeRummager') ;
/**
* Class for finding values within a page and returning them into a given object structure
*
* @param {Object} extractList An object with keys as variable names and values as 'Rummager' objects to locate and assign values to the variables
*
* @returns {ObjectRummager} An instance of ObjectRummager
*/
function ObjectRummager(extractList) {
//Call super constructor and pass value
Rummager.call(this, extractList);
//If rummageFor property contains an array, pass it to PipeRummager to process
for (var p in this.rummageFor) {
//array with a single Rummager object
if (Array.isArray(this.rummageFor[p]))
this.rummageFor[p] = new PipeRummager(this.rummageFor[p]);
}
}
//A subclass of Rummager
ObjectRummager.prototype = Object.create(Rummager.prototype) ;
/**
* This method will extract the values defined by .for() from .through(), but is normally called by the retrieve method as a standard API
*
* @returns {Object} Returns the extracted data using the variable names defined in extractList
*/
ObjectRummager.prototype.extract = function()
{
/**
* The actual data extracted is stored in this variable
*/
var data = { } ;
var rummageFor = this.rummageFor ;
//If none provided and no instance copy, barf
if (rummageFor === null)
{
console.log('The rummageFor property must be defined with an Rummager object') ;
throw "The rummageFor property must be defined with an Rummager object" ;
}
//Go through all variable names and matching Rummager objects to extract the values
for(var p in rummageFor)
{
data[p] = (rummageFor[p] instanceof Rummager)
? rummageFor[p]
.through(this.rummageThrough)
.collect()
: rummageFor[p] ;
}
//Return our extracted data
return data ;
} ;
/**
* The retrieve method is part of the API and will initiate a complete parsing of the
* data structure and ultimately return the data found, based on extractList
* and starting element provided to the instance
*
* @returns {Object} The data found with the property names matches those in extractList
*/
ObjectRummager.prototype.retrieve = function()
{
return this.extract(this.rummageFor) ;
} ;
/**
* By default, there is no extractList
*/
ObjectRummager.prototype.extractList = null ;
ObjectRummager.prototype.name = 'ObjectRummager' ;
module.exports = ObjectRummager ;
},{"./PipeRummager":105,"./Rummager":111}],101:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for locating closest ancestor of current element by css selector
*
* @param {String} selector css Selector to match closest ancestor relative to current element
* @link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
*
* @returns {ParentRummager} An instance
*/
function ParentRummager(selector)
{
//Call super constructor and pass value
Rummager.call(this,selector) ;
}
//A subclass of Rummager
ParentRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the selector on the element provided.
*
* @returns {Element} Returns the Node that was found by the selector or null
*/
ParentRummager.prototype.retrieve = function()
{
var e = this.rummageThrough ;
//If rummageThrough is null, then return null
if(e === null)
return null ;
//If no parent specified, get the first parent
if (!this.rummageFor)
return this.rummageThrough.parentElement ;
// Polyfill for closest
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
var matches = (e.document || e.ownerDocument).querySelectorAll(this.rummageFor) ;
var i ;
do
{
i = matches.length ;
while(--i >= 0 && matches.item(i) !== e) {} ;
} while((i < 0) && (e = e.parentElement)) ;
return e ;
}
ParentRummager.prototype.name = 'ParentRummager' ;
module.exports = ParentRummager ;
},{"./Rummager":111}],102:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for parsing an float value from a string (as per parseFloat function) and returning an Float primitive
*
* @returns {ParseFloatRummager} An instance of ParseFloatRummager
*/
function ParseFloatRummager()
{
//No need to call super constructor as takes no arguments
}
//A subclass of Rummager
ParseFloatRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using parseFloat on the string provided.
*
* @returns {Float} Returns a float representing the string passed to search .through() or NaN if string is not a number
*/
ParseFloatRummager.prototype.retrieve = function()
{
var num = parseFloat(this.rummageThrough,this.rummageFor) ;
return (isNaN(num)) ? null : num ;
}
ParseFloatRummager.prototype.name = 'ParseFloatRummager' ;
module.exports = ParseFloatRummager ;
},{"./Rummager":111}],103:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for parsing an integer value from a string (as per parseInt function) and returning an Integer primitive
*
* @param {Integer} radix The radix, if not provided defaults to base-10 numbers
*
* @returns {ParseIntRummager} An instance of ParseIntRummager
*/
function ParseIntRummager(radix)
{
//Call super constructor and pass value
Rummager.call(this,radix) ;
//If radix was undefined, then set it to 10 by default
if (this.rummageFor === null)
this.rummageFor = 10 ;
}
//A subclass of Rummager
ParseIntRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using parseInt on the string provided.
*
* @returns {Integer} Returns an integer representing the string passed to search .through() or NaN if string is not an integer
*/
ParseIntRummager.prototype.retrieve = function()
{
var val = parseInt(this.rummageThrough,this.rummageFor) ;
return (isNaN(val)) ? null : val ;
}
ParseIntRummager.prototype.name = 'ParseIntRummager' ;
module.exports = ParseIntRummager ;
},{"./Rummager":111}],104:[function(require,module,exports){
var Rummager = require('./Rummager') ;
var urlutils = require('urlutils');
var url = (typeof URL === "function") ? URL : urlutils ;
/**
* Rummager object for parsing a URL string to Url object
*
* @param {string} base Base url if link is relative
* @returns {ParseUrlRummager} An instance of UrlRummager
*/
function ParseUrlRummager(base)
{
//Call super constructor and pass value
Rummager.apply(this,arguments) ;
}
//A subclass of Rummager
ParseUrlRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using new URL on the string provided.
*
* @returns {Float} Returns an instance of URL or null if input is unparseable
*/
ParseUrlRummager.prototype.retrieve = function()
{
let link = null ;
if(typeof this.rummageThrough === 'string') {
link = this.rummageThrough ;
}
else if(this.rummageThrough instanceof Element) {
let tag = this.rummageThrough.tagName ;
let source = null ;
switch (tag) {
case 'AUDIO':
case 'EMBED':
case 'IFRAME':
case 'IMG':
case 'INPUT':
case 'SCRIPT':
case 'SOURCE':
case 'TRACK':
case 'VIDEO':
source = 'src' ;
break ;
case 'A':
case 'AREA':
case 'BASE':
case 'LINK':
source = 'href' ;
break ;
case 'BLOCKQUOTE':
case 'DEL':
case 'INS':
case 'Q':
source = 'cite' ;
break ;
case 'OBJECT':
source = 'data' ;
break ;
}
if(source === null)
return null ;
link = this.rummageThrough[source] ;
try {
var u = new url(link) ;
}
catch(e) {
u = null ;
}
}
else
return null ;
return u ;
} ;
ParseUrlRummager.prototype.name = 'ParseUrlRummager' ;
module.exports = ParseUrlRummager ;
},{"./Rummager":111,"urlutils":143}],105:[function(require,module,exports){
//@todo incomplete implementation as undecided whether is necessary (all .for and .through methods could take arbitrary number of parameters meaning a pipeline - cleaner code)
var Rummager = require('./Rummager') ;
/**
* PipeRummager object passes output from first argument as input to the next
* and so on, much like the UNIX pipe concept.
*
* @param {Array} Array of Rummagers where first Rummager outputs to the next and so on until the last Rummager returns the result to PipeRummager
*
* @returns {PipeRummager} An instance of PipeRummager
*/
function PipeRummager()
{
//Call super constructor and pass value
Rummager.apply(this,arguments) ;
}
//A subclass of Rummager
PipeRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the property on the element provided.
*
* @returns {String} Returns the string value of the property or null
*/
PipeRummager.prototype.retrieve = function()
{
//Initialise our starting operand
var e = this.rummageThrough ;
var rummageFor = this.rummageFor ;
var that = this ;
//If by chance, only actually passed in a single rummager for pipeline
if(!Array.isArray(rummageFor))
{
rummageFor = [ rummageFor ] ;
}
//Loop through each Rummager for the given variable 'p'
rummageFor.forEach
(
function(rummager)
{
//If e is a null value, then don't call next step, just return null
if (e === null)
return null ;
//Call the rummager's retrieve method passing in initially the base element
//and on subsequent calls to the remaining rummagers in the array, pass
//the new value from the last call. This means each Rummager in the
//array passes the result to the next Rummager as the basis element
e = rummager
.through(e)
.collect() ;
}
) ;
return e ;
}
PipeRummager.prototype.name = 'PipeRummager' ;
module.exports = PipeRummager
},{"./Rummager":111}],106:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for return a property of an element, by specifying the property name
*
* @param {String} propertyName Name of the element property to return
*
* @returns {PropRummager} An instance of PropRummager
*/
function PropRummager(propertyName)
{
//Call super constructor and pass value
Rummager.call(this,propertyName) ;
}
//A subclass of Rummager
PropRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the property on the element provided.
*
* @returns {String} Returns the string value of the property or null
*/
PropRummager.prototype.retrieve = function()
{
if(this.rummageThrough === null)
return null ;
if (this.rummageThrough === undefined) {
var error = "PropRummager: no element defined to locate propertyName: "+this.rummageFor ;
if(this.debug) console.log(error) ;
throw error ;
}
else if (this.rummageFor === undefined) {
var error = "PropRummager: no propertyName defined for element: "+JSON.stringify(this.rummageThrough) ;
if(this.debug) console.log(error) ;
throw error ;
}
var val = this.rummageThrough[this.rummageFor] ;
return (val === undefined) ? null : val ;
}
PropRummager.prototype.name = 'PropRummager' ;
module.exports = PropRummager
},{"./Rummager":111}],107:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for extracting a value from a string using an regular expression
*
* @param {RegExp} re RE object to parse the string we are rummaging .through()
*
* @param {String} replacement String representing the replacement for re including placeholders
*
* @returns {ReplaceRummager} An instance of ReplaceRummager
*/
function ReplaceRummager(re,replacement)
{
//Call super constructor and pass value
Rummager.call(this,re,replacement) ;
}
//A subclass of Rummager
ReplaceRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the re on the string provided.
*
* @returns {String} Returns the replacement of the re operation on str or null
*/
ReplaceRummager.prototype.retrieve = function()
{
if(this.rummageThrough === null)
{
return null ;
}
var res = this.rummageThrough.replace(this.rummageFor[0],this.rummageFor[1]) ;
return res ;
}
ReplaceRummager.prototype.name = 'ReplaceRummager' ;
module.exports = ReplaceRummager
},{"./Rummager":111}],108:[function(require,module,exports){
// Super-class
var Rummager = require('./Rummager') ;
var isHtml = require('is-html') ;
var isDom = require('is-dom') ;
var isUrl = require('is-url') ;
var isPromise = require('is-promise') ;
var RummageAgentAdapter = require('./agents/RummageAgentAdapter') ;
var RummageParserAdapter = require('./parsers/RummageParserAdapter') ;
/**
* If running under browser and no parser specified, then use DOMParserAdapter by default
* @type {DOMParserAdapter}
*/
var DOMParserAdapter = require('./parsers/DOMParserAdapter') ;
var RummageError = require('./RummageError') ;
/**
* Rummage .through(a DOM) searching .for(data)
*
* @param {RummageParserAdapter} [parser] A parser to use to parse HTML string
* @param {RummageAgentAdapter} [agent] An agent to use to download HTML source
*
* @returns {Rummage} An instance of Rummage
*/
function Rummage(parser,agent)
{
/**
* Parser instance
* @type {?RummageParserAdapter}
*/
this.parser = null ;
/**
* Agent instance
* @type {?RummageAgentAdapter}
*/
this.agent = null ;
/**
* If agent is used, the response object from the request
* @type {?Object}
*/
this.response = null ;
/**
* Whether agent has already fetched HTML source
* @type {boolean}
*/
this.fetched = false ;
/**
* url of source html if specified
* @type {?string}
*/
this.url = null ;
/**
* Source of html given to .through() method
* @type {string|Node}
*/
this.source = null ;
/**
* Html source as a string (as passed to .through or returned from RummageParserAdapter)
* @type {?string}
*/
this.html = null ;
/**
* After fetching using agent and/or parsing using a parser, place a DOM in this instance variable
* @type {HTMLDocument|Node}
*/
this.rummageThrough = null ;
/**
* An internal Promise created when Rummage.then() method called
* @type {?Promise}
*/
this.promise = null ;
// Set default parser if .useParser() called
if(parser !== undefined && parser !== null)
{
this.usingParser(parser) ;
}
// Set default agent if .useAgent() called
if(agent !== undefined && agent !== null)
{
this.usingAgent(agent) ;
}
}
//A subclass of Rummager
Rummage.prototype = Object.create(Rummager.prototype) ;
/**
* Specify parser to convert rummageThrough HTML string into a DOM
* @param {RummageParserAdapter} parser Parser adapter to use
*
* @returns {Rummage} Uses fluent interface. Returns this instance for method chaining
*/
Rummage.prototype.usingParser = function(parser)
{
if(parser instanceof RummageParserAdapter || 'parse' in parser)
{
this.parser = parser ;
return this ;
}
throw new RummageError("Must provide subclass of RummageParserAdapter to 'usingParser'") ;
} ;
/**
* Specify user agent to retrieve the HTML to rummageThrough
*
* @param {RummageAgentAdapter} agent Agent adapter to use
*
* @returns {Rummage} Uses fluent interface. Returns this instance for method chaining
*/
Rummage.prototype.usingAgent = function(agent)
{
if(agent instanceof RummageAgentAdapter || 'fetch' in agent)
{
this.agent = agent ;
return this ;
}
throw new RummageError("Must provide subclass of RummageAgentAdapter to 'usingAgent'") ;
} ;
Rummage.prototype.usingMap = function(json)
{
// TODO json schema validate input
if(typeof json === 'string')
json = JSON.parse(json) ;
function traverse(r)
{
}
return this.for(traverse(json.rummagemap)) ;
} ;
/**
* Parse rummageThrough HTML string into a DOM
*
* @throws {RummageError}
* @returns {Promise}
*/
Rummage.prototype.parse = function()
{
// If not parser is provided and we are in a browser that has DOMParser, just use that
if(this.parser === null)
{
try
{
this.parser = new DOMParserAdapter(new DOMParser()) ;
}
catch(err)
{
// Otherwise, throw error
throw new RummageError("No parser specified - call .usingParser() method with a RummageParserAdapter object to parse the HTML") ;
}
}
return this.parser.parse(this) ;
} ;
/**
* The fetch method is part of the API and will use the given agent to download
* the HTML to be parsed by this Rummage instance
* @todo This method needs implementation
*/
Rummage.prototype.fetch = function()
{
var self = this ;
if(this.fetched === false)
{
// If we haven't called .through() to tell our agent what to get, then barf here
if(this.source === null)
return Promise.reject(new RummageError(".through() not called on Rummage")) ;
// If no agent has been provided, then barf here
if(this.agent === null)
return Promise.reject(new RummageError("No agent adapter specified - call .usingAgent() method with a RummageAgentAdapter object to fetch the HTML")) ;
// Otherwise, lets ask our agent to fetch the HTML for us
return self.agent.fetch(this.source)
.then(function(response)
{
self.fetched = true ;
self.response = response ;
self.html = response.data ;
return Promise.resolve(self.response,self.html) ;
}) ;
}
return Promise.resolve(self.response,self.html) ;
} ;
/**
* Set the object to rummage .through() for this instance
*
* The operand must be a representation of HTML as either a DOM Element; a string containing HTML; or a Promise-like object that can retrieve HTML and return a DOM or as a string
*
* Uses fluent interface.
*
* @param {Promise|Node|String} operand The data for Rummager to operate on
*
* @returns {Rummage} Uses fluent interface. Returns this instance for method chaining
*/
Rummage.prototype.through = function(operand)
{
// Store operand as our original 'source' no matter what type it may be
this.source = operand ;
if(isDom(operand))
{
if(this.debug) console.log('Have DOM object so storing as this.rummageThrough');
return Rummager.prototype.through.call(this,operand) ;
}
if(typeof operand === 'string' && isHtml(operand))
{
if(this.debug) console.log('Provided HTML source, so storing as this.html');
this.html = operand ;
}
else if (typeof operand === 'string' && isUrl(operand))
{
if(this.debug) console.log('Provided url, so storing as this.url');
this.url = operand ;
}
// @todo else if (typeof operand === 'object') i.e. assume its object to pass to RummageAgentAdapter to download
// so
// this.agent.setRequest(operand)
// Otherwise we don't set rummageThrough yet. This is done by agent & parser
return this ;
// @todo - add tests for other forms of input, such as objects with a toString method, or an object with a url property, or a Promise that resolves to a Node object
} ;
/**
* Specify what to rummage .for()
*
* The action details what Rummager is to do when searching .through()
*
* Uses fluent interface.
*
* @param {Rummager} operand Specifies the Rummager object hierarchy for Rummager to act on when searching .through()
*
* @returns {Rummage} Uses fluent interface. Returns this instance for method chaining
*/
Rummage.prototype.for = function(operand)
{
return Rummager.prototype.for.call(this,operand) ;
} ;
/**
* Initiate asynchronous processing of instance using Promise API
*
* @param {Function} onFulfilled Function to execute if Promise is fulfilled
* @param {Function} onRejected Function to execute if Promise is rejected
*
* @returns {Promise} A Promise instance
*/
Rummage.prototype.then = function(onFulfilled, onRejected)
{
return this.go().then(onFulfilled,onRejected) ;
} ;
/**
* @todo Needs jsdoc done
* @param onRejected
* @returns {Promise}
*/
Rummage.prototype.catch = function(onRejected)
{
return this.then(undefined, onRejected);
};
/**
* The retrieve method is part of the API and will initiate a synchronous
* parsing of the data structure and return the data found.
*
* @returns {Object} The data found
*/
Rummage.prototype.retrieve = function()
{
if(!isDom(this.rummageThrough))
throw new RummageError("Cannot call synchronous method .collect() when HTML not yet parsed. Use then()") ;
//Commence rummaging by calling that.rummageFor(data)
return this.rummageFor.through(this.rummageThrough).collect() ;
} ;
Rummage.prototype.go = function()
{
var self = this;
// If a promise hasn't been created yet, then we havent initiated the Rummage
if(this.promise === null)
{
// If we already have HTML or a DOM, then we don't need an agent, so skip fetching
if(this.html !== null || this.rummageThrough !== null)
this.promise = Promise.resolve(null) ;
else // Otherwise, fetch our html using our agent
this.promise = this.fetch() ;
// Start our chaining
this.promise = this.promise
.then(function(res) { // Provided from agent, or if no agent, whatever provided by .through()
// @todo Should perhaps check or work with the resource value
// If we already have rummageThrough, then we have a DOM, so no need to call parser
if(self.rummageThrough !== null)
return Promise.resolve(self.rummageThrough) ;
// Otherwise, better parse what we have
return self.parse();
})
.then(function(doc) {
return new Promise(function(innerFulfilled,innerRejected){
if (self.debug) console.log('inside Rummage dom=' + doc.body.innerHTML);
self.rummageThrough = doc;
try
{
var data = self.rummageFor.through(doc).collect();
}
catch(err)
{
innerRejected(err) ;
}
innerFulfilled(data);
}) ;
});
}
return this.promise ;
} ;
Rummage.prototype.name = 'Rummage' ;
module.exports = Rummage ;
},{"./RummageError":109,"./Rummager":111,"./agents/RummageAgentAdapter":116,"./parsers/DOMParserAdapter":120,"./parsers/RummageParserAdapter":122,"is-dom":132,"is-html":134,"is-promise":137,"is-url":138}],109:[function(require,module,exports){
/**
* RummageError - A subclass of Error thrown when error in Rummager occurs
*
* @param {String} message Error message string
* @param {String} fileName Name of js file in which error occurred
* @param {Integer} lineNumber Line number in fileName where error occurred
*
* @returns {RummageError} Returns an instance of RummageError
*/
function RummageError(message,fileName,lineNumber)
{
this.name = 'RummageError' ;
this.message = message || '' ;
var e = new Error(message) ;
this.stack = e.stack ;
}
/* Create a subclass of Error */
// http://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript
RummageError.prototype = Object.create(Error.prototype) ;
RummageError.prototype.constructor = RummageError ;
/* Set default name property to RummageError */
RummageError.prototype.name = 'RummageError' ;
/**
* Set the name property of RummageError instance
*
* @param {String} name Name of this error instance
*
* @returns {RummageError} Using fluent interface, returns copy of self
*/
RummageError.prototype.setName = function(name)
{
this.name = name ;
return this ;
} ;
module.exports = RummageError ;
},{}],110:[function(require,module,exports){
/**
* RummageMap.js
*
* Abstract Class for creating Rummage Maps
*
* rummage
*
* 12/10/17
*
* Copyright (C) 2017 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Rummager = require('./Rummager') ;
var ArgumentTemplate = require('./ArgumentTemplate') ;
var Argument = require('./Argument') ;
var RummageError = require('./RummageError') ;
var processForDataTypes = require('./processForDataTypes') ;
var Emitter = require('events') ;
function MapEmitter() {
this.map = new Map() ;
}
MapEmitter.prototype = Object.create(Emitter.prototype) ;
MapEmitter.prototype.set = function(key,val) {
let v = this.map.set(key,val) ;
this.emit(key) ;
return v ;
} ;
MapEmitter.prototype.get = function(key) {
return this.map.get(key) ;
} ;
MapEmitter.prototype.has = function(key) {
return this.map.has(key) ;
} ;
MapEmitter.prototype.clear = function() {
return this.map.clear() ;
} ;
function RummageMap()
{
//Call super constructor and pass value
Rummager.apply(this,arguments) ;
this.options =
{
trust: false
} ;
this.run = {
out: new Set(),
in: new MapEmitter(),
depth: 0
}
}
RummageMap.prototype = Object.create(Rummager.prototype) ;
RummageMap.prototype.name = 'RummageMap' ;
RummageMap.prototype.usingArguments = function()
{
this.options.args = Array.from(arguments) ;
return this ;
} ;
RummageMap.prototype.ArgumentTemplate = function(template)
{
return new ArgumentTemplate(template,this.options.args) ;
} ;
RummageMap.prototype.Argument = function(path)
{
return new Argument(path,this.options.args) ;
} ;
/**
* Traverse parsed JSON input and reattach any circular references
* @param input
*/
function traverse(input) {
if(input === null || input === undefined)
return ;
if(Array.isArray(input)) {
for(let i = 0; i < input.length; i++) {
if(typeof input[i] === 'object' && input[i].hasOwnProperty('value'))
input[i] = input[i].value ;
else
traverse(input[i]) ;
}
}
else if(typeof input === 'object') {
Object.keys(input).forEach(key => {
if(input[key] === null || input[key] === undefined)
return ;
if(typeof input[key] === 'object' && input[key].hasOwnProperty('value'))
input[key] = input[key].value ;
else
traverse(input[key]) ;
}) ;
}
}
/**
* Reconstitute a RummageMap from JSON string or parsed JSON object
* @param {string} map The RummageMap expressed as JSON string
* @constructor
*/
RummageMap.prototype.fromJSON = function(map)
{
var obj = JSON.parse(map) ;
var tree = traverseIn(this,obj.RummageMap) ;
// Traverse tree and look for { value: Rummager } replacing it with just Rummager
traverse(tree) ;
this.for(tree) ;
return this ;
} ;
// Not sure if we need this - disable for now
// /**
// * Reconsitute a RummageMap from object using toObject() output format
// * @param {object} obj
// * @return {RummageMap}
// */
// RummageMap.prototype.fromObject = function(obj) {
// this.for(traverseIn(this,obj)) ;
// return this ;
// } ;
function traverseIn(rm,node)
{
var data = null ;
++rm.run.depth ;
switch(node.object)
{
case 'Rummager':
var rummager = node.type ;
var options = node.options ;
var ident = node.ident ;
if(Number.isInteger(ident.pointer)) {
if(rm.run.in.has(ident.pointer)) {
data = rm.run.in.get(ident.pointer) ;
}
else {
data = { value: null } ;
rm.run.in.once(ident.pointer,() => {
data.value = rm.run.in.get(ident.pointer) ;
}) ;
}
break ;
}
var rummageFor = traverseIn(rm,node.args) ;
var params = Array.isArray(rummageFor) ? rummageFor : [ rummageFor ] ;
data = rm.r[rummager].apply(null,params) ;
data.options = options ;
data.ident = {
id: ident.id,
pointer: null
} ;
rm.run.in.set(ident.id,data) ;
break ;
case 'RegExp':
data = RegExp.apply(null,node.args) ;
break ;
case 'ArgumentTemplate':
data = rm.ArgumentTemplate(node.args) ;
break ;
case 'Object':
if(node.args === null) {
data = null ;
break ;
}
// Translate key: value -> key: traverseIn(value)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries#Examples
data = Object.fromEntries(Object.entries(node.args).map(([key,val]) => [ key, traverseIn(rm,val)])) ;
break ;
case 'Array':
var args = [] ;
node.args.forEach(function(a)
{
args.push(traverseIn(rm,a)) ;
}) ;
data = args ;
break ;
case 'Function':
if(!rm.options.trust)
{
throw new RummageError('.fromJSON() argument contains a Func Rummager. Confirm you trust this code and wish to execute it by calling .trust(true) on RummageMap.') ;
}
var code = 'return (' + node.args + ')(a)' ;
// var code = `return (${node.args})(a)` ;
data = new Function('a',code) ;
break ;
case 'Undefined':
data = undefined ;
break ;
case 'Primitive':
data = node.args ;
break ;
default:
throw new RummageError('Unknown input type: '+node.object) ;
}
if(--rm.run.depth === 0)
rm.run.in.clear() ;
return data ;
}
RummageMap.prototype.toObject = function()
{
return traverseOut(this,this.rummageFor) ;
} ;
RummageMap.prototype.toJSON = function(replacer,space)
{
var output = {
"name":"test",
"version":"0.1.0",
"RummageMap": this.toObject()
} ;
// return JSON.stringify.apply(null,[json].concat(arguments)) ;
return JSON.stringify.apply(null,[output].concat(arguments)) ;
} ;
RummageMap.prototype.trust = function(trust)
{
this.options.trust = trust ;
return this ;
} ;
function traverseOut(rm,node)
{
var data = {} ;
++rm.run.depth ;
processForDataTypes(node,{
Rummager: function()
{
// Convert internal Rummager Name for JSON output
data.object = 'Rummager' ;
data.type = node.name.replace(/Rummager$/,'') ;
data.options = node.options ; // TODO This might need to be processed by traverseOut too if stores JSON incompatible objects
if(rm.run.out.has(node))
data.ident = { pointer: node.ident.id } ;
else {
rm.run.out.add(node);
data.ident = node.ident ;
data.args = traverseOut(rm,node.rummageFor) ;
}
},
RegExp: function()
{
data.object = 'RegExp' ;
data.args = [node.source,node.flags] ;
},
ArgumentTemplate: function()
{
data.object = 'ArgumentTemplate' ;
data.args = node.toString() ;
},
Argument: function()
{
data.object = 'Argument' ;
data.args = node.toString() ;
},
Null: function()
{
data.object = 'Object' ;
data.args = null ;
},
Array: function()
{
data.object = 'Array' ;
data.args = [] ;
node.forEach(function(a)
{
data.args.push(traverseOut(rm,a)) ;
}) ;
},
Object: function()
{
data.object = 'Object' ;
data.args = {} ;
for(i in node)
{
if(node.hasOwnProperty(i))
data.args[i] = traverseOut(rm,node[i]) ;
}
// If no properties, return empty object
if(Object.getOwnPropertyNames(data.args).length === 0)
data = {} ;
},
Function: function()
{
data.object = 'Function' ;
data.args = node.toString() ;
},
Undefined: function()
{
data.object = 'Undefined' ;
data.args = undefined ;
},
Primitive: function()
{
data.object = 'Primitive' ;
data.args = node ;
},
}) ;
if(--rm.run.depth === 0)
rm.run.out.clear() ;
return data ;
}
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
*
* @returns {*} Returns results of this RummageMap
*/
RummageMap.prototype.retrieve = function()
{
if (this.rummageThrough === undefined) {
var error = "RummagerMap: no input provided by .through() method: "+this.rummageFor ;
if(this.debug) console.log(error) ;
throw error ;
}
else if (this.rummageFor === undefined) {
var error = "No input provided by .for() method: "+JSON.stringify(this.rummageThrough) ;
if(this.debug) console.log(error) ;
throw error ;
}
return this.rummageFor.through(this.rummageThrough).collect() ;
}
/**
* Instance of index exports provided when Rummagemap instantiated
* @type {null}
*/
// RummageMap.prototype.r = null ;
module.exports = RummageMap ;
},{"./Argument":90,"./ArgumentTemplate":91,"./RummageError":109,"./Rummager":111,"./processForDataTypes":123,"events":15}],111:[function(require,module,exports){
var RummageError = require('./RummageError') ;
var Argument = require('./Argument') ;
var isArrayLike = require('is-array-like') ;
var indent = require('indent') ;
var id = 0 ;
/**
* Abstract Rummager prototype that can be subclassed including the generic
* setOperand method
*
* @returns {Rummager} Instance of Rummager prototype
*/
function Rummager()
{
this.run = {
} ;
this.ident = {
id: ++id,
pointer: null
} ;
this.for.apply(this,arguments) ;
} ;
module.exports = Rummager ;
// Required after export to solve circular require issue
// https://coderwall.com/p/myzvmg/circular-dependencies-in-node-js
var processForDataTypes = require('./processForDataTypes') ;
/**
* Specify what to rummage .for()
*
* The action details what this object instance is to do when searching .through()
*
* Uses fluent interface.
*
* @param {...Object} var_args Args for this object to act on when searching .through()
*
* @returns {Rummager} Uses fluent interface. Returns this instance for method chaining
*/
Rummager.prototype.for = function()
{
switch (arguments.length)
{
case 0: //No args, then set rummageFor as null (i.e. reset it)
this.rummageFor = null ;
break ;
case 1: //One arg, set it specifically as a single object
this.rummageFor = arguments[0] ;
break ;
default: //More than one arg, then store it as an array in order provided
this.rummageFor = Array.from(arguments) ;
break ;
}
return this ;
} ;
/**
* Set the object to rummage .through() for this instance
*
* The operand can be a DOM Element, or a string for instance
*
* Uses fluent interface.
*
* @param {NodeList|Node|String} operand The value for this class instance to operate on
*
* @returns {Rummager} Uses fluent interface. Returns this instance for method chaining
*/
Rummager.prototype.through = function(operand)
{
this.rummageThrough = (operand === undefined) ? null : operand ;
return this ;
} ;
/**
* Commence synchronous rummaging and return data
*/
Rummager.prototype.retrieve = function()
{
throw new RummageError('You must create your own retrieve() method') ;
} ;
Rummager.prototype.collect = function()
{
this.resolveArguments() ;
// Set debug for recurse
var args = this.rummageFor ;
var debugRummagerLevel = this.debugRummagerLevel ;
if(this.debugRecurse && args !== null)
{
if(!Array.isArray(args))
args = [ args ] ;
else
args = Array.from(args) ;
args.forEach(function(a){
if(a instanceof Rummager)
// if(a instanceof Rummager && a.debug === null)
{
if(a.debug === null)
a.debug = true ;
if(a.debugRecurse === null)
a.debugRecurse = true ;
a.debugRummagerLevel = debugRummagerLevel + 1;
}
}) ;
}
// Input to this rummage
if(this.debug) this.debugLogArgs(args) ;
// if(this.debug) this.debugLogArgs(this.rummageThrough) ;
var output = this.retrieve() ;
if(this.debug) this.debugLogData(output) ;
return output ;
} ;
/**
* Interpolate any ArgumentTemplate objects passed via RummageMap
*/
Rummager.prototype.resolveArguments = function()
{
var self = this ;
if(this.rummageFor === null)
return ;
if(Array.isArray(this.rummageFor))
{
this.rummageFor.forEach(function(e){
if(e instanceof Argument)
e = e.resolve() ;
})
}
else if(this.rummageFor instanceof Argument)
this.rummageFor = this.rummageFor.resolve() ;
} ;
/**
* Turn debugging on or off for this particular Rummager or Rummage itself
*
* @param {Boolean} debug True if debugging to be turned on, otherwise false
*/
Rummager.prototype.setDebug = function(debug,recurse)
{
this.debug = (debug) ;
if(recurse !== undefined)
this.debugRecurse = (recurse) ;
return this ;
} ;
// Data types to deal with:
// Node, NodeList, String, Moment, RegExp, Argument
Rummager.prototype.debugLogData = function(data) {
var output = '' ;
if(typeof data === 'object' && isNodelist(data) || Array.isArray(data))
{
output = 'Array('+data.length+')' ;
}
else if(typeof data === 'object' && 'nodeName' in data)
{
output = data.nodeName+'('+data.textContent.toString().trim().substr(0,10)+')' ;
}
else
{
output = data.toString().substr(0,10) ;
}
console.log(indent(this.name+' Return: '+output,4*this.debugRummagerLevel)) ;
// var throughNodes = (isArrayLike(this.rummageThrough))
// ? Array.from(this.rummageThrough)
// : [this.rummageThrough];
// var nodes = throughNodes.map(function (n) {
// return n.nodeName + '(' + n.textContent.trim().substr(0, 5) + ')';
// });
} ;
Rummager.prototype.debugLogArgs = function (data)
{
if(!Array.isArray(data))
data = [ data ] ;
else
data = Array.from(data) ;
var args = [] ;
data.forEach(function(a){
processForDataTypes(a, {
"Rummager": function () {
args.push(a.name) ;
},
RegExp: function () {
args.push('RegExp('+[a.source,a.flags].join(',')+')') ;
},
ArgumentTemplate: function () {
args.push('ArgumentTemplate('+a.toString()+')') ;
},
Argument: function () {
args.push('Argument('+a.toString()+')') ;
},
Null: function () {
args.push('Null') ;
},
Array: function () {
args.push('Array('+a.length+')') ;
},
Object: function () {
args.push('Object('+Object.getOwnPropertyNames(a).join(',')+')') ;
},
Function: function () {
args.push('Function('+a.toString()+')') ;
},
Undefined: function () {
args.push('Undefined') ;
},
Primitive: function () {
args.push(data) ;
}
}) ;
}) ;
console.log(indent(this.name+'('+args.join(',')+')',4*this.debugRummagerLevel)) ;
} ;
/** @param {Object} Runtime data store for Rummager subclass implementations */
Rummager.prototype.run = null ;
/** @param {Object} Unique identifier and pointer for referencing existing Rummagers in a RummageMap */
Rummager.prototype.ident = null ;
/**
* @param {Object} rummageFor What the object is to look for
*/
Rummager.prototype.rummageFor = null ;
/**
* @param {Object} rummageThrough What the object is searching through
*/
Rummager.prototype.rummageThrough = null ;
/**
*
* @type {{Object}}
*/
Rummager.prototype.options = null ;
/**
* Set the debugging flag
*/
Rummager.prototype.debug = null ;
Rummager.prototype.debugRummagerLevel = 0 ;
Rummager.prototype.debugRecurse = null ;
/**
* Set the name of the Rummager
* @type {string} Provide a unique name for the Rummager
*/
Rummager.prototype.name = 'Rummager' ;
// http://arjanvandergaag.nl/blog/javascript-typeof-nodelist.html
function isNodelist(n)
{
return typeof n.length != 'undefined' && typeof n.item != 'undefined' ;
}
},{"./Argument":90,"./RummageError":109,"./processForDataTypes":123,"indent":129,"is-array-like":130}],112:[function(require,module,exports){
var SelectorRummager = require('./SelectorRummager') ;
/**
* Rummager object for selecting all matching Nodes/Elements from a DOM based on CSS
*
* @param {String} function css selector string for selecting the node
*
* @returns {SelectorAllRummager} An Instance
*/
function SellectorAllRummager(selector)
{
//Call super constructor and pass value
SelectorRummager.call(this,selector) ;
}
//A subclass of SelectorRummager, where retrieve method is different
SellectorAllRummager.prototype = Object.create(SelectorRummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the selector on the element provided.
*
* @returns {Element} Returns the Node that was found by the selector or null
*/
SellectorAllRummager.prototype.retrieve = function()
{
return this.rummageThrough.querySelectorAll(this.rummageFor) ;
}
SellectorAllRummager.prototype.name = 'SelectorAllRummager' ;
module.exports = SellectorAllRummager
},{"./SelectorRummager":113}],113:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for selecting a specific Node/Element from a DOM based on CSS
*
* @param {String} selector css selector string for selecting the node
*
* @returns {SelectorRummager} An instance
*/
function SelectorRummager(selector)
{
//Call super constructor and pass value
Rummager.call(this,selector) ;
}
//A subclass of Rummager
SelectorRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the selector on the element provided.
*
* @returns {Element} Returns the Node that was found by the selector or null
*/
SelectorRummager.prototype.retrieve = function()
{
return this.rummageThrough.querySelector(this.rummageFor) ;
}
SelectorRummager.prototype.name = 'SelectorRummager' ;
module.exports = SelectorRummager
},{"./Rummager":111}],114:[function(require,module,exports){
var Rummager = require('./Rummager') ;
/**
* Rummager object for trimming whitespace from the end of the provided string
*
* @returns {TrimRummager} An instance of TrimRummager
*/
function TrimRummager()
{
//Call super constructor and pass value
Rummager.apply(this,arguments) ;
}
//A subclass of Rummager
TrimRummager.prototype = Object.create(Rummager.prototype) ;
/**
* Run this Rummager
* The retrieve method is part of the API and will initiate execution of this Rummager
* using the re on the string provided.
*
* @returns {String} Returns the replacement of the re operation on str or null
*/
TrimRummager.prototype.retrieve = function()
{
if(this.rummageThrough === null)
{
return null ;
}
return this.rummageThrough.toString().trim() ;
}
TrimRummager.prototype.name = 'TrimRummager' ;
module.exports = TrimRummager
},{"./Rummager":111}],115:[function(require,module,exports){
/**
* AxiosAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @typedef {Object} RummageAgentResponse
* @property {number} status The status response code of the request
* @property {string} statusText The status response message from server
* @property {Object} headers The headers and values of the response as an property list
* @property {string} data The response body (html) from the server as a string
*/
var RummageAgentAdapter = require('./RummageAgentAdapter') ;
var RummageError = require('../RummageError') ;
var isUrl = require('is-url') ;
var isPromise = require('is-promise') ;
/**
* RummageAgentAdapter for Axios.
*
* @implements {RummageAgentAdapter}
* @param {function} [axios] Axios constructor function
* @param {object} [options] options for fetching html using axios
* @constructor
*/
function AxiosAdapter(axios,options)
{
RummageAgentAdapter.call(this,axios,options) ;
}
AxiosAdapter.prototype = Object.create(RummageAgentAdapter.prototype) ;
/**
* Fetch html using this adapter
* @param {Object|string} request Either a configured instance of axios that resolves to HTML source, or a string representing a request URI that the axios constructor provided can generate a request from.
* @returns {RummageAgentResponse} The response from the agent request
*/
AxiosAdapter.prototype.fetch = function(request)
{
var self = this ;
// If .through() not called on Rummage, then reject
if(request === undefined || request === null)
return Promise.reject(new RummageError(".through() not called on Rummage")) ;
// If request is a promise, treat it like an instance of axios and call then
// to attempt to resolve the promise and retrieve the html
if(isPromise(request))
{
return new Promise(function (resolve, reject) {
request.then(function (res) {
self.response = setResponse(res) ;
resolve(self.response) ;
})
.catch(function(res) {
reject(setResponse(res)) ;
}) ;
}) ;
}
// If a url is provided, then use axios to 'GET' the url and resolve the promise
if(isUrl(request))
{
return new Promise(function (resolve, reject) {
self.agent.get(request,self.options).then(function (res) {
self.response = setResponse(res) ;
resolve(self.response) ;
})
.catch(function (reason) {
reject(reason) ;
}) ;
}) ;
}
return Promise.reject(new RummageError("Unable to process data passed to .through() method Rummage: "+request)) ;
} ;
/**
* Given response from request by axios, extract RummageAgentResponse fields and return
* @private
* @param {Object} response Response object from axios request
* @returns {RummageAgentResponse} response
*/
function setResponse(response)
{
var r =
{
status: response.status,
statusText: response.statusText,
headers: response.headers,
data: response.data
} ;
return r ;
}
module.exports = AxiosAdapter ;
},{"../RummageError":109,"./RummageAgentAdapter":116,"is-promise":137,"is-url":138}],116:[function(require,module,exports){
/**
* RummageAgentAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @typedef {Object} RummageAgentResponse
* @property {number} status The status response code of the request
* @property {string} statusText The status response message from server
* @property {Object} headers The headers and values of the response as an property list
* @property {string} data The response body (html) from the server as a string
*/
var RummageError = require('../RummageError') ;
/**
* Abstract interface for writing download agent adapters for Rummage.
*
* @interface
* @param {Object} agent Constructor function for this adapters agent
* @param {Object} [options] Options to be passed to the agent constructor
* @constructor
*/
function RummageAgentAdapter(agent,options)
{
/**
* Instance of agent object to use
* @type {Object}
*/
this.agent = agent ;
/**
* Options to provide to instance of agent (if it accepts options)
* @type {Object}
*/
this.options = options ;
/**
* Store the response object from last agent request
* @type {RummageAgentResponse}
*/
this.response = null ;
}
/**
* Fetch html using this adapter
* @param {Object|string} [request] An object describing the request, or a url expressed as a string
* @returns {Object} Object containing a standardised responses from the agent request
* @returns {RummageAgentResponse} The response from the agent request
*/
RummageAgentAdapter.prototype.fetch = function(request)
{
throw new RummageError("You must define your own fetch() function") ;
} ;
module.exports = RummageAgentAdapter ;
/**
* Return the response object from the last request by this agent
* @returns {RummageAgentResponse|*}
*/
RummageAgentAdapter.prototype.getResponse = function()
{
return this.response ;
} ;
},{"../RummageError":109}],117:[function(require,module,exports){
/**
* SuperAgentAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @typedef {Object} RummageAgentResponse
* @property {number} status The status response code of the request
* @property {string} statusText The status response message from server
* @property {Object} headers The headers and values of the response as an property list
* @property {string} data The response body (html) from the server as a string
*/
var RummageAgentAdapter = require('./RummageAgentAdapter') ;
var RummageError = require('../RummageError') ;
var clone = require('clone') ;
var isUrl = require('is-url') ;
var agent = require('superagent-declare') ;
var isPromise = require('is-promise') ;
/**
* RummageAgentAdapter for Superagent.
*
* @implements {RummageAgentAdapter}
* @param {function} [superagent] Superagent constructor function
* @param {object} [options] options for fetching html using superagent
* @constructor
*/
function SuperagentAdapter(superagent, options)
{
RummageAgentAdapter.call(this,superagent,options) ;
}
SuperagentAdapter.prototype = Object.create(RummageAgentAdapter.prototype) ;
/**
* Fetch html using this adapter
* @param {Object|string} request Either a configured instance of superagent that resolves to HTML source, or a string representing a request URI that the superagent constructor provided can generate a request from.
* @returns {RummageAgentResponse} The response from the agent request
*/
SuperagentAdapter.prototype.fetch = function(request)
{
var self = this ;
// If .through() not called on Rummage, then reject
if(request === undefined || request === null)
return Promise.reject(new RummageError(".through() not called on Rummage")) ;
// If request is a promise, treat it like an instance of superagent and call then
// to attempt to resolve the promise and retrieve the html
if(isPromise(request))
{
return new Promise(function (resolve, reject) {
request.then(function (res) {
self.response = setResponse(res) ;
if (res.ok)
resolve(self.response) ;
else
reject(self.response) ;
})
.catch(function(res) {
reject(setResponse(res)) ;
}) ;
}) ;
}
// If a url is provided, then use superagent to 'GET' the url and resolve the promise
if(isUrl(request))
{
return new Promise(function (resolve, reject) {
var opts = clone(self.options) || {} ;
opts.get = request ;
agent(opts,self.agent).then(function (res) {
self.response = setResponse(res) ;
if (res.ok)
resolve(self.response) ;
else
reject(self.response) ;
}) ;
}) ;
}
return Promise.reject(new RummageError("Unable to process data passed to .through() method Rummage: "+request)) ;
} ;
/**
* Given response from request by superagent, extract RummageAgentResponse fields and return
* @private
* @param {Object} response Response object from superagent request
* @returns {RummageAgentResponse} response
*/
function setResponse(response)
{
var r =
{
status: response.status,
statusText: '',
headers: response.header,
data: response.text
} ;
return r ;
}
module.exports = SuperagentAdapter ;
},{"../RummageError":109,"./RummageAgentAdapter":116,"clone":128,"is-promise":137,"is-url":138,"superagent-declare":142}],118:[function(require,module,exports){
/**
* xhrAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var RummageAgentAdapter = require('./RummageAgentAdapter') ;
var RummageError = require('../RummageError') ;
var isUrl = require('is-url') ;
var isPromise = require('is-promise') ;
/**
* RummageAgentAdapter for XMLHttpRequest.
*
* @implements {RummageAgentAdapter}
* @param {function} [xhr] XMLHttpRequest compatible function or undefined
* @param {object} [options] xhr options for fetching html
* @constructor
*/
function XHRAdapter(xhr, options)
{
if(this.agent === undefined && XMLHttpRequest !== undefined)
this.agent = XMLHttpRequest ;
else if(XMLHttpRequest === undefined)
throw new RummageError('No XMLHttpRequest object available - are you not running in a browser?') ;
RummageAgentAdapter.call(this,XMLHttpRequest,options) ;
}
XHRAdapter.prototype = Object.create(RummageAgentAdapter.prototype) ;
/**
* Fetch html using this adapter
* @param {Object|string} request Either a configured instance of xhr that has not has .send() method called, or a string representing a request URI
* @returns {RummageAgentResponse} The response from the agent request
*/
XHRAdapter.prototype.fetch = function(request)
{
var self = this ;
// If .through() not called on Rummage, then reject
if(request === undefined || request === null)
return Promise.reject(new RummageError(".through() not called on Rummage")) ;
// If request is a promise, treat it like an instance of a promisified xhr instance (such as provided by jquery .ajax
// and call then to attempt to resolve the promise and retrieve the html
if(isPromise(request))
{
return new Promise(function (resolve, reject) {
request.then(function (data,textStatus,r) {
self.response = setResponse(r) ;
resolve(self.response) ;
}, function(r) {
reject(r) ;
}) ;
}) ;
}
if(typeof request === 'object' && 'open' in request)
{
var r = request ;
return new Promise(function (resolve, reject) {
r.onreadystatechange = function()
{
if(r.readyState === XMLHttpRequest.DONE && r.status === 200)
{
self.response = setResponse(r) ;
resolve(self.response) ;
}
else if(r.readyState === XMLHttpRequest.DONE)
{
reject(setResponse(r)) ;
}
} ;
r.send() ;
}) ;
}
// If a url is provided, then use xhr to 'GET' the url and return the html
if(isUrl(request))
{
return new Promise(function (resolve, reject) {
var r = new self.agent() ;
r.open('get',request) ;
r.onreadystatechange = function()
{
if(r.readyState === XMLHttpRequest.DONE && r.status === 200)
{
self.response = setResponse(r) ;
resolve(self.response) ;
}
else if(r.readyState === XMLHttpRequest.DONE)
{
reject(setResponse(r)) ;
}
} ;
r.send() ;
}) ;
}
return Promise.reject(new RummageError("Unable to process data passed to .through() method Rummage: "+request)) ;
} ;
/**
* Given response from request by xhr, extract RummageAgentResponse fields and return
* @private
* @param {Object} xhr xhr instance containing response properties from request
* @returns {RummageAgentResponse} response
*/
function setResponse(xhr)
{
var r =
{
status: xhr.status,
statusText: xhr.statusText,
headers: xhr.getAllResponseHeaders(),
data: xhr.responseXML || xhr.responseText // If parsed HTML, otherwise raw response
} ;
return r ;
}
module.exports = XHRAdapter ;
},{"../RummageError":109,"./RummageAgentAdapter":116,"is-promise":137,"is-url":138}],119:[function(require,module,exports){
/**
* CheerioAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var RummageParserAdapter = require('./RummageParserAdapter') ;
var RummageError = require('../RummageError') ;
/**
* RummageParserAdapter for cheerio.
*
* @implements {RummageParserAdapter}
* @param {function} [cheerio] cheerio constructor function or instance
* @param {object} [options] cheerio options for parsing
* @todo This class needs to be implemented
* @constructor
*/
function CheerioAdapter(cheerio,options)
{
throw new RummageError("This hasn't been implemented yet") ;
}
CheerioAdapter.prototype = Object.create(RummageParserAdapter.prototype) ;
module.exports = CheerioAdapter ;
},{"../RummageError":109,"./RummageParserAdapter":122}],120:[function(require,module,exports){
/**
* DOMParserAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var RummageParserAdapter = require('./RummageParserAdapter') ;
var isHtml = require('is-html') ;
var RummageError = require('../RummageError') ;
/**
* RummageParserAdapter for browser DOMParser implementation.
*
* @implements {RummageParserAdapter}
* @param {function} [parser] DOMParser equivalent function or if undefined, global DOMParser
* @param {string} [mime] Mime type of source (if undefined, defaults to text/html)
* @constructor
*/
function DOMParserAdapter(parser,mime)
{
if(typeof parser !== 'function')
{
try { new DOMParser(); }
catch(err)
{
throw new RummageError('Attempting to use DOMParser in non-browser environment - no DOMParser defined') ;
}
parser = DOMParser ;
}
var options = (typeof mime === 'string') ? mime : 'text/html' ;
RummageParserAdapter.call(this,parser,options) ;
}
DOMParserAdapter.prototype = Object.create(RummageParserAdapter.prototype) ;
/**
* @todo Requires jsdoc
* @param rummage
*/
DOMParserAdapter.prototype.parse = function(rummage)
{
var parser = new this.parser() ;
var mime = this.options ;
return new Promise(function(resolve,reject)
{
if(isHtml(rummage.html))
{
var doc = parser.parseFromString(rummage.html, mime) ;
// @todo Need to implement error checking here for different browser implementations
resolve(doc) ;
}
else
{
reject(new RummageError("No 'html' for DOMParser to parse")) ;
}
}) ;
} ;
module.exports = DOMParserAdapter ;
},{"../RummageError":109,"./RummageParserAdapter":122,"is-html":134}],121:[function(require,module,exports){
/**
* JSDomAdapter
*
* 18/02/2017
*
* Copyright (C) 2017 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var isHtml = require('is-html') ;
var isUrl = require('is-url') ;
var RummageParserAdapter = require('./RummageParserAdapter') ;
var RummageError = require('../RummageError') ;
/**
* RummageParserAdapter for jsdom.
*
* @implements {RummageParserAdapter}
* @param {object} [jsdom] require('jsdom') module
* @param {object} [options] jsdom options for parsing {@see jsdom}
* @constructor
*/
function JSDomAdapter(jsdom,options)
{
if(jsdom === undefined)
{
throw new RummageError("Must provide jsdom object to constructor");
}
if(options === undefined)
{
options = {};
}
RummageParserAdapter.call(this,jsdom,options) ;
// Now this.parser = jsdom & this.options = options
}
JSDomAdapter.prototype = Object.create(RummageParserAdapter.prototype) ;
JSDomAdapter.prototype.parse = function(rummage)
{
var jsdom = this.parser ;
// Merge
var options = {} ;
for (var attrname in this.options)
{
if(this.options.hasOwnProperty(attrname))
options[attrname] = this.options[attrname] ;
}
// If we have a url source for our html, then set that property too
if(isUrl(rummage.url))
{
options.url = rummage.url ;
}
// jsdom.JSDOM (new v10+) API
if ('JSDOM' in jsdom)
return new Promise(function(resolve,reject)
{
try
{
var dom = new jsdom.JSDOM(rummage.html,options) ;
resolve(dom.window.document) ;
}
catch(err)
{
reject(err) ;
}
}) ;
// jsdom.env old API
return new Promise(function(resolve,reject)
{
if(isHtml(rummage.html))
{
options.html = rummage.html ;
}
var userDone = ('done' in options) ? options.done : null ;
options.done = function(err,window)
{
// If jsdom options from called already included a done
// callback, then call it first before we operate on DOM
if(userDone !== undefined && typeof userDone === 'function')
userDone(err,window) ;
if(err) reject(err) ;
resolve(window.document) ;
} ;
if(options.hasOwnProperty('url') || options.hasOwnProperty('html'))
{
jsdom.env(options);
}
else
{
throw new RummageError("No 'url' or 'html' for jsdom to parse") ;
}
}) ;
} ;
module.exports = JSDomAdapter ;
},{"../RummageError":109,"./RummageParserAdapter":122,"is-html":134,"is-url":138}],122:[function(require,module,exports){
/**
* RummageParserAdapter
*
* 18/02/2017
*
* Copyright (C) 2016 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Abstract interface for writing HTML parser adapters for Rummage.
*
* @interface
* @param {object} parser Class that can parse HTML
* @param {object} [options] Options to be passed to the parser object
* @constructor
*/
function RummageParserAdapter(parser,options)
{
/**
* Instance of parser object to use
* @type {Object}
*/
this.parser = parser ;
/**
* Options to provide to instance of parser (if it accepts options)
* @type {Object}
*/
this.options = options ;
}
/**
* Parse HTML source provided to Rummage object instance
*
* @abstract
* @param {Rummage} rummage A rummage instance containing the HTML source
*/
RummageParserAdapter.prototype.parse = function(rummage)
{
throw new RummageError("You must define your own parse() function") ;
} ;
module.exports = RummageParserAdapter ;
},{}],123:[function(require,module,exports){
/**
* processForDataTypes.js
*
* Custom handlers depending on data types of .for() arguments
*
* rummage
*
* 2/12/17
*
* Copyright (C) 2017 Damien Clark (damo.clarky@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
function processForDataTypes(node,handlers)
{
if(typeof node === 'object')
{
if(node instanceof Rummager)
handlers['Rummager'].call(null) ;
else if(node instanceof RegExp)
handlers['RegExp'].call(null) ;
else if(node instanceof ArgumentTemplate)
handlers['ArgumentTemplate'].call(null) ;
else if(node instanceof Argument)
handlers['Argument'].call(null) ;
else if(node === null)
handlers['Null'].call(null) ;
else if(Array.isArray(node))
handlers['Array'].call(null) ;
else // Assume generic {} object
handlers['Object'].call(null) ;
}
else if(typeof node === 'function')
handlers['Function'].call(null) ;
else if(node === undefined)
handlers['Undefined'].call(null) ;
else // Assume primitive type
handlers['Primitive'].call(null) ;
}
module.exports = processForDataTypes ;
// Required after export to solve circular require issue
// https://coderwall.com/p/myzvmg/circular-dependencies-in-node-js
var Rummager = require('./Rummager') ;
var Argument = require('./Argument') ;
var ArgumentTemplate = require('./ArgumentTemplate') ;
},{"./Argument":90,"./ArgumentTemplate":91,"./Rummager":111}],124:[function(require,module,exports){
/*!
* URI.js - Mutating URLs
* IPv6 Support
*
* Version: 1.16.1
*
* Author: Rodney Rehm
* Web: http://medialize.github.io/URI.js/
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* GPL v3 http://opensource.org/licenses/GPL-3.0
*
*/
(function (root, factory) {
'use strict';
// https://github.com/umdjs/umd/blob/master/returnExports.js
if (typeof exports === 'object') {
// Node
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals (root is window)
root.IPv6 = factory(root);
}
}(this, function (root) {
'use strict';
/*
var _in = "fe80:0000:0000:0000:0204:61ff:fe9d:f156";
var _out = IPv6.best(_in);
var _expected = "fe80::204:61ff:fe9d:f156";
console.log(_in, _out, _expected, _out === _expected);
*/
// save current IPv6 variable, if any
var _IPv6 = root && root.IPv6;
function bestPresentation(address) {
// based on:
// Javascript to test an IPv6 address for proper format, and to
// present the "best text representation" according to IETF Draft RFC at
// http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04
// 8 Feb 2010 Rich Brown, Dartware, LLC
// Please feel free to use this code as long as you provide a link to
// http://www.intermapper.com
// http://intermapper.com/support/tools/IPV6-Validator.aspx
// http://download.dartware.com/thirdparty/ipv6validator.js
var _address = address.toLowerCase();
var segments = _address.split(':');
var length = segments.length;
var total = 8;
// trim colons (:: or ::a:b:c… or …a:b:c::)
if (segments[0] === '' && segments[1] === '' && segments[2] === '') {
// must have been ::
// remove first two items
segments.shift();
segments.shift();
} else if (segments[0] === '' && segments[1] === '') {
// must have been ::xxxx
// remove the first item
segments.shift();
} else if (segments[length - 1] === '' && segments[length - 2] === '') {
// must have been xxxx::
segments.pop();
}
length = segments.length;
// adjust total segments for IPv4 trailer
if (segments[length - 1].indexOf('.') !== -1) {
// found a "." which means IPv4
total = 7;
}
// fill empty segments them with "0000"
var pos;
for (pos = 0; pos < length; pos++) {
if (segments[pos] === '') {
break;
}
}
if (pos < total) {
segments.splice(pos, 1, '0000');
while (segments.length < total) {
segments.splice(pos, 0, '0000');
}
length = segments.length;
}
// strip leading zeros
var _segments;
for (var i = 0; i < total; i++) {
_segments = segments[i].split('');
for (var j = 0; j < 3 ; j++) {
if (_segments[0] === '0' && _segments.length > 1) {
_segments.splice(0,1);
} else {
break;
}
}
segments[i] = _segments.join('');
}
// find longest sequence of zeroes and coalesce them into one segment
var best = -1;
var _best = 0;
var _current = 0;
var current = -1;
var inzeroes = false;
// i; already declared
for (i = 0; i < total; i++) {
if (inzeroes) {
if (segments[i] === '0') {
_current += 1;
} else {
inzeroes = false;
if (_current > _best) {
best = current;
_best = _current;
}
}
} else {
if (segments[i] === '0') {
inzeroes = true;
current = i;
_current = 1;
}
}
}
if (_current > _best) {
best = current;
_best = _current;
}
if (_best > 1) {
segments.splice(best, _best, '');
}
length = segments.length;
// assemble remaining segments
var result = '';
if (segments[0] === '') {
result = ':';
}
for (i = 0; i < length; i++) {
result += segments[i];
if (i === length - 1) {
break;
}
result += ':';
}
if (segments[length - 1] === '') {
result += ':';
}
return result;
}
function noConflict() {
/*jshint validthis: true */
if (root.IPv6 === this) {
root.IPv6 = _IPv6;
}
return this;
}
return {
best: bestPresentation,
noConflict: noConflict
};
}));
},{}],125:[function(require,module,exports){
/*!
* URI.js - Mutating URLs
* Second Level Domain (SLD) Support
*
* Version: 1.16.1
*
* Author: Rodney Rehm
* Web: http://medialize.github.io/URI.js/
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* GPL v3 http://opensource.org/licenses/GPL-3.0
*
*/
(function (root, factory) {
'use strict';
// https://github.com/umdjs/umd/blob/master/returnExports.js
if (typeof exports === 'object') {
// Node
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals (root is window)
root.SecondLevelDomains = factory(root);
}
}(this, function (root) {
'use strict';
// save current SecondLevelDomains variable, if any
var _SecondLevelDomains = root && root.SecondLevelDomains;
var SLD = {
// list of known Second Level Domains
// converted list of SLDs from https://github.com/gavingmiller/second-level-domains
// ----
// publicsuffix.org is more current and actually used by a couple of browsers internally.
// downside is it also contains domains like "dyndns.org" - which is fine for the security
// issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js
// ----
list: {
'ac':' com gov mil net org ',
'ae':' ac co gov mil name net org pro sch ',
'af':' com edu gov net org ',
'al':' com edu gov mil net org ',
'ao':' co ed gv it og pb ',
'ar':' com edu gob gov int mil net org tur ',
'at':' ac co gv or ',
'au':' asn com csiro edu gov id net org ',
'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ',
'bb':' biz co com edu gov info net org store tv ',
'bh':' biz cc com edu gov info net org ',
'bn':' com edu gov net org ',
'bo':' com edu gob gov int mil net org tv ',
'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ',
'bs':' com edu gov net org ',
'bz':' du et om ov rg ',
'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ',
'ck':' biz co edu gen gov info net org ',
'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ',
'co':' com edu gov mil net nom org ',
'cr':' ac c co ed fi go or sa ',
'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ',
'do':' art com edu gob gov mil net org sld web ',
'dz':' art asso com edu gov net org pol ',
'ec':' com edu fin gov info med mil net org pro ',
'eg':' com edu eun gov mil name net org sci ',
'er':' com edu gov ind mil net org rochest w ',
'es':' com edu gob nom org ',
'et':' biz com edu gov info name net org ',
'fj':' ac biz com info mil name net org pro ',
'fk':' ac co gov net nom org ',
'fr':' asso com f gouv nom prd presse tm ',
'gg':' co net org ',
'gh':' com edu gov mil org ',
'gn':' ac com gov net org ',
'gr':' com edu gov mil net org ',
'gt':' com edu gob ind mil net org ',
'gu':' com edu gov net org ',
'hk':' com edu gov idv net org ',
'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ',
'id':' ac co go mil net or sch web ',
'il':' ac co gov idf k12 muni net org ',
'in':' ac co edu ernet firm gen gov i ind mil net nic org res ',
'iq':' com edu gov i mil net org ',
'ir':' ac co dnssec gov i id net org sch ',
'it':' edu gov ',
'je':' co net org ',
'jo':' com edu gov mil name net org sch ',
'jp':' ac ad co ed go gr lg ne or ',
'ke':' ac co go info me mobi ne or sc ',
'kh':' com edu gov mil net org per ',
'ki':' biz com de edu gov info mob net org tel ',
'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ',
'kn':' edu gov net org ',
'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ',
'kw':' com edu gov net org ',
'ky':' com edu gov net org ',
'kz':' com edu gov mil net org ',
'lb':' com edu gov net org ',
'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ',
'lr':' com edu gov net org ',
'lv':' asn com conf edu gov id mil net org ',
'ly':' com edu gov id med net org plc sch ',
'ma':' ac co gov m net org press ',
'mc':' asso tm ',
'me':' ac co edu gov its net org priv ',
'mg':' com edu gov mil nom org prd tm ',
'mk':' com edu gov inf name net org pro ',
'ml':' com edu gov net org presse ',
'mn':' edu gov org ',
'mo':' com edu gov net org ',
'mt':' com edu gov net org ',
'mv':' aero biz com coop edu gov info int mil museum name net org pro ',
'mw':' ac co com coop edu gov int museum net org ',
'mx':' com edu gob net org ',
'my':' com edu gov mil name net org sch ',
'nf':' arts com firm info net other per rec store web ',
'ng':' biz com edu gov mil mobi name net org sch ',
'ni':' ac co com edu gob mil net nom org ',
'np':' com edu gov mil net org ',
'nr':' biz com edu gov info net org ',
'om':' ac biz co com edu gov med mil museum net org pro sch ',
'pe':' com edu gob mil net nom org sld ',
'ph':' com edu gov i mil net ngo org ',
'pk':' biz com edu fam gob gok gon gop gos gov net org web ',
'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ',
'pr':' ac biz com edu est gov info isla name net org pro prof ',
'ps':' com edu gov net org plo sec ',
'pw':' belau co ed go ne or ',
'ro':' arts com firm info nom nt org rec store tm www ',
'rs':' ac co edu gov in org ',
'sb':' com edu gov net org ',
'sc':' com edu gov net org ',
'sh':' co com edu gov net nom org ',
'sl':' com edu gov net org ',
'st':' co com consulado edu embaixada gov mil net org principe saotome store ',
'sv':' com edu gob org red ',
'sz':' ac co org ',
'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ',
'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ',
'tw':' club com ebiz edu game gov idv mil net org ',
'mu':' ac co com gov net or org ',
'mz':' ac co edu gov org ',
'na':' co com ',
'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ',
'pa':' abo ac com edu gob ing med net nom org sld ',
'pt':' com edu gov int net nome org publ ',
'py':' com edu gov mil net org ',
'qa':' com edu gov mil net org ',
're':' asso com nom ',
'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ',
'rw':' ac co com edu gouv gov int mil net ',
'sa':' com edu gov med net org pub sch ',
'sd':' com edu gov info med net org tv ',
'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ',
'sg':' com edu gov idn net org per ',
'sn':' art com edu gouv org perso univ ',
'sy':' com edu gov mil net news org ',
'th':' ac co go in mi net or ',
'tj':' ac biz co com edu go gov info int mil name net nic org test web ',
'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ',
'tz':' ac co go ne or ',
'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ',
'ug':' ac co go ne or org sc ',
'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ',
'us':' dni fed isa kids nsn ',
'uy':' com edu gub mil net org ',
've':' co com edu gob info mil net org web ',
'vi':' co com k12 net org ',
'vn':' ac biz com edu gov health info int name net org pro ',
'ye':' co com gov ltd me net org plc ',
'yu':' ac co edu gov org ',
'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ',
'zm':' ac co com edu gov net org sch '
},
// gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost
// in both performance and memory footprint. No initialization required.
// http://jsperf.com/uri-js-sld-regex-vs-binary-search/4
// Following methods use lastIndexOf() rather than array.split() in order
// to avoid any memory allocations.
has: function(domain) {
var tldOffset = domain.lastIndexOf('.');
if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {
return false;
}
var sldOffset = domain.lastIndexOf('.', tldOffset-1);
if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {
return false;
}
var sldList = SLD.list[domain.slice(tldOffset+1)];
if (!sldList) {
return false;
}
return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0;
},
is: function(domain) {
var tldOffset = domain.lastIndexOf('.');
if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {
return false;
}
var sldOffset = domain.lastIndexOf('.', tldOffset-1);
if (sldOffset >= 0) {
return false;
}
var sldList = SLD.list[domain.slice(tldOffset+1)];
if (!sldList) {
return false;
}
return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0;
},
get: function(domain) {
var tldOffset = domain.lastIndexOf('.');
if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {
return null;
}
var sldOffset = domain.lastIndexOf('.', tldOffset-1);
if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {
return null;
}
var sldList = SLD.list[domain.slice(tldOffset+1)];
if (!sldList) {
return null;
}
if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) {
return null;
}
return domain.slice(sldOffset+1);
},
noConflict: function(){
if (root.SecondLevelDomains === this) {
root.SecondLevelDomains = _SecondLevelDomains;
}
return this;
}
};
return SLD;
}));
},{}],126:[function(require,module,exports){
/*!
* URI.js - Mutating URLs
*
* Version: 1.16.1
*
* Author: Rodney Rehm
* Web: http://medialize.github.io/URI.js/
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* GPL v3 http://opensource.org/licenses/GPL-3.0
*
*/
(function (root, factory) {
'use strict';
// https://github.com/umdjs/umd/blob/master/returnExports.js
if (typeof exports === 'object') {
// Node
module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['./punycode', './IPv6', './SecondLevelDomains'], factory);
} else {
// Browser globals (root is window)
root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);
}
}(this, function (punycode, IPv6, SLD, root) {
'use strict';
/*global location, escape, unescape */
// FIXME: v2.0.0 renamce non-camelCase properties to uppercase
/*jshint camelcase: false */
// save current URI variable, if any
var _URI = root && root.URI;
function URI(url, base) {
var _urlSupplied = arguments.length >= 1;
var _baseSupplied = arguments.length >= 2;
// Allow instantiation without the 'new' keyword
if (!(this instanceof URI)) {
if (_urlSupplied) {
if (_baseSupplied) {
return new URI(url, base);
}
return new URI(url);
}
return new URI();
}
if (url === undefined) {
if (_urlSupplied) {
throw new TypeError('undefined is not a valid argument for URI');
}
if (typeof location !== 'undefined') {
url = location.href + '';
} else {
url = '';
}
}
this.href(url);
// resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor
if (base !== undefined) {
return this.absoluteTo(base);
}
return this;
}
URI.version = '1.16.1';
var p = URI.prototype;
var hasOwn = Object.prototype.hasOwnProperty;
function escapeRegEx(string) {
// https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963
return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
}
function getType(value) {
// IE8 doesn't return [Object Undefined] but [Object Object] for undefined value
if (value === undefined) {
return 'Undefined';
}
return String(Object.prototype.toString.call(value)).slice(8, -1);
}
function isArray(obj) {
return getType(obj) === 'Array';
}
function filterArrayValues(data, value) {
var lookup = {};
var i, length;
if (getType(value) === 'RegExp') {
lookup = null;
} else if (isArray(value)) {
for (i = 0, length = value.length; i < length; i++) {
lookup[value[i]] = true;
}
} else {
lookup[value] = true;
}
for (i = 0, length = data.length; i < length; i++) {
/*jshint laxbreak: true */
var _match = lookup && lookup[data[i]] !== undefined
|| !lookup && value.test(data[i]);
/*jshint laxbreak: false */
if (_match) {
data.splice(i, 1);
length--;
i--;
}
}
return data;
}
function arrayContains(list, value) {
var i, length;
// value may be string, number, array, regexp
if (isArray(value)) {
// Note: this can be optimized to O(n) (instead of current O(m * n))
for (i = 0, length = value.length; i < length; i++) {
if (!arrayContains(list, value[i])) {
return false;
}
}
return true;
}
var _type = getType(value);
for (i = 0, length = list.length; i < length; i++) {
if (_type === 'RegExp') {
if (typeof list[i] === 'string' && list[i].match(value)) {
return true;
}
} else if (list[i] === value) {
return true;
}
}
return false;
}
function arraysEqual(one, two) {
if (!isArray(one) || !isArray(two)) {
return false;
}
// arrays can't be equal if they have different amount of content
if (one.length !== two.length) {
return false;
}
one.sort();
two.sort();
for (var i = 0, l = one.length; i < l; i++) {
if (one[i] !== two[i]) {
return false;
}
}
return true;
}
URI._parts = function() {
return {
protocol: null,
username: null,
password: null,
hostname: null,
urn: null,
port: null,
path: null,
query: null,
fragment: null,
// state
duplicateQueryParameters: URI.duplicateQueryParameters,
escapeQuerySpace: URI.escapeQuerySpace
};
};
// state: allow duplicate query parameters (a=1&a=1)
URI.duplicateQueryParameters = false;
// state: replaces + with %20 (space in query strings)
URI.escapeQuerySpace = true;
// static properties
URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;
URI.idn_expression = /[^a-z0-9\.-]/i;
URI.punycode_expression = /(xn--)/i;
// well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?
URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
// credits to Rich Brown
// source: http://forums.intermapper.com/viewtopic.php?p=1096#1096
// specification: http://www.ietf.org/rfc/rfc4291.txt
URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
// expression used is "gruber revised" (@gruber v2) determined to be the
// best solution in a regex-golf we did a couple of ages ago at
// * http://mathiasbynens.be/demo/url-regex
// * http://rodneyrehm.de/t/url-regex.html
URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig;
URI.findUri = {
// valid "scheme://" or "www."
start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,
// everything up to the next whitespace
end: /[\s\r\n]|$/,
// trim trailing punctuation captured by end RegExp
trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/
};
// http://www.iana.org/assignments/uri-schemes.html
// http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
URI.defaultPorts = {
http: '80',
https: '443',
ftp: '21',
gopher: '70',
ws: '80',
wss: '443'
};
// allowed hostname characters according to RFC 3986
// ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded
// I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . -
URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/;
// map DOM Elements to their URI attribute
URI.domAttributes = {
'a': 'href',
'blockquote': 'cite',
'link': 'href',
'base': 'href',
'script': 'src',
'form': 'action',
'img': 'src',
'area': 'href',
'iframe': 'src',
'embed': 'src',
'source': 'src',
'track': 'src',
'input': 'src', // but only if type="image"
'audio': 'src',
'video': 'src'
};
URI.getDomAttribute = function(node) {
if (!node || !node.nodeName) {
return undefined;
}
var nodeName = node.nodeName.toLowerCase();
// <input> should only expose src for type="image"
if (nodeName === 'input' && node.type !== 'image') {
return undefined;
}
return URI.domAttributes[nodeName];
};
function escapeForDumbFirefox36(value) {
// https://github.com/medialize/URI.js/issues/91
return escape(value);
}
// encoding / decoding according to RFC3986
function strictEncodeURIComponent(string) {
// see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent
return encodeURIComponent(string)
.replace(/[!'()*]/g, escapeForDumbFirefox36)
.replace(/\*/g, '%2A');
}
URI.encode = strictEncodeURIComponent;
URI.decode = decodeURIComponent;
URI.iso8859 = function() {
URI.encode = escape;
URI.decode = unescape;
};
URI.unicode = function() {
URI.encode = strictEncodeURIComponent;
URI.decode = decodeURIComponent;
};
URI.characters = {
pathname: {
encode: {
// RFC3986 2.1: For consistency, URI producers and normalizers should
// use uppercase hexadecimal digits for all percent-encodings.
expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,
map: {
// -._~!'()*
'%24': '$',
'%26': '&',
'%2B': '+',
'%2C': ',',
'%3B': ';',
'%3D': '=',
'%3A': ':',
'%40': '@'
}
},
decode: {
expression: /[\/\?#]/g,
map: {
'/': '%2F',
'?': '%3F',
'#': '%23'
}
}
},
reserved: {
encode: {
// RFC3986 2.1: For consistency, URI producers and normalizers should
// use uppercase hexadecimal digits for all percent-encodings.
expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,
map: {
// gen-delims
'%3A': ':',
'%2F': '/',
'%3F': '?',
'%23': '#',
'%5B': '[',
'%5D': ']',
'%40': '@',
// sub-delims
'%21': '!',
'%24': '$',
'%26': '&',
'%27': '\'',
'%28': '(',
'%29': ')',
'%2A': '*',
'%2B': '+',
'%2C': ',',
'%3B': ';',
'%3D': '='
}
}
},
urnpath: {
// The characters under `encode` are the characters called out by RFC 2141 as being acceptable
// for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but
// these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also
// note that the colon character is not featured in the encoding map; this is because URI.js
// gives the colons in URNs semantic meaning as the delimiters of path segements, and so it
// should not appear unencoded in a segment itself.
// See also the note above about RFC3986 and capitalalized hex digits.
encode: {
expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,
map: {
'%21': '!',
'%24': '$',
'%27': '\'',
'%28': '(',
'%29': ')',
'%2A': '*',
'%2B': '+',
'%2C': ',',
'%3B': ';',
'%3D': '=',
'%40': '@'
}
},
// These characters are the characters called out by RFC2141 as "reserved" characters that
// should never appear in a URN, plus the colon character (see note above).
decode: {
expression: /[\/\?#:]/g,
map: {
'/': '%2F',
'?': '%3F',
'#': '%23',
':': '%3A'
}
}
}
};
URI.encodeQuery = function(string, escapeQuerySpace) {
var escaped = URI.encode(string + '');
if (escapeQuerySpace === undefined) {
escapeQuerySpace = URI.escapeQuerySpace;
}
return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;
};
URI.decodeQuery = function(string, escapeQuerySpace) {
string += '';
if (escapeQuerySpace === undefined) {
escapeQuerySpace = URI.escapeQuerySpace;
}
try {
return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string);
} catch(e) {
// we're not going to mess with weird encodings,
// give up and return the undecoded original string
// see https://github.com/medialize/URI.js/issues/87
// see https://github.com/medialize/URI.js/issues/92
return string;
}
};
// generate encode/decode path functions
var _parts = {'encode':'encode', 'decode':'decode'};
var _part;
var generateAccessor = function(_group, _part) {
return function(string) {
try {
return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {
return URI.characters[_group][_part].map[c];
});
} catch (e) {
// we're not going to mess with weird encodings,
// give up and return the undecoded original string
// see https://github.com/medialize/URI.js/issues/87
// see https://github.com/medialize/URI.js/issues/92
return string;
}
};
};
for (_part in _parts) {
URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);
URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);
}
var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {
return function(string) {
// Why pass in names of functions, rather than the function objects themselves? The
// definitions of some functions (but in particular, URI.decode) will occasionally change due
// to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure
// that the functions we use here are "fresh".
var actualCodingFunc;
if (!_innerCodingFuncName) {
actualCodingFunc = URI[_codingFuncName];
} else {
actualCodingFunc = function(string) {
return URI[_codingFuncName](URI[_innerCodingFuncName](string));
};
}
var segments = (string + '').split(_sep);
for (var i = 0, length = segments.length; i < length; i++) {
segments[i] = actualCodingFunc(segments[i]);
}
return segments.join(_sep);
};
};
// This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.
URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');
URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');
URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');
URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');
URI.encodeReserved = generateAccessor('reserved', 'encode');
URI.parse = function(string, parts) {
var pos;
if (!parts) {
parts = {};
}
// [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment]
// extract fragment
pos = string.indexOf('#');
if (pos > -1) {
// escaping?
parts.fragment = string.substring(pos + 1) || null;
string = string.substring(0, pos);
}
// extract query
pos = string.indexOf('?');
if (pos > -1) {
// escaping?
parts.query = string.substring(pos + 1) || null;
string = string.substring(0, pos);
}
// extract protocol
if (string.substring(0, 2) === '//') {
// relative-scheme
parts.protocol = null;
string = string.substring(2);
// extract "user:pass@host:port"
string = URI.parseAuthority(string, parts);
} else {
pos = string.indexOf(':');
if (pos > -1) {
parts.protocol = string.substring(0, pos) || null;
if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {
// : may be within the path
parts.protocol = undefined;
} else if (string.substring(pos + 1, pos + 3) === '//') {
string = string.substring(pos + 3);
// extract "user:pass@host:port"
string = URI.parseAuthority(string, parts);
} else {
string = string.substring(pos + 1);
parts.urn = true;
}
}
}
// what's left must be the path
parts.path = string;
// and we're done
return parts;
};
URI.parseHost = function(string, parts) {
// Copy chrome, IE, opera backslash-handling behavior.
// Back slashes before the query string get converted to forward slashes
// See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124
// See: https://code.google.com/p/chromium/issues/detail?id=25916
// https://github.com/medialize/URI.js/pull/233
string = string.replace(/\\/g, '/');
// extract host:port
var pos = string.indexOf('/');
var bracketPos;
var t;
if (pos === -1) {
pos = string.length;
}
if (string.charAt(0) === '[') {
// IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6
// I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts
// IPv6+port in the format [2001:db8::1]:80 (for the time being)
bracketPos = string.indexOf(']');
parts.hostname = string.substring(1, bracketPos) || null;
parts.port = string.substring(bracketPos + 2, pos) || null;
if (parts.port === '/') {
parts.port = null;
}
} else {
var firstColon = string.indexOf(':');
var firstSlash = string.indexOf('/');
var nextColon = string.indexOf(':', firstColon + 1);
if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {
// IPv6 host contains multiple colons - but no port
// this notation is actually not allowed by RFC 3986, but we're a liberal parser
parts.hostname = string.substring(0, pos) || null;
parts.port = null;
} else {
t = string.substring(0, pos).split(':');
parts.hostname = t[0] || null;
parts.port = t[1] || null;
}
}
if (parts.hostname && string.substring(pos).charAt(0) !== '/') {
pos++;
string = '/' + string;
}
return string.substring(pos) || '/';
};
URI.parseAuthority = function(string, parts) {
string = URI.parseUserinfo(string, parts);
return URI.parseHost(string, parts);
};
URI.parseUserinfo = function(string, parts) {
// extract username:password
var firstSlash = string.indexOf('/');
var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);
var t;
// authority@ must come before /path
if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {
t = string.substring(0, pos).split(':');
parts.username = t[0] ? URI.decode(t[0]) : null;
t.shift();
parts.password = t[0] ? URI.decode(t.join(':')) : null;
string = string.substring(pos + 1);
} else {
parts.username = null;
parts.password = null;
}
return string;
};
URI.parseQuery = function(string, escapeQuerySpace) {
if (!string) {
return {};
}
// throw out the funky business - "?"[name"="value"&"]+
string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, '');
if (!string) {
return {};
}
var items = {};
var splits = string.split('&');
var length = splits.length;
var v, name, value;
for (var i = 0; i < length; i++) {
v = splits[i].split('=');
name = URI.decodeQuery(v.shift(), escapeQuerySpace);
// no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters
value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;
if (hasOwn.call(items, name)) {
if (typeof items[name] === 'string' || items[name] === null) {
items[name] = [items[name]];
}
items[name].push(value);
} else {
items[name] = value;
}
}
return items;
};
URI.build = function(parts) {
var t = '';
if (parts.protocol) {
t += parts.protocol + ':';
}
if (!parts.urn && (t || parts.hostname)) {
t += '//';
}
t += (URI.buildAuthority(parts) || '');
if (typeof parts.path === 'string') {
if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {
t += '/';
}
t += parts.path;
}
if (typeof parts.query === 'string' && parts.query) {
t += '?' + parts.query;
}
if (typeof parts.fragment === 'string' && parts.fragment) {
t += '#' + parts.fragment;
}
return t;
};
URI.buildHost = function(parts) {
var t = '';
if (!parts.hostname) {
return '';
} else if (URI.ip6_expression.test(parts.hostname)) {
t += '[' + parts.hostname + ']';
} else {
t += parts.hostname;
}
if (parts.port) {
t += ':' + parts.port;
}
return t;
};
URI.buildAuthority = function(parts) {
return URI.buildUserinfo(parts) + URI.buildHost(parts);
};
URI.buildUserinfo = function(parts) {
var t = '';
if (parts.username) {
t += URI.encode(parts.username);
if (parts.password) {
t += ':' + URI.encode(parts.password);
}
t += '@';
}
return t;
};
URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {
// according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html
// being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed
// the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!
// URI.js treats the query string as being application/x-www-form-urlencoded
// see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type
var t = '';
var unique, key, i, length;
for (key in data) {
if (hasOwn.call(data, key) && key) {
if (isArray(data[key])) {
unique = {};
for (i = 0, length = data[key].length; i < length; i++) {
if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {
t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);
if (duplicateQueryParameters !== true) {
unique[data[key][i] + ''] = true;
}
}
}
} else if (data[key] !== undefined) {
t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);
}
}
}
return t.substring(1);
};
URI.buildQueryParameter = function(name, value, escapeQuerySpace) {
// http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded
// don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization
return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');
};
URI.addQuery = function(data, name, value) {
if (typeof name === 'object') {
for (var key in name) {
if (hasOwn.call(name, key)) {
URI.addQuery(data, key, name[key]);
}
}
} else if (typeof name === 'string') {
if (data[name] === undefined) {
data[name] = value;
return;
} else if (typeof data[name] === 'string') {
data[name] = [data[name]];
}
if (!isArray(value)) {
value = [value];
}
data[name] = (data[name] || []).concat(value);
} else {
throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');
}
};
URI.removeQuery = function(data, name, value) {
var i, length, key;
if (isArray(name)) {
for (i = 0, length = name.length; i < length; i++) {
data[name[i]] = undefined;
}
} else if (getType(name) === 'RegExp') {
for (key in data) {
if (name.test(key)) {
data[key] = undefined;
}
}
} else if (typeof name === 'object') {
for (key in name) {
if (hasOwn.call(name, key)) {
URI.removeQuery(data, key, name[key]);
}
}
} else if (typeof name === 'string') {
if (value !== undefined) {
if (getType(value) === 'RegExp') {
if (!isArray(data[name]) && value.test(data[name])) {
data[name] = undefined;
} else {
data[name] = filterArrayValues(data[name], value);
}
} else if (data[name] === value) {
data[name] = undefined;
} else if (isArray(data[name])) {
data[name] = filterArrayValues(data[name], value);
}
} else {
data[name] = undefined;
}
} else {
throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');
}
};
URI.hasQuery = function(data, name, value, withinArray) {
if (typeof name === 'object') {
for (var key in name) {
if (hasOwn.call(name, key)) {
if (!URI.hasQuery(data, key, name[key])) {
return false;
}
}
}
return true;
} else if (typeof name !== 'string') {
throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter');
}
switch (getType(value)) {
case 'Undefined':
// true if exists (but may be empty)
return name in data; // data[name] !== undefined;
case 'Boolean':
// true if exists and non-empty
var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);
return value === _booly;
case 'Function':
// allow complex comparison
return !!value(data[name], name, data);
case 'Array':
if (!isArray(data[name])) {
return false;
}
var op = withinArray ? arrayContains : arraysEqual;
return op(data[name], value);
case 'RegExp':
if (!isArray(data[name])) {
return Boolean(data[name] && data[name].match(value));
}
if (!withinArray) {
return false;
}
return arrayContains(data[name], value);
case 'Number':
value = String(value);
/* falls through */
case 'String':
if (!isArray(data[name])) {
return data[name] === value;
}
if (!withinArray) {
return false;
}
return arrayContains(data[name], value);
default:
throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');
}
};
URI.commonPath = function(one, two) {
var length = Math.min(one.length, two.length);
var pos;
// find first non-matching character
for (pos = 0; pos < length; pos++) {
if (one.charAt(pos) !== two.charAt(pos)) {
pos--;
break;
}
}
if (pos < 1) {
return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';
}
// revert to last /
if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {
pos = one.substring(0, pos).lastIndexOf('/');
}
return one.substring(0, pos + 1);
};
URI.withinString = function(string, callback, options) {
options || (options = {});
var _start = options.start || URI.findUri.start;
var _end = options.end || URI.findUri.end;
var _trim = options.trim || URI.findUri.trim;
var _attributeOpen = /[a-z0-9-]=["']?$/i;
_start.lastIndex = 0;
while (true) {
var match = _start.exec(string);
if (!match) {
break;
}
var start = match.index;
if (options.ignoreHtml) {
// attribut(e=["']?$)
var attributeOpen = string.slice(Math.max(start - 3, 0), start);
if (attributeOpen && _attributeOpen.test(attributeOpen)) {
continue;
}
}
var end = start + string.slice(start).search(_end);
var slice = string.slice(start, end).replace(_trim, '');
if (options.ignore && options.ignore.test(slice)) {
continue;
}
end = start + slice.length;
var result = callback(slice, start, end, string);
string = string.slice(0, start) + result + string.slice(end);
_start.lastIndex = start + result.length;
}
_start.lastIndex = 0;
return string;
};
URI.ensureValidHostname = function(v) {
// Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)
// they are not part of DNS and therefore ignored by URI.js
if (v.match(URI.invalid_hostname_characters)) {
// test punycode
if (!punycode) {
throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-] and Punycode.js is not available');
}
if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {
throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
}
}
};
// noConflict
URI.noConflict = function(removeAll) {
if (removeAll) {
var unconflicted = {
URI: this.noConflict()
};
if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {
unconflicted.URITemplate = root.URITemplate.noConflict();
}
if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {
unconflicted.IPv6 = root.IPv6.noConflict();
}
if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {
unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();
}
return unconflicted;
} else if (root.URI === this) {
root.URI = _URI;
}
return this;
};
p.build = function(deferBuild) {
if (deferBuild === true) {
this._deferred_build = true;
} else if (deferBuild === undefined || this._deferred_build) {
this._string = URI.build(this._parts);
this._deferred_build = false;
}
return this;
};
p.clone = function() {
return new URI(this);
};
p.valueOf = p.toString = function() {
return this.build(false)._string;
};
function generateSimpleAccessor(_part){
return function(v, build) {
if (v === undefined) {
return this._parts[_part] || '';
} else {
this._parts[_part] = v || null;
this.build(!build);
return this;
}
};
}
function generatePrefixAccessor(_part, _key){
return function(v, build) {
if (v === undefined) {
return this._parts[_part] || '';
} else {
if (v !== null) {
v = v + '';
if (v.charAt(0) === _key) {
v = v.substring(1);
}
}
this._parts[_part] = v;
this.build(!build);
return this;
}
};
}
p.protocol = generateSimpleAccessor('protocol');
p.username = generateSimpleAccessor('username');
p.password = generateSimpleAccessor('password');
p.hostname = generateSimpleAccessor('hostname');
p.port = generateSimpleAccessor('port');
p.query = generatePrefixAccessor('query', '?');
p.fragment = generatePrefixAccessor('fragment', '#');
p.search = function(v, build) {
var t = this.query(v, build);
return typeof t === 'string' && t.length ? ('?' + t) : t;
};
p.hash = function(v, build) {
var t = this.fragment(v, build);
return typeof t === 'string' && t.length ? ('#' + t) : t;
};
p.pathname = function(v, build) {
if (v === undefined || v === true) {
var res = this._parts.path || (this._parts.hostname ? '/' : '');
return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;
} else {
if (this._parts.urn) {
this._parts.path = v ? URI.recodeUrnPath(v) : '';
} else {
this._parts.path = v ? URI.recodePath(v) : '/';
}
this.build(!build);
return this;
}
};
p.path = p.pathname;
p.href = function(href, build) {
var key;
if (href === undefined) {
return this.toString();
}
this._string = '';
this._parts = URI._parts();
var _URI = href instanceof URI;
var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);
if (href.nodeName) {
var attribute = URI.getDomAttribute(href);
href = href[attribute] || '';
_object = false;
}
// window.location is reported to be an object, but it's not the sort
// of object we're looking for:
// * location.protocol ends with a colon
// * location.query != object.search
// * location.hash != object.fragment
// simply serializing the unknown object should do the trick
// (for location, not for everything...)
if (!_URI && _object && href.pathname !== undefined) {
href = href.toString();
}
if (typeof href === 'string' || href instanceof String) {
this._parts = URI.parse(String(href), this._parts);
} else if (_URI || _object) {
var src = _URI ? href._parts : href;
for (key in src) {
if (hasOwn.call(this._parts, key)) {
this._parts[key] = src[key];
}
}
} else {
throw new TypeError('invalid input');
}
this.build(!build);
return this;
};
// identification accessors
p.is = function(what) {
var ip = false;
var ip4 = false;
var ip6 = false;
var name = false;
var sld = false;
var idn = false;
var punycode = false;
var relative = !this._parts.urn;
if (this._parts.hostname) {
relative = false;
ip4 = URI.ip4_expression.test(this._parts.hostname);
ip6 = URI.ip6_expression.test(this._parts.hostname);
ip = ip4 || ip6;
name = !ip;
sld = name && SLD && SLD.has(this._parts.hostname);
idn = name && URI.idn_expression.test(this._parts.hostname);
punycode = name && URI.punycode_expression.test(this._parts.hostname);
}
switch (what.toLowerCase()) {
case 'relative':
return relative;
case 'absolute':
return !relative;
// hostname identification
case 'domain':
case 'name':
return name;
case 'sld':
return sld;
case 'ip':
return ip;
case 'ip4':
case 'ipv4':
case 'inet4':
return ip4;
case 'ip6':
case 'ipv6':
case 'inet6':
return ip6;
case 'idn':
return idn;
case 'url':
return !this._parts.urn;
case 'urn':
return !!this._parts.urn;
case 'punycode':
return punycode;
}
return null;
};
// component specific input validation
var _protocol = p.protocol;
var _port = p.port;
var _hostname = p.hostname;
p.protocol = function(v, build) {
if (v !== undefined) {
if (v) {
// accept trailing ://
v = v.replace(/:(\/\/)?$/, '');
if (!v.match(URI.protocol_expression)) {
throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]');
}
}
}
return _protocol.call(this, v, build);
};
p.scheme = p.protocol;
p.port = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v !== undefined) {
if (v === 0) {
v = null;
}
if (v) {
v += '';
if (v.charAt(0) === ':') {
v = v.substring(1);
}
if (v.match(/[^0-9]/)) {
throw new TypeError('Port "' + v + '" contains characters other than [0-9]');
}
}
}
return _port.call(this, v, build);
};
p.hostname = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v !== undefined) {
var x = {};
var res = URI.parseHost(v, x);
if (res !== '/') {
throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
}
v = x.hostname;
}
return _hostname.call(this, v, build);
};
// compound accessors
p.host = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined) {
return this._parts.hostname ? URI.buildHost(this._parts) : '';
} else {
var res = URI.parseHost(v, this._parts);
if (res !== '/') {
throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
}
this.build(!build);
return this;
}
};
p.authority = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined) {
return this._parts.hostname ? URI.buildAuthority(this._parts) : '';
} else {
var res = URI.parseAuthority(v, this._parts);
if (res !== '/') {
throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
}
this.build(!build);
return this;
}
};
p.userinfo = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined) {
if (!this._parts.username) {
return '';
}
var t = URI.buildUserinfo(this._parts);
return t.substring(0, t.length -1);
} else {
if (v[v.length-1] !== '@') {
v += '@';
}
URI.parseUserinfo(v, this._parts);
this.build(!build);
return this;
}
};
p.resource = function(v, build) {
var parts;
if (v === undefined) {
return this.path() + this.search() + this.hash();
}
parts = URI.parse(v);
this._parts.path = parts.path;
this._parts.query = parts.query;
this._parts.fragment = parts.fragment;
this.build(!build);
return this;
};
// fraction accessors
p.subdomain = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
// convenience, return "www" from "www.example.org"
if (v === undefined) {
if (!this._parts.hostname || this.is('IP')) {
return '';
}
// grab domain and add another segment
var end = this._parts.hostname.length - this.domain().length - 1;
return this._parts.hostname.substring(0, end) || '';
} else {
var e = this._parts.hostname.length - this.domain().length;
var sub = this._parts.hostname.substring(0, e);
var replace = new RegExp('^' + escapeRegEx(sub));
if (v && v.charAt(v.length - 1) !== '.') {
v += '.';
}
if (v) {
URI.ensureValidHostname(v);
}
this._parts.hostname = this._parts.hostname.replace(replace, v);
this.build(!build);
return this;
}
};
p.domain = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (typeof v === 'boolean') {
build = v;
v = undefined;
}
// convenience, return "example.org" from "www.example.org"
if (v === undefined) {
if (!this._parts.hostname || this.is('IP')) {
return '';
}
// if hostname consists of 1 or 2 segments, it must be the domain
var t = this._parts.hostname.match(/\./g);
if (t && t.length < 2) {
return this._parts.hostname;
}
// grab tld and add another segment
var end = this._parts.hostname.length - this.tld(build).length - 1;
end = this._parts.hostname.lastIndexOf('.', end -1) + 1;
return this._parts.hostname.substring(end) || '';
} else {
if (!v) {
throw new TypeError('cannot set domain empty');
}
URI.ensureValidHostname(v);
if (!this._parts.hostname || this.is('IP')) {
this._parts.hostname = v;
} else {
var replace = new RegExp(escapeRegEx(this.domain()) + '$');
this._parts.hostname = this._parts.hostname.replace(replace, v);
}
this.build(!build);
return this;
}
};
p.tld = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (typeof v === 'boolean') {
build = v;
v = undefined;
}
// return "org" from "www.example.org"
if (v === undefined) {
if (!this._parts.hostname || this.is('IP')) {
return '';
}
var pos = this._parts.hostname.lastIndexOf('.');
var tld = this._parts.hostname.substring(pos + 1);
if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {
return SLD.get(this._parts.hostname) || tld;
}
return tld;
} else {
var replace;
if (!v) {
throw new TypeError('cannot set TLD empty');
} else if (v.match(/[^a-zA-Z0-9-]/)) {
if (SLD && SLD.is(v)) {
replace = new RegExp(escapeRegEx(this.tld()) + '$');
this._parts.hostname = this._parts.hostname.replace(replace, v);
} else {
throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]');
}
} else if (!this._parts.hostname || this.is('IP')) {
throw new ReferenceError('cannot set TLD on non-domain host');
} else {
replace = new RegExp(escapeRegEx(this.tld()) + '$');
this._parts.hostname = this._parts.hostname.replace(replace, v);
}
this.build(!build);
return this;
}
};
p.directory = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined || v === true) {
if (!this._parts.path && !this._parts.hostname) {
return '';
}
if (this._parts.path === '/') {
return '/';
}
var end = this._parts.path.length - this.filename().length - 1;
var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');
return v ? URI.decodePath(res) : res;
} else {
var e = this._parts.path.length - this.filename().length;
var directory = this._parts.path.substring(0, e);
var replace = new RegExp('^' + escapeRegEx(directory));
// fully qualifier directories begin with a slash
if (!this.is('relative')) {
if (!v) {
v = '/';
}
if (v.charAt(0) !== '/') {
v = '/' + v;
}
}
// directories always end with a slash
if (v && v.charAt(v.length - 1) !== '/') {
v += '/';
}
v = URI.recodePath(v);
this._parts.path = this._parts.path.replace(replace, v);
this.build(!build);
return this;
}
};
p.filename = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined || v === true) {
if (!this._parts.path || this._parts.path === '/') {
return '';
}
var pos = this._parts.path.lastIndexOf('/');
var res = this._parts.path.substring(pos+1);
return v ? URI.decodePathSegment(res) : res;
} else {
var mutatedDirectory = false;
if (v.charAt(0) === '/') {
v = v.substring(1);
}
if (v.match(/\.?\//)) {
mutatedDirectory = true;
}
var replace = new RegExp(escapeRegEx(this.filename()) + '$');
v = URI.recodePath(v);
this._parts.path = this._parts.path.replace(replace, v);
if (mutatedDirectory) {
this.normalizePath(build);
} else {
this.build(!build);
}
return this;
}
};
p.suffix = function(v, build) {
if (this._parts.urn) {
return v === undefined ? '' : this;
}
if (v === undefined || v === true) {
if (!this._parts.path || this._parts.path === '/') {
return '';
}
var filename = this.filename();
var pos = filename.lastIndexOf('.');
var s, res;
if (pos === -1) {
return '';
}
// suffix may only contain alnum characters (yup, I made this up.)
s = filename.substring(pos+1);
res = (/^[a-z0-9%]+$/i).test(s) ? s : '';
return v ? URI.decodePathSegment(res) : res;
} else {
if (v.charAt(0) === '.') {
v = v.substring(1);
}
var suffix = this.suffix();
var replace;
if (!suffix) {
if (!v) {
return this;
}
this._parts.path += '.' + URI.recodePath(v);
} else if (!v) {
replace = new RegExp(escapeRegEx('.' + suffix) + '$');
} else {
replace = new RegExp(escapeRegEx(suffix) + '$');
}
if (replace) {
v = URI.recodePath(v);
this._parts.path = this._parts.path.replace(replace, v);
}
this.build(!build);
return this;
}
};
p.segment = function(segment, v, build) {
var separator = this._parts.urn ? ':' : '/';
var path = this.path();
var absolute = path.substring(0, 1) === '/';
var segments = path.split(separator);
if (segment !== undefined && typeof segment !== 'number') {
build = v;
v = segment;
segment = undefined;
}
if (segment !== undefined && typeof segment !== 'number') {
throw new Error('Bad segment "' + segment + '", must be 0-based integer');
}
if (absolute) {
segments.shift();
}
if (segment < 0) {
// allow negative indexes to address from the end
segment = Math.max(segments.length + segment, 0);
}
if (v === undefined) {
/*jshint laxbreak: true */
return segment === undefined
? segments
: segments[segment];
/*jshint laxbreak: false */
} else if (segment === null || segments[segment] === undefined) {
if (isArray(v)) {
segments = [];
// collapse empty elements within array
for (var i=0, l=v.length; i < l; i++) {
if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {
continue;
}
if (segments.length && !segments[segments.length -1].length) {
segments.pop();
}
segments.push(v[i]);
}
} else if (v || typeof v === 'string') {
if (segments[segments.length -1] === '') {
// empty trailing elements have to be overwritten
// to prevent results such as /foo//bar
segments[segments.length -1] = v;
} else {
segments.push(v);
}
}
} else {
if (v) {
segments[segment] = v;
} else {
segments.splice(segment, 1);
}
}
if (absolute) {
segments.unshift('');
}
return this.path(segments.join(separator), build);
};
p.segmentCoded = function(segment, v, build) {
var segments, i, l;
if (typeof segment !== 'number') {
build = v;
v = segment;
segment = undefined;
}
if (v === undefined) {
segments = this.segment(segment, v, build);
if (!isArray(segments)) {
segments = segments !== undefined ? URI.decode(segments) : undefined;
} else {
for (i = 0, l = segments.length; i < l; i++) {
segments[i] = URI.decode(segments[i]);
}
}
return segments;
}
if (!isArray(v)) {
v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;
} else {
for (i = 0, l = v.length; i < l; i++) {
v[i] = URI.encode(v[i]);
}
}
return this.segment(segment, v, build);
};
// mutating query string
var q = p.query;
p.query = function(v, build) {
if (v === true) {
return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
} else if (typeof v === 'function') {
var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
var result = v.call(this, data);
this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
this.build(!build);
return this;
} else if (v !== undefined && typeof v !== 'string') {
this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
this.build(!build);
return this;
} else {
return q.call(this, v, build);
}
};
p.setQuery = function(name, value, build) {
var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
if (typeof name === 'string' || name instanceof String) {
data[name] = value !== undefined ? value : null;
} else if (typeof name === 'object') {
for (var key in name) {
if (hasOwn.call(name, key)) {
data[key] = name[key];
}
}
} else {
throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');
}
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
if (typeof name !== 'string') {
build = value;
}
this.build(!build);
return this;
};
p.addQuery = function(name, value, build) {
var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
URI.addQuery(data, name, value === undefined ? null : value);
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
if (typeof name !== 'string') {
build = value;
}
this.build(!build);
return this;
};
p.removeQuery = function(name, value, build) {
var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
URI.removeQuery(data, name, value);
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
if (typeof name !== 'string') {
build = value;
}
this.build(!build);
return this;
};
p.hasQuery = function(name, value, withinArray) {
var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
return URI.hasQuery(data, name, value, withinArray);
};
p.setSearch = p.setQuery;
p.addSearch = p.addQuery;
p.removeSearch = p.removeQuery;
p.hasSearch = p.hasQuery;
// sanitizing URLs
p.normalize = function() {
if (this._parts.urn) {
return this
.normalizeProtocol(false)
.normalizePath(false)
.normalizeQuery(false)
.normalizeFragment(false)
.build();
}
return this
.normalizeProtocol(false)
.normalizeHostname(false)
.normalizePort(false)
.normalizePath(false)
.normalizeQuery(false)
.normalizeFragment(false)
.build();
};
p.normalizeProtocol = function(build) {
if (typeof this._parts.protocol === 'string') {
this._parts.protocol = this._parts.protocol.toLowerCase();
this.build(!build);
}
return this;
};
p.normalizeHostname = function(build) {
if (this._parts.hostname) {
if (this.is('IDN') && punycode) {
this._parts.hostname = punycode.toASCII(this._parts.hostname);
} else if (this.is('IPv6') && IPv6) {
this._parts.hostname = IPv6.best(this._parts.hostname);
}
this._parts.hostname = this._parts.hostname.toLowerCase();
this.build(!build);
}
return this;
};
p.normalizePort = function(build) {
// remove port of it's the protocol's default
if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {
this._parts.port = null;
this.build(!build);
}
return this;
};
p.normalizePath = function(build) {
var _path = this._parts.path;
if (!_path) {
return this;
}
if (this._parts.urn) {
this._parts.path = URI.recodeUrnPath(this._parts.path);
this.build(!build);
return this;
}
if (this._parts.path === '/') {
return this;
}
var _was_relative;
var _leadingParents = '';
var _parent, _pos;
// handle relative paths
if (_path.charAt(0) !== '/') {
_was_relative = true;
_path = '/' + _path;
}
// handle relative files (as opposed to directories)
if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {
_path += '/';
}
// resolve simples
_path = _path
.replace(/(\/(\.\/)+)|(\/\.$)/g, '/')
.replace(/\/{2,}/g, '/');
// remember leading parents
if (_was_relative) {
_leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || '';
if (_leadingParents) {
_leadingParents = _leadingParents[0];
}
}
// resolve parents
while (true) {
_parent = _path.indexOf('/..');
if (_parent === -1) {
// no more ../ to resolve
break;
} else if (_parent === 0) {
// top level cannot be relative, skip it
_path = _path.substring(3);
continue;
}
_pos = _path.substring(0, _parent).lastIndexOf('/');
if (_pos === -1) {
_pos = _parent;
}
_path = _path.substring(0, _pos) + _path.substring(_parent + 3);
}
// revert to relative
if (_was_relative && this.is('relative')) {
_path = _leadingParents + _path.substring(1);
}
_path = URI.recodePath(_path);
this._parts.path = _path;
this.build(!build);
return this;
};
p.normalizePathname = p.normalizePath;
p.normalizeQuery = function(build) {
if (typeof this._parts.query === 'string') {
if (!this._parts.query.length) {
this._parts.query = null;
} else {
this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));
}
this.build(!build);
}
return this;
};
p.normalizeFragment = function(build) {
if (!this._parts.fragment) {
this._parts.fragment = null;
this.build(!build);
}
return this;
};
p.normalizeSearch = p.normalizeQuery;
p.normalizeHash = p.normalizeFragment;
p.iso8859 = function() {
// expect unicode input, iso8859 output
var e = URI.encode;
var d = URI.decode;
URI.encode = escape;
URI.decode = decodeURIComponent;
try {
this.normalize();
} finally {
URI.encode = e;
URI.decode = d;
}
return this;
};
p.unicode = function() {
// expect iso8859 input, unicode output
var e = URI.encode;
var d = URI.decode;
URI.encode = strictEncodeURIComponent;
URI.decode = unescape;
try {
this.normalize();
} finally {
URI.encode = e;
URI.decode = d;
}
return this;
};
p.readable = function() {
var uri = this.clone();
// removing username, password, because they shouldn't be displayed according to RFC 3986
uri.username('').password('').normalize();
var t = '';
if (uri._parts.protocol) {
t += uri._parts.protocol + '://';
}
if (uri._parts.hostname) {
if (uri.is('punycode') && punycode) {
t += punycode.toUnicode(uri._parts.hostname);
if (uri._parts.port) {
t += ':' + uri._parts.port;
}
} else {
t += uri.host();
}
}
if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {
t += '/';
}
t += uri.path(true);
if (uri._parts.query) {
var q = '';
for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {
var kv = (qp[i] || '').split('=');
q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)
.replace(/&/g, '%26');
if (kv[1] !== undefined) {
q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)
.replace(/&/g, '%26');
}
}
t += '?' + q.substring(1);
}
t += URI.decodeQuery(uri.hash(), true);
return t;
};
// resolving relative and absolute URLs
p.absoluteTo = function(base) {
var resolved = this.clone();
var properties = ['protocol', 'username', 'password', 'hostname', 'port'];
var basedir, i, p;
if (this._parts.urn) {
throw new Error('URNs do not have any generally defined hierarchical components');
}
if (!(base instanceof URI)) {
base = new URI(base);
}
if (!resolved._parts.protocol) {
resolved._parts.protocol = base._parts.protocol;
}
if (this._parts.hostname) {
return resolved;
}
for (i = 0; (p = properties[i]); i++) {
resolved._parts[p] = base._parts[p];
}
if (!resolved._parts.path) {
resolved._parts.path = base._parts.path;
if (!resolved._parts.query) {
resolved._parts.query = base._parts.query;
}
} else if (resolved._parts.path.substring(-2) === '..') {
resolved._parts.path += '/';
}
if (resolved.path().charAt(0) !== '/') {
basedir = base.directory();
basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';
resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;
resolved.normalizePath();
}
resolved.build();
return resolved;
};
p.relativeTo = function(base) {
var relative = this.clone().normalize();
var relativeParts, baseParts, common, relativePath, basePath;
if (relative._parts.urn) {
throw new Error('URNs do not have any generally defined hierarchical components');
}
base = new URI(base).normalize();
relativeParts = relative._parts;
baseParts = base._parts;
relativePath = relative.path();
basePath = base.path();
if (relativePath.charAt(0) !== '/') {
throw new Error('URI is already relative');
}
if (basePath.charAt(0) !== '/') {
throw new Error('Cannot calculate a URI relative to another relative URI');
}
if (relativeParts.protocol === baseParts.protocol) {
relativeParts.protocol = null;
}
if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {
return relative.build();
}
if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {
return relative.build();
}
if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {
relativeParts.hostname = null;
relativeParts.port = null;
} else {
return relative.build();
}
if (relativePath === basePath) {
relativeParts.path = '';
return relative.build();
}
// determine common sub path
common = URI.commonPath(relativePath, basePath);
// If the paths have nothing in common, return a relative URL with the absolute path.
if (!common) {
return relative.build();
}
var parents = baseParts.path
.substring(common.length)
.replace(/[^\/]*$/, '')
.replace(/.*?\//g, '../');
relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';
return relative.build();
};
// comparing URIs
p.equals = function(uri) {
var one = this.clone();
var two = new URI(uri);
var one_map = {};
var two_map = {};
var checked = {};
var one_query, two_query, key;
one.normalize();
two.normalize();
// exact match
if (one.toString() === two.toString()) {
return true;
}
// extract query string
one_query = one.query();
two_query = two.query();
one.query('');
two.query('');
// definitely not equal if not even non-query parts match
if (one.toString() !== two.toString()) {
return false;
}
// query parameters have the same length, even if they're permuted
if (one_query.length !== two_query.length) {
return false;
}
one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);
two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);
for (key in one_map) {
if (hasOwn.call(one_map, key)) {
if (!isArray(one_map[key])) {
if (one_map[key] !== two_map[key]) {
return false;
}
} else if (!arraysEqual(one_map[key], two_map[key])) {
return false;
}
checked[key] = true;
}
}
for (key in two_map) {
if (hasOwn.call(two_map, key)) {
if (!checked[key]) {
// two contains a parameter not present in one
return false;
}
}
}
return true;
};
// state
p.duplicateQueryParameters = function(v) {
this._parts.duplicateQueryParameters = !!v;
return this;
};
p.escapeQuerySpace = function(v) {
this._parts.escapeQuerySpace = !!v;
return this;
};
return URI;
}));
},{"./IPv6":124,"./SecondLevelDomains":125,"./punycode":127}],127:[function(require,module,exports){
(function (global){
/*! http://mths.be/punycode v1.2.3 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings.
* @private
* @param {String} domain The domain name.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* http://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
length,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols to a Punycode string of ASCII-only
* symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name to Unicode. Only the
* Punycoded parts of the domain name will be converted, i.e. it doesn't
* matter if you call it on a string that has already been converted to
* Unicode.
* @memberOf punycode
* @param {String} domain The Punycode domain name to convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(domain) {
return mapDomain(domain, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name to Punycode. Only the
* non-ASCII parts of the domain name will be converted, i.e. it doesn't
* matter if you call it with a domain that's already in ASCII.
* @memberOf punycode
* @param {String} domain The domain name to convert, as a Unicode string.
* @returns {String} The Punycode representation of the given domain name.
*/
function toASCII(domain) {
return mapDomain(domain, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.2.3',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define(function() {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],128:[function(require,module,exports){
(function (Buffer){
var clone = (function() {
'use strict';
function _instanceof(obj, type) {
return type != null && obj instanceof type;
}
var nativeMap;
try {
nativeMap = Map;
} catch(_) {
// maybe a reference error because no `Map`. Give it a dummy value that no
// value will ever be an instanceof.
nativeMap = function() {};
}
var nativeSet;
try {
nativeSet = Set;
} catch(_) {
nativeSet = function() {};
}
var nativePromise;
try {
nativePromise = Promise;
} catch(_) {
nativePromise = function() {};
}
/**
* Clones (copies) an Object using deep copying.
*
* This function supports circular references by default, but if you are certain
* there are no circular references in your object, you can save some CPU time
* by calling clone(obj, false).
*
* Caution: if `circular` is false and `parent` contains circular references,
* your program may enter an infinite loop and crash.
*
* @param `parent` - the object to be cloned
* @param `circular` - set to true if the object to be cloned may contain
* circular references. (optional - true by default)
* @param `depth` - set to a number if the object is only to be cloned to
* a particular depth. (optional - defaults to Infinity)
* @param `prototype` - sets the prototype to be used when cloning an object.
* (optional - defaults to parent prototype).
* @param `includeNonEnumerable` - set to true if the non-enumerable properties
* should be cloned as well. Non-enumerable properties on the prototype
* chain will be ignored. (optional - false by default)
*/
function clone(parent, circular, depth, prototype, includeNonEnumerable) {
if (typeof circular === 'object') {
depth = circular.depth;
prototype = circular.prototype;
includeNonEnumerable = circular.includeNonEnumerable;
circular = circular.circular;
}
// maintain two arrays for circular references, where corresponding parents
// and children have the same index
var allParents = [];
var allChildren = [];
var useBuffer = typeof Buffer != 'undefined';
if (typeof circular == 'undefined')
circular = true;
if (typeof depth == 'undefined')
depth = Infinity;
// recurse this function so we don't reset allParents and allChildren
function _clone(parent, depth) {
// cloning null always returns null
if (parent === null)
return null;
if (depth === 0)
return parent;
var child;
var proto;
if (typeof parent != 'object') {
return parent;
}
if (_instanceof(parent, nativeMap)) {
child = new nativeMap();
} else if (_instanceof(parent, nativeSet)) {
child = new nativeSet();
} else if (_instanceof(parent, nativePromise)) {
child = new nativePromise(function (resolve, reject) {
parent.then(function(value) {
resolve(_clone(value, depth - 1));
}, function(err) {
reject(_clone(err, depth - 1));
});
});
} else if (clone.__isArray(parent)) {
child = [];
} else if (clone.__isRegExp(parent)) {
child = new RegExp(parent.source, __getRegExpFlags(parent));
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
} else if (clone.__isDate(parent)) {
child = new Date(parent.getTime());
} else if (useBuffer && Buffer.isBuffer(parent)) {
child = new Buffer(parent.length);
parent.copy(child);
return child;
} else if (_instanceof(parent, Error)) {
child = Object.create(parent);
} else {
if (typeof prototype == 'undefined') {
proto = Object.getPrototypeOf(parent);
child = Object.create(proto);
}
else {
child = Object.create(prototype);
proto = prototype;
}
}
if (circular) {
var index = allParents.indexOf(parent);
if (index != -1) {
return allChildren[index];
}
allParents.push(parent);
allChildren.push(child);
}
if (_instanceof(parent, nativeMap)) {
parent.forEach(function(value, key) {
var keyChild = _clone(key, depth - 1);
var valueChild = _clone(value, depth - 1);
child.set(keyChild, valueChild);
});
}
if (_instanceof(parent, nativeSet)) {
parent.forEach(function(value) {
var entryChild = _clone(value, depth - 1);
child.add(entryChild);
});
}
for (var i in parent) {
var attrs;
if (proto) {
attrs = Object.getOwnPropertyDescriptor(proto, i);
}
if (attrs && attrs.set == null) {
continue;
}
child[i] = _clone(parent[i], depth - 1);
}
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(parent);
for (var i = 0; i < symbols.length; i++) {
// Don't need to worry about cloning a symbol because it is a primitive,
// like a number or string.
var symbol = symbols[i];
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
continue;
}
child[symbol] = _clone(parent[symbol], depth - 1);
if (!descriptor.enumerable) {
Object.defineProperty(child, symbol, {
enumerable: false
});
}
}
}
if (includeNonEnumerable) {
var allPropertyNames = Object.getOwnPropertyNames(parent);
for (var i = 0; i < allPropertyNames.length; i++) {
var propertyName = allPropertyNames[i];
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
if (descriptor && descriptor.enumerable) {
continue;
}
child[propertyName] = _clone(parent[propertyName], depth - 1);
Object.defineProperty(child, propertyName, {
enumerable: false
});
}
}
return child;
}
return _clone(parent, depth);
}
/**
* Simple flat clone using prototype, accepts only objects, usefull for property
* override on FLAT configuration object (no nested props).
*
* USE WITH CAUTION! This may not behave as you wish if you do not know how this
* works.
*/
clone.clonePrototype = function clonePrototype(parent) {
if (parent === null)
return null;
var c = function () {};
c.prototype = parent;
return new c();
};
// private utility functions
function __objToStr(o) {
return Object.prototype.toString.call(o);
}
clone.__objToStr = __objToStr;
function __isDate(o) {
return typeof o === 'object' && __objToStr(o) === '[object Date]';
}
clone.__isDate = __isDate;
function __isArray(o) {
return typeof o === 'object' && __objToStr(o) === '[object Array]';
}
clone.__isArray = __isArray;
function __isRegExp(o) {
return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
}
clone.__isRegExp = __isRegExp;
function __getRegExpFlags(re) {
var flags = '';
if (re.global) flags += 'g';
if (re.ignoreCase) flags += 'i';
if (re.multiline) flags += 'm';
return flags;
}
clone.__getRegExpFlags = __getRegExpFlags;
return clone;
})();
if (typeof module === 'object' && module.exports) {
module.exports = clone;
}
}).call(this,require("buffer").Buffer)
},{"buffer":13}],129:[function(require,module,exports){
var assert = require('assert');
/**
* Indent a `string` by `w`.
*
* @param {String} string
* @param {String or Number} w
* @return {String}
*/
module.exports = function indent(string, w){
if (1 == arguments.length) w = 2;
assert('string' == typeof string);
assert('string' == typeof w || 'number' == typeof w);
if ('number' == typeof w) w = new Array(w + 1).join(' ');
return string.replace(/^(?!$)/mg, w);
};
},{"assert":2}],130:[function(require,module,exports){
'use strict';
var isArray = require('is-array');
var isWindow = require('is-window');
var isFunction = require('is-function');
module.exports = function (obj) {
if (!obj) {
return false;
}
if (isArray(obj)) {
return true;
}
if (isFunction(obj) || isWindow(obj)) {
return false;
}
obj = Object(obj);
var length = 'length' in obj && obj.length;
if (obj.nodeType === 1 && length) {
return true;
}
return length === 0 ||
typeof length === 'number' && length > 0 && ( length - 1 ) in obj;
};
},{"is-array":131,"is-function":133,"is-window":139}],131:[function(require,module,exports){
/**
* isArray
*/
var isArray = Array.isArray;
/**
* toString
*/
var str = Object.prototype.toString;
/**
* Whether or not the given `val`
* is an array.
*
* example:
*
* isArray([]);
* // > true
* isArray(arguments);
* // > false
* isArray('');
* // > false
*
* @param {mixed} val
* @return {bool}
*/
module.exports = isArray || function (val) {
return !! val && '[object Array]' == str.call(val);
};
},{}],132:[function(require,module,exports){
module.exports = isNode
function isNode (val) {
return (!val || typeof val !== 'object')
? false
: (typeof window === 'object' && typeof window.Node === 'object')
? (val instanceof window.Node)
: (typeof val.nodeType === 'number') &&
(typeof val.nodeName === 'string')
}
},{}],133:[function(require,module,exports){
module.exports = isFunction
var toString = Object.prototype.toString
function isFunction (fn) {
var string = toString.call(fn)
return string === '[object Function]' ||
(typeof fn === 'function' && string !== '[object RegExp]') ||
(typeof window !== 'undefined' &&
// IE8 and below
(fn === window.setTimeout ||
fn === window.alert ||
fn === window.confirm ||
fn === window.prompt))
};
},{}],134:[function(require,module,exports){
'use strict';
var htmlTags = require('html-tags');
var basic = /\s?<!doctype html>|(<html\b[^>]*>|<body\b[^>]*>|<x-[^>]+>)+/i;
var full = new RegExp(htmlTags.map(function (el) {
return '<' + el + '\\b[^>]*>';
}).join('|'), 'i');
module.exports = function (str) {
if (basic.test(str)) {
return true;
}
return full.test(str);
};
},{"html-tags":136}],135:[function(require,module,exports){
module.exports=[
"a",
"abbr",
"address",
"area",
"article",
"aside",
"audio",
"b",
"base",
"bdi",
"bdo",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"cite",
"code",
"col",
"colgroup",
"data",
"datalist",
"dd",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"keygen",
"label",
"legend",
"li",
"link",
"main",
"map",
"mark",
"math",
"menu",
"menuitem",
"meta",
"meter",
"nav",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"picture",
"pre",
"progress",
"q",
"rb",
"rp",
"rt",
"rtc",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"small",
"source",
"span",
"strong",
"style",
"sub",
"summary",
"sup",
"svg",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"u",
"ul",
"var",
"video",
"wbr"
]
},{}],136:[function(require,module,exports){
module.exports = require('./html-tags.json');
},{"./html-tags.json":135}],137:[function(require,module,exports){
module.exports = isPromise;
function isPromise(obj) {
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
}
},{}],138:[function(require,module,exports){
/**
* Expose `isUrl`.
*/
module.exports = isUrl;
/**
* Matcher.
*/
var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
/**
* Loosely validate a URL `string`.
*
* @param {String} string
* @return {Boolean}
*/
function isUrl(string){
return matcher.test(string);
}
},{}],139:[function(require,module,exports){
'use strict';
module.exports = function (obj) {
if (obj == null) {
return false;
}
var o = Object(obj);
return o === o.window;
};
},{}],140:[function(require,module,exports){
//! moment.js
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
global.moment = factory()
}(this, (function () { 'use strict';
var hookCallback;
function hooks () {
return hookCallback.apply(null, arguments);
}
// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback (callback) {
hookCallback = callback;
}
function isArray(input) {
return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
}
function isObject(input) {
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return input != null && Object.prototype.toString.call(input) === '[object Object]';
}
function isObjectEmpty(obj) {
if (Object.getOwnPropertyNames) {
return (Object.getOwnPropertyNames(obj).length === 0);
} else {
var k;
for (k in obj) {
if (obj.hasOwnProperty(k)) {
return false;
}
}
return true;
}
}
function isUndefined(input) {
return input === void 0;
}
function isNumber(input) {
return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
}
function isDate(input) {
return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
}
function map(arr, fn) {
var res = [], i;
for (i = 0; i < arr.length; ++i) {
res.push(fn(arr[i], i));
}
return res;
}
function hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
}
function extend(a, b) {
for (var i in b) {
if (hasOwnProp(b, i)) {
a[i] = b[i];
}
}
if (hasOwnProp(b, 'toString')) {
a.toString = b.toString;
}
if (hasOwnProp(b, 'valueOf')) {
a.valueOf = b.valueOf;
}
return a;
}
function createUTC (input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, true).utc();
}
function defaultParsingFlags() {
// We need to deep clone this object.
return {
empty : false,
unusedTokens : [],
unusedInput : [],
overflow : -2,
charsLeftOver : 0,
nullInput : false,
invalidMonth : null,
invalidFormat : false,
userInvalidated : false,
iso : false,
parsedDateParts : [],
meridiem : null,
rfc2822 : false,
weekdayMismatch : false
};
}
function getParsingFlags(m) {
if (m._pf == null) {
m._pf = defaultParsingFlags();
}
return m._pf;
}
var some;
if (Array.prototype.some) {
some = Array.prototype.some;
} else {
some = function (fun) {
var t = Object(this);
var len = t.length >>> 0;
for (var i = 0; i < len; i++) {
if (i in t && fun.call(this, t[i], i, t)) {
return true;
}
}
return false;
};
}
function isValid(m) {
if (m._isValid == null) {
var flags = getParsingFlags(m);
var parsedParts = some.call(flags.parsedDateParts, function (i) {
return i != null;
});
var isNowValid = !isNaN(m._d.getTime()) &&
flags.overflow < 0 &&
!flags.empty &&
!flags.invalidMonth &&
!flags.invalidWeekday &&
!flags.weekdayMismatch &&
!flags.nullInput &&
!flags.invalidFormat &&
!flags.userInvalidated &&
(!flags.meridiem || (flags.meridiem && parsedParts));
if (m._strict) {
isNowValid = isNowValid &&
flags.charsLeftOver === 0 &&
flags.unusedTokens.length === 0 &&
flags.bigHour === undefined;
}
if (Object.isFrozen == null || !Object.isFrozen(m)) {
m._isValid = isNowValid;
}
else {
return isNowValid;
}
}
return m._isValid;
}
function createInvalid (flags) {
var m = createUTC(NaN);
if (flags != null) {
extend(getParsingFlags(m), flags);
}
else {
getParsingFlags(m).userInvalidated = true;
}
return m;
}
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var momentProperties = hooks.momentProperties = [];
function copyConfig(to, from) {
var i, prop, val;
if (!isUndefined(from._isAMomentObject)) {
to._isAMomentObject = from._isAMomentObject;
}
if (!isUndefined(from._i)) {
to._i = from._i;
}
if (!isUndefined(from._f)) {
to._f = from._f;
}
if (!isUndefined(from._l)) {
to._l = from._l;
}
if (!isUndefined(from._strict)) {
to._strict = from._strict;
}
if (!isUndefined(from._tzm)) {
to._tzm = from._tzm;
}
if (!isUndefined(from._isUTC)) {
to._isUTC = from._isUTC;
}
if (!isUndefined(from._offset)) {
to._offset = from._offset;
}
if (!isUndefined(from._pf)) {
to._pf = getParsingFlags(from);
}
if (!isUndefined(from._locale)) {
to._locale = from._locale;
}
if (momentProperties.length > 0) {
for (i = 0; i < momentProperties.length; i++) {
prop = momentProperties[i];
val = from[prop];
if (!isUndefined(val)) {
to[prop] = val;
}
}
}
return to;
}
var updateInProgress = false;
// Moment prototype object
function Moment(config) {
copyConfig(this, config);
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
if (!this.isValid()) {
this._d = new Date(NaN);
}
// Prevent infinite loop in case updateOffset creates new moment
// objects.
if (updateInProgress === false) {
updateInProgress = true;
hooks.updateOffset(this);
updateInProgress = false;
}
}
function isMoment (obj) {
return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
}
function absFloor (number) {
if (number < 0) {
// -0 -> 0
return Math.ceil(number) || 0;
} else {
return Math.floor(number);
}
}
function toInt(argumentForCoercion) {
var coercedNumber = +argumentForCoercion,
value = 0;
if (coercedNumber !== 0 && isFinite(coercedNumber)) {
value = absFloor(coercedNumber);
}
return value;
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
var len = Math.min(array1.length, array2.length),
lengthDiff = Math.abs(array1.length - array2.length),
diffs = 0,
i;
for (i = 0; i < len; i++) {
if ((dontConvert && array1[i] !== array2[i]) ||
(!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
diffs++;
}
}
return diffs + lengthDiff;
}
function warn(msg) {
if (hooks.suppressDeprecationWarnings === false &&
(typeof console !== 'undefined') && console.warn) {
console.warn('Deprecation warning: ' + msg);
}
}
function deprecate(msg, fn) {
var firstTime = true;
return extend(function () {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(null, msg);
}
if (firstTime) {
var args = [];
var arg;
for (var i = 0; i < arguments.length; i++) {
arg = '';
if (typeof arguments[i] === 'object') {
arg += '\n[' + i + '] ';
for (var key in arguments[0]) {
arg += key + ': ' + arguments[0][key] + ', ';
}
arg = arg.slice(0, -2); // Remove trailing comma and space
} else {
arg = arguments[i];
}
args.push(arg);
}
warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
firstTime = false;
}
return fn.apply(this, arguments);
}, fn);
}
var deprecations = {};
function deprecateSimple(name, msg) {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(name, msg);
}
if (!deprecations[name]) {
warn(msg);
deprecations[name] = true;
}
}
hooks.suppressDeprecationWarnings = false;
hooks.deprecationHandler = null;
function isFunction(input) {
return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
}
function set (config) {
var prop, i;
for (i in config) {
prop = config[i];
if (isFunction(prop)) {
this[i] = prop;
} else {
this['_' + i] = prop;
}
}
this._config = config;
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
// TODO: Remove "ordinalParse" fallback in next major release.
this._dayOfMonthOrdinalParseLenient = new RegExp(
(this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
'|' + (/\d{1,2}/).source);
}
function mergeConfigs(parentConfig, childConfig) {
var res = extend({}, parentConfig), prop;
for (prop in childConfig) {
if (hasOwnProp(childConfig, prop)) {
if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
res[prop] = {};
extend(res[prop], parentConfig[prop]);
extend(res[prop], childConfig[prop]);
} else if (childConfig[prop] != null) {
res[prop] = childConfig[prop];
} else {
delete res[prop];
}
}
}
for (prop in parentConfig) {
if (hasOwnProp(parentConfig, prop) &&
!hasOwnProp(childConfig, prop) &&
isObject(parentConfig[prop])) {
// make sure changes to properties don't modify parent config
res[prop] = extend({}, res[prop]);
}
}
return res;
}
function Locale(config) {
if (config != null) {
this.set(config);
}
}
var keys;
if (Object.keys) {
keys = Object.keys;
} else {
keys = function (obj) {
var i, res = [];
for (i in obj) {
if (hasOwnProp(obj, i)) {
res.push(i);
}
}
return res;
};
}
var defaultCalendar = {
sameDay : '[Today at] LT',
nextDay : '[Tomorrow at] LT',
nextWeek : 'dddd [at] LT',
lastDay : '[Yesterday at] LT',
lastWeek : '[Last] dddd [at] LT',
sameElse : 'L'
};
function calendar (key, mom, now) {
var output = this._calendar[key] || this._calendar['sameElse'];
return isFunction(output) ? output.call(mom, now) : output;
}
var defaultLongDateFormat = {
LTS : 'h:mm:ss A',
LT : 'h:mm A',
L : 'MM/DD/YYYY',
LL : 'MMMM D, YYYY',
LLL : 'MMMM D, YYYY h:mm A',
LLLL : 'dddd, MMMM D, YYYY h:mm A'
};
function longDateFormat (key) {
var format = this._longDateFormat[key],
formatUpper = this._longDateFormat[key.toUpperCase()];
if (format || !formatUpper) {
return format;
}
this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
return val.slice(1);
});
return this._longDateFormat[key];
}
var defaultInvalidDate = 'Invalid date';
function invalidDate () {
return this._invalidDate;
}
var defaultOrdinal = '%d';
var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
function ordinal (number) {
return this._ordinal.replace('%d', number);
}
var defaultRelativeTime = {
future : 'in %s',
past : '%s ago',
s : 'a few seconds',
ss : '%d seconds',
m : 'a minute',
mm : '%d minutes',
h : 'an hour',
hh : '%d hours',
d : 'a day',
dd : '%d days',
M : 'a month',
MM : '%d months',
y : 'a year',
yy : '%d years'
};
function relativeTime (number, withoutSuffix, string, isFuture) {
var output = this._relativeTime[string];
return (isFunction(output)) ?
output(number, withoutSuffix, string, isFuture) :
output.replace(/%d/i, number);
}
function pastFuture (diff, output) {
var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
return isFunction(format) ? format(output) : format.replace(/%s/i, output);
}
var aliases = {};
function addUnitAlias (unit, shorthand) {
var lowerCase = unit.toLowerCase();
aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
}
function normalizeUnits(units) {
return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
}
function normalizeObjectUnits(inputObject) {
var normalizedInput = {},
normalizedProp,
prop;
for (prop in inputObject) {
if (hasOwnProp(inputObject, prop)) {
normalizedProp = normalizeUnits(prop);
if (normalizedProp) {
normalizedInput[normalizedProp] = inputObject[prop];
}
}
}
return normalizedInput;
}
var priorities = {};
function addUnitPriority(unit, priority) {
priorities[unit] = priority;
}
function getPrioritizedUnits(unitsObj) {
var units = [];
for (var u in unitsObj) {
units.push({unit: u, priority: priorities[u]});
}
units.sort(function (a, b) {
return a.priority - b.priority;
});
return units;
}
function zeroFill(number, targetLength, forceSign) {
var absNumber = '' + Math.abs(number),
zerosToFill = targetLength - absNumber.length,
sign = number >= 0;
return (sign ? (forceSign ? '+' : '') : '-') +
Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
}
var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
var formatFunctions = {};
var formatTokenFunctions = {};
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function addFormatToken (token, padded, ordinal, callback) {
var func = callback;
if (typeof callback === 'string') {
func = function () {
return this[callback]();
};
}
if (token) {
formatTokenFunctions[token] = func;
}
if (padded) {
formatTokenFunctions[padded[0]] = function () {
return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
};
}
if (ordinal) {
formatTokenFunctions[ordinal] = function () {
return this.localeData().ordinal(func.apply(this, arguments), token);
};
}
}
function removeFormattingTokens(input) {
if (input.match(/\[[\s\S]/)) {
return input.replace(/^\[|\]$/g, '');
}
return input.replace(/\\/g, '');
}
function makeFormatFunction(format) {
var array = format.match(formattingTokens), i, length;
for (i = 0, length = array.length; i < length; i++) {
if (formatTokenFunctions[array[i]]) {
array[i] = formatTokenFunctions[array[i]];
} else {
array[i] = removeFormattingTokens(array[i]);
}
}
return function (mom) {
var output = '', i;
for (i = 0; i < length; i++) {
output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
}
return output;
};
}
// format date using native date object
function formatMoment(m, format) {
if (!m.isValid()) {
return m.localeData().invalidDate();
}
format = expandFormat(format, m.localeData());
formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
return formatFunctions[format](m);
}
function expandFormat(format, locale) {
var i = 5;
function replaceLongDateFormatTokens(input) {
return locale.longDateFormat(input) || input;
}
localFormattingTokens.lastIndex = 0;
while (i >= 0 && localFormattingTokens.test(format)) {
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
localFormattingTokens.lastIndex = 0;
i -= 1;
}
return format;
}
var match1 = /\d/; // 0 - 9
var match2 = /\d\d/; // 00 - 99
var match3 = /\d{3}/; // 000 - 999
var match4 = /\d{4}/; // 0000 - 9999
var match6 = /[+-]?\d{6}/; // -999999 - 999999
var match1to2 = /\d\d?/; // 0 - 99
var match3to4 = /\d\d\d\d?/; // 999 - 9999
var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
var match1to3 = /\d{1,3}/; // 0 - 999
var match1to4 = /\d{1,4}/; // 0 - 9999
var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
var matchUnsigned = /\d+/; // 0 - inf
var matchSigned = /[+-]?\d+/; // -inf - inf
var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
// any word (or two) characters or numbers including two/three word month in arabic.
// includes scottish gaelic two word and hyphenated months
var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
var regexes = {};
function addRegexToken (token, regex, strictRegex) {
regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
return (isStrict && strictRegex) ? strictRegex : regex;
};
}
function getParseRegexForToken (token, config) {
if (!hasOwnProp(regexes, token)) {
return new RegExp(unescapeFormat(token));
}
return regexes[token](config._strict, config._locale);
}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function unescapeFormat(s) {
return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
return p1 || p2 || p3 || p4;
}));
}
function regexEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
var tokens = {};
function addParseToken (token, callback) {
var i, func = callback;
if (typeof token === 'string') {
token = [token];
}
if (isNumber(callback)) {
func = function (input, array) {
array[callback] = toInt(input);
};
}
for (i = 0; i < token.length; i++) {
tokens[token[i]] = func;
}
}
function addWeekParseToken (token, callback) {
addParseToken(token, function (input, array, config, token) {
config._w = config._w || {};
callback(input, config._w, config, token);
});
}
function addTimeToArrayFromToken(token, input, config) {
if (input != null && hasOwnProp(tokens, token)) {
tokens[token](input, config._a, config, token);
}
}
var YEAR = 0;
var MONTH = 1;
var DATE = 2;
var HOUR = 3;
var MINUTE = 4;
var SECOND = 5;
var MILLISECOND = 6;
var WEEK = 7;
var WEEKDAY = 8;
// FORMATTING
addFormatToken('Y', 0, 0, function () {
var y = this.year();
return y <= 9999 ? '' + y : '+' + y;
});
addFormatToken(0, ['YY', 2], 0, function () {
return this.year() % 100;
});
addFormatToken(0, ['YYYY', 4], 0, 'year');
addFormatToken(0, ['YYYYY', 5], 0, 'year');
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
// ALIASES
addUnitAlias('year', 'y');
// PRIORITIES
addUnitPriority('year', 1);
// PARSING
addRegexToken('Y', matchSigned);
addRegexToken('YY', match1to2, match2);
addRegexToken('YYYY', match1to4, match4);
addRegexToken('YYYYY', match1to6, match6);
addRegexToken('YYYYYY', match1to6, match6);
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
addParseToken('YYYY', function (input, array) {
array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
});
addParseToken('YY', function (input, array) {
array[YEAR] = hooks.parseTwoDigitYear(input);
});
addParseToken('Y', function (input, array) {
array[YEAR] = parseInt(input, 10);
});
// HELPERS
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
// HOOKS
hooks.parseTwoDigitYear = function (input) {
return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
};
// MOMENTS
var getSetYear = makeGetSet('FullYear', true);
function getIsLeapYear () {
return isLeapYear(this.year());
}
function makeGetSet (unit, keepTime) {
return function (value) {
if (value != null) {
set$1(this, unit, value);
hooks.updateOffset(this, keepTime);
return this;
} else {
return get(this, unit);
}
};
}
function get (mom, unit) {
return mom.isValid() ?
mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
}
function set$1 (mom, unit, value) {
if (mom.isValid() && !isNaN(value)) {
if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
}
else {
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
}
}
}
// MOMENTS
function stringGet (units) {
units = normalizeUnits(units);
if (isFunction(this[units])) {
return this[units]();
}
return this;
}
function stringSet (units, value) {
if (typeof units === 'object') {
units = normalizeObjectUnits(units);
var prioritized = getPrioritizedUnits(units);
for (var i = 0; i < prioritized.length; i++) {
this[prioritized[i].unit](units[prioritized[i].unit]);
}
} else {
units = normalizeUnits(units);
if (isFunction(this[units])) {
return this[units](value);
}
}
return this;
}
function mod(n, x) {
return ((n % x) + x) % x;
}
var indexOf;
if (Array.prototype.indexOf) {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function (o) {
// I know
var i;
for (i = 0; i < this.length; ++i) {
if (this[i] === o) {
return i;
}
}
return -1;
};
}
function daysInMonth(year, month) {
if (isNaN(year) || isNaN(month)) {
return NaN;
}
var modMonth = mod(month, 12);
year += (month - modMonth) / 12;
return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
}
// FORMATTING
addFormatToken('M', ['MM', 2], 'Mo', function () {
return this.month() + 1;
});
addFormatToken('MMM', 0, 0, function (format) {
return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
return this.localeData().months(this, format);
});
// ALIASES
addUnitAlias('month', 'M');
// PRIORITY
addUnitPriority('month', 8);
// PARSING
addRegexToken('M', match1to2);
addRegexToken('MM', match1to2, match2);
addRegexToken('MMM', function (isStrict, locale) {
return locale.monthsShortRegex(isStrict);
});
addRegexToken('MMMM', function (isStrict, locale) {
return locale.monthsRegex(isStrict);
});
addParseToken(['M', 'MM'], function (input, array) {
array[MONTH] = toInt(input) - 1;
});
addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
var month = config._locale.monthsParse(input, token, config._strict);
// if we didn't find a month name, mark the date as invalid.
if (month != null) {
array[MONTH] = month;
} else {
getParsingFlags(config).invalidMonth = input;
}
});
// LOCALES
var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
function localeMonths (m, format) {
if (!m) {
return isArray(this._months) ? this._months :
this._months['standalone'];
}
return isArray(this._months) ? this._months[m.month()] :
this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
}
var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
function localeMonthsShort (m, format) {
if (!m) {
return isArray(this._monthsShort) ? this._monthsShort :
this._monthsShort['standalone'];
}
return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
}
function handleStrictParse(monthName, format, strict) {
var i, ii, mom, llc = monthName.toLocaleLowerCase();
if (!this._monthsParse) {
// this is not used
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
for (i = 0; i < 12; ++i) {
mom = createUTC([2000, i]);
this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeMonthsParse (monthName, format, strict) {
var i, mom, regex;
if (this._monthsParseExact) {
return handleStrictParse.call(this, monthName, format, strict);
}
if (!this._monthsParse) {
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
}
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, i]);
if (strict && !this._longMonthsParse[i]) {
this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
}
if (!strict && !this._monthsParse[i]) {
regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
return i;
} else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
return i;
} else if (!strict && this._monthsParse[i].test(monthName)) {
return i;
}
}
}
// MOMENTS
function setMonth (mom, value) {
var dayOfMonth;
if (!mom.isValid()) {
// No op
return mom;
}
if (typeof value === 'string') {
if (/^\d+$/.test(value)) {
value = toInt(value);
} else {
value = mom.localeData().monthsParse(value);
// TODO: Another silent failure?
if (!isNumber(value)) {
return mom;
}
}
}
dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
return mom;
}
function getSetMonth (value) {
if (value != null) {
setMonth(this, value);
hooks.updateOffset(this, true);
return this;
} else {
return get(this, 'Month');
}
}
function getDaysInMonth () {
return daysInMonth(this.year(), this.month());
}
var defaultMonthsShortRegex = matchWord;
function monthsShortRegex (isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsShortStrictRegex;
} else {
return this._monthsShortRegex;
}
} else {
if (!hasOwnProp(this, '_monthsShortRegex')) {
this._monthsShortRegex = defaultMonthsShortRegex;
}
return this._monthsShortStrictRegex && isStrict ?
this._monthsShortStrictRegex : this._monthsShortRegex;
}
}
var defaultMonthsRegex = matchWord;
function monthsRegex (isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsStrictRegex;
} else {
return this._monthsRegex;
}
} else {
if (!hasOwnProp(this, '_monthsRegex')) {
this._monthsRegex = defaultMonthsRegex;
}
return this._monthsStrictRegex && isStrict ?
this._monthsStrictRegex : this._monthsRegex;
}
}
function computeMonthsParse () {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var shortPieces = [], longPieces = [], mixedPieces = [],
i, mom;
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, i]);
shortPieces.push(this.monthsShort(mom, ''));
longPieces.push(this.months(mom, ''));
mixedPieces.push(this.months(mom, ''));
mixedPieces.push(this.monthsShort(mom, ''));
}
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
for (i = 0; i < 12; i++) {
shortPieces[i] = regexEscape(shortPieces[i]);
longPieces[i] = regexEscape(longPieces[i]);
}
for (i = 0; i < 24; i++) {
mixedPieces[i] = regexEscape(mixedPieces[i]);
}
this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._monthsShortRegex = this._monthsRegex;
this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
}
function createDate (y, m, d, h, M, s, ms) {
// can't just apply() to create a date:
// https://stackoverflow.com/q/181348
var date;
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
date = new Date(y + 400, m, d, h, M, s, ms);
if (isFinite(date.getFullYear())) {
date.setFullYear(y);
}
} else {
date = new Date(y, m, d, h, M, s, ms);
}
return date;
}
function createUTCDate (y) {
var date;
// the Date.UTC function remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
var args = Array.prototype.slice.call(arguments);
// preserve leap years using a full 400 year cycle, then reset
args[0] = y + 400;
date = new Date(Date.UTC.apply(null, args));
if (isFinite(date.getUTCFullYear())) {
date.setUTCFullYear(y);
}
} else {
date = new Date(Date.UTC.apply(null, arguments));
}
return date;
}
// start-of-first-week - start-of-year
function firstWeekOffset(year, dow, doy) {
var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
fwd = 7 + dow - doy,
// first-week day local weekday -- which local weekday is fwd
fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
return -fwdlw + fwd - 1;
}
// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
var localWeekday = (7 + weekday - dow) % 7,
weekOffset = firstWeekOffset(year, dow, doy),
dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
resYear, resDayOfYear;
if (dayOfYear <= 0) {
resYear = year - 1;
resDayOfYear = daysInYear(resYear) + dayOfYear;
} else if (dayOfYear > daysInYear(year)) {
resYear = year + 1;
resDayOfYear = dayOfYear - daysInYear(year);
} else {
resYear = year;
resDayOfYear = dayOfYear;
}
return {
year: resYear,
dayOfYear: resDayOfYear
};
}
function weekOfYear(mom, dow, doy) {
var weekOffset = firstWeekOffset(mom.year(), dow, doy),
week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
resWeek, resYear;
if (week < 1) {
resYear = mom.year() - 1;
resWeek = week + weeksInYear(resYear, dow, doy);
} else if (week > weeksInYear(mom.year(), dow, doy)) {
resWeek = week - weeksInYear(mom.year(), dow, doy);
resYear = mom.year() + 1;
} else {
resYear = mom.year();
resWeek = week;
}
return {
week: resWeek,
year: resYear
};
}
function weeksInYear(year, dow, doy) {
var weekOffset = firstWeekOffset(year, dow, doy),
weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
}
// FORMATTING
addFormatToken('w', ['ww', 2], 'wo', 'week');
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
// ALIASES
addUnitAlias('week', 'w');
addUnitAlias('isoWeek', 'W');
// PRIORITIES
addUnitPriority('week', 5);
addUnitPriority('isoWeek', 5);
// PARSING
addRegexToken('w', match1to2);
addRegexToken('ww', match1to2, match2);
addRegexToken('W', match1to2);
addRegexToken('WW', match1to2, match2);
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
week[token.substr(0, 1)] = toInt(input);
});
// HELPERS
// LOCALES
function localeWeek (mom) {
return weekOfYear(mom, this._week.dow, this._week.doy).week;
}
var defaultLocaleWeek = {
dow : 0, // Sunday is the first day of the week.
doy : 6 // The week that contains Jan 6th is the first week of the year.
};
function localeFirstDayOfWeek () {
return this._week.dow;
}
function localeFirstDayOfYear () {
return this._week.doy;
}
// MOMENTS
function getSetWeek (input) {
var week = this.localeData().week(this);
return input == null ? week : this.add((input - week) * 7, 'd');
}
function getSetISOWeek (input) {
var week = weekOfYear(this, 1, 4).week;
return input == null ? week : this.add((input - week) * 7, 'd');
}
// FORMATTING
addFormatToken('d', 0, 'do', 'day');
addFormatToken('dd', 0, 0, function (format) {
return this.localeData().weekdaysMin(this, format);
});
addFormatToken('ddd', 0, 0, function (format) {
return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
return this.localeData().weekdays(this, format);
});
addFormatToken('e', 0, 0, 'weekday');
addFormatToken('E', 0, 0, 'isoWeekday');
// ALIASES
addUnitAlias('day', 'd');
addUnitAlias('weekday', 'e');
addUnitAlias('isoWeekday', 'E');
// PRIORITY
addUnitPriority('day', 11);
addUnitPriority('weekday', 11);
addUnitPriority('isoWeekday', 11);
// PARSING
addRegexToken('d', match1to2);
addRegexToken('e', match1to2);
addRegexToken('E', match1to2);
addRegexToken('dd', function (isStrict, locale) {
return locale.weekdaysMinRegex(isStrict);
});
addRegexToken('ddd', function (isStrict, locale) {
return locale.weekdaysShortRegex(isStrict);
});
addRegexToken('dddd', function (isStrict, locale) {
return locale.weekdaysRegex(isStrict);
});
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
var weekday = config._locale.weekdaysParse(input, token, config._strict);
// if we didn't get a weekday name, mark the date as invalid
if (weekday != null) {
week.d = weekday;
} else {
getParsingFlags(config).invalidWeekday = input;
}
});
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
week[token] = toInt(input);
});
// HELPERS
function parseWeekday(input, locale) {
if (typeof input !== 'string') {
return input;
}
if (!isNaN(input)) {
return parseInt(input, 10);
}
input = locale.weekdaysParse(input);
if (typeof input === 'number') {
return input;
}
return null;
}
function parseIsoWeekday(input, locale) {
if (typeof input === 'string') {
return locale.weekdaysParse(input) % 7 || 7;
}
return isNaN(input) ? null : input;
}
// LOCALES
function shiftWeekdays (ws, n) {
return ws.slice(n, 7).concat(ws.slice(0, n));
}
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
function localeWeekdays (m, format) {
var weekdays = isArray(this._weekdays) ? this._weekdays :
this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone'];
return (m === true) ? shiftWeekdays(weekdays, this._week.dow)
: (m) ? weekdays[m.day()] : weekdays;
}
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
function localeWeekdaysShort (m) {
return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow)
: (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
}
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
function localeWeekdaysMin (m) {
return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow)
: (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
}
function handleStrictParse$1(weekdayName, format, strict) {
var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._shortWeekdaysParse = [];
this._minWeekdaysParse = [];
for (i = 0; i < 7; ++i) {
mom = createUTC([2000, 1]).day(i);
this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeWeekdaysParse (weekdayName, format, strict) {
var i, mom, regex;
if (this._weekdaysParseExact) {
return handleStrictParse$1.call(this, weekdayName, format, strict);
}
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._minWeekdaysParse = [];
this._shortWeekdaysParse = [];
this._fullWeekdaysParse = [];
}
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, 1]).day(i);
if (strict && !this._fullWeekdaysParse[i]) {
this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
}
if (!this._weekdaysParse[i]) {
regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
return i;
}
}
}
// MOMENTS
function getSetDayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
if (input != null) {
input = parseWeekday(input, this.localeData());
return this.add(input - day, 'd');
} else {
return day;
}
}
function getSetLocaleDayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
return input == null ? weekday : this.add(input - weekday, 'd');
}
function getSetISODayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
if (input != null) {
var weekday = parseIsoWeekday(input, this.localeData());
return this.day(this.day() % 7 ? weekday : weekday - 7);
} else {
return this.day() || 7;
}
}
var defaultWeekdaysRegex = matchWord;
function weekdaysRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysStrictRegex;
} else {
return this._weekdaysRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysRegex')) {
this._weekdaysRegex = defaultWeekdaysRegex;
}
return this._weekdaysStrictRegex && isStrict ?
this._weekdaysStrictRegex : this._weekdaysRegex;
}
}
var defaultWeekdaysShortRegex = matchWord;
function weekdaysShortRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysShortStrictRegex;
} else {
return this._weekdaysShortRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysShortRegex')) {
this._weekdaysShortRegex = defaultWeekdaysShortRegex;
}
return this._weekdaysShortStrictRegex && isStrict ?
this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
}
}
var defaultWeekdaysMinRegex = matchWord;
function weekdaysMinRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysMinStrictRegex;
} else {
return this._weekdaysMinRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysMinRegex')) {
this._weekdaysMinRegex = defaultWeekdaysMinRegex;
}
return this._weekdaysMinStrictRegex && isStrict ?
this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
}
}
function computeWeekdaysParse () {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
i, mom, minp, shortp, longp;
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, 1]).day(i);
minp = this.weekdaysMin(mom, '');
shortp = this.weekdaysShort(mom, '');
longp = this.weekdays(mom, '');
minPieces.push(minp);
shortPieces.push(shortp);
longPieces.push(longp);
mixedPieces.push(minp);
mixedPieces.push(shortp);
mixedPieces.push(longp);
}
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
minPieces.sort(cmpLenRev);
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
for (i = 0; i < 7; i++) {
shortPieces[i] = regexEscape(shortPieces[i]);
longPieces[i] = regexEscape(longPieces[i]);
mixedPieces[i] = regexEscape(mixedPieces[i]);
}
this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._weekdaysShortRegex = this._weekdaysRegex;
this._weekdaysMinRegex = this._weekdaysRegex;
this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
}
// FORMATTING
function hFormat() {
return this.hours() % 12 || 12;
}
function kFormat() {
return this.hours() || 24;
}
addFormatToken('H', ['HH', 2], 0, 'hour');
addFormatToken('h', ['hh', 2], 0, hFormat);
addFormatToken('k', ['kk', 2], 0, kFormat);
addFormatToken('hmm', 0, 0, function () {
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});
addFormatToken('hmmss', 0, 0, function () {
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2);
});
addFormatToken('Hmm', 0, 0, function () {
return '' + this.hours() + zeroFill(this.minutes(), 2);
});
addFormatToken('Hmmss', 0, 0, function () {
return '' + this.hours() + zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2);
});
function meridiem (token, lowercase) {
addFormatToken(token, 0, 0, function () {
return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
});
}
meridiem('a', true);
meridiem('A', false);
// ALIASES
addUnitAlias('hour', 'h');
// PRIORITY
addUnitPriority('hour', 13);
// PARSING
function matchMeridiem (isStrict, locale) {
return locale._meridiemParse;
}
addRegexToken('a', matchMeridiem);
addRegexToken('A', matchMeridiem);
addRegexToken('H', match1to2);
addRegexToken('h', match1to2);
addRegexToken('k', match1to2);
addRegexToken('HH', match1to2, match2);
addRegexToken('hh', match1to2, match2);
addRegexToken('kk', match1to2, match2);
addRegexToken('hmm', match3to4);
addRegexToken('hmmss', match5to6);
addRegexToken('Hmm', match3to4);
addRegexToken('Hmmss', match5to6);
addParseToken(['H', 'HH'], HOUR);
addParseToken(['k', 'kk'], function (input, array, config) {
var kInput = toInt(input);
array[HOUR] = kInput === 24 ? 0 : kInput;
});
addParseToken(['a', 'A'], function (input, array, config) {
config._isPm = config._locale.isPM(input);
config._meridiem = input;
});
addParseToken(['h', 'hh'], function (input, array, config) {
array[HOUR] = toInt(input);
getParsingFlags(config).bigHour = true;
});
addParseToken('hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
getParsingFlags(config).bigHour = true;
});
addParseToken('hmmss', function (input, array, config) {
var pos1 = input.length - 4;
var pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
getParsingFlags(config).bigHour = true;
});
addParseToken('Hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
});
addParseToken('Hmmss', function (input, array, config) {
var pos1 = input.length - 4;
var pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
});
// LOCALES
function localeIsPM (input) {
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return ((input + '').toLowerCase().charAt(0) === 'p');
}
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
function localeMeridiem (hours, minutes, isLower) {
if (hours > 11) {
return isLower ? 'pm' : 'PM';
} else {
return isLower ? 'am' : 'AM';
}
}
// MOMENTS
// Setting the hour should keep the time, because the user explicitly
// specified which hour they want. So trying to maintain the same hour (in
// a new timezone) makes sense. Adding/subtracting hours does not follow
// this rule.
var getSetHour = makeGetSet('Hours', true);
var baseConfig = {
calendar: defaultCalendar,
longDateFormat: defaultLongDateFormat,
invalidDate: defaultInvalidDate,
ordinal: defaultOrdinal,
dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
relativeTime: defaultRelativeTime,
months: defaultLocaleMonths,
monthsShort: defaultLocaleMonthsShort,
week: defaultLocaleWeek,
weekdays: defaultLocaleWeekdays,
weekdaysMin: defaultLocaleWeekdaysMin,
weekdaysShort: defaultLocaleWeekdaysShort,
meridiemParse: defaultLocaleMeridiemParse
};
// internal storage for locale config files
var locales = {};
var localeFamilies = {};
var globalLocale;
function normalizeLocale(key) {
return key ? key.toLowerCase().replace('_', '-') : key;
}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function chooseLocale(names) {
var i = 0, j, next, locale, split;
while (i < names.length) {
split = normalizeLocale(names[i]).split('-');
j = split.length;
next = normalizeLocale(names[i + 1]);
next = next ? next.split('-') : null;
while (j > 0) {
locale = loadLocale(split.slice(0, j).join('-'));
if (locale) {
return locale;
}
if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
//the next array item is better than a shallower substring of this one
break;
}
j--;
}
i++;
}
return globalLocale;
}
function loadLocale(name) {
var oldLocale = null;
// TODO: Find a better way to register and load all the locales in Node
if (!locales[name] && (typeof module !== 'undefined') &&
module && module.exports) {
try {
oldLocale = globalLocale._abbr;
var aliasedRequire = require;
aliasedRequire('./locale/' + name);
getSetGlobalLocale(oldLocale);
} catch (e) {}
}
return locales[name];
}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function getSetGlobalLocale (key, values) {
var data;
if (key) {
if (isUndefined(values)) {
data = getLocale(key);
}
else {
data = defineLocale(key, values);
}
if (data) {
// moment.duration._locale = moment._locale = data;
globalLocale = data;
}
else {
if ((typeof console !== 'undefined') && console.warn) {
//warn user if arguments are passed but the locale could not be set
console.warn('Locale ' + key + ' not found. Did you forget to load it?');
}
}
}
return globalLocale._abbr;
}
function defineLocale (name, config) {
if (config !== null) {
var locale, parentConfig = baseConfig;
config.abbr = name;
if (locales[name] != null) {
deprecateSimple('defineLocaleOverride',
'use moment.updateLocale(localeName, config) to change ' +
'an existing locale. moment.defineLocale(localeName, ' +
'config) should only be used for creating a new locale ' +
'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
parentConfig = locales[name]._config;
} else if (config.parentLocale != null) {
if (locales[config.parentLocale] != null) {
parentConfig = locales[config.parentLocale]._config;
} else {
locale = loadLocale(config.parentLocale);
if (locale != null) {
parentConfig = locale._config;
} else {
if (!localeFamilies[config.parentLocale]) {
localeFamilies[config.parentLocale] = [];
}
localeFamilies[config.parentLocale].push({
name: name,
config: config
});
return null;
}
}
}
locales[name] = new Locale(mergeConfigs(parentConfig, config));
if (localeFamilies[name]) {
localeFamilies[name].forEach(function (x) {
defineLocale(x.name, x.config);
});
}
// backwards compat for now: also set the locale
// make sure we set the locale AFTER all child locales have been
// created, so we won't end up with the child locale set.
getSetGlobalLocale(name);
return locales[name];
} else {
// useful for testing
delete locales[name];
return null;
}
}
function updateLocale(name, config) {
if (config != null) {
var locale, tmpLocale, parentConfig = baseConfig;
// MERGE
tmpLocale = loadLocale(name);
if (tmpLocale != null) {
parentConfig = tmpLocale._config;
}
config = mergeConfigs(parentConfig, config);
locale = new Locale(config);
locale.parentLocale = locales[name];
locales[name] = locale;
// backwards compat for now: also set the locale
getSetGlobalLocale(name);
} else {
// pass null for config to unupdate, useful for tests
if (locales[name] != null) {
if (locales[name].parentLocale != null) {
locales[name] = locales[name].parentLocale;
} else if (locales[name] != null) {
delete locales[name];
}
}
}
return locales[name];
}
// returns locale data
function getLocale (key) {
var locale;
if (key && key._locale && key._locale._abbr) {
key = key._locale._abbr;
}
if (!key) {
return globalLocale;
}
if (!isArray(key)) {
//short-circuit everything else
locale = loadLocale(key);
if (locale) {
return locale;
}
key = [key];
}
return chooseLocale(key);
}
function listLocales() {
return keys(locales);
}
function checkOverflow (m) {
var overflow;
var a = m._a;
if (a && getParsingFlags(m).overflow === -2) {
overflow =
a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
-1;
if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
overflow = DATE;
}
if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
overflow = WEEK;
}
if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
overflow = WEEKDAY;
}
getParsingFlags(m).overflow = overflow;
}
return m;
}
// Pick the first defined of two or three arguments.
function defaults(a, b, c) {
if (a != null) {
return a;
}
if (b != null) {
return b;
}
return c;
}
function currentDateArray(config) {
// hooks is actually the exported moment object
var nowValue = new Date(hooks.now());
if (config._useUTC) {
return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
}
return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function configFromArray (config) {
var i, date, input = [], currentDate, expectedWeekday, yearToUse;
if (config._d) {
return;
}
currentDate = currentDateArray(config);
//compute day of the year from weeks and weekdays
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
dayOfYearFromWeekInfo(config);
}
//if the day of the year is set, figure out what it is
if (config._dayOfYear != null) {
yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
getParsingFlags(config)._overflowDayOfYear = true;
}
date = createUTCDate(yearToUse, 0, config._dayOfYear);
config._a[MONTH] = date.getUTCMonth();
config._a[DATE] = date.getUTCDate();
}
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for (i = 0; i < 3 && config._a[i] == null; ++i) {
config._a[i] = input[i] = currentDate[i];
}
// Zero out whatever was not defaulted, including time
for (; i < 7; i++) {
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
}
// Check for 24:00:00.000
if (config._a[HOUR] === 24 &&
config._a[MINUTE] === 0 &&
config._a[SECOND] === 0 &&
config._a[MILLISECOND] === 0) {
config._nextDay = true;
config._a[HOUR] = 0;
}
config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
if (config._tzm != null) {
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
}
if (config._nextDay) {
config._a[HOUR] = 24;
}
// check for mismatching day of week
if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
getParsingFlags(config).weekdayMismatch = true;
}
}
function dayOfYearFromWeekInfo(config) {
var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
w = config._w;
if (w.GG != null || w.W != null || w.E != null) {
dow = 1;
doy = 4;
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
week = defaults(w.W, 1);
weekday = defaults(w.E, 1);
if (weekday < 1 || weekday > 7) {
weekdayOverflow = true;
}
} else {
dow = config._locale._week.dow;
doy = config._locale._week.doy;
var curWeek = weekOfYear(createLocal(), dow, doy);
weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
// Default to current week.
week = defaults(w.w, curWeek.week);
if (w.d != null) {
// weekday -- low day numbers are considered next week
weekday = w.d;
if (weekday < 0 || weekday > 6) {
weekdayOverflow = true;
}
} else if (w.e != null) {
// local weekday -- counting starts from beginning of week
weekday = w.e + dow;
if (w.e < 0 || w.e > 6) {
weekdayOverflow = true;
}
} else {
// default to beginning of week
weekday = dow;
}
}
if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
getParsingFlags(config)._overflowWeeks = true;
} else if (weekdayOverflow != null) {
getParsingFlags(config)._overflowWeekday = true;
} else {
temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
config._a[YEAR] = temp.year;
config._dayOfYear = temp.dayOfYear;
}
}
// iso 8601 regex
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
var isoDates = [
['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
['GGGG-[W]WW', /\d{4}-W\d\d/, false],
['YYYY-DDD', /\d{4}-\d{3}/],
['YYYY-MM', /\d{4}-\d\d/, false],
['YYYYYYMMDD', /[+-]\d{10}/],
['YYYYMMDD', /\d{8}/],
// YYYYMM is NOT allowed by the standard
['GGGG[W]WWE', /\d{4}W\d{3}/],
['GGGG[W]WW', /\d{4}W\d{2}/, false],
['YYYYDDD', /\d{7}/]
];
// iso time formats and regexes
var isoTimes = [
['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
['HH:mm:ss', /\d\d:\d\d:\d\d/],
['HH:mm', /\d\d:\d\d/],
['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
['HHmmss', /\d\d\d\d\d\d/],
['HHmm', /\d\d\d\d/],
['HH', /\d\d/]
];
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
// date from iso format
function configFromISO(config) {
var i, l,
string = config._i,
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
allowTime, dateFormat, timeFormat, tzFormat;
if (match) {
getParsingFlags(config).iso = true;
for (i = 0, l = isoDates.length; i < l; i++) {
if (isoDates[i][1].exec(match[1])) {
dateFormat = isoDates[i][0];
allowTime = isoDates[i][2] !== false;
break;
}
}
if (dateFormat == null) {
config._isValid = false;
return;
}
if (match[3]) {
for (i = 0, l = isoTimes.length; i < l; i++) {
if (isoTimes[i][1].exec(match[3])) {
// match[2] should be 'T' or space
timeFormat = (match[2] || ' ') + isoTimes[i][0];
break;
}
}
if (timeFormat == null) {
config._isValid = false;
return;
}
}
if (!allowTime && timeFormat != null) {
config._isValid = false;
return;
}
if (match[4]) {
if (tzRegex.exec(match[4])) {
tzFormat = 'Z';
} else {
config._isValid = false;
return;
}
}
config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
configFromStringAndFormat(config);
} else {
config._isValid = false;
}
}
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
var result = [
untruncateYear(yearStr),
defaultLocaleMonthsShort.indexOf(monthStr),
parseInt(dayStr, 10),
parseInt(hourStr, 10),
parseInt(minuteStr, 10)
];
if (secondStr) {
result.push(parseInt(secondStr, 10));
}
return result;
}
function untruncateYear(yearStr) {
var year = parseInt(yearStr, 10);
if (year <= 49) {
return 2000 + year;
} else if (year <= 999) {
return 1900 + year;
}
return year;
}
function preprocessRFC2822(s) {
// Remove comments and folding whitespace and replace multiple-spaces with a single space
return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
function checkWeekday(weekdayStr, parsedInput, config) {
if (weekdayStr) {
// TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
if (weekdayProvided !== weekdayActual) {
getParsingFlags(config).weekdayMismatch = true;
config._isValid = false;
return false;
}
}
return true;
}
var obsOffsets = {
UT: 0,
GMT: 0,
EDT: -4 * 60,
EST: -5 * 60,
CDT: -5 * 60,
CST: -6 * 60,
MDT: -6 * 60,
MST: -7 * 60,
PDT: -7 * 60,
PST: -8 * 60
};
function calculateOffset(obsOffset, militaryOffset, numOffset) {
if (obsOffset) {
return obsOffsets[obsOffset];
} else if (militaryOffset) {
// the only allowed military tz is Z
return 0;
} else {
var hm = parseInt(numOffset, 10);
var m = hm % 100, h = (hm - m) / 100;
return h * 60 + m;
}
}
// date and time from ref 2822 format
function configFromRFC2822(config) {
var match = rfc2822.exec(preprocessRFC2822(config._i));
if (match) {
var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
if (!checkWeekday(match[1], parsedArray, config)) {
return;
}
config._a = parsedArray;
config._tzm = calculateOffset(match[8], match[9], match[10]);
config._d = createUTCDate.apply(null, config._a);
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
getParsingFlags(config).rfc2822 = true;
} else {
config._isValid = false;
}
}
// date from iso format or fallback
function configFromString(config) {
var matched = aspNetJsonRegex.exec(config._i);
if (matched !== null) {
config._d = new Date(+matched[1]);
return;
}
configFromISO(config);
if (config._isValid === false) {
delete config._isValid;
} else {
return;
}
configFromRFC2822(config);
if (config._isValid === false) {
delete config._isValid;
} else {
return;
}
// Final attempt, use Input Fallback
hooks.createFromInputFallback(config);
}
hooks.createFromInputFallback = deprecate(
'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
'discouraged and will be removed in an upcoming major release. Please refer to ' +
'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
function (config) {
config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
}
);
// constant that refers to the ISO standard
hooks.ISO_8601 = function () {};
// constant that refers to the RFC 2822 form
hooks.RFC_2822 = function () {};
// date from string and format string
function configFromStringAndFormat(config) {
// TODO: Move this to another part of the creation flow to prevent circular deps
if (config._f === hooks.ISO_8601) {
configFromISO(config);
return;
}
if (config._f === hooks.RFC_2822) {
configFromRFC2822(config);
return;
}
config._a = [];
getParsingFlags(config).empty = true;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var string = '' + config._i,
i, parsedInput, tokens, token, skipped,
stringLength = string.length,
totalParsedInputLength = 0;
tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
// console.log('token', token, 'parsedInput', parsedInput,
// 'regex', getParseRegexForToken(token, config));
if (parsedInput) {
skipped = string.substr(0, string.indexOf(parsedInput));
if (skipped.length > 0) {
getParsingFlags(config).unusedInput.push(skipped);
}
string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
totalParsedInputLength += parsedInput.length;
}
// don't parse if it's not a known token
if (formatTokenFunctions[token]) {
if (parsedInput) {
getParsingFlags(config).empty = false;
}
else {
getParsingFlags(config).unusedTokens.push(token);
}
addTimeToArrayFromToken(token, parsedInput, config);
}
else if (config._strict && !parsedInput) {
getParsingFlags(config).unusedTokens.push(token);
}
}
// add remaining unparsed input length to the string
getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
if (string.length > 0) {
getParsingFlags(config).unusedInput.push(string);
}
// clear _12h flag if hour is <= 12
if (config._a[HOUR] <= 12 &&
getParsingFlags(config).bigHour === true &&
config._a[HOUR] > 0) {
getParsingFlags(config).bigHour = undefined;
}
getParsingFlags(config).parsedDateParts = config._a.slice(0);
getParsingFlags(config).meridiem = config._meridiem;
// handle meridiem
config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
configFromArray(config);
checkOverflow(config);
}
function meridiemFixWrap (locale, hour, meridiem) {
var isPm;
if (meridiem == null) {
// nothing to do
return hour;
}
if (locale.meridiemHour != null) {
return locale.meridiemHour(hour, meridiem);
} else if (locale.isPM != null) {
// Fallback
isPm = locale.isPM(meridiem);
if (isPm && hour < 12) {
hour += 12;
}
if (!isPm && hour === 12) {
hour = 0;
}
return hour;
} else {
// this is not supposed to happen
return hour;
}
}
// date from string and array of format strings
function configFromStringAndArray(config) {
var tempConfig,
bestMoment,
scoreToBeat,
i,
currentScore;
if (config._f.length === 0) {
getParsingFlags(config).invalidFormat = true;
config._d = new Date(NaN);
return;
}
for (i = 0; i < config._f.length; i++) {
currentScore = 0;
tempConfig = copyConfig({}, config);
if (config._useUTC != null) {
tempConfig._useUTC = config._useUTC;
}
tempConfig._f = config._f[i];
configFromStringAndFormat(tempConfig);
if (!isValid(tempConfig)) {
continue;
}
// if there is any input that was not parsed add a penalty for that format
currentScore += getParsingFlags(tempConfig).charsLeftOver;
//or tokens
currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
getParsingFlags(tempConfig).score = currentScore;
if (scoreToBeat == null || currentScore < scoreToBeat) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
}
}
extend(config, bestMoment || tempConfig);
}
function configFromObject(config) {
if (config._d) {
return;
}
var i = normalizeObjectUnits(config._i);
config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
return obj && parseInt(obj, 10);
});
configFromArray(config);
}
function createFromConfig (config) {
var res = new Moment(checkOverflow(prepareConfig(config)));
if (res._nextDay) {
// Adding is smart enough around DST
res.add(1, 'd');
res._nextDay = undefined;
}
return res;
}
function prepareConfig (config) {
var input = config._i,
format = config._f;
config._locale = config._locale || getLocale(config._l);
if (input === null || (format === undefined && input === '')) {
return createInvalid({nullInput: true});
}
if (typeof input === 'string') {
config._i = input = config._locale.preparse(input);
}
if (isMoment(input)) {
return new Moment(checkOverflow(input));
} else if (isDate(input)) {
config._d = input;
} else if (isArray(format)) {
configFromStringAndArray(config);
} else if (format) {
configFromStringAndFormat(config);
} else {
configFromInput(config);
}
if (!isValid(config)) {
config._d = null;
}
return config;
}
function configFromInput(config) {
var input = config._i;
if (isUndefined(input)) {
config._d = new Date(hooks.now());
} else if (isDate(input)) {
config._d = new Date(input.valueOf());
} else if (typeof input === 'string') {
configFromString(config);
} else if (isArray(input)) {
config._a = map(input.slice(0), function (obj) {
return parseInt(obj, 10);
});
configFromArray(config);
} else if (isObject(input)) {
configFromObject(config);
} else if (isNumber(input)) {
// from milliseconds
config._d = new Date(input);
} else {
hooks.createFromInputFallback(config);
}
}
function createLocalOrUTC (input, format, locale, strict, isUTC) {
var c = {};
if (locale === true || locale === false) {
strict = locale;
locale = undefined;
}
if ((isObject(input) && isObjectEmpty(input)) ||
(isArray(input) && input.length === 0)) {
input = undefined;
}
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
c._isAMomentObject = true;
c._useUTC = c._isUTC = isUTC;
c._l = locale;
c._i = input;
c._f = format;
c._strict = strict;
return createFromConfig(c);
}
function createLocal (input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, false);
}
var prototypeMin = deprecate(
'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
function () {
var other = createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other < this ? this : other;
} else {
return createInvalid();
}
}
);
var prototypeMax = deprecate(
'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
function () {
var other = createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other > this ? this : other;
} else {
return createInvalid();
}
}
);
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function pickBy(fn, moments) {
var res, i;
if (moments.length === 1 && isArray(moments[0])) {
moments = moments[0];
}
if (!moments.length) {
return createLocal();
}
res = moments[0];
for (i = 1; i < moments.length; ++i) {
if (!moments[i].isValid() || moments[i][fn](res)) {
res = moments[i];
}
}
return res;
}
// TODO: Use [].sort instead?
function min () {
var args = [].slice.call(arguments, 0);
return pickBy('isBefore', args);
}
function max () {
var args = [].slice.call(arguments, 0);
return pickBy('isAfter', args);
}
var now = function () {
return Date.now ? Date.now() : +(new Date());
};
var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
function isDurationValid(m) {
for (var key in m) {
if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
return false;
}
}
var unitHasDecimal = false;
for (var i = 0; i < ordering.length; ++i) {
if (m[ordering[i]]) {
if (unitHasDecimal) {
return false; // only allow non-integers for smallest unit
}
if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
unitHasDecimal = true;
}
}
}
return true;
}
function isValid$1() {
return this._isValid;
}
function createInvalid$1() {
return createDuration(NaN);
}
function Duration (duration) {
var normalizedInput = normalizeObjectUnits(duration),
years = normalizedInput.year || 0,
quarters = normalizedInput.quarter || 0,
months = normalizedInput.month || 0,
weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
days = normalizedInput.day || 0,
hours = normalizedInput.hour || 0,
minutes = normalizedInput.minute || 0,
seconds = normalizedInput.second || 0,
milliseconds = normalizedInput.millisecond || 0;
this._isValid = isDurationValid(normalizedInput);
// representation for dateAddRemove
this._milliseconds = +milliseconds +
seconds * 1e3 + // 1000
minutes * 6e4 + // 1000 * 60
hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days = +days +
weeks * 7;
// It is impossible to translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months = +months +
quarters * 3 +
years * 12;
this._data = {};
this._locale = getLocale();
this._bubble();
}
function isDuration (obj) {
return obj instanceof Duration;
}
function absRound (number) {
if (number < 0) {
return Math.round(-1 * number) * -1;
} else {
return Math.round(number);
}
}
// FORMATTING
function offset (token, separator) {
addFormatToken(token, 0, 0, function () {
var offset = this.utcOffset();
var sign = '+';
if (offset < 0) {
offset = -offset;
sign = '-';
}
return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
});
}
offset('Z', ':');
offset('ZZ', '');
// PARSING
addRegexToken('Z', matchShortOffset);
addRegexToken('ZZ', matchShortOffset);
addParseToken(['Z', 'ZZ'], function (input, array, config) {
config._useUTC = true;
config._tzm = offsetFromString(matchShortOffset, input);
});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var chunkOffset = /([\+\-]|\d\d)/gi;
function offsetFromString(matcher, string) {
var matches = (string || '').match(matcher);
if (matches === null) {
return null;
}
var chunk = matches[matches.length - 1] || [];
var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
var minutes = +(parts[1] * 60) + toInt(parts[2]);
return minutes === 0 ?
0 :
parts[0] === '+' ? minutes : -minutes;
}
// Return a moment from input, that is local/utc/zone equivalent to model.
function cloneWithOffset(input, model) {
var res, diff;
if (model._isUTC) {
res = model.clone();
diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
// Use low-level api, because this fn is low-level api.
res._d.setTime(res._d.valueOf() + diff);
hooks.updateOffset(res, false);
return res;
} else {
return createLocal(input).local();
}
}
function getDateOffset (m) {
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
}
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
hooks.updateOffset = function () {};
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function getSetOffset (input, keepLocalTime, keepMinutes) {
var offset = this._offset || 0,
localAdjust;
if (!this.isValid()) {
return input != null ? this : NaN;
}
if (input != null) {
if (typeof input === 'string') {
input = offsetFromString(matchShortOffset, input);
if (input === null) {
return this;
}
} else if (Math.abs(input) < 16 && !keepMinutes) {
input = input * 60;
}
if (!this._isUTC && keepLocalTime) {
localAdjust = getDateOffset(this);
}
this._offset = input;
this._isUTC = true;
if (localAdjust != null) {
this.add(localAdjust, 'm');
}
if (offset !== input) {
if (!keepLocalTime || this._changeInProgress) {
addSubtract(this, createDuration(input - offset, 'm'), 1, false);
} else if (!this._changeInProgress) {
this._changeInProgress = true;
hooks.updateOffset(this, true);
this._changeInProgress = null;
}
}
return this;
} else {
return this._isUTC ? offset : getDateOffset(this);
}
}
function getSetZone (input, keepLocalTime) {
if (input != null) {
if (typeof input !== 'string') {
input = -input;
}
this.utcOffset(input, keepLocalTime);
return this;
} else {
return -this.utcOffset();
}
}
function setOffsetToUTC (keepLocalTime) {
return this.utcOffset(0, keepLocalTime);
}
function setOffsetToLocal (keepLocalTime) {
if (this._isUTC) {
this.utcOffset(0, keepLocalTime);
this._isUTC = false;
if (keepLocalTime) {
this.subtract(getDateOffset(this), 'm');
}
}
return this;
}
function setOffsetToParsedOffset () {
if (this._tzm != null) {
this.utcOffset(this._tzm, false, true);
} else if (typeof this._i === 'string') {
var tZone = offsetFromString(matchOffset, this._i);
if (tZone != null) {
this.utcOffset(tZone);
}
else {
this.utcOffset(0, true);
}
}
return this;
}
function hasAlignedHourOffset (input) {
if (!this.isValid()) {
return false;
}
input = input ? createLocal(input).utcOffset() : 0;
return (this.utcOffset() - input) % 60 === 0;
}
function isDaylightSavingTime () {
return (
this.utcOffset() > this.clone().month(0).utcOffset() ||
this.utcOffset() > this.clone().month(5).utcOffset()
);
}
function isDaylightSavingTimeShifted () {
if (!isUndefined(this._isDSTShifted)) {
return this._isDSTShifted;
}
var c = {};
copyConfig(c, this);
c = prepareConfig(c);
if (c._a) {
var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
this._isDSTShifted = this.isValid() &&
compareArrays(c._a, other.toArray()) > 0;
} else {
this._isDSTShifted = false;
}
return this._isDSTShifted;
}
function isLocal () {
return this.isValid() ? !this._isUTC : false;
}
function isUtcOffset () {
return this.isValid() ? this._isUTC : false;
}
function isUtc () {
return this.isValid() ? this._isUTC && this._offset === 0 : false;
}
// ASP.NET json date format regex
var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
function createDuration (input, key) {
var duration = input,
// matching against regexp is expensive, do it on demand
match = null,
sign,
ret,
diffRes;
if (isDuration(input)) {
duration = {
ms : input._milliseconds,
d : input._days,
M : input._months
};
} else if (isNumber(input)) {
duration = {};
if (key) {
duration[key] = input;
} else {
duration.milliseconds = input;
}
} else if (!!(match = aspNetRegex.exec(input))) {
sign = (match[1] === '-') ? -1 : 1;
duration = {
y : 0,
d : toInt(match[DATE]) * sign,
h : toInt(match[HOUR]) * sign,
m : toInt(match[MINUTE]) * sign,
s : toInt(match[SECOND]) * sign,
ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
};
} else if (!!(match = isoRegex.exec(input))) {
sign = (match[1] === '-') ? -1 : 1;
duration = {
y : parseIso(match[2], sign),
M : parseIso(match[3], sign),
w : parseIso(match[4], sign),
d : parseIso(match[5], sign),
h : parseIso(match[6], sign),
m : parseIso(match[7], sign),
s : parseIso(match[8], sign)
};
} else if (duration == null) {// checks for null or undefined
duration = {};
} else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
duration = {};
duration.ms = diffRes.milliseconds;
duration.M = diffRes.months;
}
ret = new Duration(duration);
if (isDuration(input) && hasOwnProp(input, '_locale')) {
ret._locale = input._locale;
}
return ret;
}
createDuration.fn = Duration.prototype;
createDuration.invalid = createInvalid$1;
function parseIso (inp, sign) {
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var res = inp && parseFloat(inp.replace(',', '.'));
// apply sign while we're at it
return (isNaN(res) ? 0 : res) * sign;
}
function positiveMomentsDifference(base, other) {
var res = {};
res.months = other.month() - base.month() +
(other.year() - base.year()) * 12;
if (base.clone().add(res.months, 'M').isAfter(other)) {
--res.months;
}
res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
return res;
}
function momentsDifference(base, other) {
var res;
if (!(base.isValid() && other.isValid())) {
return {milliseconds: 0, months: 0};
}
other = cloneWithOffset(other, base);
if (base.isBefore(other)) {
res = positiveMomentsDifference(base, other);
} else {
res = positiveMomentsDifference(other, base);
res.milliseconds = -res.milliseconds;
res.months = -res.months;
}
return res;
}
// TODO: remove 'name' arg after deprecation is removed
function createAdder(direction, name) {
return function (val, period) {
var dur, tmp;
//invert the arguments, but complain about it
if (period !== null && !isNaN(+period)) {
deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
tmp = val; val = period; period = tmp;
}
val = typeof val === 'string' ? +val : val;
dur = createDuration(val, period);
addSubtract(this, dur, direction);
return this;
};
}
function addSubtract (mom, duration, isAdding, updateOffset) {
var milliseconds = duration._milliseconds,
days = absRound(duration._days),
months = absRound(duration._months);
if (!mom.isValid()) {
// No op
return;
}
updateOffset = updateOffset == null ? true : updateOffset;
if (months) {
setMonth(mom, get(mom, 'Month') + months * isAdding);
}
if (days) {
set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
}
if (milliseconds) {
mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
}
if (updateOffset) {
hooks.updateOffset(mom, days || months);
}
}
var add = createAdder(1, 'add');
var subtract = createAdder(-1, 'subtract');
function getCalendarFormat(myMoment, now) {
var diff = myMoment.diff(now, 'days', true);
return diff < -6 ? 'sameElse' :
diff < -1 ? 'lastWeek' :
diff < 0 ? 'lastDay' :
diff < 1 ? 'sameDay' :
diff < 2 ? 'nextDay' :
diff < 7 ? 'nextWeek' : 'sameElse';
}
function calendar$1 (time, formats) {
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var now = time || createLocal(),
sod = cloneWithOffset(now, this).startOf('day'),
format = hooks.calendarFormat(this, sod) || 'sameElse';
var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
}
function clone () {
return new Moment(this);
}
function isAfter (input, units) {
var localInput = isMoment(input) ? input : createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() > localInput.valueOf();
} else {
return localInput.valueOf() < this.clone().startOf(units).valueOf();
}
}
function isBefore (input, units) {
var localInput = isMoment(input) ? input : createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() < localInput.valueOf();
} else {
return this.clone().endOf(units).valueOf() < localInput.valueOf();
}
}
function isBetween (from, to, units, inclusivity) {
var localFrom = isMoment(from) ? from : createLocal(from),
localTo = isMoment(to) ? to : createLocal(to);
if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
return false;
}
inclusivity = inclusivity || '()';
return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) &&
(inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
}
function isSame (input, units) {
var localInput = isMoment(input) ? input : createLocal(input),
inputMs;
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() === localInput.valueOf();
} else {
inputMs = localInput.valueOf();
return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
}
}
function isSameOrAfter (input, units) {
return this.isSame(input, units) || this.isAfter(input, units);
}
function isSameOrBefore (input, units) {
return this.isSame(input, units) || this.isBefore(input, units);
}
function diff (input, units, asFloat) {
var that,
zoneDelta,
output;
if (!this.isValid()) {
return NaN;
}
that = cloneWithOffset(input, this);
if (!that.isValid()) {
return NaN;
}
zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
units = normalizeUnits(units);
switch (units) {
case 'year': output = monthDiff(this, that) / 12; break;
case 'month': output = monthDiff(this, that); break;
case 'quarter': output = monthDiff(this, that) / 3; break;
case 'second': output = (this - that) / 1e3; break; // 1000
case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
default: output = this - that;
}
return asFloat ? output : absFloor(output);
}
function monthDiff (a, b) {
// difference in months
var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
anchor = a.clone().add(wholeMonthDiff, 'months'),
anchor2, adjust;
if (b - anchor < 0) {
anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor - anchor2);
} else {
anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor2 - anchor);
}
//check for negative zero, return zero if negative zero
return -(wholeMonthDiff + adjust) || 0;
}
hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
function toString () {
return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
}
function toISOString(keepOffset) {
if (!this.isValid()) {
return null;
}
var utc = keepOffset !== true;
var m = utc ? this.clone().utc() : this;
if (m.year() < 0 || m.year() > 9999) {
return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
}
if (isFunction(Date.prototype.toISOString)) {
// native implementation is ~50x faster, use it when we can
if (utc) {
return this.toDate().toISOString();
} else {
return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
}
}
return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
}
/**
* Return a human readable representation of a moment that can
* also be evaluated to get a new moment which is the same
*
* @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
*/
function inspect () {
if (!this.isValid()) {
return 'moment.invalid(/* ' + this._i + ' */)';
}
var func = 'moment';
var zone = '';
if (!this.isLocal()) {
func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
zone = 'Z';
}
var prefix = '[' + func + '("]';
var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
var datetime = '-MM-DD[T]HH:mm:ss.SSS';
var suffix = zone + '[")]';
return this.format(prefix + year + datetime + suffix);
}
function format (inputString) {
if (!inputString) {
inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
}
var output = formatMoment(this, inputString);
return this.localeData().postformat(output);
}
function from (time, withoutSuffix) {
if (this.isValid() &&
((isMoment(time) && time.isValid()) ||
createLocal(time).isValid())) {
return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function fromNow (withoutSuffix) {
return this.from(createLocal(), withoutSuffix);
}
function to (time, withoutSuffix) {
if (this.isValid() &&
((isMoment(time) && time.isValid()) ||
createLocal(time).isValid())) {
return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function toNow (withoutSuffix) {
return this.to(createLocal(), withoutSuffix);
}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function locale (key) {
var newLocaleData;
if (key === undefined) {
return this._locale._abbr;
} else {
newLocaleData = getLocale(key);
if (newLocaleData != null) {
this._locale = newLocaleData;
}
return this;
}
}
var lang = deprecate(
'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
function (key) {
if (key === undefined) {
return this.localeData();
} else {
return this.locale(key);
}
}
);
function localeData () {
return this._locale;
}
var MS_PER_SECOND = 1000;
var MS_PER_MINUTE = 60 * MS_PER_SECOND;
var MS_PER_HOUR = 60 * MS_PER_MINUTE;
var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
// actual modulo - handles negative numbers (for dates before 1970):
function mod$1(dividend, divisor) {
return (dividend % divisor + divisor) % divisor;
}
function localStartOfDate(y, m, d) {
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return new Date(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return new Date(y, m, d).valueOf();
}
}
function utcStartOfDate(y, m, d) {
// Date.UTC remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return Date.UTC(y, m, d);
}
}
function startOf (units) {
var time;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year(), 0, 1);
break;
case 'quarter':
time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
break;
case 'month':
time = startOfDate(this.year(), this.month(), 1);
break;
case 'week':
time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
break;
case 'isoWeek':
time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date());
break;
case 'hour':
time = this._d.valueOf();
time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
break;
case 'minute':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_MINUTE);
break;
case 'second':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_SECOND);
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
function endOf (units) {
var time;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year() + 1, 0, 1) - 1;
break;
case 'quarter':
time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
break;
case 'month':
time = startOfDate(this.year(), this.month() + 1, 1) - 1;
break;
case 'week':
time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
break;
case 'isoWeek':
time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
break;
case 'hour':
time = this._d.valueOf();
time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
break;
case 'minute':
time = this._d.valueOf();
time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
break;
case 'second':
time = this._d.valueOf();
time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
function valueOf () {
return this._d.valueOf() - ((this._offset || 0) * 60000);
}
function unix () {
return Math.floor(this.valueOf() / 1000);
}
function toDate () {
return new Date(this.valueOf());
}
function toArray () {
var m = this;
return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
}
function toObject () {
var m = this;
return {
years: m.year(),
months: m.month(),
date: m.date(),
hours: m.hours(),
minutes: m.minutes(),
seconds: m.seconds(),
milliseconds: m.milliseconds()
};
}
function toJSON () {
// new Date(NaN).toJSON() === null
return this.isValid() ? this.toISOString() : null;
}
function isValid$2 () {
return isValid(this);
}
function parsingFlags () {
return extend({}, getParsingFlags(this));
}
function invalidAt () {
return getParsingFlags(this).overflow;
}
function creationData() {
return {
input: this._i,
format: this._f,
locale: this._locale,
isUTC: this._isUTC,
strict: this._strict
};
}
// FORMATTING
addFormatToken(0, ['gg', 2], 0, function () {
return this.weekYear() % 100;
});
addFormatToken(0, ['GG', 2], 0, function () {
return this.isoWeekYear() % 100;
});
function addWeekYearFormatToken (token, getter) {
addFormatToken(0, [token, token.length], 0, getter);
}
addWeekYearFormatToken('gggg', 'weekYear');
addWeekYearFormatToken('ggggg', 'weekYear');
addWeekYearFormatToken('GGGG', 'isoWeekYear');
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
// ALIASES
addUnitAlias('weekYear', 'gg');
addUnitAlias('isoWeekYear', 'GG');
// PRIORITY
addUnitPriority('weekYear', 1);
addUnitPriority('isoWeekYear', 1);
// PARSING
addRegexToken('G', matchSigned);
addRegexToken('g', matchSigned);
addRegexToken('GG', match1to2, match2);
addRegexToken('gg', match1to2, match2);
addRegexToken('GGGG', match1to4, match4);
addRegexToken('gggg', match1to4, match4);
addRegexToken('GGGGG', match1to6, match6);
addRegexToken('ggggg', match1to6, match6);
addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
week[token.substr(0, 2)] = toInt(input);
});
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
week[token] = hooks.parseTwoDigitYear(input);
});
// MOMENTS
function getSetWeekYear (input) {
return getSetWeekYearHelper.call(this,
input,
this.week(),
this.weekday(),
this.localeData()._week.dow,
this.localeData()._week.doy);
}
function getSetISOWeekYear (input) {
return getSetWeekYearHelper.call(this,
input, this.isoWeek(), this.isoWeekday(), 1, 4);
}
function getISOWeeksInYear () {
return weeksInYear(this.year(), 1, 4);
}
function getWeeksInYear () {
var weekInfo = this.localeData()._week;
return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
}
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
var weeksTarget;
if (input == null) {
return weekOfYear(this, dow, doy).year;
} else {
weeksTarget = weeksInYear(input, dow, doy);
if (week > weeksTarget) {
week = weeksTarget;
}
return setWeekAll.call(this, input, week, weekday, dow, doy);
}
}
function setWeekAll(weekYear, week, weekday, dow, doy) {
var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
this.year(date.getUTCFullYear());
this.month(date.getUTCMonth());
this.date(date.getUTCDate());
return this;
}
// FORMATTING
addFormatToken('Q', 0, 'Qo', 'quarter');
// ALIASES
addUnitAlias('quarter', 'Q');
// PRIORITY
addUnitPriority('quarter', 7);
// PARSING
addRegexToken('Q', match1);
addParseToken('Q', function (input, array) {
array[MONTH] = (toInt(input) - 1) * 3;
});
// MOMENTS
function getSetQuarter (input) {
return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
}
// FORMATTING
addFormatToken('D', ['DD', 2], 'Do', 'date');
// ALIASES
addUnitAlias('date', 'D');
// PRIORITY
addUnitPriority('date', 9);
// PARSING
addRegexToken('D', match1to2);
addRegexToken('DD', match1to2, match2);
addRegexToken('Do', function (isStrict, locale) {
// TODO: Remove "ordinalParse" fallback in next major release.
return isStrict ?
(locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
locale._dayOfMonthOrdinalParseLenient;
});
addParseToken(['D', 'DD'], DATE);
addParseToken('Do', function (input, array) {
array[DATE] = toInt(input.match(match1to2)[0]);
});
// MOMENTS
var getSetDayOfMonth = makeGetSet('Date', true);
// FORMATTING
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
// ALIASES
addUnitAlias('dayOfYear', 'DDD');
// PRIORITY
addUnitPriority('dayOfYear', 4);
// PARSING
addRegexToken('DDD', match1to3);
addRegexToken('DDDD', match3);
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
config._dayOfYear = toInt(input);
});
// HELPERS
// MOMENTS
function getSetDayOfYear (input) {
var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
}
// FORMATTING
addFormatToken('m', ['mm', 2], 0, 'minute');
// ALIASES
addUnitAlias('minute', 'm');
// PRIORITY
addUnitPriority('minute', 14);
// PARSING
addRegexToken('m', match1to2);
addRegexToken('mm', match1to2, match2);
addParseToken(['m', 'mm'], MINUTE);
// MOMENTS
var getSetMinute = makeGetSet('Minutes', false);
// FORMATTING
addFormatToken('s', ['ss', 2], 0, 'second');
// ALIASES
addUnitAlias('second', 's');
// PRIORITY
addUnitPriority('second', 15);
// PARSING
addRegexToken('s', match1to2);
addRegexToken('ss', match1to2, match2);
addParseToken(['s', 'ss'], SECOND);
// MOMENTS
var getSetSecond = makeGetSet('Seconds', false);
// FORMATTING
addFormatToken('S', 0, 0, function () {
return ~~(this.millisecond() / 100);
});
addFormatToken(0, ['SS', 2], 0, function () {
return ~~(this.millisecond() / 10);
});
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
addFormatToken(0, ['SSSS', 4], 0, function () {
return this.millisecond() * 10;
});
addFormatToken(0, ['SSSSS', 5], 0, function () {
return this.millisecond() * 100;
});
addFormatToken(0, ['SSSSSS', 6], 0, function () {
return this.millisecond() * 1000;
});
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
return this.millisecond() * 10000;
});
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
return this.millisecond() * 100000;
});
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
return this.millisecond() * 1000000;
});
// ALIASES
addUnitAlias('millisecond', 'ms');
// PRIORITY
addUnitPriority('millisecond', 16);
// PARSING
addRegexToken('S', match1to3, match1);
addRegexToken('SS', match1to3, match2);
addRegexToken('SSS', match1to3, match3);
var token;
for (token = 'SSSS'; token.length <= 9; token += 'S') {
addRegexToken(token, matchUnsigned);
}
function parseMs(input, array) {
array[MILLISECOND] = toInt(('0.' + input) * 1000);
}
for (token = 'S'; token.length <= 9; token += 'S') {
addParseToken(token, parseMs);
}
// MOMENTS
var getSetMillisecond = makeGetSet('Milliseconds', false);
// FORMATTING
addFormatToken('z', 0, 0, 'zoneAbbr');
addFormatToken('zz', 0, 0, 'zoneName');
// MOMENTS
function getZoneAbbr () {
return this._isUTC ? 'UTC' : '';
}
function getZoneName () {
return this._isUTC ? 'Coordinated Universal Time' : '';
}
var proto = Moment.prototype;
proto.add = add;
proto.calendar = calendar$1;
proto.clone = clone;
proto.diff = diff;
proto.endOf = endOf;
proto.format = format;
proto.from = from;
proto.fromNow = fromNow;
proto.to = to;
proto.toNow = toNow;
proto.get = stringGet;
proto.invalidAt = invalidAt;
proto.isAfter = isAfter;
proto.isBefore = isBefore;
proto.isBetween = isBetween;
proto.isSame = isSame;
proto.isSameOrAfter = isSameOrAfter;
proto.isSameOrBefore = isSameOrBefore;
proto.isValid = isValid$2;
proto.lang = lang;
proto.locale = locale;
proto.localeData = localeData;
proto.max = prototypeMax;
proto.min = prototypeMin;
proto.parsingFlags = parsingFlags;
proto.set = stringSet;
proto.startOf = startOf;
proto.subtract = subtract;
proto.toArray = toArray;
proto.toObject = toObject;
proto.toDate = toDate;
proto.toISOString = toISOString;
proto.inspect = inspect;
proto.toJSON = toJSON;
proto.toString = toString;
proto.unix = unix;
proto.valueOf = valueOf;
proto.creationData = creationData;
proto.year = getSetYear;
proto.isLeapYear = getIsLeapYear;
proto.weekYear = getSetWeekYear;
proto.isoWeekYear = getSetISOWeekYear;
proto.quarter = proto.quarters = getSetQuarter;
proto.month = getSetMonth;
proto.daysInMonth = getDaysInMonth;
proto.week = proto.weeks = getSetWeek;
proto.isoWeek = proto.isoWeeks = getSetISOWeek;
proto.weeksInYear = getWeeksInYear;
proto.isoWeeksInYear = getISOWeeksInYear;
proto.date = getSetDayOfMonth;
proto.day = proto.days = getSetDayOfWeek;
proto.weekday = getSetLocaleDayOfWeek;
proto.isoWeekday = getSetISODayOfWeek;
proto.dayOfYear = getSetDayOfYear;
proto.hour = proto.hours = getSetHour;
proto.minute = proto.minutes = getSetMinute;
proto.second = proto.seconds = getSetSecond;
proto.millisecond = proto.milliseconds = getSetMillisecond;
proto.utcOffset = getSetOffset;
proto.utc = setOffsetToUTC;
proto.local = setOffsetToLocal;
proto.parseZone = setOffsetToParsedOffset;
proto.hasAlignedHourOffset = hasAlignedHourOffset;
proto.isDST = isDaylightSavingTime;
proto.isLocal = isLocal;
proto.isUtcOffset = isUtcOffset;
proto.isUtc = isUtc;
proto.isUTC = isUtc;
proto.zoneAbbr = getZoneAbbr;
proto.zoneName = getZoneName;
proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
function createUnix (input) {
return createLocal(input * 1000);
}
function createInZone () {
return createLocal.apply(null, arguments).parseZone();
}
function preParsePostFormat (string) {
return string;
}
var proto$1 = Locale.prototype;
proto$1.calendar = calendar;
proto$1.longDateFormat = longDateFormat;
proto$1.invalidDate = invalidDate;
proto$1.ordinal = ordinal;
proto$1.preparse = preParsePostFormat;
proto$1.postformat = preParsePostFormat;
proto$1.relativeTime = relativeTime;
proto$1.pastFuture = pastFuture;
proto$1.set = set;
proto$1.months = localeMonths;
proto$1.monthsShort = localeMonthsShort;
proto$1.monthsParse = localeMonthsParse;
proto$1.monthsRegex = monthsRegex;
proto$1.monthsShortRegex = monthsShortRegex;
proto$1.week = localeWeek;
proto$1.firstDayOfYear = localeFirstDayOfYear;
proto$1.firstDayOfWeek = localeFirstDayOfWeek;
proto$1.weekdays = localeWeekdays;
proto$1.weekdaysMin = localeWeekdaysMin;
proto$1.weekdaysShort = localeWeekdaysShort;
proto$1.weekdaysParse = localeWeekdaysParse;
proto$1.weekdaysRegex = weekdaysRegex;
proto$1.weekdaysShortRegex = weekdaysShortRegex;
proto$1.weekdaysMinRegex = weekdaysMinRegex;
proto$1.isPM = localeIsPM;
proto$1.meridiem = localeMeridiem;
function get$1 (format, index, field, setter) {
var locale = getLocale();
var utc = createUTC().set(setter, index);
return locale[field](utc, format);
}
function listMonthsImpl (format, index, field) {
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
if (index != null) {
return get$1(format, index, field, 'month');
}
var i;
var out = [];
for (i = 0; i < 12; i++) {
out[i] = get$1(format, i, field, 'month');
}
return out;
}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function listWeekdaysImpl (localeSorted, format, index, field) {
if (typeof localeSorted === 'boolean') {
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
} else {
format = localeSorted;
index = format;
localeSorted = false;
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
}
var locale = getLocale(),
shift = localeSorted ? locale._week.dow : 0;
if (index != null) {
return get$1(format, (index + shift) % 7, field, 'day');
}
var i;
var out = [];
for (i = 0; i < 7; i++) {
out[i] = get$1(format, (i + shift) % 7, field, 'day');
}
return out;
}
function listMonths (format, index) {
return listMonthsImpl(format, index, 'months');
}
function listMonthsShort (format, index) {
return listMonthsImpl(format, index, 'monthsShort');
}
function listWeekdays (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
}
function listWeekdaysShort (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
}
function listWeekdaysMin (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
}
getSetGlobalLocale('en', {
dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
ordinal : function (number) {
var b = number % 10,
output = (toInt(number % 100 / 10) === 1) ? 'th' :
(b === 1) ? 'st' :
(b === 2) ? 'nd' :
(b === 3) ? 'rd' : 'th';
return number + output;
}
});
// Side effect imports
hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
var mathAbs = Math.abs;
function abs () {
var data = this._data;
this._milliseconds = mathAbs(this._milliseconds);
this._days = mathAbs(this._days);
this._months = mathAbs(this._months);
data.milliseconds = mathAbs(data.milliseconds);
data.seconds = mathAbs(data.seconds);
data.minutes = mathAbs(data.minutes);
data.hours = mathAbs(data.hours);
data.months = mathAbs(data.months);
data.years = mathAbs(data.years);
return this;
}
function addSubtract$1 (duration, input, value, direction) {
var other = createDuration(input, value);
duration._milliseconds += direction * other._milliseconds;
duration._days += direction * other._days;
duration._months += direction * other._months;
return duration._bubble();
}
// supports only 2.0-style add(1, 's') or add(duration)
function add$1 (input, value) {
return addSubtract$1(this, input, value, 1);
}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function subtract$1 (input, value) {
return addSubtract$1(this, input, value, -1);
}
function absCeil (number) {
if (number < 0) {
return Math.floor(number);
} else {
return Math.ceil(number);
}
}
function bubble () {
var milliseconds = this._milliseconds;
var days = this._days;
var months = this._months;
var data = this._data;
var seconds, minutes, hours, years, monthsFromDays;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
(milliseconds <= 0 && days <= 0 && months <= 0))) {
milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
days = 0;
months = 0;
}
// The following code bubbles up values, see the tests for
// examples of what that means.
data.milliseconds = milliseconds % 1000;
seconds = absFloor(milliseconds / 1000);
data.seconds = seconds % 60;
minutes = absFloor(seconds / 60);
data.minutes = minutes % 60;
hours = absFloor(minutes / 60);
data.hours = hours % 24;
days += absFloor(hours / 24);
// convert days to months
monthsFromDays = absFloor(daysToMonths(days));
months += monthsFromDays;
days -= absCeil(monthsToDays(monthsFromDays));
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
data.days = days;
data.months = months;
data.years = years;
return this;
}
function daysToMonths (days) {
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return days * 4800 / 146097;
}
function monthsToDays (months) {
// the reverse of daysToMonths
return months * 146097 / 4800;
}
function as (units) {
if (!this.isValid()) {
return NaN;
}
var days;
var months;
var milliseconds = this._milliseconds;
units = normalizeUnits(units);
if (units === 'month' || units === 'quarter' || units === 'year') {
days = this._days + milliseconds / 864e5;
months = this._months + daysToMonths(days);
switch (units) {
case 'month': return months;
case 'quarter': return months / 3;
case 'year': return months / 12;
}
} else {
// handle milliseconds separately because of floating point math errors (issue #1867)
days = this._days + Math.round(monthsToDays(this._months));
switch (units) {
case 'week' : return days / 7 + milliseconds / 6048e5;
case 'day' : return days + milliseconds / 864e5;
case 'hour' : return days * 24 + milliseconds / 36e5;
case 'minute' : return days * 1440 + milliseconds / 6e4;
case 'second' : return days * 86400 + milliseconds / 1000;
// Math.floor prevents floating point math errors here
case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
default: throw new Error('Unknown unit ' + units);
}
}
}
// TODO: Use this.as('ms')?
function valueOf$1 () {
if (!this.isValid()) {
return NaN;
}
return (
this._milliseconds +
this._days * 864e5 +
(this._months % 12) * 2592e6 +
toInt(this._months / 12) * 31536e6
);
}
function makeAs (alias) {
return function () {
return this.as(alias);
};
}
var asMilliseconds = makeAs('ms');
var asSeconds = makeAs('s');
var asMinutes = makeAs('m');
var asHours = makeAs('h');
var asDays = makeAs('d');
var asWeeks = makeAs('w');
var asMonths = makeAs('M');
var asQuarters = makeAs('Q');
var asYears = makeAs('y');
function clone$1 () {
return createDuration(this);
}
function get$2 (units) {
units = normalizeUnits(units);
return this.isValid() ? this[units + 's']() : NaN;
}
function makeGetter(name) {
return function () {
return this.isValid() ? this._data[name] : NaN;
};
}
var milliseconds = makeGetter('milliseconds');
var seconds = makeGetter('seconds');
var minutes = makeGetter('minutes');
var hours = makeGetter('hours');
var days = makeGetter('days');
var months = makeGetter('months');
var years = makeGetter('years');
function weeks () {
return absFloor(this.days() / 7);
}
var round = Math.round;
var thresholds = {
ss: 44, // a few seconds to seconds
s : 45, // seconds to minute
m : 45, // minutes to hour
h : 22, // hours to day
d : 26, // days to month
M : 11 // months to year
};
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
}
function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
var duration = createDuration(posNegDuration).abs();
var seconds = round(duration.as('s'));
var minutes = round(duration.as('m'));
var hours = round(duration.as('h'));
var days = round(duration.as('d'));
var months = round(duration.as('M'));
var years = round(duration.as('y'));
var a = seconds <= thresholds.ss && ['s', seconds] ||
seconds < thresholds.s && ['ss', seconds] ||
minutes <= 1 && ['m'] ||
minutes < thresholds.m && ['mm', minutes] ||
hours <= 1 && ['h'] ||
hours < thresholds.h && ['hh', hours] ||
days <= 1 && ['d'] ||
days < thresholds.d && ['dd', days] ||
months <= 1 && ['M'] ||
months < thresholds.M && ['MM', months] ||
years <= 1 && ['y'] || ['yy', years];
a[2] = withoutSuffix;
a[3] = +posNegDuration > 0;
a[4] = locale;
return substituteTimeAgo.apply(null, a);
}
// This function allows you to set the rounding function for relative time strings
function getSetRelativeTimeRounding (roundingFunction) {
if (roundingFunction === undefined) {
return round;
}
if (typeof(roundingFunction) === 'function') {
round = roundingFunction;
return true;
}
return false;
}
// This function allows you to set a threshold for relative time strings
function getSetRelativeTimeThreshold (threshold, limit) {
if (thresholds[threshold] === undefined) {
return false;
}
if (limit === undefined) {
return thresholds[threshold];
}
thresholds[threshold] = limit;
if (threshold === 's') {
thresholds.ss = limit - 1;
}
return true;
}
function humanize (withSuffix) {
if (!this.isValid()) {
return this.localeData().invalidDate();
}
var locale = this.localeData();
var output = relativeTime$1(this, !withSuffix, locale);
if (withSuffix) {
output = locale.pastFuture(+this, output);
}
return locale.postformat(output);
}
var abs$1 = Math.abs;
function sign(x) {
return ((x > 0) - (x < 0)) || +x;
}
function toISOString$1() {
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
if (!this.isValid()) {
return this.localeData().invalidDate();
}
var seconds = abs$1(this._milliseconds) / 1000;
var days = abs$1(this._days);
var months = abs$1(this._months);
var minutes, hours, years;
// 3600 seconds -> 60 minutes -> 1 hour
minutes = absFloor(seconds / 60);
hours = absFloor(minutes / 60);
seconds %= 60;
minutes %= 60;
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var Y = years;
var M = months;
var D = days;
var h = hours;
var m = minutes;
var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
var total = this.asSeconds();
if (!total) {
// this is the same as C#'s (Noda) and python (isodate)...
// but not other JS (goog.date)
return 'P0D';
}
var totalSign = total < 0 ? '-' : '';
var ymSign = sign(this._months) !== sign(total) ? '-' : '';
var daysSign = sign(this._days) !== sign(total) ? '-' : '';
var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
return totalSign + 'P' +
(Y ? ymSign + Y + 'Y' : '') +
(M ? ymSign + M + 'M' : '') +
(D ? daysSign + D + 'D' : '') +
((h || m || s) ? 'T' : '') +
(h ? hmsSign + h + 'H' : '') +
(m ? hmsSign + m + 'M' : '') +
(s ? hmsSign + s + 'S' : '');
}
var proto$2 = Duration.prototype;
proto$2.isValid = isValid$1;
proto$2.abs = abs;
proto$2.add = add$1;
proto$2.subtract = subtract$1;
proto$2.as = as;
proto$2.asMilliseconds = asMilliseconds;
proto$2.asSeconds = asSeconds;
proto$2.asMinutes = asMinutes;
proto$2.asHours = asHours;
proto$2.asDays = asDays;
proto$2.asWeeks = asWeeks;
proto$2.asMonths = asMonths;
proto$2.asQuarters = asQuarters;
proto$2.asYears = asYears;
proto$2.valueOf = valueOf$1;
proto$2._bubble = bubble;
proto$2.clone = clone$1;
proto$2.get = get$2;
proto$2.milliseconds = milliseconds;
proto$2.seconds = seconds;
proto$2.minutes = minutes;
proto$2.hours = hours;
proto$2.days = days;
proto$2.weeks = weeks;
proto$2.months = months;
proto$2.years = years;
proto$2.humanize = humanize;
proto$2.toISOString = toISOString$1;
proto$2.toString = toISOString$1;
proto$2.toJSON = toISOString$1;
proto$2.locale = locale;
proto$2.localeData = localeData;
proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
proto$2.lang = lang;
// Side effect imports
// FORMATTING
addFormatToken('X', 0, 0, 'unix');
addFormatToken('x', 0, 0, 'valueOf');
// PARSING
addRegexToken('x', matchSigned);
addRegexToken('X', matchTimestamp);
addParseToken('X', function (input, array, config) {
config._d = new Date(parseFloat(input, 10) * 1000);
});
addParseToken('x', function (input, array, config) {
config._d = new Date(toInt(input));
});
// Side effect imports
hooks.version = '2.24.0';
setHookCallback(createLocal);
hooks.fn = proto;
hooks.min = min;
hooks.max = max;
hooks.now = now;
hooks.utc = createUTC;
hooks.unix = createUnix;
hooks.months = listMonths;
hooks.isDate = isDate;
hooks.locale = getSetGlobalLocale;
hooks.invalid = createInvalid;
hooks.duration = createDuration;
hooks.isMoment = isMoment;
hooks.weekdays = listWeekdays;
hooks.parseZone = createInZone;
hooks.localeData = getLocale;
hooks.isDuration = isDuration;
hooks.monthsShort = listMonthsShort;
hooks.weekdaysMin = listWeekdaysMin;
hooks.defineLocale = defineLocale;
hooks.updateLocale = updateLocale;
hooks.locales = listLocales;
hooks.weekdaysShort = listWeekdaysShort;
hooks.normalizeUnits = normalizeUnits;
hooks.relativeTimeRounding = getSetRelativeTimeRounding;
hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
hooks.calendarFormat = getCalendarFormat;
hooks.prototype = proto;
// currently HTML5 input type only supports 24-hour formats
hooks.HTML5_FMT = {
DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
DATE: 'YYYY-MM-DD', // <input type="date" />
TIME: 'HH:mm', // <input type="time" />
TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
WEEK: 'GGGG-[W]WW', // <input type="week" />
MONTH: 'YYYY-MM' // <input type="month" />
};
return hooks;
})));
},{}],141:[function(require,module,exports){
var pope=function(e){"use strict";function r(e,r){if("object"!=typeof e||"string"!=typeof r)return e;for(var n=r.split("."),i=0;i<n.length;i++){var t=n[i];if(null===(e=e.hasOwnProperty(t)?e[t]:null))break}return e}return e.pope=function(e,n,i){i=i||{skipUndefined:!1,throwOnUndefined:!1};for(var t,o=/{{2}(.+?)}{2}/g,f=e;null!==(t=o.exec(e));){var l=t[1].trim();if(l){var p=r(n,l);if(void 0!==p&&null!==p)f=f.replace(t[0],p);else{if(i.throwOnUndefined){var u=new Error("Missing value for "+t[0]);throw u.key=l,u.code="E_MISSING_KEY",u}i.skipUndefined||(f=f.replace(t[0],""))}}}return f},e.prop=r,e}({});
},{}],142:[function(require,module,exports){
/*
* Copyright (c) 2018 Damien Clark
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var clone = require('clone') ;
// Only these methods are supported
var allowedOptions =
{
accept: null,
agent: null,
attach: null,
auth: null,
buffer: null,
ca: null,
catch: null,
cert: null,
clearTimeout: null,
del: null,
delete: null,
end: null,
field: null,
get: null,
getHeader: null,
head: null,
key: null,
maxResponseSize: null,
ok: null,
on: null,
once: null,
options: null,
parse: null,
patch: null,
pfx: null,
pipe: null,
post: null,
p
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment