"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GotoScope = exports.WithinScope = void 0;
const node_query_1 = __importDefault(require("@synvert-hq/node-query"));
/**
* Scope just likes its name, different scope points to different current node.
* One scope defines some rules, it finds nodes and changes current node to the matching node.
*/
class Scope {
/**
* Create a Scope
* @param {Instance} instance
*/
constructor(instance) {
this.instance = instance;
}
}
/**
* WithinScope finds out nodes which match rules, then changes its scope to matching node.
* @extends Scope
*/
class WithinScope extends Scope {
/**
* Create a WithinScope
* @param {Instance} instance
* @param {string|Object} nqlOrRules - nql or rules to find nodes.
* @param {QueryOptions} options
* @param {Function} func - a function to be called if rules are matched.
*/
constructor(instance, nqlOrRules, options, func) {
super(instance);
this.func = func;
this.nodeQuery = new node_query_1.default(nqlOrRules, { adapter: instance.parser });
this.options = Object.assign({ includingSelf: true, stopAtFirstMatch: false, recursive: true }, options);
}
/**
* Find out the matching nodes.
* It checks the current node and iterates all child nodes,
* then run the function code on each matching node.
*/
processSync() {
const instance = this.instance;
const currentNode = instance.currentNode;
if (!currentNode) {
return;
}
instance.processWithNodeSync(currentNode, () => {
this.nodeQuery
.queryNodes(currentNode, this.options)
.forEach((matchingNode) => {
instance.processWithNodeSync(matchingNode, () => {
this.func.call(this.instance, this.instance);
});
});
});
}
process() {
return __awaiter(this, void 0, void 0, function* () {
const instance = this.instance;
const currentNode = instance.currentNode;
if (!currentNode) {
return;
}
yield instance.processWithNode(currentNode, () => __awaiter(this, void 0, void 0, function* () {
const matchingNodes = this.nodeQuery.queryNodes(currentNode, this.options);
for (const matchingNode of matchingNodes) {
yield instance.processWithNode(matchingNode, () => __awaiter(this, void 0, void 0, function* () {
yield this.func.call(this.instance, this.instance);
}));
}
}));
});
}
}
exports.WithinScope = WithinScope;
/**
* Go to and change its scope to a child node.
* @extends Scope
*/
class GotoScope extends Scope {
/**
* Create a GotoScope
* @param {Instance} instance
* @param {string} childNodeName
* @param {Function} func
*/
constructor(instance, childNodeName, func) {
super(instance);
this.childNodeName = childNodeName;
this.func = func;
}
/**
* Go to a child now, then run the func with the the child node.
*/
processSync() {
const currentNode = this.instance.currentNode;
if (!currentNode)
return;
let childNode = currentNode;
this.childNodeName.split(".").forEach((childNodeName) => {
childNode =
Array.isArray(childNode) && /-?d+/.test(childNodeName)
? childNode[Number.parseInt(childNodeName)]
: childNode[childNodeName];
});
if (!childNode)
return;
this.instance.processWithOtherNodeSync(childNode, () => {
this.func.call(this.instance, this.instance);
});
}
process() {
return __awaiter(this, void 0, void 0, function* () {
const currentNode = this.instance.currentNode;
if (!currentNode)
return;
let childNode = currentNode;
this.childNodeName.split(".").forEach((childNodeName) => {
childNode =
Array.isArray(childNode) && /-?d+/.test(childNodeName)
? childNode[Number.parseInt(childNodeName)]
: childNode[childNodeName];
});
if (!childNode)
return;
yield this.instance.processWithOtherNode(childNode, () => __awaiter(this, void 0, void 0, function* () {
yield this.func.call(this.instance, this.instance);
}));
});
}
}
exports.GotoScope = GotoScope;