{"id":50902934,"url":"https://github.com/stacksjs/very-happy-dom","last_synced_at":"2026-06-16T04:31:26.503Z","repository":{"id":323601168,"uuid":"1093924052","full_name":"stacksjs/very-happy-dom","owner":"stacksjs","description":"A very performant virtual DOM implementation.","archived":false,"fork":false,"pushed_at":"2026-06-15T22:52:58.000Z","size":951,"stargazers_count":13,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-16T00:20:17.749Z","etag":null,"topics":["browser","bun","dom","happy-dom","jsdom","screenshot","typescript","virtual"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stacksjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["stacksjs","chrisbbreuer"],"open_collective":"stacksjs"}},"created_at":"2025-11-11T02:49:54.000Z","updated_at":"2026-06-10T11:51:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"8be330db-82bd-4e38-8db7-49b6f32ae7fc","html_url":"https://github.com/stacksjs/very-happy-dom","commit_stats":null,"previous_names":["stacksjs/very-happy-dom"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/stacksjs/very-happy-dom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacksjs%2Fvery-happy-dom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacksjs%2Fvery-happy-dom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacksjs%2Fvery-happy-dom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacksjs%2Fvery-happy-dom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stacksjs","download_url":"https://codeload.github.com/stacksjs/very-happy-dom/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacksjs%2Fvery-happy-dom/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34391702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","bun","dom","happy-dom","jsdom","screenshot","typescript","virtual"],"created_at":"2026-06-16T04:31:25.621Z","updated_at":"2026-06-16T04:31:26.498Z","avatar_url":"https://github.com/stacksjs.png","language":"TypeScript","funding_links":["https://github.com/sponsors/stacksjs","https://github.com/sponsors/chrisbbreuer","https://opencollective.com/stacksjs"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\".github/art/cover.jpg\" alt=\"Social Card of this repo\"\u003e\u003c/p\u003e\n\n[![npm version][npm-version-src]][npm-version-href]\n[![GitHub Actions][github-actions-src]][github-actions-href]\n[![Commitizen friendly][commitizen-src]][commitizen-href]\n\u003c!-- [![npm downloads][npm-downloads-src]][npm-downloads-href] --\u003e\n\u003c!-- [![Codecov][codecov-src]][codecov-href] --\u003e\n\n# very-happy-dom\n\nA blazingly fast, lightweight virtual DOM implementation powered by Bun. Drop-in replacement for happy-dom and jsdom in testing environments.\n\n## Features\n\n- **Comprehensive DOM** - Full DOM manipulation, CSS selectors, XPath, events with bubbling/capturing\n- **Network APIs** - Fetch, XMLHttpRequest, WebSocket, Server-Sent Events, BroadcastChannel, MessageChannel, request interception\n- **Browser APIs** - Storage, Timers, Canvas 2D, Observers (Mutation/Intersection/Resize/Performance), Clipboard, History, Cookies, File API, IndexedDB, Web Storage\n- **Web Components** - Custom Elements and Shadow DOM\n- **Framework Agnostic** - Works with Bun, Vitest, or any testing framework\n- **jsdom-compatible** - Real `JSDOM` class with `.serialize()`, `.reconfigure()`, `.fromURL()`, `.fromFile()`, `.fragment()`, `VirtualConsole`, `CookieJar`, `ResourceLoader`\n- **happy-dom-compatible** - Drop-in for `GlobalRegistrator`, `window.happyDOM` API, virtual consoles\n- **Screenshot** - Pure-JS PNG/JPEG/WebP rendering + optional `Bun.WebView` real-browser screenshots\n\n## Installation\n\n```bash\nbun add -d very-happy-dom\n```\n\nOr with npm/pnpm:\n\n```bash\nnpm install --save-dev very-happy-dom\npnpm add -D very-happy-dom\n```\n\n## Quick Start\n\n```typescript\nimport { Window } from 'very-happy-dom'\n\nconst window = new Window()\nconst document = window.document\n\ndocument.body.innerHTML = '\u003ch1\u003eHello World\u003c/h1\u003e'\nconst heading = document.querySelector('h1')\nconsole.log(heading?.textContent) // \"Hello World\"\n```\n\n### Testing with Bun\n\nThe simplest way — create a `Window` per test:\n\n```typescript\nimport { describe, expect, test } from 'bun:test'\nimport { Window } from 'very-happy-dom'\n\ndescribe('MyComponent', () =\u003e {\n  test('renders correctly', () =\u003e {\n    const window = new Window()\n    const document = window.document\n\n    document.body.innerHTML = '\u003cdiv class=\"container\"\u003eTest\u003c/div\u003e'\n    const element = document.querySelector('.container')\n\n    expect(element?.textContent).toBe('Test')\n  })\n})\n```\n\n### Global DOM Environment\n\nFor Testing Library, React, and other frameworks that expect browser globals (`document`, `window`, etc.), either use the one-line preload subpath or call `GlobalRegistrator` manually.\n\n**Easiest — the `/register` subpath:**\n\n```toml\n# bunfig.toml\n[test]\npreload = [\"very-happy-dom/register\"]\n```\n\nYou can override the URL with `VERY_HAPPY_DOM_URL` or `HAPPY_DOM_URL` env vars.\n\n**Manual — drop-in for `@happy-dom/global-registrator`:**\n\n```typescript\n// happy-dom.ts (preload script)\nimport { GlobalRegistrator } from 'very-happy-dom'\n\nGlobalRegistrator.register()\n```\n\n```toml\n# bunfig.toml\n[test]\npreload = [\"./happy-dom.ts\"]\n```\n\nThat's it. All browser globals are now available in your tests:\n\n```typescript\nimport { test, expect } from 'bun:test'\nimport { screen, render } from '@testing-library/react'\nimport { MyComponent } from './MyComponent'\n\ntest('renders correctly', () =\u003e {\n  render(\u003cMyComponent /\u003e)\n  expect(screen.getByTestId('my-component')).toBeInTheDocument()\n})\n```\n\n### Migrating from happy-dom\n\nOne-line change — the `GlobalRegistrator` API is the same:\n\n```diff\n-import { GlobalRegistrator } from '@happy-dom/global-registrator'\n+import { GlobalRegistrator } from 'very-happy-dom'\n\nGlobalRegistrator.register()\n```\n\n## Advanced Usage\n\n### Browser Context\n\n```typescript\nimport { Browser } from 'very-happy-dom'\n\nconst browser = new Browser()\nconst context = browser.createContext()\nconst page = context.newPage()\n\npage.goto('https://example.com')\n```\n\n### Request Interception\n\n```typescript\nimport { Window } from 'very-happy-dom'\n\nconst window = new Window()\n\nwindow.interceptor.addInterceptor({\n  onRequest: (request) =\u003e {\n    if (request.url.includes('/api/')) {\n      return new Response(JSON.stringify({ mocked: true }))\n    }\n    return request\n  }\n})\n```\n\n### Custom Window Configuration\n\n```typescript\nimport { Window } from 'very-happy-dom'\n\nconst window = new Window({\n  url: 'https://example.com',\n  width: 1920,\n  height: 1080,\n  settings: {\n    navigator: {\n      userAgent: 'MyCustomUserAgent/1.0'\n    },\n    device: {\n      prefersColorScheme: 'dark'\n    }\n  }\n})\n```\n\n### Event Handling\n\n```typescript\nconst window = new Window()\nconst document = window.document\n\nconst button = document.createElement('button')\nlet clicked = false\n\nbutton.addEventListener('click', () =\u003e {\n  clicked = true\n})\n\nbutton.click()\nconsole.log(clicked) // true\n```\n\n### Storage APIs\n\n```typescript\nconst window = new Window()\n\n// localStorage\nwindow.localStorage.setItem('key', 'value')\nconsole.log(window.localStorage.getItem('key')) // \"value\"\n\n// sessionStorage\nwindow.sessionStorage.setItem('session', 'data')\n```\n\n### Observers\n\n```typescript\nconst window = new Window()\nconst document = window.document\n\n// MutationObserver\nconst observer = new window.MutationObserver((mutations) =\u003e {\n  mutations.forEach((mutation) =\u003e {\n    console.log('DOM changed:', mutation.type)\n  })\n})\n\nobserver.observe(document.body, {\n  childList: true,\n  attributes: true,\n  subtree: true\n})\n\n// IntersectionObserver\nconst io = new window.IntersectionObserver((entries) =\u003e {\n  entries.forEach((entry) =\u003e {\n    console.log('Visibility changed:', entry.isIntersecting)\n  })\n})\n\n// ResizeObserver\nconst ro = new window.ResizeObserver((entries) =\u003e {\n  entries.forEach((entry) =\u003e {\n    console.log('Size changed:', entry.contentRect)\n  })\n})\n```\n\n### Canvas API\n\n```typescript\nconst window = new Window()\nconst document = window.document\n\nconst canvas = document.createElement('canvas')\nconst ctx = canvas.getContext('2d')\n\nctx.fillStyle = 'red'\nctx.fillRect(0, 0, 100, 100)\nctx.strokeStyle = 'blue'\nctx.strokeRect(10, 10, 80, 80)\n\n// Export canvas data\nconst dataUrl = canvas.toDataURL()\nconst blob = await canvas.toBlob()\n```\n\n## Performance\n\n### vs happy-dom vs jsdom\n\n| Operation | very-happy-dom | happy-dom | jsdom | Faster\u0026nbsp;by |\n|---|---|---|---|---|\n| Window\u0026nbsp;Creation | **4.08\u0026nbsp;µs** | 92.83\u0026nbsp;µs | 1.22\u0026nbsp;ms | 22.7x |\n| createElement | **463.02\u0026nbsp;ns** | 2.62\u0026nbsp;µs | 4.67\u0026nbsp;µs | 5.7x |\n| createElement\u0026nbsp;+\u0026nbsp;setAttribute | **748.35\u0026nbsp;ns** | 15.41\u0026nbsp;µs | 6.62\u0026nbsp;µs | 8.8x |\n| innerHTML\u0026nbsp;(medium) | **41.61\u0026nbsp;µs** | 47.48\u0026nbsp;µs | 168.98\u0026nbsp;µs | 1.1x |\n| innerHTML\u0026nbsp;(large,\u0026nbsp;200\u0026nbsp;nodes) | **1.92\u0026nbsp;ms** | 3.72\u0026nbsp;ms | 6.27\u0026nbsp;ms | 1.9x |\n| querySelector\u0026nbsp;by\u0026nbsp;ID | **81.03\u0026nbsp;ns** | n/a | 2.76\u0026nbsp;µs | 34.1x |\n| querySelector\u0026nbsp;by\u0026nbsp;class | **242.20\u0026nbsp;ns** | n/a | 3.52\u0026nbsp;µs | 14.5x |\n| querySelectorAll\u0026nbsp;(200\u0026nbsp;matches) | **66.44\u0026nbsp;µs** | n/a | 66.55\u0026nbsp;µs | ~1x |\n| querySelectorAll\u0026nbsp;+\u0026nbsp;iteration | **76.44\u0026nbsp;µs** | n/a | 170.37\u0026nbsp;µs | 2.2x |\n| appendChild\u0026nbsp;(single) | **1.70\u0026nbsp;µs** | 4.58\u0026nbsp;µs | 6.14\u0026nbsp;µs | 2.7x |\n| appendChild\u0026nbsp;(1000\u0026nbsp;children) | **852.90\u0026nbsp;µs** | 1.54\u0026nbsp;ms | 4.45\u0026nbsp;ms | 1.8x |\n| setAttribute | **124.66\u0026nbsp;ns** | 2.64\u0026nbsp;µs | 1.43\u0026nbsp;µs | 11.5x |\n| getAttribute | **2.18\u0026nbsp;ns** | 28.85\u0026nbsp;ns | 194.98\u0026nbsp;ns | 13.2x |\n| classList.add | **3.97\u0026nbsp;µs** | 6.88\u0026nbsp;µs | 4.87\u0026nbsp;µs | 1.2x |\n| addEventListener\u0026nbsp;+\u0026nbsp;dispatch | **2.67\u0026nbsp;µs** | 5.43\u0026nbsp;µs | 3.65\u0026nbsp;µs | 1.4x |\n| textContent\u0026nbsp;set | **470.48\u0026nbsp;ns** | 1.72\u0026nbsp;µs | 4.67\u0026nbsp;µs | 3.7x |\n| cloneNode\u0026nbsp;(deep) | **6.16\u0026nbsp;µs** | 21.59\u0026nbsp;µs | 15.55\u0026nbsp;µs | 2.5x |\n| style.setProperty | **490.62\u0026nbsp;ns** | 4.20\u0026nbsp;µs | 4.64\u0026nbsp;µs | 8.6x |\n| Build\u0026nbsp;data\u0026nbsp;table\u0026nbsp;(50x5) | **519.30\u0026nbsp;µs** | 754.42\u0026nbsp;µs | 2.89\u0026nbsp;ms | 1.5x |\n| Update\u0026nbsp;list\u0026nbsp;items\u0026nbsp;(100) | **454.98\u0026nbsp;µs** | n/a | 2.41\u0026nbsp;ms | 5.3x |\n\n\u003e **Note:** \"Faster by\" compares very-happy-dom to the next-fastest result. Benchmarks run on Apple M3 Pro with Bun 1.3.11. Run them yourself:\n\n```bash\nbun run bench\n```\n\n## Migration\n\n### From happy-dom\n\nOne-line change — the API is compatible:\n\n```typescript\n// Before\nimport { Window } from 'happy-dom'\n\n// After\nimport { Window } from 'very-happy-dom'\n```\n\n### From jsdom\n\nvery-happy-dom ships a jsdom-compatible `JSDOM` class — the exact idiom works unchanged:\n\n```typescript\n// Before (jsdom)\nimport { JSDOM } from 'jsdom'\n\n// After (very-happy-dom) — one-line change\nimport { JSDOM } from 'very-happy-dom'\n// or: import { JSDOM } from 'very-happy-dom/jsdom'\n\nconst dom = new JSDOM('\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003cbody\u003e\u003ch1\u003eHi\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e', {\n  url: 'https://example.com/',\n  runScripts: 'dangerously',\n})\nconst { window } = dom\nconst { document } = window\n\ndom.serialize()                       // full HTML string\ndom.reconfigure({ url: '...' })       // change URL mid-test\nJSDOM.fragment('\u003cp\u003ex\u003c/p\u003e')            // DocumentFragment\nawait JSDOM.fromFile('./page.html')   // parse a local file\nawait JSDOM.fromURL('https://x.test') // fetch + parse\n```\n\nFull surface: `JSDOM`, `VirtualConsole`, `CookieJar`, `ResourceLoader` — each with the same method names and overloads as jsdom.\n\nSee the [drop-in compatibility guide][drop-in-compat-href] for the complete migration reference.\n\n## API Reference\n\n### Core Classes\n\n- **Window** - Main window/global object with all browser APIs\n- **Document** - DOM document with querySelector, createElement, etc.\n- **Element** - DOM elements with full manipulation API\n- **Browser** - Browser instance for advanced scenarios\n- **BrowserContext** - Isolated browser contexts\n- **BrowserPage** - Individual pages with navigation\n\n### Supported APIs\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand full API list\u003c/summary\u003e\n\n#### DOM\n\n- Document, Element, TextNode, CommentNode, DocumentFragment\n- Attributes, ClassList (iterable, `toggle(x, force)`, `replace`), Style, dataset\n- `innerHTML`, `outerHTML` (getter + setter), `insertAdjacentHTML`\n- `document.readyState` lifecycle (loading → interactive → complete) + `DOMContentLoaded` + `load`\n- `document.cookie` read/write, `document.title` live getter/setter, `document.parentWindow` alias\n\n#### Selectors\n\n- `querySelector` / `querySelectorAll`, `matches`, `closest`\n- `getElementById` / `getElementsByClassName` / `getElementsByTagName` / `getElementsByTagNameNS`\n- Full CSS selectors — combinators, attribute selectors (quoted + unquoted), `:not`, `:is`, `:where`, `:has`, `:nth-child`, etc.\n- XPath (`document.evaluate`, `XPathEvaluator`, `XPathResult`)\n\n#### Events\n\n- `addEventListener` / `removeEventListener` with `{ once, passive, capture, signal }`\n- Bubbling, capturing, `stopPropagation`, `stopImmediatePropagation`\n- Full event classes: `Event`, `CustomEvent`, `MouseEvent`, `KeyboardEvent`, `PointerEvent`, `TouchEvent`, `WheelEvent`, `InputEvent`, `FocusEvent`, `SubmitEvent`, `DragEvent`, `ClipboardEvent`, `AnimationEvent`, `TransitionEvent`, `CompositionEvent`, `ProgressEvent`, `MessageEvent`, `CloseEvent`, `StorageEvent`, `PopStateEvent`, `HashChangeEvent`, `ErrorEvent`, `MediaQueryListEvent`\n- Focus model: `focus`/`blur` + bubbling `focusin`/`focusout`, `document.activeElement` tracking\n\n#### Network\n\n- `fetch()`, `Request`, `Response`, `Headers`, `FormData` (with `new FormData(form)` populating from a form element)\n- `XMLHttpRequest` with full event handling\n- `WebSocket` (backed by Bun's native)\n- `EventSource` (Server-Sent Events) — real `fetch` + stream parsing\n- `BroadcastChannel`, `MessageChannel`, `MessagePort`\n- `navigator.sendBeacon()`\n- Request Interception via `RequestInterceptor`\n\n#### Storage\n\n- `localStorage`, `sessionStorage` (isolated per instance)\n- `document.cookie` → `CookieContainer`\n- `indexedDB` — in-memory `IDBFactory`/`IDBDatabase`/`IDBObjectStore`/`IDBTransaction`\n- `navigator.storage` with `estimate()`/`persist()`/`persisted()`\n\n#### Timers\n\n- `setTimeout` / `clearTimeout`, `setInterval` / `clearInterval`\n- `requestAnimationFrame` / `cancelAnimationFrame`\n- `requestIdleCallback` / `cancelIdleCallback`\n- `queueMicrotask`\n\n#### Observers\n\n- `MutationObserver` (childList, attributes, characterData, subtree, oldValue, filters)\n- `IntersectionObserver`, `ResizeObserver`\n- `PerformanceObserver` with `supportedEntryTypes`\n\n#### Canvas + Screenshots\n\n- `HTMLCanvasElement.getContext('2d')`, `toDataURL`/`toBlob`\n- `CanvasRenderingContext2D` with full drawing surface\n- Pure-JS rendering pipeline: `ScreenshotCapture`, `captureHtml`, `captureUrl`, `compareImages`, WebP/PNG encoders\n- Optional `Bun.WebView`-backed real-browser screenshots (`useWebView: true`)\n\n#### Web Components + CSS\n\n- `customElements.define/.get/.whenDefined`, lifecycle callbacks (`connected`/`disconnected`/`adopted`/`attributeChanged`)\n- Shadow DOM (open + closed), event retargeting, slot support\n- `CSSStyleSheet` with `replaceSync()` parsing declarations into `cssRules`\n- `document.adoptedStyleSheets`\n- `CSS.supports()`, `CSS.escape()`\n- `getComputedStyle()` with per-tag `display` defaults + common computed fallbacks\n\n#### Forms\n\n- Constraint validation: `checkValidity`, `reportValidity`, `setCustomValidity`, `validity`, `validationMessage`, `willValidate`\n- `form.submit()`, `form.requestSubmit(submitter?)`, `form.reset()`\n- `new FormData(form)` populates from disabled/checkbox/radio/select/file fields\n\n#### Media\n\n- `HTMLMediaElement.play()` → Promise, `pause()`, `load()`, `canPlayType()`\n- `currentTime`, `duration`, `paused`, `ended`, `volume`, `muted`, `playbackRate`, `readyState`, `networkState`\n- Dispatches `play`, `playing`, `pause`, `timeupdate`, `volumechange`, `ratechange`, `loadstart`, `loadedmetadata`\n- `HTMLImageElement.decode()`, `Element.animate()`\n\n#### jsdom-compatible surface\n\n- `JSDOM` class with `.window`, `.serialize()`, `.reconfigure()`, `.nodeLocation()`, static `fragment`/`fromURL`/`fromFile`\n- `VirtualConsole` with `on/off/emit/sendTo`, `jsdomError` for uncaught exceptions\n- `CookieJar` (tough-cookie-style callback + promise API)\n- `ResourceLoader` (subclassable fetch interceptor)\n- `runScripts: 'outside-only' | 'dangerously'` — opt-in inline-script execution\n\n#### happy-dom-compatible surface\n\n- `Window` with `url`, `width`, `height`, `console`, `settings` options\n- `window.happyDOM` with `close/abort/waitUntilComplete/setURL/setViewport`\n- `GlobalRegistrator.register/unregister`\n- `/register` subpath for one-line preload\n\n#### Other\n\n- Performance API + `PerformanceObserver`\n- `navigator.permissions.query()`, `navigator.sendBeacon()`\n- Clipboard API + `ClipboardItem`\n- Geolocation API, Notification API\n- History API (`pushState`/`replaceState`/`back`/`forward`/`go`/`state`)\n- Location API (full `href`/`protocol`/`host`/`hostname`/`port`/`pathname`/`search`/`hash`/`origin` + assignment setters)\n- File API (`File`, `FileReader`, `FileList`, `Blob`)\n- `URL`, `URLSearchParams`, `AbortController`, `AbortSignal`\n- `TextEncoder`, `TextDecoder`, `ReadableStream`, `WritableStream`, `TransformStream`\n- `DOMParser`, `XMLSerializer`, `Range`, `Selection`, `NodeIterator`, `TreeWalker`\n\n\u003c/details\u003e\n\n## Testing\n\n```bash\nbun test                  # Run all tests\nbun test --coverage      # Run with coverage\n```\n\n## Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING][contributing-href] for details.\n\n## Changelog\n\nPlease see our [releases][releases-href] page for more information on what has changed recently.\n\n## Community\n\nFor help, discussion about best practices, or any other conversation that would benefit from being searchable:\n\n[Discussions on GitHub][discussions-href]\n\nFor casual chit-chat with others using this package:\n\n[Join the Stacks Discord Server][discord-href]\n\n## Postcardware\n\nVery Happy DOM is free and open-source, but we'd love to receive a postcard from you! Send one to:\n\n\u003c!-- eslint-disable-next-line markdown/no-emphasis-as-heading --\u003e\n**Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎**\n\nWe showcase postcards from around the world on our website!\n\n## Sponsors\n\nWe would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.\n\n- [JetBrains][jetbrains-href]\n- [The Solana Foundation][solana-href]\n\n## License\n\nThe MIT License (MIT). Please see [LICENSE][license-href] for more information.\n\nMade with 💙\n\n\u003c!-- Badges --\u003e\n[npm-version-src]: https://img.shields.io/npm/v/very-happy-dom?style=flat-square\n[npm-version-href]: https://npmjs.com/package/very-happy-dom\n[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/very-happy-dom/ci.yml?style=flat-square\u0026branch=main\n[github-actions-href]: https://github.com/stacksjs/very-happy-dom/actions?query=workflow%3Aci\n[commitizen-src]: https://img.shields.io/badge/commitizen-friendly-brightgreen.svg\n[commitizen-href]: http://commitizen.github.io/cz-cli/\n[contributing-href]: .github/CONTRIBUTING.md\n[releases-href]: https://github.com/stacksjs/very-happy-dom/releases\n[discussions-href]: https://github.com/stacksjs/very-happy-dom/discussions\n[discord-href]: https://discord.gg/stacksjs\n[jetbrains-href]: https://www.jetbrains.com/\n[solana-href]: https://solana.com/\n[license-href]: LICENSE.md\n[drop-in-compat-href]: ./docs/drop-in-compat.md\n\n\u003c!-- [codecov-src]: https://img.shields.io/codecov/c/gh/stacksjs/very-happy-dom/main?style=flat-square\n[codecov-href]: https://codecov.io/gh/stacksjs/very-happy-dom --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstacksjs%2Fvery-happy-dom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstacksjs%2Fvery-happy-dom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstacksjs%2Fvery-happy-dom/lists"}