From 55439f431a3c14366c90f8c58b1bec1fc3247bb1 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 24 Jan 2023 14:16:02 +0100 Subject: [PATCH] Add improved docs --- index.d.ts | 4 +- lib/index.js | 8 +- readme.md | 233 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 170 insertions(+), 75 deletions(-) diff --git a/index.d.ts b/index.d.ts index 07a1dcb..29af1e6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2,9 +2,9 @@ export type {Test} from 'unist-util-is' export type { Action, ActionTuple, + BuildVisitor, Index, - VisitorResult, Visitor, - BuildVisitor + VisitorResult } from './lib/index.js' export {CONTINUE, EXIT, SKIP, visitParents} from './lib/index.js' diff --git a/lib/index.js b/lib/index.js index a199bec..7bd4fe8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,7 +10,7 @@ * * @typedef {number} Index * Move to the sibling at `index` next (after node itself is completely - * traversed), when moving in an array. + * traversed). * * Useful if mutating the tree, such as removing the node the visitor is * currently on, or any of its previous siblings. @@ -20,7 +20,7 @@ * @typedef {[(Action | null | undefined | void)?, (Index | null | undefined)?]} ActionTuple * List with one or two values, the first an action, the second an index. * - * @typedef {Action | Index | ActionTuple | null | undefined | void} VisitorResult + * @typedef {Action | ActionTuple | Index | null | undefined | void} VisitorResult * Any value that can be returned from a visitor. */ @@ -30,7 +30,7 @@ * @template {Parent} [Ancestor=Parent] * Ancestor type. * @callback Visitor - * Handle a node (matching test, if given). + * Handle a node (matching `test`, if given). * * Visitors are free to transform `node`. * They can also transform the parent of node (the last of `ancestors`). @@ -69,7 +69,7 @@ * @typedef {Visitor, Check>, Extract, Parent>>} BuildVisitor * Build a typed `visitor` function from a tree and a test. * - * It will infer which values are passed as `node`, and which as `parents`. + * It will infer which values are passed as `node` and which as `parents`. */ import {convert} from 'unist-util-is' diff --git a/readme.md b/readme.md index dedbc52..2f849ac 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,16 @@ * [Use](#use) * [API](#api) * [`visitParents(tree[, test], visitor[, reverse])`](#visitparentstree-test-visitor-reverse) + * [`CONTINUE`](#continue) + * [`EXIT`](#exit) + * [`SKIP`](#skip) + * [`Action`](#action) + * [`ActionTuple`](#actiontuple) + * [BuildVisitor](#buildvisitor) + * [`Index`](#index) + * [`Test`](#test) + * [`Visitor`](#visitor) + * [`VisitorResult`](#visitorresult) * [Types](#types) * [Compatibility](#compatibility) * [Related](#related) @@ -39,7 +49,7 @@ entire stack of parents. ## Install This package is [ESM only][esm]. -In Node.js (version 12.20+, 14.14+, 16.0+, 18.0+), install with [npm][]: +In Node.js (version 14.14+ and 16.0+), install with [npm][]: ```sh npm install unist-util-visit-parents @@ -48,14 +58,14 @@ npm install unist-util-visit-parents In Deno with [`esm.sh`][esmsh]: ```js -import {visitParents} from "https://esm.sh/unist-util-visit-parents@5" +import {visitParents} from 'https://esm.sh/unist-util-visit-parents@5' ``` In browsers with [`esm.sh`][esmsh]: ```html ``` @@ -80,108 +90,185 @@ strong ['root', 'paragraph'] ## API -This package exports the identifiers `visitParents`, `SKIP`, `CONTINUE`, and -`EXIT`. +This package exports the identifiers [`CONTINUE`][api-continue], +[`EXIT`][api-exit], [`SKIP`][api-skip], and [`visitParents`][api-visitparents]. There is no default export. ### `visitParents(tree[, test], visitor[, reverse])` -Walk the `tree` ([`Node`][node]) and visit [*inclusive descendants*][descendant] -with ancestral information. +Visit nodes, with ancestral information. -This algorithm performs *[depth-first][]* *[tree traversal][tree-traversal]* in -*[preorder][]* (**NLR**), or if `reverse` is given, in *reverse preorder* +This algorithm performs *[depth-first][]* *[tree traversal][tree-traversal]* +in *[preorder][]* (**NLR**) or if `reverse` is given, in *reverse preorder* (**NRL**). You can choose for which nodes `visitor` is called by passing a `test`. +For complex tests, you should test yourself in `visitor`, as it will be +faster and will have improved type information. Walking the tree is an intensive task. Make use of the return values of the visitor when possible. -Instead of walking a tree multiple times with different `test`s, walk it once -without a test, and use [`unist-util-is`][unist-util-is] to check if a node -matches a test, and then perform different operations. +Instead of walking a tree multiple times, walk it once, use +[`unist-util-is`][unist-util-is] to check if a node matches, and then perform +different operations. You can change the tree. -See `visitor` below for more info. +See [`Visitor`][api-visitor] for more info. ###### Parameters * `tree` ([`Node`][node]) — tree to traverse -* `test` ([`Test`][test], optional) +* `test` ([`Test`][api-test], optional) — [`unist-util-is`][unist-util-is]-compatible test -* `visitor` ([Function][visitor]) - — function called for nodes that pass `test` +* `visitor` ([`Visitor`][api-visitor]) + — handle each node * `reverse` (`boolean`, default: `false`) - — traverse in reverse preorder (NRL) instead of preorder (NLR) (default + — traverse in reverse preorder (NRL) instead of the default preorder (NLR) -#### `next? = visitor(node, ancestors)` +###### Returns -Called when a node (matching `test`, if given) is entered. +Nothing (`void`). -Visitors are free to change `node`. -They can also transform the [parent][] of node (the last of `ancestors`). -Replacing `node` itself is okay if `SKIP` is returned. -When adding or removing previous [sibling][]s (or next siblings, in case of -`reverse`) of `node`, `visitor` must return a new [`index`][index] (`number`) -to specify the sibling to move to after `node` is traversed. -Adding or removing next siblings of `node` (or previous siblings, in case of -`reverse`) is fine without needing to return a new `index`. -Replacing the `children` of a node is fine, but replacing them on an ancestor -is not okay and still causes them to be visited. +### `CONTINUE` -###### Parameters +Continue traversing as normal (`true`). + +### `EXIT` + +Stop traversing immediately (`false`). + +### `SKIP` + +Do not traverse this node’s children (`'skip'`). + +### `Action` + +Union of the action types (TypeScript type). + +###### Type + +```ts +type Action = typeof CONTINUE | typeof EXIT | typeof SKIP +``` + +### `ActionTuple` + +List with one or two values, the first an action, the second an index +(TypeScript type). -* `node` ([`Node`][node]) — found node -* `ancestors` (`Array`) — [ancestor][]s of `node` +###### Type -##### Returns +```ts +type ActionTuple = [ + (Action | null | undefined | void)?, + (Index | null | undefined)? +] +``` + +### BuildVisitor + +Build a typed `visitor` function from a tree and a test (TypeScript type). -The return value can have the following forms: +It will infer which values are passed as `node` and which as `parents`. -* [`index`][index] (`number`) — like a tuple of `[CONTINUE, index]` -* `action` (`*`) — like a tuple of `[action]` -* `tuple` (`[action, index?]`) — array with one or two values, the first an - `action`, the second and `index`. +###### Type parameters -> 👉 **Note**: yielding a tuple only makes sense if the `action` is `SKIP`. -> Otherwise, if the `action` is `EXIT`, that action can be returned. -> Or if the `action` is `CONTINUE`, `index` can be returned. +* `Tree` ([`Node`][node], default: `Node`) + — tree type +* `Check` ([`Test`][api-test], default: `string`) + — test type -###### `action` +###### Returns -An action can have the following values: +[`Visitor`][api-visitor]. -* `EXIT` (`false`) — stop traversing immediately -* `CONTINUE` (`true`) — continue traversing as normal -* `SKIP` (`'skip'`) — do not traverse this node’s children +### `Index` -###### `index` +Move to the sibling at `index` next (after node itself is completely +traversed) (TypeScript type). -Next [`index`][index] (`number`). -Defines that the sibling at `index` should be moved to (after `node` itself is -completely traversed). Useful if mutating the tree, such as removing the node the visitor is currently -on, or any of its previous siblings (or next siblings, in case of `reverse`). +on, or any of its previous siblings. Results less than `0` or greater than or equal to `children.length` stop -traversing the parent +traversing the parent. + +###### Type + +```ts +type Index = number +``` + +### `Test` + +[`unist-util-is`][unist-util-is] compatible test (TypeScript type). + +### `Visitor` + +Handle a node (matching `test`, if given) (TypeScript type). + +Visitors are free to transform `node`. +They can also transform the parent of node (the last of `ancestors`). + +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 an ancestor still results in them being +traversed. + +###### Parameters + +* `node` ([`Node`][node]) + — found node +* `parents` ([`Array`][node]) + — ancestors of `node` + +###### Returns + +What to do next. + +An `Index` is treated as a tuple of `[CONTINUE, Index]`. +An `Action` is treated as a tuple of `[Action]`. + +Passing a tuple back only makes sense if the `Action` is `SKIP`. +When the `Action` is `EXIT`, that action can be returned. +When the `Action` is `CONTINUE`, `Index` can be returned. + +### `VisitorResult` + +Any value that can be returned from a visitor (TypeScript type). + +###### Type + +```ts +type VisitorResult = + | Action + | ActionTuple + | Index + | null + | undefined + | void +``` ## Types This package is fully typed with [TypeScript][]. -It exports the additional types `Test`, `Action`, `Index`, `ActionTuple`, -`VisitorResult`, and `Visitor`. - -It also exports the types `BuildVisitor` to properly type visitors from a tree and a test, and -`Visitor` to -build an arbitrary visitor, from `unist-util-visit-parents/complex-types.d.ts`. +It exports the additional types [`Action`][api-action], +[`ActionTuple`][api-actiontuple], [`BuildVisitor`][api-buildvisitor], +[`Index`][api-index], [`Test`][api-test], [`Visitor`][api-visitor], and +[`VisitorResult`][api-visitorresult]. ## Compatibility Projects maintained by the unified collective are compatible with all maintained versions of Node.js. -As of now, that is Node.js 12.20+, 14.14+, 16.0+, and 18.0+. +As of now, that is Node.js 14.14+ and 16.0+. Our projects sometimes work with older versions, but this is not guaranteed. ## Related @@ -271,20 +358,28 @@ abide by its terms. [preorder]: https://github.com/syntax-tree/unist#preorder -[descendant]: https://github.com/syntax-tree/unist#descendant +[unist-util-visit]: https://github.com/syntax-tree/unist-util-visit -[parent]: https://github.com/syntax-tree/unist#parent-1 +[unist-util-is]: https://github.com/syntax-tree/unist-util-is -[sibling]: https://github.com/syntax-tree/unist#sibling +[api-visitparents]: #visitparentstree-test-visitor-reverse -[index]: https://github.com/syntax-tree/unist#index +[api-continue]: #continue -[ancestor]: https://github.com/syntax-tree/unist#ancestor +[api-exit]: #exit -[unist-util-visit]: https://github.com/syntax-tree/unist-util-visit +[api-skip]: #skip -[unist-util-is]: https://github.com/syntax-tree/unist-util-is +[api-action]: #action + +[api-actiontuple]: #actiontuple + +[api-buildvisitor]: #buildvisitor + +[api-index]: #index + +[api-test]: #test -[test]: https://github.com/syntax-tree/unist-util-is#test +[api-visitor]: #visitor -[visitor]: #next--visitornode-ancestors +[api-visitorresult]: #visitorresult