CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-symbol-tree

Efficient tree and linked list data structure using ES6 Symbols for DOM tree backing

Pending
Overview
Eval results
Files

tree-modification.mddocs/

Tree Modification

Insert, append, and remove objects with constant-time operations.

Capabilities

Append Child

Insert an object as the last child of a parent.

/**
 * Insert object as the last child of the reference object
 * Time Complexity: O(1)
 * @param {Object} referenceObject - Parent object
 * @param {Object} newObject - Object to insert as last child
 * @returns {Object} The inserted newObject
 * @throws {Error} If newObject is already present in this SymbolTree
 */
appendChild(referenceObject: Object, newObject: Object): Object;

Prepend Child

Insert an object as the first child of a parent.

/**
 * Insert object as the first child of the reference object
 * Time Complexity: O(1)
 * @param {Object} referenceObject - Parent object
 * @param {Object} newObject - Object to insert as first child
 * @returns {Object} The inserted newObject
 * @throws {Error} If newObject is already present in this SymbolTree
 */
prependChild(referenceObject: Object, newObject: Object): Object;

Insert Before

Insert an object before a reference object (as a sibling).

/**
 * Insert object before the reference object as a sibling
 * Time Complexity: O(1)
 * @param {Object} referenceObject - Reference object
 * @param {Object} newObject - Object to insert before reference
 * @returns {Object} The inserted newObject
 * @throws {Error} If newObject is already present in this SymbolTree
 */
insertBefore(referenceObject: Object, newObject: Object): Object;

Insert After

Insert an object after a reference object (as a sibling).

/**
 * Insert object after the reference object as a sibling
 * Time Complexity: O(1)
 * @param {Object} referenceObject - Reference object
 * @param {Object} newObject - Object to insert after reference
 * @returns {Object} The inserted newObject
 * @throws {Error} If newObject is already present in this SymbolTree
 */
insertAfter(referenceObject: Object, newObject: Object): Object;

Remove Object

Remove an object from the tree.

/**
 * Remove object from the tree
 * Time Complexity: O(1)
 * @param {Object} removeObject - Object to remove
 * @returns {Object} The removed object (same as removeObject)
 */
remove(removeObject: Object): Object;

Usage Examples

Building Trees

const SymbolTree = require("symbol-tree");
const tree = new SymbolTree();

// Create DOM-like structure
const html = { tag: "html" };
const head = { tag: "head" };
const body = { tag: "body" };
const title = { tag: "title", text: "My Page" };
const h1 = { tag: "h1", text: "Welcome" };
const p = { tag: "p", text: "Hello world" };

// Build the tree structure
tree.appendChild(html, head);
tree.appendChild(html, body);
tree.appendChild(head, title);
tree.appendChild(body, h1);
tree.appendChild(body, p);

console.log(tree.firstChild(html) === head); // true
console.log(tree.lastChild(body) === p); // true

Manipulating Tree Structure

const tree = new SymbolTree();

const parent = { name: "parent" };
const child1 = { name: "child1" };
const child2 = { name: "child2" };
const child3 = { name: "child3" };

// Add children in order
tree.appendChild(parent, child2);
tree.prependChild(parent, child1); // child1 is now first
tree.insertAfter(child2, child3);  // child3 comes after child2

// Final order: child1 -> child2 -> child3
let current = tree.firstChild(parent);
while (current) {
  console.log(current.name);
  current = tree.nextSibling(current);
}
// Output: child1, child2, child3

// Rearrange - move child3 to the beginning
tree.remove(child3);
tree.prependChild(parent, child3);

// New order: child3 -> child1 -> child2

Building Linked Lists

const tree = new SymbolTree();

// Create nodes
const nodes = [
  { id: 1, value: "first" },
  { id: 2, value: "second" },
  { id: 3, value: "third" },
  { id: 4, value: "fourth" }
];

// Build linked list using insertAfter
let current = nodes[0];
for (let i = 1; i < nodes.length; i++) {
  tree.insertAfter(current, nodes[i]);
  current = nodes[i];
}

// Or build using insertBefore
const moreNodes = [
  { id: 5, value: "fifth" },
  { id: 6, value: "sixth" }
];

tree.insertBefore(nodes[0], moreNodes[1]); // sixth -> first -> ...
tree.insertBefore(moreNodes[1], moreNodes[0]); // fifth -> sixth -> first -> ...

Dynamic Tree Operations

const tree = new SymbolTree();

function createNode(name, children = []) {
  const node = { name };
  
  for (const childName of children) {
    const child = createNode(childName);
    tree.appendChild(node, child);
  }
  
  return node;
}

// Create initial tree
const root = createNode("root", ["branch1", "branch2"]);

// Add more nodes dynamically
const newBranch = createNode("branch3", ["leaf1", "leaf2"]);
tree.appendChild(root, newBranch);

// Insert between existing branches
const middleBranch = createNode("branch1.5");
const branch2 = tree.lastChild(tree.firstChild(root)); // Navigate to branch2
tree.insertBefore(branch2, middleBranch);

// Remove and reorganize
const branch1 = tree.firstChild(root);
tree.remove(branch1);
tree.prependChild(newBranch, branch1); // Move branch1 under branch3

Error Handling

All insertion methods will throw an Error if the object being inserted is already present in the tree:

const tree = new SymbolTree();
const parent = { name: "parent" };
const child = { name: "child" };

tree.appendChild(parent, child);

try {
  // This will throw an error
  tree.appendChild(parent, child);
} catch (error) {
  console.log(error.message); 
  // "Given object is already present in this SymbolTree, remove it first"
}

// To move an object, remove it first
tree.remove(child);
tree.prependChild(parent, child); // Now this works

Install with Tessl CLI

npx tessl i tessl/npm-symbol-tree

docs

array-conversion.md

index.md

tree-analysis.md

tree-construction.md

tree-iterators.md

tree-modification.md

tree-navigation.md

tree-traversal.md

tile.json