Skip to content

Commit

Permalink
feat: include keyPath in NodePath
Browse files Browse the repository at this point in the history
  • Loading branch information
aleclarson committed Sep 9, 2024
1 parent fabb903 commit d877d9b
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 11 deletions.
2 changes: 1 addition & 1 deletion node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type NodeByTag<TNodeTag extends NodeTag> = Node extends infer TNode
: never

export class NodePath<TNodeTag extends NodeTag = NodeTag> {
constructor(readonly tag: TNodeTag, readonly node: NodeByTag<TNodeTag>, readonly parent: NodePath | null) {}
constructor(readonly tag: TNodeTag, readonly node: NodeByTag<TNodeTag>, readonly parent: NodePath | null, readonly keyPath: readonly (string | number)[]) {}
isList(): this is NodePath<"List"> {
return this.tag === "List"
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/generateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ export type NodeByTag<TNodeTag extends NodeTag> = Node extends infer TNode
: never
export class NodePath<TNodeTag extends NodeTag = NodeTag> {
constructor(readonly tag: TNodeTag, readonly node: NodeByTag<TNodeTag>, readonly parent: NodePath | null) {}
constructor(readonly tag: TNodeTag, readonly node: NodeByTag<TNodeTag>, readonly parent: NodePath | null, readonly keyPath: readonly (string | number)[]) {}
${Array.from(
nodeTypes,
(name) => `
Expand Down
23 changes: 14 additions & 9 deletions walk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,32 @@ export function walk(
root: any,
callback: Walker | Visitor,
parent: NodePath | null = null,
keyPath: readonly (string | number)[] = [],
) {
if (typeof callback !== "function") {
const visitor = callback
callback = (path) => visitor[path.tag]?.(path as any)
}
if (Array.isArray(root)) {
root.forEach((node) => walk(node, callback))
root.forEach((node, index) => {
walk(node, callback, parent, [...keyPath, index])
})
} else if (typeof root === "object" && root !== null) {
const keys = Object.keys(root)
if (keys.length === 1 && /^[A-Z]/.test(keys[0])) {
const tag = keys[0] as NodeTag
const path = new NodePath(tag, root[tag], parent)
const result = callback(path)
if (result === false) {
const node = root[tag]
const path = new NodePath(tag, node, parent, keyPath)
if (callback(path) === false) {
return
}
parent = path
}
for (const key in root) {
const value = root[key]
walk(value, callback)
for (const key in node) {
walk(node[key], callback, path, [...keyPath, key])
}
} else {
for (const key of keys) {
walk(root[key], callback, parent, [...keyPath, key])
}
}
}
}

0 comments on commit d877d9b

Please sign in to comment.