UNPKG

@wroud/navigation

Version:

A flexible, pattern-matching navigation system for JavaScript applications with built-in routing, browser integration, and navigation state management

213 lines 5.28 kB
export class LinkedList { get size() { return this.length; } get first() { return this.head?.value; } get last() { return this.tail?.value; } head = null; tail = null; length = 0; constructor(elements = []) { for (const element of elements) { this.push(element); } } setHead(head) { this.head = head; if (this.head) { this.head.back = null; } this.length = 0; this.tail = head; while (this.tail?.next) { this.tail.next.back = this.tail; this.tail = this.tail.next; this.length += 1; } } get(index) { if (index < 0 || index >= this.length) { return null; } let current = this.head; let i = 0; while (current && i < index) { current = current.next; i += 1; } return current?.value; } set(index, value) { this.assertIndexInBounds(index); let current = this.head; let i = 0; while (current && i < index) { current = current.next; i += 1; } if (current) { current.value = value; } } add(index, value) { this.assertIndexInBounds(index); if (index === 0) { this.head = { value, next: this.head, back: null }; if (this.head.next) { this.head.next.back = this.head; } this.length += 1; return; } if (index === this.length) { this.push(value); return; } let current = this.head; let i = 0; while (current && i < index - 1) { current = current.next; i += 1; } if (!current) { return; } const node = { value, next: current.next, back: current, }; current.next = node; if (node.next) { node.next.back = node; } this.length += 1; } push(value) { const node = { value, next: null, back: this.tail }; if (!this.head) { this.head = node; this.tail = node; } else { this.tail.next = node; this.tail = node; } this.length += 1; } remove(value) { let current = this.head; let previous = null; while (current) { if (current.value === value) { if (previous) { previous.next = current.next; } else { this.head = current.next; } if (current.next) { current.next.back = previous; } if (current === this.tail) { this.tail = previous; } this.length -= 1; return; } previous = current; current = current.next; } } removeFrom(index) { this.assertIndexInBounds(index); if (index === 0) { this.head = null; this.tail = null; this.length = 0; return; } let current = this.head; let i = 0; while (current && i < index - 1) { current = current.next; i += 1; } if (current) { current.next = null; this.tail = current; this.length = index; } } removeFirst() { if (!this.head) { return; } const value = this.head.value; this.head = this.head.next; if (this.head) { this.head.back = null; } else { this.tail = null; } this.length -= 1; return value; } removeLast() { if (!this.tail) { return; } const value = this.tail.value; this.tail = this.tail.back; if (this.tail) { this.tail.next = null; } else { this.head = null; } this.length -= 1; return value; } forEach(callback) { let current = this.head; while (current) { callback(current.value); current = current.next; } } /** * Serialize the linked list into a plain object. */ toJSON() { const head = this.head; if (!head) { return null; } let current = { ...head, back: null }; while (current.next) { current.next = { ...current.next, back: null }; current = current.next; } return head; } toArray() { const array = []; let current = this.head; while (current) { array.push(current.value); current = current.next; } return array; } assertIndexInBounds(index) { if (index < 0 || index >= this.length) { throw new Error("Index out of bounds"); } } } //# sourceMappingURL=LinkedList.js.map