UNPKG

canner-compiler

Version:

Compiler for Canner CMS schema

91 lines (82 loc) 2.48 kB
// @flow import TreeHandler from './tree'; import VisitorHandler from './visitor'; import type {Tree, NodeType, InputVisitor, ParentNode, Route, Path} from './types'; export default class Traverser { tree: TreeHandler; visitor: VisitorHandler; constructor(tree: Tree, visitor: InputVisitor) { this.tree = new TreeHandler(tree); this.visitor = new VisitorHandler(visitor); } addVisitor(visitor: InputVisitor) { this.visitor.merge(visitor); } traverse() { Object.keys(this.tree.getTree()).forEach((key) => { this.traverseNode(this.tree.getTree()[key], null, key); }); return this.tree.getTree(); } traverseNode(node: NodeType, parent: ?ParentNode, route: Route) { const path: Path = { node: node, parent: parent, tree: this.tree, route: route, }; this.nodeCallEnter(path); if (node.children && node.children.length) { this.traverseChildren(node, 0, route); } this.nodeCallExit(path); } traverseChildren(parent: ParentNode, childIndex: number, route: Route) { if (childIndex >= parent.children.length) { return; } parent.children.forEach((child, i) => { if (!parent.children[i]) { return; } this.traverseNode(parent.children[i], parent, `${route}.${i}`); }); // this.traverseNode(parent.children[childIndex], parent, `${route}.${childIndex}`); // this.traverseChildren(parent, this.childIndex + 1, route); } nodeCallEnter(path: Path) { const visitor = this.visitor.getVisitor(); const nodeTypes = path.node.nodeType.split('.'); let nodeType = ''; nodeTypes.forEach((type) => { if (nodeType === '') { nodeType = type; } else { nodeType += `.${type}`; } let nodeVisitor = visitor[nodeType]; if (nodeVisitor && 'enter' in nodeVisitor) { nodeVisitor.enter.forEach((method) => method(path)); } }); } nodeCallExit(path: Path) { const visitor = this.visitor.getVisitor(); let nodeTypes = path.node.nodeType.split('.'); let nodeType = ''; nodeTypes.map((type) => { if (nodeType === '') { nodeType = type; } else { nodeType += `.${type}`; } return nodeType; }).reverse() .forEach((type) => { let nodeVisitor = visitor[type]; if (nodeVisitor && 'exit' in nodeVisitor) { nodeVisitor.exit.forEach((method) => method(path)); } }); } }