1
1
Fork
You've already forked zeed-dom
0
🌱 Lightweight offline DOM
  • HTML 99.5%
  • TypeScript 0.5%
Find a file
2026年05月04日 11:47:47 +02:00
.github Github releases 2023年12月04日 14:43:50 +01:00
.vscode fix: eslint 2024年08月29日 21:57:31 +02:00
docs fix: tests, docs, eslint 2023年12月16日 18:31:43 +01:00
examples fix: sample 2023年12月16日 18:23:03 +01:00
files fix: tests 2025年07月19日 23:45:07 +02:00
jsx-runtime fix: again fixing jsx types 2024年05月16日 15:30:15 +02:00
src markdown tweak options 2026年05月04日 11:47:28 +02:00
test profile 2025年07月20日 11:27:41 +02:00
.editorconfig Initial 2021年07月20日 10:50:45 +02:00
.gitignore profile 2025年07月20日 11:27:41 +02:00
env.d.ts fix: again fixing jsx types 2024年05月16日 15:30:15 +02:00
eslint.config.js feat: ai improve css selectors 2025年07月18日 11:33:09 +02:00
LICENSE added message for @types/react and JSX 2024年03月11日 09:46:08 +01:00
package.json 0.18.0 2026年05月04日 11:47:47 +02:00
README.md markdown tweak options 2026年05月04日 11:47:28 +02:00
SECURITY.md Add security info 2021年10月25日 10:55:39 +02:00
tsconfig.json feat: Generate docs 2023年12月16日 18:18:44 +01:00
vitest.config.ts fix: vitest 2023年12月15日 13:18:20 +01:00

🌱 zeed-dom

A modern, lightweight, TypeScript virtual DOM for Node.js, browser, and static content generation.


  • Fast: Efficient HTML parsing and serialization
  • 🧩 JSX Compatible: Works seamlessly with JSX/TSX
  • 🔍 CSS Selectors: Query with a subset of CSS selectors
  • 🛠 Easy Manipulation: Chainable API, .handle() helper, and more
  • 📝 HTML, XML, Markdown, Plaintext: Serialize to multiple formats
  • 🧹 Pretty Print: Tidy up HTML with tidyDOM
  • 🦾 TypeScript: Full typings, modern codebase
  • 🔒 Safe HTML: Output sanitized HTML for user content

Note: This project does not aim for full browser DOM completeness, but covers most practical use cases for static content, SSR, and offline DOM manipulation.


🚀 Get Started

npm i zeed-dom
  • zeed – Foundation library
  • zerva – Event-driven server

Features

  • Virtual DOM tree with VNode, VElement, VDocument, etc.
  • HTML parsing and serialization
  • XML output support
  • CSS selector engine (subset)
  • JSX/TSX support (see below)
  • Safe HTML serialization (serializeSafeHTML)
  • Markdown and plaintext serialization
  • Manipulation helpers: .handle(), .replaceWith(), .remove(), etc.
  • Works in Node.js, browser, and serverless
  • Pretty print HTML (tidyDOM)
  • TypeScript-first API

🛠 Usage Examples

Manipulation

Drop in HTML, query, and change it. Returns HTML again. Great for post-processing:

import { handleHTML } from 'zeed-dom'
const newHTML = handleHTML(html, (document) => {
 const img = document.querySelector('.img-wrapper img')
 if (img)
 img.setAttribute('title', img.getAttribute('src'))
})

Serialization

Take any HTML node or document and serialize it to another format:

  • serializePlaintext(node): Readable and searchable plain text
  • serializeMarkdown(node, options?): Simple Markdown. Options:
    • wrap: column to soft-wrap long lines at (e.g. 80); 0 or omitted disables wrapping. Code fences and table rows are not wrapped, and list-item continuations keep the proper indent.
    • linkStyle: how <a href="...">...</a> and <img src="..." alt="..."> are rendered. 'inline' (default) → [text](url) / ![alt](src), 'autolink'text <url> / alt <src> (or just <url> / <src> when the label is empty or equals the URL).
    • inlineStyles: when false, strips inline text-styling tags (b, strong, i, em, u, mark, tt, code, strike, del, ins, sub, sup) and emits their content as plain text. Default true.
  • serializeSafeHTML(node) or safeHTML(htmlString): Allow only basic tags and attributes

Virtual DOM Example (no JSX)

import { h, xml } from 'zeed-dom'
const dom = h(
 'ol',
 { class: 'projects' },
 [
 h('li', null, 'zeed ', h('img', { src: 'logo.png' })),
 h('li', null, 'zeed-dom'),
 ]
)
console.log(dom.render())
// <ol class="projects"><li>zeed <img src="logo.png"></li><li>zeed-dom</li></ol>

console.log(dom.render(xml))
// <ol class="projects"><li>zeed <img src="logo.png" /></li><li>zeed-dom</li></ol>

JSX Example

import { h } from 'zeed-dom'
let dom = (
 <ol className="projects">
 <li>zeed</li>
 <li>zeed-dom</li>
 </ol>
)
dom.handle('li', (e) => {
 if (!e.textContent.endsWith('-dom')) {
 e.remove()
 } else {
 e.innerHTML = '<b>zeed-dom</b> - great DOM helper for static content'
 }
})
console.log(dom.render())
// <ol class="projects"><li><b>zeed-dom</b> - great DOM helper for static content</li></ol>

HTML Parsing & Tidy

import { tidyDOM, vdom } from 'zeed-dom'
const dom = vdom('<div>Hello World</div>')
tidyDOM(dom)
console.log(dom.render())
// Output is pretty printed like:
// <div>
// Hello World
// </div>

⚛️ JSX Setup

JSX is supported out of the box. For TypeScript, add to your tsconfig.json:

{
 "compilerOptions": {
 "jsx": "react",
 "jsxFactory": "h"
 }
}

Add this to your shims.d.ts:

// https://www.typescriptlang.org/docs/handbook/jsx.html#intrinsic-elements
declare namespace JSX {
 interface IntrinsicElements {
 [elemName: string]: any
 }
}

For ESBuild:

{
 jsxFactory: 'h'
}

Or as a CLI option: --jsx-factory=h

For browser DOM:

const { hFactory } = require('zeed-dom')
export const h = hFactory({ document })

🧪 API Highlights

  • vdom(htmlString): Parse HTML to virtual DOM
  • tidyDOM(node): Pretty print/format DOM
  • serializeSafeHTML(node): Output safe HTML
  • serializeMarkdown(node): Output Markdown
  • serializePlaintext(node): Output plain text
  • handleHTML(html, fn): Manipulate HTML with a callback
  • VElement, VNode, VDocument, etc.: Core classes
  • .handle(selector, fn): Manipulate elements by selector
  • .querySelector, .querySelectorAll: CSS selector queries
  • .replaceWith(), .remove(), .setAttribute(), etc.: DOM-like methods

🚦 Performance

The parser is fast, as shown in htmlparser-benchmark


📝 Misc

  • Use double underscore in JSX for namespaces: <xhtml__link /><xhtml:link />
  • Use CDATA helper for raw data: <div>{CDATA(yourRawData)}</div>
  • style attributes can be objects: <span style={{backgroundColor: 'red'}} /><span style="background-color: red" />
  • Works in Node.js, browser, and serverless
  • TypeScript-first, but works with plain JS too