{"id":16159,"library":"nwsapi","title":"NWSAPI CSS Selector Engine","description":"NWSAPI is a high-performance CSS selector engine, serving as a continuation and significant rework of the earlier `nwmatcher` project, currently at version 2.2.23. Its primary goal is to provide comprehensive and fast support for the latest CSS Level 4 Selectors, while also meticulously emulating native browser APIs such as `querySelector()`, `querySelectorAll()`, `matches()`, and `closest()`. The library is actively maintained, with a focus on continuous bug fixes and feature enhancements, and is intended to replace `nwmatcher` in environments like `jsdom`. NWSAPI differentiates itself through a unique architecture that employs regular expressions to parse CSS selector strings and metaprogramming to transform these into memoized JavaScript function resolvers, a process executed only once per selector for 'unmatched performances'. It ships with no external dependencies and supports both browser environments (via a global `NW.Dom` object) and headless environments like Node.js (as a CommonJS module).","status":"active","version":"2.2.23","language":"javascript","source_language":"en","source_url":"git://github.com/dperini/nwsapi","tags":["javascript","css","css3","css4","matcher","selector"],"install":[{"cmd":"npm install nwsapi","lang":"bash","label":"npm"},{"cmd":"yarn add nwsapi","lang":"bash","label":"yarn"},{"cmd":"pnpm add nwsapi","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This is a named export for ESM. For CommonJS, use `const { select } = require('nwsapi');`. Attempting a default import will fail.","wrong":"import select from 'nwsapi';","symbol":"select","correct":"import { select } from 'nwsapi';"},{"note":"The `configure` function is a named export used to get a customized NWSAPI engine instance. For CommonJS, use `const { configure } = require('nwsapi');`.","wrong":"import nwsapi from 'nwsapi'; nwsapi.configure();","symbol":"configure","correct":"import { configure } from 'nwsapi';"},{"note":"This is a global method exclusively available when NWSAPI is loaded directly in a browser via a `<script>` tag. It automatically polyfills or overrides native DOM methods like `document.querySelector`.","wrong":"import { install } from 'nwsapi';","symbol":"NW.Dom.install","correct":"<script type=\"text/javascript\" src=\"nwsapi.js\" onload=\"NW.Dom.install()\"></script>"}],"quickstart":{"code":"const { JSDOM } = require('jsdom');\nconst nwsapi = require('nwsapi');\n\n// Create a JSDOM instance to simulate a browser environment\nconst dom = new JSDOM(`\n  <!DOCTYPE html>\n  <html>\n    <body>\n      <div id=\"app\">\n        <header>\n          <h1>My Title</h1>\n          <nav>\n            <ul>\n              <li><a href=\"#home\">Home</a></li>\n              <li><a href=\"#about\" class=\"active\">About</a></li>\n            </ul>\n          </nav>\n        </header>\n        <main>\n          <section class=\"content\">\n            <p>Some text here.</p>\n            <button id=\"myButton\">Click Me</button>\n          </section>\n          <section class=\"footer-content\">\n            <p>More text.</p>\n          </section>\n        </main>\n      </div>\n    </body>\n  </html>\n`);\n\n// Get the document object from the JSDOM instance\nconst document = dom.window.document;\n\n// Configure NWSAPI to work with the JSDOM document context\n// The library's functions need to be bound to a context that behaves like a DOM element/document.\nconst engine = nwsapi.configure({\n  // Example configuration: allow duplicate IDs (default is true)\n  IDS_DUPES: true\n});\n\n// Manually bind NWSAPI methods to the JSDOM document and Element prototype\n// This makes it behave like a polyfilled native API.\ndocument.querySelector = (selector) => engine.first(selector, document);\ndocument.querySelectorAll = (selector) => engine.select(selector, document);\ndom.window.Element.prototype.matches = function(selector) { return engine.match(selector, this); };\ndom.window.Element.prototype.closest = function(selector) { return engine.ancestor(selector, this); };\n\n// --- Using the NWSAPI-enhanced JSDOM document --- \n\n// Find the first element matching a selector\nconst mainTitle = document.querySelector('h1');\nconsole.log('Main title:', mainTitle ? mainTitle.textContent : 'Not found');\n\n// Find all elements matching a selector\nconst allParagraphs = document.querySelectorAll('p');\nconsole.log('Number of paragraphs:', allParagraphs.length);\nallParagraphs.forEach((p, i) => console.log(`Paragraph ${i + 1}:`, p.textContent));\n\n// Check if an element matches a selector\nconst aboutLink = document.querySelector('a.active');\nif (aboutLink) {\n  console.log('Is \"About\" link active?', aboutLink.matches('.active'));\n  console.log('Is \"About\" link a button?', aboutLink.matches('button'));\n}\n\n// Find the closest ancestor\nconst myButton = document.getElementById('myButton');\nif (myButton) {\n  const closestSection = myButton.closest('section');\n  console.log('Closest section to button:', closestSection ? closestSection.className : 'Not found');\n}","lang":"javascript","description":"Demonstrates how to install `nwsapi` in a Node.js environment using `jsdom` to simulate a browser DOM, and then how to configure and bind its selector methods (`querySelector`, `querySelectorAll`, `matches`, `closest`) to the `JSDOM` document and `Element` prototype for a familiar API experience."},"warnings":[{"fix":"Review the NWSAPI documentation and API for any behavioral changes or renamed methods compared to `nwmatcher` when upgrading or migrating.","message":"NWSAPI (v2.0.0 and later) is a complete rewrite and continuation of the `nwmatcher` project. While aiming for similar functionality, significant internal changes mean it is not a drop-in replacement for `nwmatcher` and requires careful migration.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"If strict ID uniqueness is required, configure NWSAPI explicitly: `nwsapi.configure({ IDS_DUPES: false })`.","message":"The `configure` option `IDS_DUPES` defaults to `true`, which means NWSAPI will allow multiple elements to share the same ID. This deviates from strict HTML/DOM specifications where IDs must be unique and might lead to unexpected behavior if not accounted for.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Manually bind NWSAPI methods to your DOM context, e.g., `document.querySelector = (s) => engine.first(s, document);` as shown in the quickstart example.","message":"When using NWSAPI in Node.js with a virtual DOM library like JSDOM, its selector methods (`first`, `select`, `match`, `ancestor`) are not automatically bound to `document` or `Element.prototype`. Developers must manually bind these methods to achieve a native-like API (`document.querySelector`, `Element.prototype.matches`).","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Manually bind NWSAPI's functions to the `document` object or `Element.prototype` as demonstrated in the quickstart, or use the NWSAPI functions directly with a context: `engine.first('selector', document.body)`.","cause":"In Node.js or browser environments where NWSAPI is not directly replacing native DOM APIs, the `document.querySelector` and similar methods are not automatically polyfilled or overridden by `nwsapi` upon import.","error":"TypeError: document.querySelector is not a function"},{"fix":"For Node.js, use `require('nwsapi')` or `import { ... } from 'nwsapi'` to access the module exports. For browsers, ensure `nwsapi.js` is loaded via a `<script>` tag before attempting to access `NW.Dom`.","cause":"The global `NW.Dom` object is only available when NWSAPI is loaded directly into a browser environment via a `<script>` tag. This error occurs when trying to access `NW.Dom` in Node.js or before the script has executed in a browser.","error":"ReferenceError: NW is not defined"}],"ecosystem":"npm"}