| 53 | const treeProperties = Object.keys(emptyTree) as (keyof TreeObject)[]; |
| 54 | |
| 55 | export class Tree implements TreeObject { |
| 56 | nodeMap: Record<string, Node>; // A map from node ID to the Node object for quick lookup. |
| 57 | text: string; // The raw text content of the JSON string. |
| 58 | nestNodeMap?: Record<string, Node>; // A map from node ID to the root Node of a nested JSON string that has been parsed into its own tree. |
| 59 | errors?: ContextError[]; // An array of parsing errors. |
| 60 | version?: number; // A version number for the tree, can be used to track changes. |
| 61 | needReset?: boolean; // If true, reset the editor's cursor to the beginning and the graph's viewport. |
| 62 | |
| 63 | constructor(text: string = "") { |
| 64 | this.nodeMap = {}; |
| 65 | this.text = text; |
| 66 | } |
| 67 | |
| 68 | static assign<A extends Tree | TreeObject, B extends Tree | TreeObject>(a: A, b: B) { |
| 69 | for (const key of treeProperties) { |
| 70 | if (b[key] !== undefined) { |
| 71 | (a as any)[key] = b[key]; |
| 72 | } |
| 73 | } |
| 74 | return a; |
| 75 | } |
| 76 | |
| 77 | static fromObject(treeObject: TreeObject, nestNodeMap?: Record<string, Node>) { |
| 78 | const tree = Tree.assign(new Tree(), treeObject); |
| 79 | tree.nestNodeMap = nestNodeMap; |
| 80 | return tree; |
| 81 | } |
| 82 | |
| 83 | toObject(): TreeObject { |
| 84 | return Tree.assign({} as TreeObject, this); |
| 85 | } |
| 86 | |
| 87 | valid() { |
| 88 | return this.root() && !this.hasError(); |
| 89 | } |
| 90 | |
| 91 | root() { |
| 92 | return this.node(rootMarker); |
| 93 | } |
| 94 | |
| 95 | isRoot(node: Node) { |
| 96 | return node.id === rootMarker; |
| 97 | } |
| 98 | |
| 99 | node(id: string) { |
| 100 | return this.nodeMap[id]; |
| 101 | } |
| 102 | |
| 103 | getNodeToken(node: Node) { |
| 104 | return this.text.slice(node.offset, node.offset + node.length); |
| 105 | } |
| 106 | |
| 107 | getParent(id: string) { |
| 108 | const parentId = getParentId(id); |
| 109 | return parentId !== undefined ? this.nodeMap[parentId] : undefined; |
| 110 | } |
| 111 | |
| 112 | getChild(node: Node, key: string): Node | undefined { |
nothing calls this directly
no outgoing calls
no test coverage detected