{"id":13084,"library":"domino","title":"Domino: Server-side DOM Implementation","description":"Domino provides a lightweight, server-side implementation of the Document Object Model (DOM) for Node.js, currently at version 2.1.7. Its primary goal is to enable server-side rendering and manipulation of HTML structures without the overhead of a full browser engine. It prioritizes performance and simplicity over strict compliance with the latest DOM specifications or script execution. Domino adheres to DOM Level 4, meaning certain modern browser APIs and behaviors (like Attributes inheriting Node) are not present. It explicitly does not execute scripts or download external resources, making it unsuitable for scraping pages that rely heavily on client-side JavaScript. The library offers both a standard `createWindow` / `createDocument` API and an incremental HTML parser for streaming input. It differentiates itself from alternatives like `jsdom` by not aiming to run untrusted code, avoiding proxy facades and leading to a more performant internal structure, especially for tree modification if `Node#childNodes` is avoided.","status":"active","version":"2.1.7","language":"javascript","source_language":"en","source_url":"https://github.com/fgnass/domino","tags":["javascript","typescript"],"install":[{"cmd":"npm install domino","lang":"bash","label":"npm"},{"cmd":"yarn add domino","lang":"bash","label":"yarn"},{"cmd":"pnpm add domino","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While CommonJS `require` is shown in the README, modern TypeScript/ESM usage prefers named or wildcard imports. The library ships types.","wrong":"const domino = require('domino');","symbol":"domino","correct":"import * as domino from 'domino';"},{"note":"One of the primary entry points for creating a new DOM environment, allowing a base URL to be specified.","wrong":"const window = domino.createWindow(...);","symbol":"createWindow","correct":"import { createWindow } from 'domino';"},{"note":"An alternative, more direct way to create a Document object without an associated Window.","wrong":"const document = domino.createDocument(...);","symbol":"createDocument","correct":"import { createDocument } from 'domino';"},{"note":"Specific DOM interfaces like `Element` are exposed via the `impl` namespace within the main domino export, not as direct named exports from the root module.","wrong":"import { Element } from 'domino';","symbol":"Element","correct":"import { impl } from 'domino'; const { Element } = impl;"}],"quickstart":{"code":"import { createWindow, impl } from 'domino';\n\nconst { Element } = impl;\n\n// Create a new window and document with initial HTML content\nconst window = createWindow('<h1>Hello domino world</h1><p id=\"msg\">This is a server-side DOM.</p>', 'http://example.com');\nconst document = window.document;\n\n// Query elements using standard DOM APIs\nconst h1 = document.querySelector('h1');\nconst messageParagraph = document.getElementById('msg');\n\nconsole.log(`H1 content: ${h1?.innerHTML}`);\nconsole.log(`Paragraph text: ${messageParagraph?.textContent}`);\n\n// Verify element instance\nif (h1 instanceof Element) {\n  console.log('h1 is an instance of Element.');\n}\n\n// Manipulate the DOM\nconst newParagraph = document.createElement('p');\nnewParagraph.textContent = 'This paragraph was added dynamically.';\ndocument.body.appendChild(newParagraph);\n\nconsole.log('\\nDocument after modification:');\nconsole.log(document.body.outerHTML);\n","lang":"typescript","description":"Demonstrates creating a DOM window/document, querying elements, verifying element types, and basic DOM manipulation."},"warnings":[{"fix":"To use array methods, convert `element.attributes` to an array first: `Array.from(element.attributes).map(...)` or `[...element.attributes].forEach(...)`.","message":"The `Element.attributes` property is not a true JavaScript array; it's an object with `length` and `item(n)` methods, and indexed access (`[i]`), but lacks full array prototype methods like `map` or `forEach`. Direct iteration might require conversion to an array.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Do not rely on client-side script execution or external resource loading. For dynamic content, manipulate the DOM programmatically. For resource fetching, handle it externally before injecting content.","message":"Domino is designed for 'building' pages, not scraping. It does not execute scripts (e.g., `<script>` tags) and does not download external resources (e.g., images, stylesheets, external scripts).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Consult MDN's DOM Level 4 documentation for API compatibility. If you require full HTML5 compliance or newer DOM APIs, consider libraries like `jsdom`.","message":"Domino strictly adheres to DOM Level 4. This means certain modern HTML5 DOM features and behaviors, such as `Attribute` nodes inheriting from `Node`, or deprecated HTML5 properties, are not implemented.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Refactor DOM modification logic to avoid repeated access to `Node#childNodes` if performance is critical for large trees or frequent changes.","message":"For optimal performance during tree modification (inserting/removing children), it is recommended to traverse the DOM using `Node#firstChild`, `Node#nextSibling`, `Node#lastChild`, or `Node#previousSibling` rather than repeatedly accessing `Node#childNodes`.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Convert `element.attributes` to an array before using array methods: `Array.from(element.attributes).map(...)` or `[...element.attributes].forEach(...)`.","cause":"Attempting to use array prototype methods directly on `Element.attributes`, which is an array-like object but not a true JavaScript array.","error":"TypeError: element.attributes.map is not a function"},{"fix":"Always create a `domino` `window` or `document` instance explicitly using `createWindow()` or `createDocument()`, then access the document via `window.document` or the returned `document` object.","cause":"Attempting to access the global `document` object in a Node.js environment without creating a `domino` document first.","error":"ReferenceError: document is not defined"},{"fix":"Client-side scripts are not supported. Any dynamic behavior must be implemented programmatically using Domino's DOM manipulation APIs in your Node.js code, or by pre-rendering the final HTML.","cause":"Domino explicitly does not execute JavaScript code embedded in the parsed HTML content, as it prioritizes performance and server-side rendering without browser engine overhead.","error":"Scripts embedded in HTML are not executing as expected."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}