Efficient tree and linked list data structure using ES6 Symbols for DOM tree backing
npx @tessl/cli install tessl/npm-symbol-tree@3.2.0Symbol Tree is an efficient tree and linked list data structure library that uses ES6 Symbols to store metadata directly on objects without interference. Designed specifically for DOM tree implementations, it provides constant-time insertion and deletion operations while maintaining tree relationships through Symbol-based metadata storage.
npm install symbol-treeconst SymbolTree = require("symbol-tree");For ES modules:
import SymbolTree from "symbol-tree";const SymbolTree = require("symbol-tree");
const tree = new SymbolTree();
// Create objects - any objects work
let parent = { name: "parent" };
let child1 = { name: "child1" };
let child2 = { name: "child2" };
// Build a tree structure
tree.appendChild(parent, child1);
tree.appendChild(parent, child2);
// Navigate the tree
console.log(tree.firstChild(parent) === child1); // true
console.log(tree.nextSibling(child1) === child2); // true
console.log(tree.parent(child1) === parent); // true
// Create a linked list
let a = { value: "a" };
let b = { value: "b" };
let c = { value: "c" };
tree.insertBefore(b, a); // a comes before b
tree.insertAfter(b, c); // c comes after b
console.log(tree.nextSibling(a) === b); // true
console.log(tree.nextSibling(b) === c); // trueSymbol Tree is built around several key components:
Initialize objects for optimal performance and create new tree instances.
/**
* Create a new SymbolTree instance
* @param {string} [description='SymbolTree data'] - Description for the internal Symbol
*/
class SymbolTree {
constructor(description?: string);
}
/**
* Initialize an object for tree operations (optional optimization)
* @param {Object} object - Object to initialize
* @returns {Object} The same object
*/
initialize(object: Object): Object;Navigate between parents, children, and siblings with constant-time operations.
/**
* Check if object has children
* @param {Object} object - Object to check
* @returns {boolean} True if object has children
*/
hasChildren(object: Object): boolean;
/**
* Get first child of object
* @param {Object} object - Parent object
* @returns {Object|null} First child or null
*/
firstChild(object: Object): Object | null;
/**
* Get parent of object
* @param {Object} object - Child object
* @returns {Object|null} Parent object or null
*/
parent(object: Object): Object | null;Insert, append, and remove objects with constant-time operations.
/**
* Insert object as last child of parent
* @param {Object} referenceObject - Parent object
* @param {Object} newObject - Object to insert
* @returns {Object} The inserted object
* @throws {Error} If newObject is already in tree
*/
appendChild(referenceObject: Object, newObject: Object): Object;
/**
* Remove object from tree
* @param {Object} removeObject - Object to remove
* @returns {Object} The removed object
*/
remove(removeObject: Object): Object;Advanced traversal operations for finding preceding/following objects and tree boundaries.
/**
* Find preceding object in tree order
* @param {Object} object - Reference object
* @param {Object} [options] - Traversal options
* @param {Object} [options.root] - Root boundary for traversal
* @returns {Object|null} Preceding object or null
*/
preceding(object: Object, options?: { root?: Object }): Object | null;
/**
* Find last inclusive descendant
* @param {Object} object - Starting object
* @returns {Object} Last descendant in tree order
*/
lastInclusiveDescendant(object: Object): Object;Convert tree structures to arrays with optional filtering.
/**
* Convert children to array
* @param {Object} parent - Parent object
* @param {Object} [options] - Conversion options
* @param {Array} [options.array] - Target array
* @param {Function} [options.filter] - Filter function
* @returns {Object[]} Array of children
*/
childrenToArray(parent: Object, options?: {
array?: Object[];
filter?: (object: Object) => boolean;
thisArg?: any;
}): Object[];ES6-compatible iterators for all traversal patterns.
/**
* Iterate over children
* @param {Object} parent - Parent object
* @param {Object} [options] - Iterator options
* @param {boolean} [options.reverse] - Iterate in reverse
* @returns {Iterator} ES6 iterator
*/
childrenIterator(parent: Object, options?: { reverse?: boolean }): Iterator<Object>;
/**
* Iterate over entire tree
* @param {Object} root - Root object
* @param {Object} [options] - Iterator options
* @param {boolean} [options.reverse] - Iterate in reverse
* @returns {Iterator} ES6 iterator
*/
treeIterator(root: Object, options?: { reverse?: boolean }): Iterator<Object>;Index calculation, counting, and position comparison operations.
/**
* Get index position among siblings
* @param {Object} child - Child object
* @returns {number} Index position or -1 if no parent
*/
index(child: Object): number;
/**
* Compare positions of two objects
* @param {Object} left - Left object
* @param {Object} right - Right object
* @returns {number} Position bitmask
*/
compareTreePosition(left: Object, right: Object): number;Position relationship constants for compareTreePosition results.
// Access via SymbolTree.TreePosition
const TreePosition = {
DISCONNECTED: 1, // Objects are in different trees
PRECEDING: 2, // Left object precedes right object
FOLLOWING: 4, // Left object follows right object
CONTAINS: 8, // Left object contains right object
CONTAINED_BY: 16 // Left object is contained by right object
};Error if the object being inserted is already present in the tree-1 if the object has no parentnull for non-existent relationshipsTreePosition.DISCONNECTED for objects in different trees