unist-util-map
Version:
unist utility to create a new tree by mapping all nodes
133 lines (132 loc) • 4.12 kB
TypeScript
/**
* @typedef {import('unist').Node} UnistNode
* @typedef {import('unist').Parent} UnistParent
*/
/**
* @typedef {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10} Uint
* Number; capped reasonably.
* @see https://github.com/syntax-tree/unist-util-visit-parents/blob/main/lib/index.js
*/
/**
* @typedef {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} Increment
* Increment a number in the type system.
* @template {Uint} [I=0]
* Index.
* @see https://github.com/syntax-tree/unist-util-visit-parents/blob/main/lib/index.js
*/
/**
* @typedef {(
* Tree extends UnistParent
* ? Depth extends Max
* ? Tree
* : Tree | InclusiveDescendant<Tree['children'][number], Max, Increment<Depth>>
* : Tree
* )} InclusiveDescendant
* 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.
* @template {UnistNode} Tree
* Tree type.
* @template {Uint} [Max=10]
* Max; searches up to this depth.
* @template {Uint} [Depth=0]
* Current depth.
* @see https://github.com/syntax-tree/unist-util-visit-parents/blob/main/lib/index.js
*/
/**
* @template {UnistNode} Tree
* Node type.
* @typedef {(
* (
* node: InclusiveDescendant<Tree>,
* index: number | undefined,
* parent: Extract<InclusiveDescendant<Tree>, UnistParent> | undefined
* ) => Tree | InclusiveDescendant<Tree>
* )} MapFunction
* Function called with a node, its index, and its parent to produce a new
* node.
*/
/**
* Create a new tree by mapping all nodes with the given function.
*
* @template {UnistNode} Tree
* Type of input tree.
* @param {Tree} tree
* Tree to map.
* @param {MapFunction<Tree>} mapFunction
* Function called with a node, its index, and its parent to produce a new
* node.
* @returns {InclusiveDescendant<Tree>}
* New mapped tree.
*/
export function map<Tree extends import('unist').Node>(
tree: Tree,
mapFunction: MapFunction<Tree>
): InclusiveDescendant<Tree, 10, 0>
export type UnistNode = import('unist').Node
export type UnistParent = import('unist').Parent
/**
* 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 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
/**
* Function called with a node, its index, and its parent to produce a new
* node.
*/
export type MapFunction<Tree extends import('unist').Node> = (
node: InclusiveDescendant<Tree>,
index: number | undefined,
parent: Extract<InclusiveDescendant<Tree>, UnistParent> | undefined
) => Tree | InclusiveDescendant<Tree>