twing
Version:
First-class Twig engine for Node.js
94 lines (93 loc) • 3.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSandboxNodeVisitor = void 0;
const node_1 = require("../node");
const check_security_1 = require("../node/check-security");
const check_to_string_1 = require("../node/check-to-string");
const node_visitor_1 = require("../node-visitor");
const createSandboxNodeVisitor = () => {
let tags;
let filters;
let functions;
let shouldWrap = true;
const enterNode = (node) => {
if (node.type === "template") {
tags = new Map();
filters = new Map();
functions = new Map();
return node;
}
else {
// look for tags
const { tag } = node;
if (tag && !(tags.has(tag))) {
tags.set(tag, node);
}
// look for filters
if (node.type === "filter") {
const { operatorName } = node.attributes;
if (!filters.has(operatorName)) {
filters.set(operatorName, node);
}
}
// look for functions
if (node.type === "function") {
const { operatorName } = node.attributes;
if (!functions.has(operatorName)) {
functions.set(operatorName, node);
}
}
// the .. operator is equivalent to the range() function
if (node.type === "range" && !(functions.has('range'))) {
functions.set('range', node);
}
if (node.type === "print") {
shouldWrap = true;
wrapNode(node, "expression");
}
if (node.type === "set") {
shouldWrap = true;
}
if (shouldWrap) {
if (node.type === "concatenate") {
wrapNode(node, "left");
wrapNode(node, "right");
}
if (node.type === "filter") {
wrapNode(node, "operand");
wrapArrayNode(node, "arguments");
}
if (node.type === "function") {
wrapArrayNode(node, "arguments");
}
if (node.type === "escape") {
wrapNode(node, "body");
}
}
}
return node;
};
const leaveNode = (node) => {
if (node.type === "template") {
node.children.securityCheck = (0, check_security_1.createCheckSecurityNode)(filters, tags, functions, node.line, node.column);
}
else if (node.type === "print" || node.type === "set") {
shouldWrap = false;
}
return node;
};
const wrapNode = (node, name) => {
const expression = node.children[name];
if (expression.type === "name" || expression.type === "attribute_accessor") {
node.children[name] = (0, check_to_string_1.createCheckToStringNode)(expression, expression.line, expression.column);
}
};
const wrapArrayNode = (node, name) => {
const args = node.children[name]; // todo: check with TS team with we have to cast children as any
for (const [name] of (0, node_1.getChildren)(args)) {
wrapNode(args, name);
}
};
return (0, node_visitor_1.createNodeVisitor)(enterNode, leaveNode);
};
exports.createSandboxNodeVisitor = createSandboxNodeVisitor;