@lcap/asl
Version:
NetEase Application Specific Language
126 lines • 5.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.traverse = void 0;
function handleNext(func, current, options) {
if (options.mode === 'onlyChildren') {
const list = current.node && current.node.children;
if (!list)
return;
for (let index = 0; index < list.length; index++) {
const child = list[index];
if (!child)
continue;
const nodeInfo = {
node: child,
parent: current.node,
stack: current.stack.concat([current.node]),
nodePath: `${current.nodePath}/${index}`,
jsonPath: `${current.jsonPath}.children[${index}]`.replace(/^\./, ''),
index,
key: index,
};
const result = func(nodeInfo);
// if (result !== undefined)
// return result;
}
}
else if (options.mode === 'onlyArray') {
for (const key in current.node) {
if (!current.node.hasOwnProperty(key) || options.excludedKeySet.has(key))
continue;
const value = current.node[key];
if (!Array.isArray(value))
continue;
const list = value;
for (let index = 0; index < list.length; index++) {
const child = list[index];
if (!child)
continue;
const nodeInfo = {
node: child,
parent: current.node,
stack: current.stack.concat([current.node]),
nodePath: `${current.nodePath}/${index}`,
jsonPath: `${current.jsonPath}.${key}[${index}]`.replace(/^\./, ''),
index,
key: index,
};
const result = func(nodeInfo);
// if (result !== undefined)
// return result;
}
}
}
else if (options.mode === 'anyObject') {
for (const key in current.node) {
if (!current.node.hasOwnProperty(key) || options.excludedKeySet.has(key))
continue;
const value = current.node[key];
if (Array.isArray(value)) {
const list = value;
for (let index = 0; index < list.length; index++) {
const child = list[index];
if (!child)
continue;
const nodeInfo = {
node: child,
parent: current.node,
stack: current.stack.concat([current.node]),
nodePath: `${current.nodePath}/${index}`,
jsonPath: `${current.jsonPath}.${key}[${index}]`.replace(/^\./, ''),
index,
key: index,
};
const result = func(nodeInfo);
// if (result !== undefined)
// return result;
}
}
else if (typeof value === 'object' && value !== null) {
const nodeInfo = {
node: value,
parent: current.node,
stack: current.stack.concat([current.node]),
nodePath: `${current.nodePath}/${key}`,
jsonPath: `${current.jsonPath}['${key}']`,
index: undefined,
key,
};
const result = func(nodeInfo);
// if (result !== undefined)
// return result;
}
}
}
}
/**
* 遍历树
* @param func
* @param init 初始点信息
* @param options.mode 'onlyChildren' 表示只向下遍历 children 的元素(默认);'onlyArray' 表示只向下遍历 Array 的元素;'anyObject' 表示只要属性为 Object 类型都会遍历
* @param options.depthFirst 默认广度优先搜索,是否深度优先搜索
* @example traverse((current) => console.log(current.node.name), { init: rootNode });
* @example traverse((current) => console.log(current.jsonPath), { init: ast }, { mode: 'anyObject' });
*/
function traverse(func, init, options) {
init = Object.assign({ parent: undefined, stack: [], nodePath: '', jsonPath: '', index: undefined }, init);
options = Object.assign({ mode: 'onlyChildren', depthFirst: false, excludedKeySet: new Set() }, options);
if (options.depthFirst) {
func(init);
handleNext((next) => traverse(func, next, options), init, options);
}
else {
let queue = [];
queue = queue.concat(init);
let current;
while ((current = queue.shift())) {
const result = func(current);
if (result !== undefined)
return result;
handleNext((next) => queue.push(next), current, options);
}
}
}
exports.traverse = traverse;
exports.default = traverse;
//# sourceMappingURL=traverse.js.map