Security News
Weekly Downloads Now Available in npm Package Search Results
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
@asamuzakjp/dom-selector
Advanced tools
A CSS selector engine.
npm i @asamuzakjp/dom-selector
import { DOMSelector } from '@asamuzakjp/dom-selector';
import { JSDOM } from 'jsdom';
const { window } = new JSDOM();
const {
closest, matches, querySelector, querySelectorAll
} = new DOMSelector(window);
matches - same functionality as Element.matches()
Returns boolean true
if matched, false
otherwise
closest - same functionality as Element.closest()
Returns object? matched node
querySelector - same functionality as Document.querySelector(), DocumentFragment.querySelector(), Element.querySelector()
selector
string CSS selectornode
object Document, DocumentFragment or Element nodeopt
object? options
Returns object? matched node
querySelectorAll - same functionality as Document.querySelectorAll(), DocumentFragment.querySelectorAll(), Element.querySelectorAll()
NOTE: returns Array, not NodeList
selector
string CSS selectornode
object Document, DocumentFragment or Element nodeopt
object? options
Returns Array<(object | undefined)> array of matched nodes
Pattern | Supported | Note |
---|---|---|
* | ✓ | |
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:defined | Unsupported | |
E:dir(ltr) | ✓ | |
E:lang(en) | Partially supported | Comma-separated list of language codes, e.g. :lang(en, fr) , is not yet supported. |
E:any‑link | ✓ | |
E:link | ✓ | |
E:visited | ✓ | Returns false or null to prevent fingerprinting. |
E:local‑link | ✓ | |
E:target | ✓ | |
E:target‑within | ✓ | |
E:scope | ✓ | |
E:current | Unsupported | |
E:current(s) | Unsupported | |
E:past | Unsupported | |
E:future | Unsupported | |
E:active | Unsupported | |
E:hover | Unsupported | |
E:focus | ✓ | |
E:focus‑within | ✓ | |
E:focus‑visible | Unsupported | |
E:open E:closed | Partially supported | Matching on <select>, e.g. select:open , is not supported. |
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:blank | Unsupported | |
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 F | ✓ | |
E > F | ✓ | |
E + F | ✓ | |
E ~ F | ✓ | |
F || E | Unsupported | |
E:nth‑col(n) | Unsupported | |
E:nth‑last‑col(n) | Unsupported | |
E:host | ✓ | |
E:host(s) | ✓ | |
E:host‑context(s) | ✓ |
import { DOMSelector } from '@asamuzakjp/dom-selector';
import { JSDOM } from 'jsdom';
const dom = new JSDOM('', {
runScripts: 'dangerously',
url: 'http://localhost/',
beforeParse: window => {
const domSelector = new DOMSelector(window);
const matches = domSelector.matches.bind(domSelector);
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);
};
const closest = domSelector.closest.bind(domSelector);
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);
};
const querySelector = domSelector.querySelector.bind(domSelector);
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);
};
const querySelectorAll = domSelector.querySelectorAll.bind(domSelector);
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);
};
}
});
Selector | jsdom v24.0.0 (nwsapi) | happy-dom | linkeDom | patched-jsdom (dom-selector) | Result |
---|---|---|---|---|---|
simple selector:matches('.content') | 1,000,095 ops/sec ±0.29% | 6,105 ops/sec ±0.45% | 8,636 ops/sec ±0.36% | 949,741 ops/sec ±0.21% | jsdom is the fastest and 1.1 times faster than patched-jsdom. |
compound selector:matches('p.content[id]:is(:last-child, :only-child)') | 592,559 ops/sec ±1.72% | 5,932 ops/sec ±0.48% | 8,724 ops/sec ±0.67% | 517,958 ops/sec ±0.28% | jsdom is the fastest and 1.1 times faster than patched-jsdom. |
compound selector:matches('p.content[id]:is(:invalid-nth-child, :only-child)') | N/A | 5,893 ops/sec ±0.35% | N/A | 157,436 ops/sec ±0.22% | patched-jsdom is the fastest. |
compound selector:matches('p.content[id]:not(:is(.foo, .bar))') | 481,007 ops/sec ±0.24% | N/A | 8,232 ops/sec ±0.26% | 405,841 ops/sec ±1.50% | jsdom is the fastest and 1.2 times faster than patched-jsdom. |
complex selector:matches('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content') | 162,394 ops/sec ±1.46% | N/A | 7,686 ops/sec ±0.76% | 143,901 ops/sec ±1.34% | 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/A | N/A | 7,645 ops/sec ±0.91% | 46,398 ops/sec ±1.03% | patched-jsdom is the fastest. |
Selector | jsdom v24.0.0 (nwsapi) | happy-dom | linkeDom | patched-jsdom (dom-selector) | Result |
---|---|---|---|---|---|
simple selector:closest('.container') | 384,943 ops/sec ±0.17% | 6,050 ops/sec ±0.26% | 8,544 ops/sec ±0.49% | 373,062 ops/sec ±2.06% | jsdom is the fastest and 1.0 times faster than patched-jsdom. |
compound selector:closest('div.container[id]:not(.foo, .box)') | 136,836 ops/sec ±1.49% | N/A | 8,201 ops/sec ±0.65% | 133,472 ops/sec ±1.39% | 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') | 151,300 ops/sec ±1.42% | N/A | 7,769 ops/sec ±0.48% | 136,348 ops/sec ±1.36% | 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/A | N/A | 7,648 ops/sec ±0.60% | 32,514 ops/sec ±0.85% | patched-jsdom is the fastest. |
Selector | jsdom v24.0.0 (nwsapi) | happy-dom | linkeDom | patched-jsdom (dom-selector) | Result |
---|---|---|---|---|---|
simple selector:querySelector('.content') | 36,453 ops/sec ±1.64% | 7,377 ops/sec ±0.82% | 9,762 ops/sec ±0.43% | 30,278 ops/sec ±1.31% | jsdom is the fastest and 1.2 times faster than patched-jsdom. |
compound selector:querySelector('p.content[id]:is(:last-child, :only-child)') | 10,518 ops/sec ±1.26% | 7,286 ops/sec ±0.67% | 9,400 ops/sec ±0.54% | 9,657 ops/sec ±1.35% | 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') | 230 ops/sec ±1.38% | N/A | 1,309 ops/sec ±1.39% | 732 ops/sec ±2.31% | linkedom is the fastest and 1.8 times faster than patched-jsdom. patched-jsdom is 3.2 times faster than jsdom. |
complex selector:querySelector('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)') | N/A | N/A | 1,626 ops/sec ±0.28% | 493 ops/sec ±2.35% | linkedom is the fastest and 3.3 times faster than patched-jsdom. |
Selector | jsdom v24.0.0 (nwsapi) | happy-dom | linkeDom | patched-jsdom (dom-selector) | Result |
---|---|---|---|---|---|
simple selector:querySelectorAll('.content') | 3,194 ops/sec ±1.32% | 794 ops/sec ±1.69% | 1,213 ops/sec ±0.20% | 3,526 ops/sec ±0.24% | patched-jsdom is the fastest. patched-jsdom is 1.1 times faster than jsdom. |
compound selector:querySelectorAll('p.content[id]:is(:last-child, :only-child)') | 1,056 ops/sec ±0.21% | 946 ops/sec ±1.32% | 1,166 ops/sec ±1.19% | 1,063 ops/sec ±1.09% | linkedom is the fastest and 1.1 times faster than patched-jsdom. patched-jsdom is 1.0 times faster than jsdom. |
complex selector:querySelectorAll('.box:first-child ~ .box:nth-of-type(4n+1) + .box[id] .block.inner > .content') | 233 ops/sec ±1.24% | N/A | 428 ops/sec ±1.25% | 819 ops/sec ±1.43% | patched-jsdom is the fastest. patched-jsdom is 3.5 times faster than jsdom. |
complex selector:querySelectorAll('.box:first-child ~ .box:nth-of-type(4n+1) + .box .block.inner:has(> .content)') | N/A | N/A | 460 ops/sec ±0.20% | 534 ops/sec ±1.83% | patched-jsdom is the fastest. |
The following resources have been of great help in the development of the DOM Selector.
Copyright (c) 2023 asamuzaK (Kazz)
FAQs
A CSS selector engine.
The npm package @asamuzakjp/dom-selector receives a total of 278,557 weekly downloads. As such, @asamuzakjp/dom-selector popularity was classified as popular.
We found that @asamuzakjp/dom-selector demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
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.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
Security News
A Stanford study reveals 9.5% of engineers contribute almost nothing, costing tech $90B annually, with remote work fueling the rise of "ghost engineers."
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.