UNPKG

unist-util-visit

Version:
199 lines (198 loc) 5.88 kB
export function visit<Tree extends import('unist').Node, Check extends Test>( tree: Tree, check: Check, visitor: BuildVisitor<Tree, Check>, reverse?: boolean | null | undefined ): undefined export function visit<Tree extends import('unist').Node, Check extends Test>( tree: Tree, visitor: BuildVisitor<Tree, Test>, reverse?: boolean | null | undefined ): undefined export type UnistNode = import('unist').Node export type UnistParent = import('unist').Parent export type VisitorResult = import('unist-util-visit-parents').VisitorResult /** * Test from `unist-util-is`. * * Note: we have remove and add `undefined`, because otherwise when generating * automatic `.d.ts` files, TS tries to flatten paths from a local perspective, * which doesn’t work when publishing on npm. */ export type Test = Exclude<import('unist-util-is').Test, undefined> | undefined /** * Get the value of a type guard `Fn`. */ export type Predicate<Fn, Fallback> = Fn extends ( value: any ) => value is infer Thing ? Thing : Fallback /** * Check whether a node matches a primitive check in the type system. */ export type MatchesOne<Value, Check> = Check extends null | undefined ? Value : Value extends { type: Check } ? Value : Value extends Check ? Value : Check extends Function ? Predicate<Check, Value> extends Value ? Predicate<Check, Value> : never : never /** * Check whether a node matches a check in the type system. */ export type Matches<Value, Check> = Check extends Array<any> ? MatchesOne<Value, Check[keyof Check]> : MatchesOne<Value, Check> /** * Number; capped reasonably. */ export type Uint = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 /** * Increment a number in the type system. */ export type Increment<I extends Uint = 0> = I extends 0 ? 1 : I extends 1 ? 2 : I extends 2 ? 3 : I extends 3 ? 4 : I extends 4 ? 5 : I extends 5 ? 6 : I extends 6 ? 7 : I extends 7 ? 8 : I extends 8 ? 9 : 10 /** * Collect nodes that can be parents of `Child`. */ export type InternalParent< Node extends import('unist').Node, Child extends import('unist').Node > = Node extends import('unist').Parent ? Node extends { children: (infer Children)[] } ? Child extends Children ? Node : never : never : never /** * Collect nodes in `Tree` that can be parents of `Child`. */ export type Parent< Tree extends import('unist').Node, Child extends import('unist').Node > = InternalParent<InclusiveDescendant<Tree>, Child> /** * Collect nodes in `Tree` that can be ancestors of `Child`. */ export type InternalAncestor< Node extends import('unist').Node, Child extends import('unist').Node, Max extends Uint = 10, Depth extends Uint = 0 > = Depth extends Max ? never : | InternalParent<Node, Child> | InternalAncestor< Node, InternalParent<Node, Child>, Max, Increment<Depth> > /** * Collect all (inclusive) descendants of `Tree`. * * > 👉 **Note**: for performance reasons, this seems to be the fastest way to * > recurse without actually running into an infinite loop, which the * > previous version did. * > * > Practically, a max of `2` is typically enough assuming a `Root` is * > passed, but it doesn’t improve performance. * > It gets higher with `List > ListItem > Table > TableRow > TableCell`. * > Using up to `10` doesn’t hurt or help either. */ export type InclusiveDescendant< Tree extends import('unist').Node, Max extends Uint = 10, Depth extends Uint = 0 > = Tree extends UnistParent ? Depth extends Max ? Tree : | Tree | InclusiveDescendant<Tree['children'][number], Max, Increment<Depth>> : Tree /** * Handle a node (matching `test`, if given). * * Visitors are free to transform `node`. * They can also transform `parent`. * * Replacing `node` itself, if `SKIP` is not returned, still causes its * descendants to be walked (which is a bug). * * When adding or removing previous siblings of `node` (or next siblings, in * case of reverse), the `Visitor` should return a new `Index` to specify the * sibling to traverse after `node` is traversed. * Adding or removing next siblings of `node` (or previous siblings, in case * of reverse) is handled as expected without needing to return a new `Index`. * * Removing the children property of `parent` still results in them being * traversed. */ export type Visitor< Visited extends import('unist').Node = import('unist').Node, Ancestor extends import('unist').Parent = import('unist').Parent > = ( node: Visited, index: Visited extends UnistNode ? number | undefined : never, parent: Ancestor extends UnistParent ? Ancestor | undefined : never ) => VisitorResult /** * Build a typed `Visitor` function from a node and all possible parents. * * It will infer which values are passed as `node` and which as `parent`. */ export type BuildVisitorFromMatch< Visited extends import('unist').Node, Ancestor extends import('unist').Parent > = Visitor<Visited, Parent<Ancestor, Visited>> /** * Build a typed `Visitor` function from a list of descendants and a test. * * It will infer which values are passed as `node` and which as `parent`. */ export type BuildVisitorFromDescendants< Descendant extends import('unist').Node, Check extends Test > = BuildVisitorFromMatch< Matches<Descendant, Check>, Extract<Descendant, UnistParent> > /** * Build a typed `Visitor` function from a tree and a test. * * It will infer which values are passed as `node` and which as `parent`. */ export type BuildVisitor< Tree extends import('unist').Node = import('unist').Node, Check extends Test = Test > = BuildVisitorFromDescendants<InclusiveDescendant<Tree>, Check> export {CONTINUE, EXIT, SKIP} from 'unist-util-visit-parents'