325 lines
7.7 KiB
JavaScript
325 lines
7.7 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var ArrayProto = Array.prototype;
|
||
|
var ObjProto = Object.prototype;
|
||
|
var escapeMap = {
|
||
|
'&': '&',
|
||
|
'"': '"',
|
||
|
'\'': ''',
|
||
|
'<': '<',
|
||
|
'>': '>',
|
||
|
'\\': '\'
|
||
|
};
|
||
|
var escapeRegex = /[&"'<>\\]/g;
|
||
|
var _exports = module.exports = {};
|
||
|
function hasOwnProp(obj, k) {
|
||
|
return ObjProto.hasOwnProperty.call(obj, k);
|
||
|
}
|
||
|
_exports.hasOwnProp = hasOwnProp;
|
||
|
function lookupEscape(ch) {
|
||
|
return escapeMap[ch];
|
||
|
}
|
||
|
function _prettifyError(path, withInternals, err) {
|
||
|
if (!err.Update) {
|
||
|
// not one of ours, cast it
|
||
|
err = new _exports.TemplateError(err);
|
||
|
}
|
||
|
err.Update(path);
|
||
|
|
||
|
// Unless they marked the dev flag, show them a trace from here
|
||
|
if (!withInternals) {
|
||
|
var old = err;
|
||
|
err = new Error(old.message);
|
||
|
err.name = old.name;
|
||
|
}
|
||
|
return err;
|
||
|
}
|
||
|
_exports._prettifyError = _prettifyError;
|
||
|
function TemplateError(message, lineno, colno) {
|
||
|
var err;
|
||
|
var cause;
|
||
|
if (message instanceof Error) {
|
||
|
cause = message;
|
||
|
message = cause.name + ": " + cause.message;
|
||
|
}
|
||
|
if (Object.setPrototypeOf) {
|
||
|
err = new Error(message);
|
||
|
Object.setPrototypeOf(err, TemplateError.prototype);
|
||
|
} else {
|
||
|
err = this;
|
||
|
Object.defineProperty(err, 'message', {
|
||
|
enumerable: false,
|
||
|
writable: true,
|
||
|
value: message
|
||
|
});
|
||
|
}
|
||
|
Object.defineProperty(err, 'name', {
|
||
|
value: 'Template render error'
|
||
|
});
|
||
|
if (Error.captureStackTrace) {
|
||
|
Error.captureStackTrace(err, this.constructor);
|
||
|
}
|
||
|
var getStack;
|
||
|
if (cause) {
|
||
|
var stackDescriptor = Object.getOwnPropertyDescriptor(cause, 'stack');
|
||
|
getStack = stackDescriptor && (stackDescriptor.get || function () {
|
||
|
return stackDescriptor.value;
|
||
|
});
|
||
|
if (!getStack) {
|
||
|
getStack = function getStack() {
|
||
|
return cause.stack;
|
||
|
};
|
||
|
}
|
||
|
} else {
|
||
|
var stack = new Error(message).stack;
|
||
|
getStack = function getStack() {
|
||
|
return stack;
|
||
|
};
|
||
|
}
|
||
|
Object.defineProperty(err, 'stack', {
|
||
|
get: function get() {
|
||
|
return getStack.call(err);
|
||
|
}
|
||
|
});
|
||
|
Object.defineProperty(err, 'cause', {
|
||
|
value: cause
|
||
|
});
|
||
|
err.lineno = lineno;
|
||
|
err.colno = colno;
|
||
|
err.firstUpdate = true;
|
||
|
err.Update = function Update(path) {
|
||
|
var msg = '(' + (path || 'unknown path') + ')';
|
||
|
|
||
|
// only show lineno + colno next to path of template
|
||
|
// where error occurred
|
||
|
if (this.firstUpdate) {
|
||
|
if (this.lineno && this.colno) {
|
||
|
msg += " [Line " + this.lineno + ", Column " + this.colno + "]";
|
||
|
} else if (this.lineno) {
|
||
|
msg += " [Line " + this.lineno + "]";
|
||
|
}
|
||
|
}
|
||
|
msg += '\n ';
|
||
|
if (this.firstUpdate) {
|
||
|
msg += ' ';
|
||
|
}
|
||
|
this.message = msg + (this.message || '');
|
||
|
this.firstUpdate = false;
|
||
|
return this;
|
||
|
};
|
||
|
return err;
|
||
|
}
|
||
|
if (Object.setPrototypeOf) {
|
||
|
Object.setPrototypeOf(TemplateError.prototype, Error.prototype);
|
||
|
} else {
|
||
|
TemplateError.prototype = Object.create(Error.prototype, {
|
||
|
constructor: {
|
||
|
value: TemplateError
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
_exports.TemplateError = TemplateError;
|
||
|
function escape(val) {
|
||
|
return val.replace(escapeRegex, lookupEscape);
|
||
|
}
|
||
|
_exports.escape = escape;
|
||
|
function isFunction(obj) {
|
||
|
return ObjProto.toString.call(obj) === '[object Function]';
|
||
|
}
|
||
|
_exports.isFunction = isFunction;
|
||
|
function isArray(obj) {
|
||
|
return ObjProto.toString.call(obj) === '[object Array]';
|
||
|
}
|
||
|
_exports.isArray = isArray;
|
||
|
function isString(obj) {
|
||
|
return ObjProto.toString.call(obj) === '[object String]';
|
||
|
}
|
||
|
_exports.isString = isString;
|
||
|
function isObject(obj) {
|
||
|
return ObjProto.toString.call(obj) === '[object Object]';
|
||
|
}
|
||
|
_exports.isObject = isObject;
|
||
|
|
||
|
/**
|
||
|
* @param {string|number} attr
|
||
|
* @returns {(string|number)[]}
|
||
|
* @private
|
||
|
*/
|
||
|
function _prepareAttributeParts(attr) {
|
||
|
if (!attr) {
|
||
|
return [];
|
||
|
}
|
||
|
if (typeof attr === 'string') {
|
||
|
return attr.split('.');
|
||
|
}
|
||
|
return [attr];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} attribute Attribute value. Dots allowed.
|
||
|
* @returns {function(Object): *}
|
||
|
*/
|
||
|
function getAttrGetter(attribute) {
|
||
|
var parts = _prepareAttributeParts(attribute);
|
||
|
return function attrGetter(item) {
|
||
|
var _item = item;
|
||
|
for (var i = 0; i < parts.length; i++) {
|
||
|
var part = parts[i];
|
||
|
|
||
|
// If item is not an object, and we still got parts to handle, it means
|
||
|
// that something goes wrong. Just roll out to undefined in that case.
|
||
|
if (hasOwnProp(_item, part)) {
|
||
|
_item = _item[part];
|
||
|
} else {
|
||
|
return undefined;
|
||
|
}
|
||
|
}
|
||
|
return _item;
|
||
|
};
|
||
|
}
|
||
|
_exports.getAttrGetter = getAttrGetter;
|
||
|
function groupBy(obj, val, throwOnUndefined) {
|
||
|
var result = {};
|
||
|
var iterator = isFunction(val) ? val : getAttrGetter(val);
|
||
|
for (var i = 0; i < obj.length; i++) {
|
||
|
var value = obj[i];
|
||
|
var key = iterator(value, i);
|
||
|
if (key === undefined && throwOnUndefined === true) {
|
||
|
throw new TypeError("groupby: attribute \"" + val + "\" resolved to undefined");
|
||
|
}
|
||
|
(result[key] || (result[key] = [])).push(value);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
_exports.groupBy = groupBy;
|
||
|
function toArray(obj) {
|
||
|
return Array.prototype.slice.call(obj);
|
||
|
}
|
||
|
_exports.toArray = toArray;
|
||
|
function without(array) {
|
||
|
var result = [];
|
||
|
if (!array) {
|
||
|
return result;
|
||
|
}
|
||
|
var length = array.length;
|
||
|
var contains = toArray(arguments).slice(1);
|
||
|
var index = -1;
|
||
|
while (++index < length) {
|
||
|
if (indexOf(contains, array[index]) === -1) {
|
||
|
result.push(array[index]);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
_exports.without = without;
|
||
|
function repeat(char_, n) {
|
||
|
var str = '';
|
||
|
for (var i = 0; i < n; i++) {
|
||
|
str += char_;
|
||
|
}
|
||
|
return str;
|
||
|
}
|
||
|
_exports.repeat = repeat;
|
||
|
function each(obj, func, context) {
|
||
|
if (obj == null) {
|
||
|
return;
|
||
|
}
|
||
|
if (ArrayProto.forEach && obj.forEach === ArrayProto.forEach) {
|
||
|
obj.forEach(func, context);
|
||
|
} else if (obj.length === +obj.length) {
|
||
|
for (var i = 0, l = obj.length; i < l; i++) {
|
||
|
func.call(context, obj[i], i, obj);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
_exports.each = each;
|
||
|
function map(obj, func) {
|
||
|
var results = [];
|
||
|
if (obj == null) {
|
||
|
return results;
|
||
|
}
|
||
|
if (ArrayProto.map && obj.map === ArrayProto.map) {
|
||
|
return obj.map(func);
|
||
|
}
|
||
|
for (var i = 0; i < obj.length; i++) {
|
||
|
results[results.length] = func(obj[i], i);
|
||
|
}
|
||
|
if (obj.length === +obj.length) {
|
||
|
results.length = obj.length;
|
||
|
}
|
||
|
return results;
|
||
|
}
|
||
|
_exports.map = map;
|
||
|
function asyncIter(arr, iter, cb) {
|
||
|
var i = -1;
|
||
|
function next() {
|
||
|
i++;
|
||
|
if (i < arr.length) {
|
||
|
iter(arr[i], i, next, cb);
|
||
|
} else {
|
||
|
cb();
|
||
|
}
|
||
|
}
|
||
|
next();
|
||
|
}
|
||
|
_exports.asyncIter = asyncIter;
|
||
|
function asyncFor(obj, iter, cb) {
|
||
|
var keys = keys_(obj || {});
|
||
|
var len = keys.length;
|
||
|
var i = -1;
|
||
|
function next() {
|
||
|
i++;
|
||
|
var k = keys[i];
|
||
|
if (i < len) {
|
||
|
iter(k, obj[k], i, len, next);
|
||
|
} else {
|
||
|
cb();
|
||
|
}
|
||
|
}
|
||
|
next();
|
||
|
}
|
||
|
_exports.asyncFor = asyncFor;
|
||
|
function indexOf(arr, searchElement, fromIndex) {
|
||
|
return Array.prototype.indexOf.call(arr || [], searchElement, fromIndex);
|
||
|
}
|
||
|
_exports.indexOf = indexOf;
|
||
|
function keys_(obj) {
|
||
|
/* eslint-disable no-restricted-syntax */
|
||
|
var arr = [];
|
||
|
for (var k in obj) {
|
||
|
if (hasOwnProp(obj, k)) {
|
||
|
arr.push(k);
|
||
|
}
|
||
|
}
|
||
|
return arr;
|
||
|
}
|
||
|
_exports.keys = keys_;
|
||
|
function _entries(obj) {
|
||
|
return keys_(obj).map(function (k) {
|
||
|
return [k, obj[k]];
|
||
|
});
|
||
|
}
|
||
|
_exports._entries = _entries;
|
||
|
function _values(obj) {
|
||
|
return keys_(obj).map(function (k) {
|
||
|
return obj[k];
|
||
|
});
|
||
|
}
|
||
|
_exports._values = _values;
|
||
|
function extend(obj1, obj2) {
|
||
|
obj1 = obj1 || {};
|
||
|
keys_(obj2).forEach(function (k) {
|
||
|
obj1[k] = obj2[k];
|
||
|
});
|
||
|
return obj1;
|
||
|
}
|
||
|
_exports._assign = _exports.extend = extend;
|
||
|
function inOperator(key, val) {
|
||
|
if (isArray(val) || isString(val)) {
|
||
|
return val.indexOf(key) !== -1;
|
||
|
} else if (isObject(val)) {
|
||
|
return key in val;
|
||
|
}
|
||
|
throw new Error('Cannot use "in" operator to search for "' + key + '" in unexpected types.');
|
||
|
}
|
||
|
_exports.inOperator = inOperator;
|