@papit/html
v0.0.1
Published
a minimal html parser intended for node that exposes the core set of functionalities regular document DOM exposes
Downloads
206
Readme
@papit/html
A lightweight, deterministic HTML and DOM-like implementation for Node.js.
This library provides a minimal, predictable subset of the DOM focused on:
- Server-side HTML generation
- Tree-based manipulation
- Deterministic querying
- Zero browser globals
- No polyfills or environment magic
It is not a browser DOM and does not aim to be one.
Features
- ✅ Zero dependencies
- ✅ Small footprint
- ✅ DOM-inspired class hierarchy (
Node,Element,Text,Document,Comment) - ✅ Tree construction from HTML strings
- ✅
querySelector,querySelectorAll, andclosest - ✅ Attribute handling via
Map - ✅
classListvia a simplifiedDOMTokenList - ✅
NodeList/ read-only array-like traversal helpers - ✅
innerHTML/outerHTMLserialization - ✅ Deterministic, explicit behavior (no hidden browser magic)
- ✅ Explicit ownership via
ownerDocument
Core Concepts
Document as the Node Factory
All nodes should be created via Document.
const doc = new Document();
const el = doc.createElement("div");
const text = doc.createTextNode("Hello");
el.appendChild(text);⚠️ Nodes are expected to have an owning
Document. Constructing nodes manually may lead to missing ownership and broken tree relationships.
Nodes
Node
Base class for all nodes.
Properties:
parentNodechildNodestextContentnodeTypeownerDocument
Node extends EventTarget.
Text
Represents text nodes.
const text = doc.createTextNode("Hello");nodeType === Node.TEXT_NODEtextContentalways returns a string
Element
Represents HTML elements.
const el = doc.createElement("div", {
attributes: { id: "main" },
className: "foo bar",
});Properties:
tagNameattributes: Map<string, string | true>classNameclassListchildren
Methods:
appendChildremoveChildclosestquerySelectorquerySelectorAll
HTMLElement
class HTMLElement<T = string> extends Element {}HTMLElement<T> currently behaves the same as Element and exists
to enable future specialization and typing improvements.
NodeList
childNodes and children return a read-only, array-like NodeList.
Supported methods:
forEachentrieskeysvaluesitem(index)
The list itself cannot be mutated, but the nodes inside it can.
classList
classList behaves like a simplified DOMTokenList.
Supported methods:
addremovetogglecontains
Changes are reflected in className.
HTML Serialization
innerHTML
- Serializes child nodes
- Setting it rebuilds the subtree
el.innerHTML = "<span>Hello</span>";outerHTML
- Serializes the node including its own tag
- Produces valid HTML strings
Document.outerHTML serializes the document’s child nodes.
Querying
Limited, deterministic selector support:
- Tag selectors:
div - Class selectors:
.foo - Attribute selectors:
[id=main] - Text selectors:
{Hello} - Combined selectors:
div.foo[id=bar]{Hello} - Descendant and child combinators:
,>
The sibling (
+) combinator is parsed but currently treated as a descendant. Proper sibling matching may be implemented in a future release.
This is not CSS-complete by design.
Why not jsdom?
@papit/html intentionally solves a different problem.
jsdom
- Full browser DOM emulation
- Heavy
- Environment-dependent
- Complex edge cases
- Slow for simple HTML tasks
@papit/html
Deterministic
Lightweight
Explicit tree ownership
No browser assumptions
Ideal for:
- Build tools
- Static HTML generation
- Controlled DOM manipulation
- Testing
If you need browser fidelity — use jsdom.
If you need control and predictability — use @papit/html.
License
Licensed under the @Papit License 1.0 Copyright (c) 2024 Henry Pap (@onkelhoy)
Summary:
- ✅ Free for commercial use
- ✅ Free to modify and distribute
- ✅ Attribution required
- ❌ Cannot resell as a standalone product
See the LICENSE file for full details.
