devsite/node_modules/nunjucks/src/jinja-compat.js

293 lines
8.2 KiB
JavaScript
Raw Normal View History

2024-07-08 01:49:38 +00:00
"use strict";
function installCompat() {
'use strict';
/* eslint-disable camelcase */
// This must be called like `nunjucks.installCompat` so that `this`
// references the nunjucks instance
var runtime = this.runtime;
var lib = this.lib;
// Handle slim case where these 'modules' are excluded from the built source
var Compiler = this.compiler.Compiler;
var Parser = this.parser.Parser;
var nodes = this.nodes;
var lexer = this.lexer;
var orig_contextOrFrameLookup = runtime.contextOrFrameLookup;
var orig_memberLookup = runtime.memberLookup;
var orig_Compiler_assertType;
var orig_Parser_parseAggregate;
if (Compiler) {
orig_Compiler_assertType = Compiler.prototype.assertType;
}
if (Parser) {
orig_Parser_parseAggregate = Parser.prototype.parseAggregate;
}
function uninstall() {
runtime.contextOrFrameLookup = orig_contextOrFrameLookup;
runtime.memberLookup = orig_memberLookup;
if (Compiler) {
Compiler.prototype.assertType = orig_Compiler_assertType;
}
if (Parser) {
Parser.prototype.parseAggregate = orig_Parser_parseAggregate;
}
}
runtime.contextOrFrameLookup = function contextOrFrameLookup(context, frame, key) {
var val = orig_contextOrFrameLookup.apply(this, arguments);
if (val !== undefined) {
return val;
}
switch (key) {
case 'True':
return true;
case 'False':
return false;
case 'None':
return null;
default:
return undefined;
}
};
function getTokensState(tokens) {
return {
index: tokens.index,
lineno: tokens.lineno,
colno: tokens.colno
};
}
if (process.env.BUILD_TYPE !== 'SLIM' && nodes && Compiler && Parser) {
// i.e., not slim mode
var Slice = nodes.Node.extend('Slice', {
fields: ['start', 'stop', 'step'],
init: function init(lineno, colno, start, stop, step) {
start = start || new nodes.Literal(lineno, colno, null);
stop = stop || new nodes.Literal(lineno, colno, null);
step = step || new nodes.Literal(lineno, colno, 1);
this.parent(lineno, colno, start, stop, step);
}
});
Compiler.prototype.assertType = function assertType(node) {
if (node instanceof Slice) {
return;
}
orig_Compiler_assertType.apply(this, arguments);
};
Compiler.prototype.compileSlice = function compileSlice(node, frame) {
this._emit('(');
this._compileExpression(node.start, frame);
this._emit('),(');
this._compileExpression(node.stop, frame);
this._emit('),(');
this._compileExpression(node.step, frame);
this._emit(')');
};
Parser.prototype.parseAggregate = function parseAggregate() {
var _this = this;
var origState = getTokensState(this.tokens);
// Set back one accounting for opening bracket/parens
origState.colno--;
origState.index--;
try {
return orig_Parser_parseAggregate.apply(this);
} catch (e) {
var errState = getTokensState(this.tokens);
var rethrow = function rethrow() {
lib._assign(_this.tokens, errState);
return e;
};
// Reset to state before original parseAggregate called
lib._assign(this.tokens, origState);
this.peeked = false;
var tok = this.peekToken();
if (tok.type !== lexer.TOKEN_LEFT_BRACKET) {
throw rethrow();
} else {
this.nextToken();
}
var node = new Slice(tok.lineno, tok.colno);
// If we don't encounter a colon while parsing, this is not a slice,
// so re-raise the original exception.
var isSlice = false;
for (var i = 0; i <= node.fields.length; i++) {
if (this.skip(lexer.TOKEN_RIGHT_BRACKET)) {
break;
}
if (i === node.fields.length) {
if (isSlice) {
this.fail('parseSlice: too many slice components', tok.lineno, tok.colno);
} else {
break;
}
}
if (this.skip(lexer.TOKEN_COLON)) {
isSlice = true;
} else {
var field = node.fields[i];
node[field] = this.parseExpression();
isSlice = this.skip(lexer.TOKEN_COLON) || isSlice;
}
}
if (!isSlice) {
throw rethrow();
}
return new nodes.Array(tok.lineno, tok.colno, [node]);
}
};
}
function sliceLookup(obj, start, stop, step) {
obj = obj || [];
if (start === null) {
start = step < 0 ? obj.length - 1 : 0;
}
if (stop === null) {
stop = step < 0 ? -1 : obj.length;
} else if (stop < 0) {
stop += obj.length;
}
if (start < 0) {
start += obj.length;
}
var results = [];
for (var i = start;; i += step) {
if (i < 0 || i > obj.length) {
break;
}
if (step > 0 && i >= stop) {
break;
}
if (step < 0 && i <= stop) {
break;
}
results.push(runtime.memberLookup(obj, i));
}
return results;
}
function hasOwnProp(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
var ARRAY_MEMBERS = {
pop: function pop(index) {
if (index === undefined) {
return this.pop();
}
if (index >= this.length || index < 0) {
throw new Error('KeyError');
}
return this.splice(index, 1);
},
append: function append(element) {
return this.push(element);
},
remove: function remove(element) {
for (var i = 0; i < this.length; i++) {
if (this[i] === element) {
return this.splice(i, 1);
}
}
throw new Error('ValueError');
},
count: function count(element) {
var count = 0;
for (var i = 0; i < this.length; i++) {
if (this[i] === element) {
count++;
}
}
return count;
},
index: function index(element) {
var i;
if ((i = this.indexOf(element)) === -1) {
throw new Error('ValueError');
}
return i;
},
find: function find(element) {
return this.indexOf(element);
},
insert: function insert(index, elem) {
return this.splice(index, 0, elem);
}
};
var OBJECT_MEMBERS = {
items: function items() {
return lib._entries(this);
},
values: function values() {
return lib._values(this);
},
keys: function keys() {
return lib.keys(this);
},
get: function get(key, def) {
var output = this[key];
if (output === undefined) {
output = def;
}
return output;
},
has_key: function has_key(key) {
return hasOwnProp(this, key);
},
pop: function pop(key, def) {
var output = this[key];
if (output === undefined && def !== undefined) {
output = def;
} else if (output === undefined) {
throw new Error('KeyError');
} else {
delete this[key];
}
return output;
},
popitem: function popitem() {
var keys = lib.keys(this);
if (!keys.length) {
throw new Error('KeyError');
}
var k = keys[0];
var val = this[k];
delete this[k];
return [k, val];
},
setdefault: function setdefault(key, def) {
if (def === void 0) {
def = null;
}
if (!(key in this)) {
this[key] = def;
}
return this[key];
},
update: function update(kwargs) {
lib._assign(this, kwargs);
return null; // Always returns None
}
};
OBJECT_MEMBERS.iteritems = OBJECT_MEMBERS.items;
OBJECT_MEMBERS.itervalues = OBJECT_MEMBERS.values;
OBJECT_MEMBERS.iterkeys = OBJECT_MEMBERS.keys;
runtime.memberLookup = function memberLookup(obj, val, autoescape) {
if (arguments.length === 4) {
return sliceLookup.apply(this, arguments);
}
obj = obj || {};
// If the object is an object, return any of the methods that Python would
// otherwise provide.
if (lib.isArray(obj) && hasOwnProp(ARRAY_MEMBERS, val)) {
return ARRAY_MEMBERS[val].bind(obj);
}
if (lib.isObject(obj) && hasOwnProp(OBJECT_MEMBERS, val)) {
return OBJECT_MEMBERS[val].bind(obj);
}
return orig_memberLookup.apply(this, arguments);
};
return uninstall;
}
module.exports = installCompat;