You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Lightweight virtual / offline DOM (Document Object Model)
4
-
- Great to use in node or exporting to plain strings
5
-
- Written in Typescript
6
-
- Generates HTML and XML
7
-
- Parses HTML
8
-
- Supports some CSS selectors and queries
9
-
- JSX compatible
10
-
- Easy content manipulation (e.g. through `element.handle` helper)
11
-
- Pretty print HTML (`tidyDOM`)
3
+
> **A modern, lightweight, TypeScript virtual DOM for Node.js, browser, and static content generation.**
4
+
5
+
---
6
+
7
+
- ⚡️ **Fast**: Efficient HTML parsing and serialization
8
+
- 🧩 **JSX Compatible**: Works seamlessly with JSX/TSX
9
+
- 🔍 **CSS Selectors**: Query with a subset of CSS selectors
10
+
- 🛠 **Easy Manipulation**: Chainable API, `.handle()` helper, and more
11
+
- 📝 **HTML, XML, Markdown, Plaintext**: Serialize to multiple formats
12
+
- 🧹 **Pretty Print**: Tidy up HTML with `tidyDOM`
13
+
- 🦾 **TypeScript**: Full typings, modern codebase
14
+
- 🔒 **Safe HTML**: Output sanitized HTML for user content
15
+
16
+
**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.
12
17
13
-
**Does not aim for completeness!**
18
+
---
14
19
15
-
## Get started
20
+
## 🚀 Get Started
16
21
17
22
```sh
18
23
npm i zeed-dom
19
24
```
20
25
21
-
## Related projects
26
+
## 🔗 Related Projects
22
27
23
-
-[zeed](https://github.com/holtwick/zeed) - Foundation library
24
-
-[zerva](https://github.com/holtwick/zerva) - Event driven server
25
-
-[hostic](https://github.com/holtwick/hostic) - Static site generator
28
+
-[zeed](https://github.com/holtwick/zeed) – Foundation library
29
+
-[zerva](https://github.com/holtwick/zerva) – Event-driven server
26
30
27
-
Used by [TipTap](https://www.tiptap.dev/) in its [html-package](https://github.com/ueberdosis/tiptap/tree/aac0193050228a8b6237d84f1eb587cfc0d08e24/packages/html).
31
+
> **Used by [TipTap](https://www.tiptap.dev/) in its [html-package](https://github.com/ueberdosis/tiptap/tree/main/packages/html).**
32
+
33
+
---
34
+
35
+
## ✨ Features
36
+
37
+
- Virtual DOM tree with `VNode`, `VElement`, `VDocument`, etc.
38
+
- HTML parsing and serialization
39
+
- XML output support
40
+
- CSS selector engine (subset)
41
+
- JSX/TSX support (see below)
42
+
- Safe HTML serialization (`serializeSafeHTML`)
43
+
- Markdown and plaintext serialization
44
+
- Manipulation helpers: `.handle()`, `.replaceWith()`, `.remove()`, etc.
45
+
- Works in Node.js, browser, and serverless
46
+
- Pretty print HTML (`tidyDOM`)
47
+
- TypeScript-first API
28
48
29
-
## Utils
49
+
---
50
+
51
+
## 🛠 Usage Examples
30
52
31
53
### Manipulation
32
54
33
-
Drop in HTML and query and change it. Returns HTML again. Nice for postprocessing.
55
+
Drop in HTML, query, and change it. Returns HTML again. Great for post-processing:
e.innerHTML="<b>zeed-dom</b> - great DOM helper for static content"
112
+
e.innerHTML='<b>zeed-dom</b> - great DOM helper for static content'
101
113
}
102
114
})
103
115
104
116
console.log(dom.render())
105
-
//Output: <ol class="projects"><li><b>zeed-dom</b> - great DOM helper for static content</li></ol>
117
+
// <ol class="projects"><li><b>zeed-dom</b> - great DOM helper for static content</li></ol>
106
118
```
107
119
108
-
In the second example you can see the special manipulation helper `.handle(selector, fn)` in action. You can also see HTML parsing works seamlessly. You can also parse directly:
120
+
### HTML Parsing & Tidy
109
121
110
122
```js
111
123
import { tidyDOM, vdom } from'zeed-dom'
112
124
113
125
constdom=vdom('<div>Hello World</div>')
114
126
tidyDOM(dom)
115
127
console.log(dom.render())
116
-
// Output is pretty printed like: <div>
128
+
// Output is pretty printed like:
129
+
// <div>
117
130
// Hello World
118
131
// </div>
119
132
```
120
133
121
-
These examples are available at [/example](/example).
122
-
123
-
## JSX
124
-
125
-
Usually JSX is optimized for React i.e. it expects `React.creatElement` to exist and be the factory for generating the nodes. You can of course get the same effect here if you set up a helper like this:
126
-
127
-
```js
128
-
import { html } from'zeed-dom'
129
-
130
-
constReact= {
131
-
createElement: html,
132
-
}
133
-
```
134
-
135
-
But more common is the use of `h` as the factory function. Here is how you can set up this behavior for various environments:
134
+
---
136
135
137
-
> In case of error messages on JSX in your Typescript project, try to add `npm install -D @types/react`.
138
-
136
+
## ⚛️ JSX Setup
139
137
140
-
### TypeScript
141
-
142
-
In [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/compiler-options-in-msbuild.html#mappings):
138
+
JSX is supported out of the box. For TypeScript, add to your `tsconfig.json`:
143
139
144
140
```json
145
141
{
@@ -150,7 +146,7 @@ In [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/compiler-optio
150
146
}
151
147
```
152
148
153
-
To avoid type checking issues you should add this to you`shims.d.ts`:
Or alternatively as [command line option](https://github.com/evanw/esbuild#command-line-usage): `--jsx-factory=h`
168
+
Or as a CLI option: `--jsx-factory=h`
175
169
176
-
### Browser DOM
177
-
178
-
The JSX factory can also be used to directly create HTML DOM nodes in the browser. Just create the `h` function and let it use the browser's `document` object:
170
+
For browser DOM:
179
171
180
172
```js
181
173
const { hFactory } =require('zeed-dom')
182
-
183
174
exportconsth=hFactory({ document })
184
175
```
185
176
186
-
## Performance
177
+
---
178
+
179
+
## 🧪 API Highlights
180
+
181
+
-`vdom(htmlString)`: Parse HTML to virtual DOM
182
+
-`tidyDOM(node)`: Pretty print/format DOM
183
+
-`serializeSafeHTML(node)`: Output safe HTML
184
+
-`serializeMarkdown(node)`: Output Markdown
185
+
-`serializePlaintext(node)`: Output plain text
186
+
-`handleHTML(html, fn)`: Manipulate HTML with a callback
The parser isn't doing too bad, according to the benchmarks of [htmlparser-benchmark](https://github.com/AndreasMadsen/htmlparser-benchmark/blob/master/stats.txt) ;)
192
+
---
193
+
194
+
## 🚦 Performance
195
+
196
+
The parser is fast, as shown in [htmlparser-benchmark](https://github.com/AndreasMadsen/htmlparser-benchmark/blob/master/stats.txt) (2025-07-19):
189
197
190
198
```
191
-
tl : 1.02699 ms/file ± 0.679139
192
-
htmlparser2 : 1.98505 ms/file ± 2.94434
193
-
node-html-parser : 2.24176 ms/file ± 1.52112
194
-
neutron-html5parser: 2.36648 ms/file ± 1.38879
195
-
html5parser : 2.39891 ms/file ± 2.83056
196
-
htmlparser2-dom : 2.57523 ms/file ± 3.35587
197
-
html-dom-parser : 2.84910 ms/file ± 3.61615
198
-
libxmljs : 3.81665 ms/file ± 2.79295
199
-
zeed-dom : 5.05130 ms/file ± 3.57184
200
-
htmljs-parser : 5.58557 ms/file ± 6.47597
201
-
parse5 : 9.07862 ms/file ± 6.50856
202
-
htmlparser : 21.2274 ms/file ± 150.951
203
-
html-parser : 30.9104 ms/file ± 24.3930
204
-
saxes : 49.5906 ms/file ± 141.194
205
-
html5 : 114.771 ms/file ± 148.345
199
+
htmljs-parser : 0.153576 ms/file ± 0.339639
200
+
tl : 0.344457 ms/file ± 0.209764
201
+
htmlparser2 : 0.543453 ms/file ± 0.438753
202
+
html5parser : 0.605998 ms/file ± 0.387632
203
+
neutron-html5parser: 0.606776 ms/file ± 0.324339
204
+
htmlparser2-dom : 0.713802 ms/file ± 0.551285
205
+
node-html-parser : 0.811724 ms/file ± 0.532164
206
+
zeed-dom : 1.09377 ms/file ± 0.595654
207
+
sax : 1.84714 ms/file ± 1.50359
208
+
parse5 : 1.99615 ms/file ± 1.36227
209
+
arijs-stream : 4.34379 ms/file ± 2.40653
210
+
arijs-tree : 4.68313 ms/file ± 2.57017
211
+
html5 : 4.81755 ms/file ± 3.35113
212
+
htmlparser : 7.98449 ms/file ± 57.5936
213
+
html-parser : 8.33241 ms/file ± 6.56205
214
+
saxes : 24.3492 ms/file ± 70.5843
206
215
```
207
216
208
-
## Misc
217
+
---
218
+
219
+
## 📝 Misc
209
220
210
-
- To set namespace colons in JSX use double underscore i.e. `<xhtml__link />` becomes `<xhtml:link />`
211
-
- To allow `CDATA` use the helper function e.g. `<div>{ CDATA(yourRawData) }</div>`
212
-
-`style` attributes can handle objects e.g. `<span style={{backgroundColor: 'red'}} />` becomes `<span style="background-color: red" />`
221
+
- Use double underscore in JSX for namespaces: `<xhtml__link />` → `<xhtml:link />`
222
+
- Use `CDATA` helper for raw data: `<div>{CDATA(yourRawData)}</div>`
223
+
-`style` attributes can be objects: `<span style={{backgroundColor: 'red'}} />` → `<span style="background-color: red" />`
0 commit comments