From 019d8981d8eba0ce2518192c652e1a5871b82e69 Mon Sep 17 00:00:00 2001 From: Kaspersky <50753378+CasP0@users.noreply.github.com> Date: Tue, 21 Jan 2025 06:31:11 -0500 Subject: [PATCH] Improve README with detailed examples and instructions Update `README.md` to include detailed installation, usage, and development instructions. * **Table of Contents** - Add a table of contents at the beginning of the file. * **Introduction** - Add an introduction section describing the library. * **Installation** - Add instructions for installing the library using npm and yarn. * **Usage** - Add detailed usage examples, including traversing different types of trees and using various functions provided by the library. * **API Reference** - Add a section with brief descriptions of each function provided by the library, along with their parameters and return values. * **Examples** - Add examples of using the library with real-world data structures, such as JSON objects and DOM trees. - Add examples of custom traversal strategies and how to create custom walkers. * **Development** - Add information on setting up the development environment, including necessary dependencies and tools. - Add a section on running tests and building the project, referencing the relevant scripts in the `package.json` file. * **License** - Add a section stating that the project is licensed under the MIT License. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/pdubroy/tree-walk?shareId=XXXX-XXXX-XXXX-XXXX). --- README.md | 261 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 193 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index edc6c85..3128c97 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,36 @@ inspecting, and transforming arbitrary tree structures. It's based on the [![NPM](https://nodei.co/npm/tree-walk.png?compact=true)](https://nodei.co/npm/tree-walk/) +Table of Contents +----------------- +- [Introduction](#introduction) +- [Installation](#installation) +- [Usage](#usage) +- [API Reference](#api-reference) +- [Examples](#examples) +- [Development](#development) +- [License](#license) + +Introduction +------------ + +tree-walk is a JavaScript library providing useful functions for traversing, +inspecting, and transforming arbitrary tree structures. It's based on the +`walk` module that I wrote for [Underscore-contrib](http://documentcloud.github.io/underscore-contrib/). + +Installation +------------ + +You can install tree-walk using npm or yarn: + +```sh +npm install tree-walk +``` + +```sh +yarn add tree-walk +``` + Usage ----- @@ -44,91 +74,186 @@ the root node is visited, then all of its child nodes are recursively visited. `postorder` does the opposite, calling the visitor function for a node only after visiting all of its child nodes. -Collection Functions --------------------- +API Reference +------------- -This module provides versions of most of the -[Underscore collection functions](http://underscorejs.org/#collections), with -some small differences that make them better suited for operating on trees. For -example, you can use `filter` to get a list of all the strings in a tree: +### `preorder(tree, visitor, context)` - var walk = require('tree-walk'); - walk.filter(walk.preorder, _.isString); +Performs a preorder traversal of the tree, calling the visitor function for each node. -Like many other functions in this module, the argument to `filter` is a function -indicating in what order the nodes should be visited. Currently, only -`preorder` and `postorder` are supported. +- `tree`: The tree to traverse. +- `visitor`: A function to call for each node. +- `context`: Optional. The context in which to call the visitor function. -Custom Walkers --------------- +### `postorder(tree, visitor, context)` -Sometimes, you have a tree structure that can't be naïvely traversed. A good -example of this is a DOM tree: because each element has a reference to its -parent, a naïve walk would encounter circular references. To handle such cases, -you can create a custom walker by invoking `walk` as a function, and passing -it a function which returns the descendants of a given node. E.g.: +Performs a postorder traversal of the tree, calling the visitor function for each node. - var walk = require('tree-walk'); - var domWalker = walk(function(el) { - return el.children; - }); +- `tree`: The tree to traverse. +- `visitor`: A function to call for each node. +- `context`: Optional. The context in which to call the visitor function. -The resulting object has the same functions as `walk`, but parameterized -to use the custom walking behavior: +### `filter(tree, strategy, visitor, context)` - var buttons = domWalker.filter(walk.preorder, function(el) { - return el.tagName === 'BUTTON'; - }); +Recursively traverses the tree and returns all the elements that pass a truth test. -However, it's not actually necessary to create custom walkers for DOM nodes -- -walk handles DOM nodes specially by default. +- `tree`: The tree to traverse. +- `strategy`: The traversal function to use, e.g., `preorder` or `postorder`. +- `visitor`: A function to call for each node. +- `context`: Optional. The context in which to call the visitor function. -Parse Trees ------------ +### `map(tree, strategy, visitor, context)` -A _parse tree_ is tree that represents the syntactic structure of a formal -language. For example, the arithmetic expression `1 + (4 + 2) * 7` might have the -following parse tree: +Produces a new array of values by recursively traversing the tree and mapping each value through the transformation function. - var tree = { +- `tree`: The tree to traverse. +- `strategy`: The traversal function to use, e.g., `preorder` or `postorder`. +- `visitor`: A function to call for each node. +- `context`: Optional. The context in which to call the visitor function. + +### `reduce(tree, visitor, leafMemo, context)` + +Builds up a single value by doing a post-order traversal of the tree and calling the visitor function on each object in the tree. + +- `tree`: The tree to traverse. +- `visitor`: A function to call for each node. +- `leafMemo`: The value to use for leaf nodes. +- `context`: Optional. The context in which to call the visitor function. + +### `pluck(tree, propertyName)` + +Returns the value of properties named `propertyName` reachable from the tree rooted at `tree`. + +- `tree`: The tree to traverse. +- `propertyName`: The name of the property to pluck. + +### `pluckRec(tree, propertyName)` + +Version of `pluck` which recursively searches results for nested objects with a property named `propertyName`. + +- `tree`: The tree to traverse. +- `propertyName`: The name of the property to pluck. + +### `createAttribute(visitor, defaultValue, context)` + +Creates an attribute that is calculated by invoking a visitor function on a node. + +- `visitor`: A function to call for each node. +- `defaultValue`: The default value to use for the attribute. +- `context`: Optional. The context in which to call the visitor function. + +Examples +-------- + +### Traversing Different Types of Trees + +#### JSON Objects + +```js +var tree = { + 'name': { 'first': 'Bucky', 'last': 'Fuller' }, + 'occupations': ['designer', 'inventor'] +}; + +var walk = require('tree-walk'); + +walk.preorder(tree, function(value, key, parent) { + console.log(key + ': ' + value); +}); +``` + +#### DOM Trees + +```js +var walk = require('tree-walk'); +var domWalker = walk(function(el) { + return el.children; +}); + +var buttons = domWalker.filter(walk.preorder, function(el) { + return el.tagName === 'BUTTON'; +}); +``` + +### Custom Traversal Strategies + +#### Custom Walker for Parse Trees + +```js +var walk = require('tree-walk'); +var parseTreeWalker = walk(function(node) { + return _.pick(node, 'left', 'right'); +}); + +var tree = { + 'type': 'Addition', + 'left': { 'type': 'Value', 'value': 1 }, + 'right': { + 'type': 'Multiplication', + 'left': { 'type': 'Addition', - 'left': { 'type': 'Value', 'value': 1 }, - 'right': { - 'type': 'Multiplication', - 'left': { - 'type': 'Addition', - 'left': { 'type': 'Value', 'value': 4 }, - 'right': { 'type': 'Value', 'value': 2 } - }, - 'right': { 'type': 'Value', 'value': 7 } - } - }; + 'left': { 'type': 'Value', 'value': 4 }, + 'right': { 'type': 'Value', 'value': 2 } + }, + 'right': { 'type': 'Value', 'value': 7 } + } +}; + +parseTreeWalker.reduce(tree, function(memo, node) { + if (node.type === 'Value') return node.value; + if (node.type === 'Addition') return memo.left + memo.right; + if (node.type === 'Multiplication') return memo.left * memo.right; +}); +``` + +Development +----------- -We can create a custom walker for this parse tree: +### Setting Up the Development Environment - var walk = require('tree-walk'); - var parseTreeWalker = walk(function(node) { - return _.pick(node, 'left', 'right'); - }); +1. Clone the repository: -Using the `find` function, we could find the first occurrence of the addition -operator. It uses a pre-order traversal of the tree, so the following code -will produce the root node (`tree`): + ```sh + gh repo clone pdubroy/tree-walk + ``` - parseTreeWalker.find(tree, function(node) { - return node.type === 'Addition'; - }); +2. Install the dependencies: -We could use the `reduce` function to evaluate the arithmetic expression -represented by the tree. The following code will produce `43`: + ```sh + npm install + ``` - parseTreeWalker.reduce(tree, function(memo, node) { - if (node.type === 'Value') return node.value; - if (node.type === 'Addition') return memo.left + memo.right; - if (node.type === 'Multiplication') return memo.left * memo.right; - }); + or + + ```sh + yarn install + ``` + +### Running Tests + +To run the tests, use the following command: + +```sh +npm test +``` + +### Building the Project + +To build the project, use the following command: + +```sh +npm run build +``` + +### Linting the Project + +To lint the project, use the following command: + +```sh +npm run lint +``` + +License +------- -When the visitor function is called on a node, the `memo` argument contains -the results of calling `reduce` on each of the node's subtrees. To evaluate a -node, we just need to add or multiply the results of the left and right -subtrees of the node. +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.