New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@asamuzakjp/dom-selector

Package Overview
Dependencies
Maintainers
1
Versions
194
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@asamuzakjp/dom-selector

A CSS selector engine.

  • 4.1.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
364K
decreased by-8.12%
Maintainers
1
Weekly downloads
 
Created
Source

DOM Selector

build CodeQL npm (scoped)

A CSS selector engine.

Install

npm i @asamuzakjp/dom-selector

Usage

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

const { window } = new JSDOM();
const {
  closest, matches, querySelector, querySelectorAll
} = new DOMSelector(window);

matches(selector, node, opt)

matches - same functionality as Element.matches()

Parameters
  • selector string CSS selector
  • node object Element node
  • opt object? options
    • opt.noexcept boolean? no exception
    • opt.warn boolean? console warn e.g. unsupported pseudo-class

Returns boolean true if matched, false otherwise

closest(selector, node, opt)

closest - same functionality as Element.closest()

Parameters
  • selector string CSS selector
  • node object Element node
  • opt object? options
    • opt.noexcept boolean? no exception
    • opt.warn boolean? console warn e.g. unsupported pseudo-class

Returns object? matched node

querySelector(selector, node, opt)

querySelector - same functionality as Document.querySelector(), DocumentFragment.querySelector(), Element.querySelector()

Parameters
  • selector string CSS selector
  • node object Document, DocumentFragment or Element node
  • opt object? options
    • opt.noexcept boolean? no exception
    • opt.warn boolean? console warn e.g. unsupported pseudo-class

Returns object? matched node

querySelectorAll(selector, node, opt)

querySelectorAll - same functionality as Document.querySelectorAll(), DocumentFragment.querySelectorAll(), Element.querySelectorAll()
NOTE: returns Array, not NodeList

Parameters
  • selector string CSS selector
  • node object Document, DocumentFragment or Element node
  • opt object? options
    • opt.noexcept boolean? no exception
    • opt.warn boolean? console warn e.g. unsupported pseudo-class

Returns Array<(object | undefined)> array of matched nodes

Supported CSS selectors

PatternSupportedNote
*
ns|E
*|E
|E
E
E:not(s1, s2, …)
E:is(s1, s2, …)
E:where(s1, s2, …)
E:has(rs1, rs2, …)
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:definedUnsupported
E:dir(ltr)
E:lang(en)Partially supportedComma-separated list of language codes, e.g. :lang(en, fr), is not yet supported.
E:any‑link
E:link
E:visitedReturns false or null to prevent fingerprinting.
E:local‑link
E:target
E:target‑within
E:scope
E:currentUnsupported
E:current(s)Unsupported
E:pastUnsupported
E:futureUnsupported
E:activeUnsupported
E:hoverUnsupported
E:focus
E:focus‑within
E:focus‑visibleUnsupported
E:enabled
E:disabled
E:read‑write
E:read‑only
E:placeholder‑shown
E:default
E:checked
E:indeterminate
E:valid
E:invalid
E:required
E:optional
E:blankUnsupported
E:user‑invalidUnsupported
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 F
E > F
E + F
E ~ F
F || EUnsupported
E:nth‑col(n)Unsupported
E:nth‑last‑col(n)Unsupported
E:host
E:host(s)
E:host‑context(s)

Monkey patch jsdom

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

const dom = new JSDOM('', {
  runScripts: 'dangerously',
  url: 'http://localhost/',
  beforeParse: window => {
    const {
      closest, matches, querySelector, querySelectorAll
    } = new DOMSelector(window);
    window.Element.prototype.matches = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return matches(selector, this);
    };
    window.Element.prototype.closest = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return closest(selector, this);
    };
    window.Document.prototype.querySelector = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelector(selector, this);
    };
    window.DocumentFragment.prototype.querySelector = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelector(selector, this);
    };
    window.Element.prototype.querySelector = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelector(selector, this);
    };
    window.Document.prototype.querySelectorAll = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelectorAll(selector, this);
    };
    window.DocumentFragment.prototype.querySelectorAll = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelectorAll(selector, this);
    };
    window.Element.prototype.querySelectorAll = function (...args) {
      if (!args.length) {
        throw new window.TypeError('1 argument required, but only 0 present.');
      }
      const [selector] = args;
      return querySelectorAll(selector, this);
    };
  }
});

Performance

matches()

Selectorjsdom v24.0.0 (nwsapi)happy-domlinkeDompatched-jsdom (dom-selector)Result
simple selector:
matches('.content')
1,069,929 ops/sec ±0.34%7,126 ops/sec ±0.88%8,555 ops/sec ±0.70%946,961 ops/sec ±0.15%jsdom is the fastest and 1.1 times faster than patched-jsdom.
compound selector:
matches('p.content[id]:is(:last-child, :only-child)')
601,355 ops/sec ±0.33%7,016 ops/sec ±1.12%8,644 ops/sec ±0.51%508,012 ops/sec ±0.24%jsdom is the fastest and 1.2 times faster than patched-jsdom.
compound selector:
matches('p.content[id]:is(:invalid-nth-child, :only-child)')
N/A7,082 ops/sec ±0.21%N/A153,958 ops/sec ±0.96%patched-jsdom is the fastest.
complex selector:
matches('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content')
167,052 ops/sec ±0.19%N/A7,700 ops/sec ±0.45%146,612 ops/sec ±0.22%jsdom is the fastest and 1.1 times faster than patched-jsdom.
complex selector:
matches('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)')
N/AN/A7,573 ops/sec ±0.47%44,413 ops/sec ±0.66%patched-jsdom is the fastest.

closest()

Selectorjsdom v24.0.0 (nwsapi)happy-domlinkeDompatched-jsdom (dom-selector)Result
simple selector:
closest('.container')
387,330 ops/sec ±1.52%7,076 ops/sec ±0.91%8,491 ops/sec ±0.53%375,594 ops/sec ±1.31%jsdom is the fastest and 1.0 times faster than patched-jsdom.
compound selector:
closest('div.container[id]:not(.box)')
180,638 ops/sec ±1.58%6,492 ops/sec ±1.00%8,198 ops/sec ±0.71%173,121 ops/sec ±0.10%jsdom is the fastest and 1.0 times faster than patched-jsdom.
complex selector:
closest('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content')
152,683 ops/sec ±0.08%N/A7,548 ops/sec ±0.85%137,912 ops/sec ±1.40%jsdom is the fastest and 1.1 times faster than patched-jsdom.
complex selector:
closest('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)')
N/AN/A7,469 ops/sec ±0.65%30,497 ops/sec ±0.84%patched-jsdom is the fastest.

querySelector()

Selectorjsdom v24.0.0 (nwsapi)happy-domlinkeDompatched-jsdom (dom-selector)Result
simple selector:
querySelector('.content')
35,135 ops/sec ±1.63%8,473 ops/sec ±0.72%9,958 ops/sec ±0.90%28,201 ops/sec ±2.12%jsdom is the fastest and 1.2 times faster than patched-jsdom.
compound selector:
querySelector('p.content[id]:is(:last-child, :only-child)')
10,717 ops/sec ±1.39%8,378 ops/sec ±0.70%9,366 ops/sec ±0.27%9,348 ops/sec ±1.76%jsdom is the fastest and 1.1 times faster than patched-jsdom.
complex selector:
querySelector('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content')
233 ops/sec ±0.71%N/A1,298 ops/sec ±0.40%689 ops/sec ±1.14%linkedom is the fastest and 1.9 times faster than patched-jsdom. patched-jsdom is 3.0 times faster than jsdom.
complex selector:
querySelector('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)')
N/AN/A1,569 ops/sec ±0.29%464 ops/sec ±1.73%linkedom is the fastest and 3.4 times faster than patched-jsdom.

querySelectorAll()

Selectorjsdom v24.0.0 (nwsapi)happy-domlinkeDompatched-jsdom (dom-selector)Result
simple selector:
querySelectorAll('.content')
2,839 ops/sec ±1.01%822 ops/sec ±1.68%1,215 ops/sec ±1.37%3,398 ops/sec ±0.33%patched-jsdom is the fastest. patched-jsdom is 1.2 times faster than jsdom.
compound selector:
querySelectorAll('p.content[id]:is(:last-child, :only-child)')
1,003 ops/sec ±1.20%987 ops/sec ±1.66%1,195 ops/sec ±1.07%1,059 ops/sec ±1.09%linkedom is the fastest and 1.1 times faster than patched-jsdom. patched-jsdom is 1.1 times faster than jsdom.
complex selector:
querySelectorAll('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content')
230 ops/sec ±0.84%N/A426 ops/sec ±0.18%781 ops/sec ±1.34%patched-jsdom is the fastest. patched-jsdom is 3.4 times faster than jsdom.
complex selector:
querySelectorAll('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)')
N/AN/A463 ops/sec ±0.25%492 ops/sec ±2.09%patched-jsdom is the fastest.

Acknowledgments

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


Copyright (c) 2023 asamuzaK (Kazz)

FAQs

Package last updated on 16 Feb 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc