LinkeDOM
A fast, triple-linked-list DOM implementation for Node.js and Workers
Repository Health
Technical Analysis
LinkeDOM is a DOM-like implementation designed for environments without a browser, such as Node.js, Deno, and Web/Service Workers. Instead of building the tree on arrays or object references the way JSDOM does, it links every node to its neighbors in a triple-linked list, which keeps mutations cheap and avoids the recursion-heavy operations that cause stack overflows or out-of-memory crashes on very large documents.
It exposes a DOMParser and a convenience parseHTML helper that return a close-to-standard document, window, and DOM classes (HTMLElement, Event, CustomEvent, and more) without polluting global scope, along with CSS-selector querying via css-select and an HTML/XML/SVG parser built on htmlparser2. It’s commonly reached for as a lighter, faster drop-in for JSDOM in server-side rendering, static site generation, HTML scraping/transformation, and testing scenarios where full browser-spec compliance isn’t required.
What You Get
- A
DOMParser/parseHTMLAPI that parses HTML, XML, or SVG into adocumentwithquerySelector/querySelectorAll(CSS selectors viacss-select) - Non-global DOM classes (
HTMLElement,Event,CustomEvent,EventTarget,NodeList,NodeFilter) reachable viadocument.defaultViewor theparseHTMLreturn value - Working Custom Elements support, including
connectedCallbackand builtin-extends patterns - A
linkedom/cachedvariant that memoizeschildNodes/children/query results for read-heavy, rarely-mutated documents - A
linkedom/workerexport for Deno, Web Workers, and Service Workers that drops the optionalcanvasdependency - Fast structural JSON serialization/deserialization of whole documents via
toJSON/parseJSON(backed by the JSDON format)
Common Use Cases
- Server-side rendering and static site generation where a full JSDOM instance is too slow or memory-hungry
- Scraping and transforming HTML/XML/SVG documents in a Node.js script or serverless function
- Unit testing DOM-dependent code without spinning up a headless browser
- Rendering or diffing large HTML documents (tens of thousands of nodes) where JSDOM’s array-based tree causes call-stack or memory errors
Under The Hood
Architecture — Parsing enters through esm/dom/parser.js’s DOMParser, which dispatches by MIME type to an HTMLDocument, SVGDocument, or XMLDocument (each in its own esm/html, esm/svg, esm/xml subtree) and hands markup to shared/parse-from-string.js, which streams tokens from htmlparser2 and builds nodes directly onto the triple-linked structure rather than an intermediate array-backed tree. Every node (esm/interface/node.js) carries direct pointers to its previous/next sibling and parent; elements (esm/interface/element.js) are represented as a linked start/end pair so a whole subtree can be excised or spliced by rewiring a handful of pointers instead of copying arrays. CSS-selector matching is delegated to the css-select package via shared/matches.js, and the top-level esm/index.js assembles the public surface (DOMParser, parseHTML, Document, event classes) without ever touching globalThis. A parallel linkedom/cached entry point wraps the same node classes with memoized childNodes/children/query caches for read-heavy workloads, and worker.js is a bundled, canvas-free build for Deno/Worker runtimes.
Tech Stack — Pure JavaScript (ESM, "type": "module" in package.json) with a generated CommonJS build (cjs/) produced via ascjs. Runtime dependencies are narrowly scoped: htmlparser2 for tokenizing HTML/XML, css-select for selector matching, cssom for inline style parsing, html-escaper and uhyphen for small serialization helpers. canvas is an optional peer dependency used only for <canvas> element support. Types are hand-authored under types/ (not the same install as source) and the build pipeline (tsc, rollup, ascjs) is orchestrated through npm scripts rather than a bundler config file. Requires Node.js >= 16.
Code Quality — The test suite (test/index.js) is substantial: it runs every module under test/xml, test/svg, test/html, test/interface, and test/shared twice — once against the standard build and once with global[Symbol.for('linkedom')] swapped to the cached variant — piped through c8 for coverage and eslint as a pre-test gate. There’s no assertion-library abstraction; tests use Node’s built-in assert, keeping the dependency surface minimal. Source files are small and single-purpose (most interface files are under 200 lines), naming closely mirrors the DOM spec (Node, Element, CharacterData), and JSDoc @implements/@typedef annotations back the hand-written .d.ts files instead of being TypeScript-authored directly.
API Design — The public API is intentionally small and spec-shaped: new DOMParser().parseFromString(html, mimeType) mirrors the browser standard, and parseHTML(html) is a documented shortcut that returns a pseudo-window object for callers who just want document/window without the two-step dance. Because classes are returned per-parse via defaultView rather than attached to globalThis, there’s a small extra step (destructure from the parse result) compared to JSDOM’s global-patching pattern, which the README explains explicitly with a function JSDOM(html) { return parseHTML(html); } drop-in shim. The README’s FAQ section proactively documents behavioral gaps (e.g., no live NodeList/HTMLCollection) so callers aren’t surprised by spec deviations.
Used by 14 apps in this directory
Omnivore
Bookmarks Archiving · Knowledge Management · Note Taking
Self-hosted read-it-later platform with highlights, newsletters, PDFs, and seamless Obsidian and Logseq integration.
OpenClaw
AI Agents · AI Assistants
An open-source AI assistant that runs on your own hardware and meets you in Discord, Slack, WhatsApp, iMessage, Telegram, and 20+ other channels, with native apps for every major platform.
reader
Data Engineering · Developer Tools
Production-grade open source web scraping engine that turns any URL into clean markdown for AI agents — with built-in anti-bot bypass, proxy rotation, and browser session management.
SurfSense
AI Assistants · Search
The open-source, unlimited NotebookLM alternative with real-time collaboration, a desktop app, and no vendor lock-in.
understudy
AI Agents · Automation
Open-source local AI agent that operates your entire computer — GUI, browser, shell, and messaging — from a single instruction, using your own models.