nunjucks
Version:
A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)
370 lines (280 loc) • 6.86 kB
JavaScript
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 _this = this;
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(_this);
}
});
Object.defineProperty(err, 'cause', {
value: cause
});
err.lineno = lineno;
err.colno = colno;
err.firstUpdate = true;
err.Update = function (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;
function groupBy(obj, val) {
var result = {};
var iterator = isFunction(val) ? val : function (o) {
return o[val];
};
for (var i = 0; i < obj.length; i++) {
var value = obj[i];
var key = iterator(value, i);
(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;
;