tree-visit
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -7,2 +7,3 @@ "use strict"; | ||
const withOptions_1 = require("../withOptions"); | ||
const diagram_1 = require("../diagram"); | ||
function getChildren(node) { | ||
@@ -139,2 +140,96 @@ var _a; | ||
}); | ||
describe('diagram', () => { | ||
const getLabel = (node) => node.name; | ||
const getMultilineLabel = (node) => `name: ${node.name}\npath: ${node.indexPath.join('.')}`; | ||
it('generates folder diagram', () => { | ||
expect(diagram_1.diagram(example, { getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates folder diagram with single child case', () => { | ||
const singleChild = { | ||
name: 'a', | ||
children: [ | ||
{ | ||
name: 'b', | ||
indexPath: [0], | ||
children: [{ name: 'b1', indexPath: [0, 0] }], | ||
}, | ||
], | ||
indexPath: [], | ||
}; | ||
expect(diagram_1.diagram(singleChild, { getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates folder diagram with hidden root', () => { | ||
const singleChild = { | ||
name: '', | ||
children: [ | ||
{ | ||
name: 'b', | ||
indexPath: [0], | ||
children: [{ name: 'b1', indexPath: [0, 0] }], | ||
}, | ||
], | ||
indexPath: [], | ||
}; | ||
expect(diagram_1.diagram(singleChild, { getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates folder diagram with multiline label', () => { | ||
expect(diagram_1.diagram(example, { getChildren, getLabel: getMultilineLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates folder diagram with multiline label and single child case', () => { | ||
const singleChild = { | ||
name: 'a', | ||
children: [ | ||
{ | ||
name: 'b', | ||
indexPath: [0], | ||
children: [{ name: 'b1', indexPath: [0, 0] }], | ||
}, | ||
], | ||
indexPath: [], | ||
}; | ||
expect(diagram_1.diagram(singleChild, { getChildren, getLabel: getMultilineLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates box diagram', () => { | ||
expect(diagram_1.diagram(example, { type: 'box', getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates multiline box diagram', () => { | ||
expect(diagram_1.diagram(example, { | ||
type: 'box', | ||
getChildren, | ||
getLabel: (node) => node.name === 'b' | ||
? `name: ${node.name}\npath: ${node.indexPath.join('.')}` | ||
: `name: ${node.name}`, | ||
})).toMatchSnapshot(); | ||
}); | ||
it('generates uneven box diagram', () => { | ||
const node = { | ||
name: 'a', | ||
children: [ | ||
{ | ||
name: 'hello', | ||
indexPath: [0], | ||
}, | ||
{ | ||
name: 'c', | ||
indexPath: [1], | ||
}, | ||
], | ||
indexPath: [], | ||
}; | ||
expect(diagram_1.diagram(node, { type: 'box', getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
it('generates single child box', () => { | ||
const node = { | ||
name: 'a', | ||
children: [ | ||
{ | ||
name: 'okay', | ||
indexPath: [0], | ||
}, | ||
], | ||
indexPath: [], | ||
}; | ||
expect(diagram_1.diagram(node, { type: 'box', getChildren, getLabel })).toMatchSnapshot(); | ||
}); | ||
}); | ||
describe('withOptions', () => { | ||
@@ -158,3 +253,3 @@ it('binds options', () => { | ||
var _a; | ||
const { find, visit } = withOptions_1.withOptions({ getChildren }); | ||
const { find, visit, diagram } = withOptions_1.withOptions({ getChildren }); | ||
let enterNames = []; | ||
@@ -166,3 +261,4 @@ visit(example, (child) => { | ||
expect((_a = find(example, (node) => node.name === 'b1')) === null || _a === void 0 ? void 0 : _a.name).toEqual('b1'); | ||
expect(diagram(example, (node) => node.name)).toMatchSnapshot(); | ||
}); | ||
}); |
import { IndexPath } from './indexPath'; | ||
import { BaseOptions } from './options'; | ||
/** | ||
* 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`). | ||
*/ | ||
export declare function access<T>(node: T, indexPath: IndexPath, options: BaseOptions<T>): 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`). | ||
*/ | ||
export declare function accessPath<T>(node: T, indexPath: IndexPath, options: BaseOptions<T>): T[]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.accessPath = exports.access = void 0; | ||
/** | ||
* 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`). | ||
*/ | ||
function access(node, indexPath, options) { | ||
@@ -11,2 +16,7 @@ if (indexPath.length === 0) | ||
exports.access = access; | ||
/** | ||
* 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`). | ||
*/ | ||
function accessPath(node, indexPath, options) { | ||
@@ -13,0 +23,0 @@ if (indexPath.length === 0) |
import { IndexPath } from './indexPath'; | ||
import { BaseOptions } from './options'; | ||
export declare type FindOptions<T> = BaseOptions<T> & { | ||
/** | ||
* Return `true` to include this node in the results. | ||
*/ | ||
predicate: (node: T, indexPath: IndexPath) => boolean; | ||
}; | ||
/** | ||
* Find a node matching a predicate function. | ||
*/ | ||
export declare function find<T>(node: T, options: FindOptions<T>): T | undefined; | ||
/** | ||
* Find all nodes matching a predicate function. | ||
*/ | ||
export declare function findAll<T>(node: T, options: FindOptions<T>): T[]; | ||
/** | ||
* Find the `IndexPath` of a node matching a predicate function. | ||
*/ | ||
export declare function findIndexPath<T>(node: T, options: FindOptions<T>): IndexPath | undefined; |
@@ -5,2 +5,5 @@ "use strict"; | ||
const visit_1 = require("./visit"); | ||
/** | ||
* Find a node matching a predicate function. | ||
*/ | ||
function find(node, options) { | ||
@@ -20,2 +23,5 @@ let found; | ||
exports.find = find; | ||
/** | ||
* Find all nodes matching a predicate function. | ||
*/ | ||
function findAll(node, options) { | ||
@@ -34,2 +40,5 @@ let found = []; | ||
exports.findAll = findAll; | ||
/** | ||
* Find the `IndexPath` of a node matching a predicate function. | ||
*/ | ||
function findIndexPath(node, options) { | ||
@@ -36,0 +45,0 @@ let found; |
@@ -5,3 +5,4 @@ export * from './indexPath'; | ||
export * from './access'; | ||
export * from './diagram'; | ||
export * from './find'; | ||
export * from './withOptions'; |
@@ -17,3 +17,4 @@ "use strict"; | ||
__exportStar(require("./access"), exports); | ||
__exportStar(require("./diagram"), exports); | ||
__exportStar(require("./find"), exports); | ||
__exportStar(require("./withOptions"), exports); |
@@ -11,2 +11,16 @@ import { IndexPath } from './indexPath'; | ||
}; | ||
/** | ||
* Visit each node in the tree, calling an optional `onEnter` and `onLeave` for each. | ||
* | ||
* From `onEnter`: | ||
* | ||
* - return nothing or `undefined` to continue | ||
* - return `"skip"` to skip the children of that node and the subsequent `onLeave` | ||
* - return `"stop"` to end traversal | ||
* | ||
* From `onLeave`: | ||
* | ||
* - return nothing or `undefined` to continue | ||
* - return `"stop"` to end traversal | ||
*/ | ||
export declare function visit<T>(node: T, options: VisitOptions<T>): void; |
@@ -6,2 +6,16 @@ "use strict"; | ||
exports.STOP = 'stop'; | ||
/** | ||
* Visit each node in the tree, calling an optional `onEnter` and `onLeave` for each. | ||
* | ||
* From `onEnter`: | ||
* | ||
* - return nothing or `undefined` to continue | ||
* - return `"skip"` to skip the children of that node and the subsequent `onLeave` | ||
* - return `"stop"` to end traversal | ||
* | ||
* From `onLeave`: | ||
* | ||
* - return nothing or `undefined` to continue | ||
* - return `"stop"` to end traversal | ||
*/ | ||
function visit(node, options) { | ||
@@ -8,0 +22,0 @@ const normalizedOptions = Object.assign({ onEnter: () => { }, onLeave: () => { } }, options); |
@@ -5,5 +5,8 @@ import { BaseOptions } from './options'; | ||
import { FindOptions } from './find'; | ||
import { DiagramOptions } from './diagram'; | ||
export declare type WithOptions<T> = { | ||
access(node: T, indexPath: IndexPath): T; | ||
accessPath(node: T, indexPath: IndexPath): T[]; | ||
diagram(node: T, getLabel: DiagramOptions<T>['getLabel']): string; | ||
diagram(node: T, options: DiagramOptions<T>): string; | ||
find(node: T, predicate: FindOptions<T>['predicate']): T | undefined; | ||
@@ -10,0 +13,0 @@ find(node: T, options: Omit<FindOptions<T>, keyof BaseOptions<T>>): T | undefined; |
@@ -7,2 +7,3 @@ "use strict"; | ||
const find_1 = require("./find"); | ||
const diagram_1 = require("./diagram"); | ||
/** | ||
@@ -17,2 +18,5 @@ * Return every tree utility function with options partially applied. | ||
accessPath: (node, indexPath) => access_1.accessPath(node, indexPath, baseOptions), | ||
diagram: (node, getLabelOrOptions) => typeof getLabelOrOptions === 'function' | ||
? diagram_1.diagram(node, Object.assign(Object.assign({}, baseOptions), { getLabel: getLabelOrOptions })) | ||
: diagram_1.diagram(node, Object.assign(Object.assign({}, baseOptions), getLabelOrOptions)), | ||
find: (node, predicateOrOptions) => typeof predicateOrOptions === 'function' | ||
@@ -19,0 +23,0 @@ ? find_1.find(node, Object.assign(Object.assign({}, baseOptions), { predicate: predicateOrOptions })) |
{ | ||
"name": "tree-visit", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "A tree traversal library.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
289
README.md
@@ -8,1 +8,290 @@ # tree-visit | ||
``` | ||
OR | ||
```bash | ||
yarn add tree-visit | ||
``` | ||
## API | ||
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. | ||
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`). | ||
- [access](#access) | ||
- [accessPath](#accessPath) | ||
- [diagram](#diagram) | ||
- [find](#find) | ||
- [findAll](#findAll) | ||
- [findIndexPath](#findIndexPath) | ||
- [visit](#visit) | ||
- [withOptions](#withOptions) | ||
--- | ||
### `access` | ||
Returns a node by its `IndexPath`. | ||
**Type**: `function access<T>(node: T, indexPath: IndexPath, options: BaseOptions<T>): T` | ||
#### Example | ||
```js | ||
import { access } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
access(rootNode, [1, 0], { getChildren }) | ||
// #=> { name: 'd' } | ||
``` | ||
--- | ||
### `accessPath` | ||
Returns an array of each node in an `IndexPath`. | ||
**Type**: `function accessPath<T>(node: T, indexPath: IndexPath, options: BaseOptions<T>): T` | ||
#### Example | ||
```js | ||
import { accessPath } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
access(rootNode, [1, 0], { getChildren }) | ||
// #=> [{ name: 'a', children: [...] }, { name: 'c', children: [...] }, { name: 'd' }] | ||
``` | ||
--- | ||
### `diagram` | ||
Generate a diagram of the tree, as a string. | ||
**Type**: `function diagram<T>(node: T, options: DiagramOptions<T>): string` | ||
#### Example | ||
```js | ||
import { diagram } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const getLabel = (node) => node.name | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
diagram(rootNode, { getChildren, getLabel }) | ||
// #=> a | ||
// #=> ├── b | ||
// #=> └── c / d | ||
``` | ||
--- | ||
### `find` | ||
Find a node matching a predicate function. | ||
**Type**: `function find<T>(node: T, options: FindOptions<T>): T | undefined` | ||
#### Example | ||
```js | ||
import { find } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
find(rootNode, { getChildren, predicate: (node) => node.name === 'd' }) | ||
// #=> { name: 'd' } | ||
``` | ||
--- | ||
### `findAll` | ||
Find all nodes matching a predicate function. | ||
**Type**: `findAll<T>(node: T, options: FindOptions<T>): T[]` | ||
#### Example | ||
```js | ||
import { findAll } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
findAll(rootNode, { getChildren, predicate: (node) => node.name === 'd' }) | ||
// #=> [{ name: 'd' }] | ||
``` | ||
--- | ||
### `findIndexPath` | ||
Find the `IndexPath` of a node matching a predicate function. | ||
**Type**: `findIndexPath<T>(node: T, options: FindOptions<T>): T[]` | ||
#### Example | ||
```js | ||
import { findIndexPath } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
findIndexPath(rootNode, { getChildren, predicate: (node) => node.name === 'd' }) | ||
// #=> [1, 0] | ||
``` | ||
--- | ||
### `visit` | ||
Visit each node in the tree, calling an optional `onEnter` and `onLeave` for each. | ||
From `onEnter`: | ||
- return nothing or `undefined` to continue | ||
- return `"skip"` to skip the children of that node and the subsequent `onLeave` | ||
- return `"stop"` to end traversal | ||
From `onLeave`: | ||
- return nothing or `undefined` to continue | ||
- return `"stop"` to end traversal | ||
**Type**: `function visit<T>(node: T, options: VisitOptions<T>): void` | ||
#### Example | ||
```js | ||
import { visit } from 'tree-visit' | ||
const getChildren = (node) => node.children || [] | ||
const rootNode = { | ||
name: 'a', | ||
children: [ | ||
{ name: 'b' }, | ||
{ | ||
name: 'c', | ||
children: [{ name: 'd' }], | ||
}, | ||
], | ||
} | ||
visit(rootNode, { | ||
getChildren, | ||
onEnter: (node) => { | ||
console.log(node) | ||
}, | ||
}) | ||
// #=> a, b, c, d | ||
``` | ||
--- | ||
### `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
36379
24
799
297