npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lukeaus/plain-tree

v2.1.2

Published

A plain tree with a bunch of tree tools

Downloads

60

Readme

Plain Tree


Tests MIT License version npm downloads semantic-release contributions welcome Speed

What

Performant tree and node utility library.

Features

  • Create trees
    • manually
    • from array
  • Create nodes
    • manually
    • from array
    • from object
  • Search
    • Find one
    • Find all
    • Some/Every
  • Traverse (breath first and depth first)
  • Nodes at height
  • Nodes count
    • all
    • by height
  • Width
  • Height
  • Depth
  • Manipulate trees and nodes
  • FlatMap
    • Into single array
    • Into array of arrays by height
  • Convert to JSON
  • ... and more (see below)

Why

Tree and node tools all in one handy, well tested package.

Install

npm i --save @lukeaus/plain-tree

Usage

import { Node, Tree } from '@lukeaus/plain-tree';

const rootNode = new Node('a');
const tree = new Tree(rootNode);
rootNode.addChild('b');

console.log(tree);
/*
Tree {
  root:
    Node {
      children: [ [Node] ],
      id: 'twsychkc3gdj7o30o3s3z6cb7vfpzb2xfgjl',
      parent: null,
      data: 'a'
    }
  }
*/

API

Creating a Tree

There are multiple ways to create a tree.

Manually via Declared Nodes

Assign nodes to variables then use node.addChild

import { Node, Tree } from '@lukeaus/plain-tree';

const rootNode = new Node('a');
const tree = new Tree(rootNode);
const nodeB = rootNode.addChild('b');
const nodeC = nodeB.addChild('c');

/* Tree Outline:
 * a
 *   - b
 *     - c
 */

Manually via Children

Add nodes by accessing the root node's children (and their children, and their children's children etc.)

import { Node, Tree } from '@lukeaus/plain-tree';

const rootNode = new Node('a');
const tree = new Tree(rootNode);
rootNode.addChild('b');
rootNode.children[0].addChild('c');

/* Tree Outline:
 * a
 *   - b
 *     - c
 */

Create a Tree From a Flat Array of Objects

createTreeFromFlatArray(arr, ?opts)

Return: Tree instance

arr

Type: Array

Description: An array of objects. Object should have:

  • id
  • parent id (optional)
  • children (optional)
  • some other properties (all other properties will be converted to an object and will be available on node's data property )
opts

Type: Object

Description: Options for creation of tree

| Parameter | Type | Default | Description | | ----------- | ------ | ---------- | ------------------------------------------------- | | idKey | String | 'id' | Object's property whose value is each node's id | | parentIdKey | String | 'parentId' | Object's property whose value is parent node's id | | childrenKey | String | 'children' | Object's property whose value is child objects |

Example
import { createTreeFromFlatArray } from '@lukeaus/plain-tree';

const arr = [
  {
    id: 'sports',
    name: 'Sports',
    parentId: null
  },
  {
    id: 'ball',
    name: 'Ball',
    parentId: 'sports'
  },
  {
    id: 'non-ball',
    name: 'Non Ball',
    parentId: 'sports'
  },
  {
    id: 'tennis',
    name: 'Tennis',
    parentId: 'ball'
  }
];

createTreeFromFlatArray(arr);

/* Tree Outline:
 * Sports
 *   - Ball
 *     - Tennis
 *   - Non Ball
 */

Create a Tree From an Array of Nested Objects

createTreeFromTreeArray(arr, ?opts)

Return: Tree instance

arr

Type: Array

Description: An array of objects. Object should have:

  • id
  • parent id (optional)
  • children (optional)
  • some other properties (all other properties will be converted to an object and will be available on node's data property )
opts

Type: Object

Description: Options for creation of tree

| Parameter | Type | Default | Description | | ----------- | ------ | ---------- | ------------------------------------------------- | | idKey | String | 'id' | Object's property whose value is each node's id | | parentIdKey | String | 'parentId' | Object's property whose value is parent node's id | | childrenKey | String | 'children' | Object's property whose value is child objects |

Example
import { createTreeFromTreeArray } from '@lukeaus/plain-tree';

const arr = [
  {
    id: 'sports',
    name: 'Sports',
    parentId: null,
    children: [
      {
        id: 'ball',
        name: 'Ball',
        parentId: 'sports',
        children: [
          {
            id: 'tennis',
            name: 'Tennis',
            parentId: 'ball',
            children: []
          }
        ]
      },
      {
        id: 'non-ball',
        name: 'Non Ball',
        parentId: 'sports',
        children: []
      }
    ]
  }
];
createTreeFromTreeArray(arr);

/* Tree Outline:
 * Sports
 *   - Ball
 *     - Tennis
 *   - Non Ball
 */

Adding Additional Nodes to Existing Tree

Manually via Declared Nodes

Assign nodes to variables then use node.addChild

import { Node } from '@lukeaus/plain-tree';

// find/use an existing node
const nodeB = node.addChild('b');
const nodeC = nodeB.addChild('c');

Manually via Children

Add nodes by accessinga node's children (and their children, and their children's children etc.)

import { Node, Tree } from '@lukeaus/plain-tree';

// find/use an existing node
node.addChild('b');
node.children[0].addChild('c');

From Tree Array

createNodes(arr, ?parentNode, ?opts)

Create nodes from an array of nested objects

Return: void

arr

Type: Array

Description: An array of objects. Object should have:

  • id
  • parent id (optional)
  • children (optional)
  • some other properties (all other properties will be converted to an object and will be available on node's data property )
parentNode

Type: Node | null

Description: Parent node for nodes in array

opts

Type: Object

Description: Options for creation of tree

| Parameter | Type | Default | Description | | ----------- | ------ | ---------- | ------------------------------------------------- | | idKey | String | 'id' | Object's property whose value is each node's id | | parentIdKey | String | 'parentId' | Object's property whose value is parent node's id | | childrenKey | String | 'children' | Object's property whose value is child objects |

Example
import { createNodes } from '@lukeaus/plain-tree';

const parentNode = new Node('a'));
const arr: any = [
  {
    id: 'sports',
    name: 'Sports',
    parentId: null,
    children: [
      {
        id: 'ball',
        name: 'Ball',
        parentId: 'sports',
        children: [
          {
            id: 'tennis',
            name: 'Tennis',
            parentId: 'ball',
            children: []
          }
        ]
      },
      {
        id: 'non-ball',
        name: 'Non Ball',
        parentId: 'sports',
        children: []
      }
    ]
  }
];

createNodes(arr, parentNode);

Tree

constructor(root)

Creates and returns the tree

root

Type: Node or null

Default: null

Description: The tree root

traverseBreathFirst(fn)

Traverse every node in the tree breath first

Return: void

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

traverseDepthFirst(fn)

Traverse every node in the tree depth first

Return: void

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

findOneBreathFirst(fn)

Traverse nodes in the tree breath first. Returns the first matching Node or null.

Return: Node | null

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

findOneDepthFirst(fn)

Traverse nodes in the tree depth first. Returns the first matching Node or null.

Return: Node | null

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

findAllBreathFirst(fn)

Traverse nodes in the tree breath first. Returns an array containing all matching Nodes.

Return: Array

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

findAllDepthFirst(fn)

Traverse nodes in the tree depth first. Returns an array containing all matching Nodes.

Return: Array

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

someBreathFirst(fn)

Traverse nodes in the tree breath first. Return true if a single node is truthy for fn, else return false. Breaks on first truthy for performance.

Return: Boolean

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

someDepthFirst(fn)

Traverse nodes in the tree depth first. Return true if a single node is truthy for fn, else return false. Breaks on first truthy for performance.

Return: Boolean

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

everyBreathFirst(fn)

Traverse every node in the tree breath first. Return true if every node is truthy for fn, else return false. Breaks on first falsey for performance.

Return: Boolean

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

everyDepthFirst(fn)

Traverse every node in the tree depth first. Return true if every node is truthy for fn, else return false. Breaks on first falsey for performance.

Return: Boolean

fn

Type: Function

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

flatMap(?fn)

Traverse every node in the tree breath first and flatten the tree into a single array.

Return: Array<Node|null>

fn

Type: Function

Default: null (if null, flatten will push the node into the array)

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

flattenData()

Traverse every node in the tree breath first and flatten the tree into a single array. Extract the 'data' property of each Node (if node is not null) and return an array of any. This is a helper method which is essentially flatten(nodeData);

Return: Array

flattenByHeight(?fn)

Traverse every node in the tree breath first and flatten the tree into an array of arrays, where each array is for each height level in the tree.

Return: Array<Array>

fn

Type: Function

Default: null (if null, flatten will push the node into the array)

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

Example
import { Node, Tree } from '@lukeaus/plain-tree';

const nodeA = new Node('a');
const tree = new Tree(nodeA);
nodeA.addChild('b');
const nodeC = nodeA.addChild('c');
nodeC.addChild('d');

tree.flattenByHeight(nodeData);
/* Output
[['a'], ['b', 'c'], ['d']];
*/

flattenDataByHeight()

Traverse every node in the tree breath first and flatten the tree into an array of arrays, where each array is for each height level in the tree. Extract the 'data' property of each Node (if node is not null). This is a helper method which is essentially flattenByHeight(nodeData);

Return: Array<Array>

widthsByHeight()

Return the width of children at each height

Example
import { Tree, Node, hasChildren, nodeData } from '@lukeaus/plain-tree';

const nodeA = new Node('a');
const tree = new Tree(nodeA);
nodeA.addChild('b');
nodeA.addChild('c');
nodeA.children[0].addChild('d');

tree.widthsByHeight(); // [1, 2 , 1]

nodesAtHeight(number)

Return all the nodes at that height (root is at height 0)

Return: Array<Node|null>

number

Type: Number

Description: Number indicating the tree height at which you want to obtain all nodes

maxWidth()

Return the maximum width of any height level in the tree

Return: Number

height()

Return the height of the tree. Equivalent to height of root node. A tree with only root will be height 0.

Return: Number

countNodes()

Return the number of nodes in a tree. A tree with root of null will return 1.

Return: Number

toJson()

Stringify the tree. Due to circular dependencies, the parent property is dropped and replaced with property parentId (type String | null) which is the id of the parent (if it exists) else null.

If root is null, an empty string is returned.

Return: String

Node

constructor(data, ?opts)

Create a new Node instance

Return: Node

data

The node's data (excluding interal node properties)

Type: any

parent

The node's parent node (if it exists, otherwise null)

Type: Node | null

opts

| Parameter | Type | Description | | --------- | ------------ | ----------- | | id | String | id | | parent | Node | null | parent node |

addChild(data)

Add a child to this node. Return the newly created child Node instance.

Return: Node

data

Type: any

removeChildren(fn)

Remove all children where fn returns truthy. Use this where data is complex (e.g. data is an Object or Array). Returns removed children.

Return: Array

fn

| Parameter | Type | Description | | --------- | ------------ | --------------------- | | 1 | Node | null | A child Node instance |

removeChildrenByData(data)

Remove all children where child's data property matches data. Use removeChildren where data is complex (e.g. data is an Object or Array). Returns removed children.

Return: Array

data

Type: any

removeChildrenById(id)

Remove all children where child's id property matches id. Use removeChildren where data is complex (e.g. data is an Object or Array). Returns removed children.

Return: Array

id

Type: String

isLeaf()

Returns a Boolean. False if this Node instance has children. True if it does have children.

Return: Boolean

hasChildren()

Returns a Boolean. True if this Node instance has children. False if it does have children.

Return: Boolean

widthsByHeight()

Return the width of children at each height

Example
import { Tree, Node, hasChildren, nodeData } from '@lukeaus/plain-tree';

const nodeA = new Node('a');
nodeA.addChild('b');
nodeA.addChild('c');
nodeA.children[0].addChild('d');

nodeA.widthsByHeight(); // [1, 2 , 1]

height()

Return the height of the node.

Return: Number

depth()

Return the depth of the node.

Return: Number

flattenByHeight(?fn)

Traverse node and its children breath first and flatten into an array of arrays, where each array is for each height level (with this node at height 0).

Return: Array<Array>

fn

Type: Function

Default: null (if null, flatten will push the node into the array)

| Parameter | Type | Description | | --------- | ------------ | -------------- | | 1 | Node | null | A Node or null |

Example
import { Node } from '@lukeaus/plain-tree';

const nodeA = new Node('a');
nodeA.addChild('b');
const nodeC = nodeA.addChild('c');
nodeC.addChild('d');

nodeA.flattenByHeight(nodeData);
/* Output
[['a'], ['b', 'c'], ['d']];
*/

toJson()

Stringify the node. Due to circular dependencies, parent property is dropped and replaced with parentId (type String | null).

Return: String

Utils

nodeData(any)

Return a nodes data. Safe function to protect against accessing data property on null.

Return: any

any

Type: any

nodesData(any)

Convenience method to return all node data on an array of nodes.

Return: Array

any

Type: Array

hasChildren(any)

Return true if node has children. Return false if no children.

Return: boolean

any

Type: any

Contributing

Contributions are welcomed. How to make a contribution:

  • Create an issue on Github
  • Fork project
  • Make changes
  • Test changes npm run test
  • Use npm run commit to commit
  • Create a pull request