§ Quick Take

import { strict as assert } from "assert";
import {
} from "ast-monkey-util";

assert.equal(pathNext("9.children.3"), "9.children.4");



§ Idea

codsen-parser and emlint both use object-path opens in a new tab notation. This utility program contains helper functions to traverse the paths.

Conceptually, we'd use ast-monkey-traverse, identify the node we need, then get its path (from the same program, from callbacks), then amend that path (using this program), then use object-path to get/set/delete that path.

§ API - pathNext


It takes (a string) path and increments the last digit:

// => "1"

// => "9.children.4"

// => "9.children.1.children.1"

§ API - pathPrev


It takes (a string) path and decrements the last digit:

// => null

// => "9.children.32"

// => "9.children.1.children.1"

§ API - pathUp


It takes (a string) path and goes "one level" up, discarding the last two path parts:

// => null

// => "9"

// => "9.children.1"

Practically, if you think, codsen-parser always outputs an array. It contains zero or more plain objects, each representing a tag, a chunk of text, a comment tag and so on.

Since root element is array, paths of those plain objects are digits: 0, 1, 5.children.0 and so on.

In codsen-parser AST's, child nodes are nested within children key - its value is array:

The following HTML:


Would yield AST (many keys omitted):

"type": "tag",
"start": 0,
"end": 3,
"value": "<a>",
"attribs": [],
"children": [
"type": "text",
"start": 3,
"end": 7,
"value": "text"
"type": "tag",
"start": 7,
"end": 11,
"value": "</a>",
"attribs": [],
"children": []

Thus, a text node for value "text" (one with "start": 3 above) is at the path 0.children.0 (first element's first child node) and "going up" would mean "0" - that's splitting by dot into an array and discarding the last two elements from that array, then joining it back with a dot.

0 . children . 0
        ^      ^
    these two are removed during the "go up" action

§ object-path notation

The notation used in this program is based on object-path opens in a new tab - an array elements are marked with dot - if object's key value is an array and we want to a path of the fourth element in there, it's key.3, not key[3].

A drawback of this notation is that keys can't be numeric strings. But the advantage of this notation is that all children are now separated with a dot - you can split by dot String.split(".") and quickly process the path elements, unlike JS notation with square brackets.

§ Changelog

See it in the monorepo opens in a new tab, on Sourcehut.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 object-path opens in a new tab
Access deep object properties using a path
📦 ast-monkey 7.12.1
Traverse and edit AST
📦 ast-monkey-traverse 1.13.1
Utility library to traverse AST
📦 json-comb-core 6.7.1
The inner core of json-comb
📦 json-variables 9.0.3
Resolves custom-marked, cross-referenced paths in parsed JSON
📦 object-merge-advanced 10.12.1
Recursive, deep merge of anything (objects, arrays, strings or nested thereof), which weighs contents by type hierarchy to ensure the maximum content is retained
📦 object-boolean-combinations 3.0.0
Consumes a defaults object with booleans, generates all possible variations of it