tree-visit
Advanced tools
Comparing version 0.3.0 to 0.4.0
@@ -15,2 +15,3 @@ "use strict"; | ||
const access_1 = require("../access"); | ||
const defineTree_1 = require("../defineTree"); | ||
const diagram_1 = require("../diagram"); | ||
@@ -23,3 +24,2 @@ const find_1 = require("../find"); | ||
const reduce_1 = require("../reduce"); | ||
const withOptions_1 = require("../withOptions"); | ||
function getChildren(node) { | ||
@@ -464,5 +464,3 @@ var _a; | ||
var _a; | ||
const _b = (0, withOptions_1.withOptions)({ | ||
getChildren, | ||
}), { find, access, visit, reduce, flatMap, map } = _b, Tree = __rest(_b, ["find", "access", "visit", "reduce", "flatMap", "map"]); | ||
const _b = (0, defineTree_1.defineTree)(getChildren), { find, access, visit, reduce, flatMap, map } = _b, Tree = __rest(_b, ["find", "access", "visit", "reduce", "flatMap", "map"]); | ||
expect(Tree.getChildren(example, []).map((node) => node.name)).toEqual([ | ||
@@ -504,3 +502,3 @@ 'b', | ||
var _a, _b; | ||
const { find, findAll } = (0, withOptions_1.withOptions)({ getChildren: getTypedChildren }); | ||
const { find, findAll } = (0, defineTree_1.defineTree)(getTypedChildren); | ||
expect(((_a = find(typedExample, { | ||
@@ -515,5 +513,3 @@ predicate: (node) => node.type === 'a', | ||
var _a; | ||
const { find, findAllIndexPaths, visit, diagram, flat } = (0, withOptions_1.withOptions)({ | ||
getChildren, | ||
}); | ||
const { find, findAllIndexPaths, visit, diagram, flat } = (0, defineTree_1.defineTree)(getChildren); | ||
let enterNames = []; | ||
@@ -540,2 +536,17 @@ visit(example, (child) => { | ||
}); | ||
it('type checks', () => { | ||
const Tree = (0, defineTree_1.defineTree)(getChildren); | ||
const TreeWithOptions = Tree.withOptions({ getLabel: (node) => node.name }); | ||
expect(() => { | ||
// @ts-expect-error | ||
Tree.diagram(example); | ||
}).toThrowError(); | ||
expect(() => { | ||
// @ts-expect-error | ||
Tree.diagram(example, {}); | ||
}).toThrowError(); | ||
TreeWithOptions.diagram(example); | ||
TreeWithOptions.diagram(example, {}); | ||
TreeWithOptions.diagram(example, (node) => node.name); | ||
}); | ||
}); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const node_1 = require("../__mocks__/node"); | ||
const defineTree_1 = require("../defineTree"); | ||
const diagram_1 = require("../diagram"); | ||
@@ -9,3 +10,2 @@ const insert_1 = require("../insert"); | ||
const replace_1 = require("../replace"); | ||
const withOptions_1 = require("../withOptions"); | ||
describe('insert', () => { | ||
@@ -241,5 +241,24 @@ it('inserts node at start', () => { | ||
}); | ||
describe('tree with no options', () => { | ||
const Tree = (0, defineTree_1.defineTree)(node_1.getChildren); | ||
it('inserts node', () => { | ||
const result = Tree.insert(node_1.example, { | ||
at: [1], | ||
nodes: [{ name: 'x', indexPath: [] }], | ||
create: node_1.createNode, | ||
}); | ||
expect((0, diagram_1.diagram)(result, { getChildren: node_1.getChildren, getLabel: node_1.getLabel })).toMatchSnapshot(); | ||
}); | ||
it('type checks', () => { | ||
expect(() => { | ||
// @ts-expect-error | ||
Tree.insert(node_1.example, { | ||
at: [1], | ||
nodes: [{ name: 'x', indexPath: [] }], | ||
}); | ||
}).toThrowError(); | ||
}); | ||
}); | ||
describe('partially applied', () => { | ||
const Tree = (0, withOptions_1.withOptions)({ | ||
getChildren: node_1.getChildren, | ||
const Tree = (0, defineTree_1.defineTree)(node_1.getChildren).withOptions({ | ||
create: node_1.createNode, | ||
@@ -246,0 +265,0 @@ }); |
export * from './access'; | ||
export * from './ancestors'; | ||
export * from './defineTree'; | ||
export * from './diagram'; | ||
@@ -4,0 +5,0 @@ export * from './find'; |
@@ -15,2 +15,3 @@ "use strict"; | ||
__exportStar(require("./ancestors"), exports); | ||
__exportStar(require("./defineTree"), exports); | ||
__exportStar(require("./diagram"), exports); | ||
@@ -17,0 +18,0 @@ __exportStar(require("./find"), exports); |
@@ -1,115 +0,7 @@ | ||
import { DiagramOptions } from './diagram'; | ||
import { FindOptions, FindOptionsTyped } from './find'; | ||
import { FlatMapOptions } from './flatMap'; | ||
import { IndexPath } from './indexPath'; | ||
import { InsertOptions } from './insert'; | ||
import { MapOptions } from './map'; | ||
import { MoveOptions } from './move'; | ||
import { BaseOptions, MutationBaseOptions } from './options'; | ||
import { ReduceOptions } from './reduce'; | ||
import { RemoveOptions } from './remove'; | ||
import { ReplaceOptions } from './replace'; | ||
import { VisitOptions } from './visit'; | ||
declare type WithoutBase<O> = Omit<O, keyof BaseOptions<unknown>>; | ||
export declare type WithOptions<T> = { | ||
/** | ||
* Returns the node's children. | ||
* | ||
* This is the same as the `getChildren` option passed to `withOptions`, included here for convenience. | ||
*/ | ||
getChildren: BaseOptions<T>['getChildren']; | ||
/** | ||
* Returns a node by its `IndexPath`. | ||
* | ||
* The first node is implicitly included in the `IndexPath` (i.e. no need to pass a `0` first in every `IndexPath`). | ||
*/ | ||
access(node: T, indexPath: IndexPath): T; | ||
/** | ||
* Returns an array of each node in an `IndexPath`. | ||
* | ||
* The first node is implicitly included in the `IndexPath` (i.e. no need to pass a `0` first in every `IndexPath`). | ||
*/ | ||
accessPath(node: T, indexPath: IndexPath): T[]; | ||
/** | ||
* Generate a diagram of the tree, as a string. | ||
*/ | ||
diagram(node: T, getLabel: DiagramOptions<T>['getLabel']): string; | ||
diagram(node: T, options: WithoutBase<DiagramOptions<T>>): string; | ||
/** | ||
* Find a node matching a predicate function. | ||
*/ | ||
find(node: T, predicate: FindOptions<T>['predicate']): T | undefined; | ||
find(node: T, options: WithoutBase<FindOptions<T>>): T | undefined; | ||
find<S extends T>(node: T, predicate: FindOptionsTyped<T, S>['predicate']): S | undefined; | ||
find<S extends T>(node: T, options: WithoutBase<FindOptionsTyped<T, S>>): S | undefined; | ||
/** | ||
* Find all nodes matching a predicate function. | ||
*/ | ||
findAll(node: T, predicate: FindOptions<T>['predicate']): T[]; | ||
findAll(node: T, options: WithoutBase<FindOptions<T>>): T[]; | ||
findAll<S extends T>(node: T, predicate: FindOptionsTyped<T, S>['predicate']): S[]; | ||
findAll<S extends T>(node: T, options: WithoutBase<FindOptionsTyped<T, S>>): S[]; | ||
/** | ||
* Find the `IndexPath` of a node matching a predicate function. | ||
*/ | ||
findIndexPath(node: T, predicate: FindOptions<T>['predicate']): IndexPath | undefined; | ||
findIndexPath(node: T, options: WithoutBase<FindOptions<T>>): IndexPath | undefined; | ||
/** | ||
* Find the `IndexPath` of all nodes matching a predicate function. | ||
*/ | ||
findAllIndexPaths(node: T, predicate: FindOptions<T>['predicate']): IndexPath[]; | ||
findAllIndexPaths(node: T, options: WithoutBase<FindOptions<T>>): IndexPath[]; | ||
/** | ||
* Returns an array containing the root node and all of its descendants. | ||
* | ||
* This is analogous to `Array.prototype.flat` for flattening arrays. | ||
*/ | ||
flat(node: T): T[]; | ||
/** | ||
* Map each node into an array of values, which are then flattened into a single array. | ||
* | ||
* This is analogous to `Array.prototype.flatMap` for arrays. | ||
*/ | ||
flatMap<R>(node: T, transform: FlatMapOptions<T, R>['transform']): R[]; | ||
reduce<R>(node: T, nextResult: ReduceOptions<T, R>['nextResult'], initialResult: R): R; | ||
map<R>(node: T, transform: MapOptions<T, R>['transform']): R; | ||
/** | ||
* Visit each node using preorder DFS traversal. | ||
*/ | ||
visit(node: T, onEnter: NonNullable<VisitOptions<T>>['onEnter']): void; | ||
/** | ||
* Visit each node using DFS traversal. | ||
*/ | ||
visit(node: T, options: WithoutBase<VisitOptions<T>>): void; | ||
/** | ||
* Insert nodes at a given `IndexPath`. | ||
*/ | ||
insert(node: T, options: WithoutBase<InsertOptions<T>>): T; | ||
/** | ||
* Remove nodes at the given `IndexPath`s. | ||
*/ | ||
remove(node: T, options: WithoutBase<RemoveOptions<T>>): T; | ||
/** | ||
* Move nodes from one `IndexPath` to another. | ||
*/ | ||
move(node: T, options: WithoutBase<MoveOptions<T>>): T; | ||
/** | ||
* Replace the node at the given `IndexPath` with another | ||
*/ | ||
replace(node: T, options: WithoutBase<ReplaceOptions<T>>): T; | ||
}; | ||
declare type WithoutMutationBase<O> = Omit<O, keyof MutationBaseOptions<unknown>>; | ||
export declare type WithMutationOptions<T> = Omit<WithOptions<T>, 'insert' | 'remove' | 'move' | 'replace'> & { | ||
insert: (node: T, options: WithoutMutationBase<InsertOptions<T>>) => T; | ||
remove: (node: T, options: WithoutMutationBase<RemoveOptions<T>>) => T; | ||
move: (node: T, options: WithoutMutationBase<MoveOptions<T>>) => T; | ||
replace: (node: T, options: WithoutMutationBase<ReplaceOptions<T>>) => T; | ||
}; | ||
import { defineTree } from './defineTree'; | ||
/** | ||
* Return every tree utility function with options partially applied. | ||
* | ||
* @param baseOptions | ||
* @deprecated Use `defineTree` instead | ||
*/ | ||
export declare function withOptions<T>(baseOptions: BaseOptions<T>): WithOptions<T>; | ||
export declare function withOptions<T>(baseOptions: MutationBaseOptions<T>): WithMutationOptions<T>; | ||
export {}; | ||
export declare const withOptions: typeof defineTree; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.withOptions = void 0; | ||
const access_1 = require("./access"); | ||
const diagram_1 = require("./diagram"); | ||
const find_1 = require("./find"); | ||
const flat_1 = require("./flat"); | ||
const flatMap_1 = require("./flatMap"); | ||
const insert_1 = require("./insert"); | ||
const map_1 = require("./map"); | ||
const move_1 = require("./move"); | ||
const reduce_1 = require("./reduce"); | ||
const remove_1 = require("./remove"); | ||
const replace_1 = require("./replace"); | ||
const visit_1 = require("./visit"); | ||
function withOptionsBase(baseOptions) { | ||
return { | ||
getChildren: baseOptions.getChildren, | ||
access: (node, indexPath) => (0, access_1.access)(node, indexPath, baseOptions), | ||
accessPath: (node, indexPath) => (0, access_1.accessPath)(node, indexPath, baseOptions), | ||
diagram: (node, getLabelOrOptions) => typeof getLabelOrOptions === 'function' | ||
? (0, diagram_1.diagram)(node, Object.assign(Object.assign({}, baseOptions), { getLabel: getLabelOrOptions })) | ||
: (0, diagram_1.diagram)(node, Object.assign(Object.assign({}, baseOptions), getLabelOrOptions)), | ||
find: (node, predicateOrOptions) => typeof predicateOrOptions === 'function' | ||
? (0, find_1.find)(node, Object.assign(Object.assign({}, baseOptions), { predicate: predicateOrOptions })) | ||
: (0, find_1.find)(node, Object.assign(Object.assign({}, baseOptions), predicateOrOptions)), | ||
findAll: (node, predicateOrOptions) => typeof predicateOrOptions === 'function' | ||
? (0, find_1.findAll)(node, Object.assign(Object.assign({}, baseOptions), { predicate: predicateOrOptions })) | ||
: (0, find_1.findAll)(node, Object.assign(Object.assign({}, baseOptions), predicateOrOptions)), | ||
findIndexPath: (node, predicateOrOptions) => typeof predicateOrOptions === 'function' | ||
? (0, find_1.findIndexPath)(node, Object.assign(Object.assign({}, baseOptions), { predicate: predicateOrOptions })) | ||
: (0, find_1.findIndexPath)(node, Object.assign(Object.assign({}, baseOptions), predicateOrOptions)), | ||
flat: (node) => (0, flat_1.flat)(node, baseOptions), | ||
flatMap: (node, transform) => (0, flatMap_1.flatMap)(node, Object.assign(Object.assign({}, baseOptions), { transform })), | ||
reduce: (node, nextResult, initialResult) => (0, reduce_1.reduce)(node, Object.assign(Object.assign({}, baseOptions), { nextResult, initialResult })), | ||
map: (node, transform) => (0, map_1.map)(node, Object.assign(Object.assign({}, baseOptions), { transform })), | ||
findAllIndexPaths: (node, predicateOrOptions) => typeof predicateOrOptions === 'function' | ||
? (0, find_1.findAllIndexPaths)(node, Object.assign(Object.assign({}, baseOptions), { predicate: predicateOrOptions })) | ||
: (0, find_1.findAllIndexPaths)(node, Object.assign(Object.assign({}, baseOptions), predicateOrOptions)), | ||
visit: (node, onEnterOrOptions) => typeof onEnterOrOptions === 'function' | ||
? (0, visit_1.visit)(node, Object.assign(Object.assign({}, baseOptions), { onEnter: onEnterOrOptions })) | ||
: (0, visit_1.visit)(node, Object.assign(Object.assign({}, baseOptions), onEnterOrOptions)), | ||
insert: (node, options) => (0, insert_1.insert)(node, Object.assign(Object.assign({}, baseOptions), options)), | ||
remove: (node, options) => (0, remove_1.remove)(node, Object.assign(Object.assign({}, baseOptions), options)), | ||
move: (node, options) => (0, move_1.move)(node, Object.assign(Object.assign({}, baseOptions), options)), | ||
replace: (node, options) => (0, replace_1.replace)(node, Object.assign(Object.assign({}, baseOptions), options)), | ||
}; | ||
} | ||
function withMutationOptions(baseOptions) { | ||
const tree = withOptionsBase(baseOptions); | ||
return Object.assign(Object.assign({}, tree), { insert: (node, options) => (0, insert_1.insert)(node, Object.assign(Object.assign({}, baseOptions), options)), remove: (node, options) => (0, remove_1.remove)(node, Object.assign(Object.assign({}, baseOptions), options)), move: (node, options) => (0, move_1.move)(node, Object.assign(Object.assign({}, baseOptions), options)), replace: (node, options) => (0, replace_1.replace)(node, Object.assign(Object.assign({}, baseOptions), options)) }); | ||
} | ||
function withOptions(baseOptions) { | ||
if ('create' in baseOptions) { | ||
return withMutationOptions(baseOptions); | ||
} | ||
return withOptionsBase(baseOptions); | ||
} | ||
exports.withOptions = withOptions; | ||
const defineTree_1 = require("./defineTree"); | ||
/** | ||
* Return every tree utility function with options partially applied. | ||
* | ||
* @deprecated Use `defineTree` instead | ||
*/ | ||
exports.withOptions = defineTree_1.defineTree; |
{ | ||
"name": "tree-visit", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "A tree traversal library.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -17,8 +17,11 @@ # tree-visit | ||
All functions take an `options` parameter that must contain _at least_ a `getChildren` function which specifies how to find a node's children. The `withOptions` API returns a version of every function with the `getChildren` option already set. Using `withOptions` instead of the bare functions is recommended for convenience. | ||
The recommended way to use `tree-visit` is by calling `defineTree(getChildren)`, where `getChildren` is a function which returns a node's children as an array. The `defineTree` API returns an object containing every library function with the `getChildren` option already set. | ||
Most functions, such as `getChildren`, `predicate`, `onEnter`, and `onLeave`, are passed an `IndexPath` as the second argument, containing an array of integer indexes that identify that node. The root node is implicitly included in the `IndexPath` (i.e. there's no `0` first in every `IndexPath`). | ||
You may alternately import individual functions, e.g. `visit`, and pass the `{ getChildren }` option when calling them. Importing individual functions can reduce your bundle size to the bear minimum (though the entire library is small and has 0 dependencies, so this may not be necessary). | ||
Most callback functions, such as `getChildren`, `predicate`, `onEnter`, and `onLeave`, are passed an `IndexPath` as the second argument, containing an array of integer indexes that identify that node. The root node is implicitly included in the `IndexPath` (i.e. there's no `0` first in every `IndexPath`). | ||
- [access](#access) | ||
- [accessPath](#accessPath) | ||
- [defineTree](#defineTree) | ||
- [diagram](#diagram) | ||
@@ -30,3 +33,2 @@ - [find](#find) | ||
- [visit](#visit) | ||
- [withOptions](#withOptions) | ||
@@ -95,2 +97,41 @@ --- | ||
### `defineTree` | ||
Returns a version of every library function with the `getChildren` option already set. | ||
This also allows for more concise calls to most functions. | ||
**Type**: `function defineTree<T>(baseOptions: BaseOptions<T>): Tree<T>` | ||
#### Example | ||
```js | ||
import { defineTree } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const { visit, find } = defineTree({ getChildren }) | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
visit(rootNode, (node) => { | ||
console.log(node) | ||
}) | ||
// #=> a, b, c, d | ||
find(rootNode, (node) => node.name === 'd') | ||
// #=> { name: 'd' } | ||
``` | ||
--- | ||
### `diagram` | ||
@@ -327,40 +368,1 @@ | ||
``` | ||
--- | ||
### `withOptions` | ||
Returns a version of every function with the `getChildren` option already set. | ||
This allows for more concise calls to most functions. | ||
**Type**: `function withOptions<T>(baseOptions: BaseOptions<T>): WithOptions<T>` | ||
#### Example | ||
```js | ||
import { withOptions } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const { visit, find } = withOptions({ getChildren }) | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
visit(rootNode, (node) => { | ||
console.log(node) | ||
}) | ||
// #=> a, b, c, d | ||
find(rootNode, (node) => node.name === 'd') | ||
// #=> { name: 'd' } | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
94962
57
2207
365