tatianamac 6d5445ecc5 update
2019-11-26 14:50:43 -08:00

409 lines
8.8 KiB
JavaScript

'use strict';
var lib = require('./lib');
var arrayFrom = Array.from;
var supportsIterators = typeof Symbol === 'function' && Symbol.iterator && typeof arrayFrom === 'function'; // Frames keep track of scoping both at compile-time and run-time so
// we know how to access variables. Block tags can introduce special
// variables, for example.
var Frame =
/*#__PURE__*/
function () {
function Frame(parent, isolateWrites) {
this.variables = {};
this.parent = parent;
this.topLevel = false; // if this is true, writes (set) should never propagate upwards past
// this frame to its parent (though reads may).
this.isolateWrites = isolateWrites;
}
var _proto = Frame.prototype;
_proto.set = function set(name, val, resolveUp) {
// Allow variables with dots by automatically creating the
// nested structure
var parts = name.split('.');
var obj = this.variables;
var frame = this;
if (resolveUp) {
if (frame = this.resolve(parts[0], true)) {
frame.set(name, val);
return;
}
}
for (var i = 0; i < parts.length - 1; i++) {
var id = parts[i];
if (!obj[id]) {
obj[id] = {};
}
obj = obj[id];
}
obj[parts[parts.length - 1]] = val;
};
_proto.get = function get(name) {
var val = this.variables[name];
if (val !== undefined) {
return val;
}
return null;
};
_proto.lookup = function lookup(name) {
var p = this.parent;
var val = this.variables[name];
if (val !== undefined) {
return val;
}
return p && p.lookup(name);
};
_proto.resolve = function resolve(name, forWrite) {
var p = forWrite && this.isolateWrites ? undefined : this.parent;
var val = this.variables[name];
if (val !== undefined) {
return this;
}
return p && p.resolve(name);
};
_proto.push = function push(isolateWrites) {
return new Frame(this, isolateWrites);
};
_proto.pop = function pop() {
return this.parent;
};
return Frame;
}();
function makeMacro(argNames, kwargNames, func) {
var _this = this;
return function () {
for (var _len = arguments.length, macroArgs = new Array(_len), _key = 0; _key < _len; _key++) {
macroArgs[_key] = arguments[_key];
}
var argCount = numArgs(macroArgs);
var args;
var kwargs = getKeywordArgs(macroArgs);
if (argCount > argNames.length) {
args = macroArgs.slice(0, argNames.length); // Positional arguments that should be passed in as
// keyword arguments (essentially default values)
macroArgs.slice(args.length, argCount).forEach(function (val, i) {
if (i < kwargNames.length) {
kwargs[kwargNames[i]] = val;
}
});
args.push(kwargs);
} else if (argCount < argNames.length) {
args = macroArgs.slice(0, argCount);
for (var i = argCount; i < argNames.length; i++) {
var arg = argNames[i]; // Keyword arguments that should be passed as
// positional arguments, i.e. the caller explicitly
// used the name of a positional arg
args.push(kwargs[arg]);
delete kwargs[arg];
}
args.push(kwargs);
} else {
args = macroArgs;
}
return func.apply(_this, args);
};
}
function makeKeywordArgs(obj) {
obj.__keywords = true;
return obj;
}
function isKeywordArgs(obj) {
return obj && Object.prototype.hasOwnProperty.call(obj, '__keywords');
}
function getKeywordArgs(args) {
var len = args.length;
if (len) {
var lastArg = args[len - 1];
if (isKeywordArgs(lastArg)) {
return lastArg;
}
}
return {};
}
function numArgs(args) {
var len = args.length;
if (len === 0) {
return 0;
}
var lastArg = args[len - 1];
if (isKeywordArgs(lastArg)) {
return len - 1;
} else {
return len;
}
} // A SafeString object indicates that the string should not be
// autoescaped. This happens magically because autoescaping only
// occurs on primitive string objects.
function SafeString(val) {
if (typeof val !== 'string') {
return val;
}
this.val = val;
this.length = val.length;
}
SafeString.prototype = Object.create(String.prototype, {
length: {
writable: true,
configurable: true,
value: 0
}
});
SafeString.prototype.valueOf = function valueOf() {
return this.val;
};
SafeString.prototype.toString = function toString() {
return this.val;
};
function copySafeness(dest, target) {
if (dest instanceof SafeString) {
return new SafeString(target);
}
return target.toString();
}
function markSafe(val) {
var type = typeof val;
if (type === 'string') {
return new SafeString(val);
} else if (type !== 'function') {
return val;
} else {
return function wrapSafe(args) {
var ret = val.apply(this, arguments);
if (typeof ret === 'string') {
return new SafeString(ret);
}
return ret;
};
}
}
function suppressValue(val, autoescape) {
val = val !== undefined && val !== null ? val : '';
if (autoescape && !(val instanceof SafeString)) {
val = lib.escape(val.toString());
}
return val;
}
function ensureDefined(val, lineno, colno) {
if (val === null || val === undefined) {
throw new lib.TemplateError('attempted to output null or undefined value', lineno + 1, colno + 1);
}
return val;
}
function memberLookup(obj, val) {
if (obj === undefined || obj === null) {
return undefined;
}
if (typeof obj[val] === 'function') {
return function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return obj[val].apply(obj, args);
};
}
return obj[val];
}
function callWrap(obj, name, context, args) {
if (!obj) {
throw new Error('Unable to call `' + name + '`, which is undefined or falsey');
} else if (typeof obj !== 'function') {
throw new Error('Unable to call `' + name + '`, which is not a function');
}
return obj.apply(context, args);
}
function contextOrFrameLookup(context, frame, name) {
var val = frame.lookup(name);
return val !== undefined ? val : context.lookup(name);
}
function handleError(error, lineno, colno) {
if (error.lineno) {
return error;
} else {
return new lib.TemplateError(error, lineno, colno);
}
}
function asyncEach(arr, dimen, iter, cb) {
if (lib.isArray(arr)) {
var len = arr.length;
lib.asyncIter(arr, function iterCallback(item, i, next) {
switch (dimen) {
case 1:
iter(item, i, len, next);
break;
case 2:
iter(item[0], item[1], i, len, next);
break;
case 3:
iter(item[0], item[1], item[2], i, len, next);
break;
default:
item.push(i, len, next);
iter.apply(this, item);
}
}, cb);
} else {
lib.asyncFor(arr, function iterCallback(key, val, i, len, next) {
iter(key, val, i, len, next);
}, cb);
}
}
function asyncAll(arr, dimen, func, cb) {
var finished = 0;
var len;
var outputArr;
function done(i, output) {
finished++;
outputArr[i] = output;
if (finished === len) {
cb(null, outputArr.join(''));
}
}
if (lib.isArray(arr)) {
len = arr.length;
outputArr = new Array(len);
if (len === 0) {
cb(null, '');
} else {
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
switch (dimen) {
case 1:
func(item, i, len, done);
break;
case 2:
func(item[0], item[1], i, len, done);
break;
case 3:
func(item[0], item[1], item[2], i, len, done);
break;
default:
item.push(i, len, done);
func.apply(this, item);
}
}
}
} else {
var keys = lib.keys(arr || {});
len = keys.length;
outputArr = new Array(len);
if (len === 0) {
cb(null, '');
} else {
for (var _i = 0; _i < keys.length; _i++) {
var k = keys[_i];
func(k, arr[k], _i, len, done);
}
}
}
}
function fromIterator(arr) {
if (typeof arr !== 'object' || arr === null || lib.isArray(arr)) {
return arr;
} else if (supportsIterators && Symbol.iterator in arr) {
return arrayFrom(arr);
} else {
return arr;
}
}
module.exports = {
Frame: Frame,
makeMacro: makeMacro,
makeKeywordArgs: makeKeywordArgs,
numArgs: numArgs,
suppressValue: suppressValue,
ensureDefined: ensureDefined,
memberLookup: memberLookup,
contextOrFrameLookup: contextOrFrameLookup,
callWrap: callWrap,
handleError: handleError,
isArray: lib.isArray,
keys: lib.keys,
SafeString: SafeString,
copySafeness: copySafeness,
markSafe: markSafe,
asyncEach: asyncEach,
asyncAll: asyncAll,
inOperator: lib.inOperator,
fromIterator: fromIterator
};