Skip to content

Commit

Permalink
Add improved docs
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Jan 24, 2023
1 parent 0fa5fcb commit 55439f4
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 75 deletions.
4 changes: 2 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
8 changes: 4 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
*/

Expand All @@ -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`).
Expand Down Expand Up @@ -69,7 +69,7 @@
* @typedef {Visitor<import('./complex-types.js').Matches<import('./complex-types.js').InclusiveDescendant<Tree>, Check>, Extract<import('./complex-types.js').InclusiveDescendant<Tree>, 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'
Expand Down
233 changes: 164 additions & 69 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
<script type="module">
import {visitParents} from "https://esm.sh/unist-util-visit-parents@5?bundle"
import {visitParents} from 'https://esm.sh/unist-util-visit-parents@5?bundle'
</script>
```

Expand All @@ -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<Node>`) — [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>`][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<Tree extends Node = Node, Check extends
Test = string>` to properly type visitors from a tree and a test, and
`Visitor<Visited extends Node = Node, Ancestor extends Parent = Parent>` 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
Expand Down Expand Up @@ -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

0 comments on commit 55439f4

Please sign in to comment.