Files
2026-08-20 22:43:58 +03:00
..
2026-08-20 22:43:58 +03:00
2026-08-20 22:43:58 +03:00
2026-08-20 22:43:58 +03:00
2026-08-20 22:43:58 +03:00
2026-08-20 22:43:58 +03:00

DOM Selector

build CodeQL npm (scoped)

A CSS selector engine built for strict specification compliance.

Features

  • Strict Specification Compliance: Strictly adheres to modern web standards. It accurately parses, evaluates, and extracts elements across complex combinations of pseudo-classes and HTML attributes. Features comprehensive support for CSS Selectors Level 4 (e.g., :is(), :not(), :where(), :has()) and Shadow DOM pseudo-classes (:host, :host-context).
  • Utility Functions: Provides utility methods alongside standard querying, such as check() for AST evaluation and extractSubjects() for extracting subject keys from selectors.
  • jsdom's Default Engine: Adopted as the CSS selector engine for jsdom.

Install

npm i @asamuzakjp/dom-selector

Usage

import { DOMSelector } from '@asamuzakjp/dom-selector';
import { JSDOM } from 'jsdom';

const { window } = new JSDOM();

// Destructuring methods (all methods are bound to the instance)
const {
  check, closest, extractSubjects, matches, querySelector, querySelectorAll, supports
} = new DOMSelector(window);

API

new DOMSelector(window, document?, opt?)

Creates an instance of the DOMSelector.

  • window {Window} The window object.
  • document {Document}? The document object. Defaults to window.document.
  • opt {object}? Options:
    • opt.cacheSize {number}? Maximum number of items to store in the internal cache. Default is 2048.

matches(selector, node, opt?)

Equivalent to Element.matches().

  • selector {string} CSS selector.
  • node {Element} Element node.
  • opt {object}? Options:
    • opt.noexcept {boolean}? Do not throw exceptions.
    • opt.warn {boolean}? Console warn (e.g. unsupported pseudo-class).
  • Returns {boolean} true if matched, false otherwise.

closest(selector, node, opt?)

Equivalent to Element.closest().

  • selector {string} CSS selector.
  • node {Element} Element node.
  • opt {object}? Options:
    • opt.noexcept {boolean}? Do not throw exceptions.
    • opt.warn {boolean}? Console warn (e.g. unsupported pseudo-class).
  • Returns {Element | null} The matched ancestor node or null.

querySelector(selector, node, opt?)

Equivalent to Document.querySelector(), DocumentFragment.querySelector() and Element.querySelector().

  • selector {string} CSS selector.
  • node {Document | DocumentFragment | Element} Node to find within.
  • opt {object}? Options:
    • opt.noexcept {boolean}? Do not throw exceptions.
    • opt.warn {boolean}? Console warn (e.g. unsupported pseudo-class).
  • Returns {Element | null} The matched node or null.

querySelectorAll(selector, node, opt?)

Equivalent to Document.querySelectorAll(), DocumentFragment.querySelectorAll() and Element.querySelectorAll(). NOTE: Returns a standard Array, not a NodeList.

  • selector {string} CSS selector.
  • node {Document | DocumentFragment | Element} Node to find within.
  • opt {object}? Options:
    • opt.noexcept {boolean}? Do not throw exceptions.
    • opt.warn {boolean}? Console warn (e.g. unsupported pseudo-class).
  • Returns {Array} Array of matched nodes.

check(selector, node, opt?)

Checks if an element matches a CSS selector and returns additional abstract syntax tree (AST) information. NOTE: Any pseudo-elements in the selector are excluded from the matching evaluation.

  • selector {string} CSS selector.
  • node {Element} Element node.
  • opt {object}? Options:
    • opt.noexcept {boolean}? Do not throw exceptions.
    • opt.warn {boolean}? Console warn (e.g. unsupported pseudo-class).
  • Returns {object} An object containing the following properties:
    • match {boolean} true if the element matches the selector, false otherwise.
    • pseudoElement {string | null} The pseudo-element extracted from the selector, if any.
    • ast {object | null} The parsed AST object.

extractSubjects(selector, caseSensitive?)

Parses a selector and extracts the rightmost subject keys (Id, Class, Tag).

  • selector {string} CSS selector.
  • caseSensitive {boolean}? true if the tag key should be case sensitive. Defaults to false.
  • Returns {Array<{id: string|null, className: string|null, tag: string|null}>} An array of extracted keys.

supports(selector)

Checks if the given CSS selector is supported by this engine. See the table below for the full list of supported selectors.

  • selector {string} CSS selector.
  • Returns {boolean} true if the selector is supported, false otherwise.

clear(clearAll?)

Clears the internal caches to free up memory.

  • clearAll {boolean}? Whether to clear all caches. If false, only cached matching results are cleared. Defaults to false.
  • Returns {void}

Supported CSS selectors

Pattern Supported Note
* ✓
E ✓
ns|E ✓
*|E ✓
|E ✓
E F ✓
E > F ✓
E + F ✓
E ~ F ✓
F || E Unsupported
E.warning ✓
E#myid ✓
E[foo] ✓
E[foo="bar"] ✓
E[foo="bar" i] ✓
E[foo="bar" s] ✓
E[foo~="bar"] ✓
E[foo^="bar"] ✓
E[foo$="bar"] ✓
E[foo*="bar"] ✓
E[foo|="en"] ✓
E:is(s1, s2, …) ✓
E:not(s1, s2, …) ✓
E:where(s1, s2, …) ✓
E:has(rs1, rs2, …) ✓
E:defined Partially supported Matching with MathML is not yet supported.
E:dir(ltr) ✓
E:lang(en) ✓
E:any-link ✓
E:link ✓
E:visited ✓ Returns false or null to prevent fingerprinting.
E:local-link ✓
E:target ✓
E:target-within Removed from spec.
E:scope ✓
E:hover ✓
E:active ✓
E:focus ✓
E:focus-visible ✓
E:focus-within ✓
E:current Unsupported
E:current(s) Unsupported
E:past Unsupported
E:future Unsupported
E:open Partially supported Matching with <select>, e.g. select:open, or <input type="color"> are not supported.
E:popover-open Unsupported
E:enabled
E:disabled
✓
E:read-write
E:read-only
✓
E:placeholder-shown ✓
E:default ✓
E:checked ✓
E:indeterminate ✓
E:blank Unsupported
E:valid
E:invalid
✓
E:in-range
E:out-of-range
✓
E:required
E:optional
✓
E:user-valid
E:user-invalid
Unsupported
E:root ✓
E:empty ✓
E:nth-child(n [of S]?) ✓
E:nth-last-child(n [of S]?) ✓
E:first-child ✓
E:last-child ✓
E:only-child ✓
E:nth-of-type(n) ✓
E:nth-last-of-type(n) ✓
E:first-of-type ✓
E:last-of-type ✓
E:only-of-type ✓
E:nth-col(n) Unsupported
E:nth-last-col(n) Unsupported
CE:state(v) ✓ *1
:host ✓
:host(s) ✓
:host(:state(v)) ✓ *1
:host:has(rs1, rs2, ...) ✓
:host(s):has(rs1, rs2, ...) ✓
:host-context(s) ✓
:host-context(s):has(rs1, rs2, ...) ✓
& ✓ Only supports outermost &, i.e. equivalent to :scope

*1: ElementInternals.states, i.e. CustomStateSet, is not implemented in jsdom, so you need to apply a patch in the custom element constructor.

class LabeledCheckbox extends window.HTMLElement {
  #internals;
  constructor() {
    super();
    this.#internals = this.attachInternals();
    // patch CustomStateSet
    if (!this.#internals.states) {
      this.#internals.states = new Set();
    }
    this.addEventListener('click', this._onClick.bind(this));
  }
  get checked() {
    return this.#internals.states.has('checked');
  }
  set checked(flag) {
    if (flag) {
      this.#internals.states.add('checked');
    } else {
      this.#internals.states.delete('checked');
    }
  }
  _onClick(event) {
    this.checked = !this.checked;
  }
}

Performance

See benchmark for the latest results.

Acknowledgments

The following resources have been of great help in the development of the DOM Selector.


Copyright (c) 2023 asamuzaK (Kazz)