diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-13 21:34:48 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-13 21:34:48 -0800 |
| commit | 76cb9c2a39d477a64824a985ade40507e3bbade1 (patch) | |
| tree | 41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/@asamuzakjp/dom-selector/README.md | |
| parent | 819a39a21ac992b1393244a4c283bbb125208c69 (diff) | |
| download | neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2 neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip | |
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/@asamuzakjp/dom-selector/README.md')
| -rw-r--r-- | vanilla/node_modules/@asamuzakjp/dom-selector/README.md | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/README.md b/vanilla/node_modules/@asamuzakjp/dom-selector/README.md new file mode 100644 index 0000000..f4f2296 --- /dev/null +++ b/vanilla/node_modules/@asamuzakjp/dom-selector/README.md @@ -0,0 +1,324 @@ +# DOM Selector
+
+[](https://github.com/asamuzaK/domSelector/actions/workflows/node.js.yml)
+[](https://github.com/asamuzaK/domSelector/actions/workflows/github-code-scanning/codeql)
+[](https://www.npmjs.com/package/@asamuzakjp/dom-selector)
+
+A CSS selector engine.
+
+## Install
+
+```console
+npm i @asamuzakjp/dom-selector
+```
+
+## Usage
+
+```javascript
+import { DOMSelector } from '@asamuzakjp/dom-selector';
+import { JSDOM } from 'jsdom';
+
+const { window } = new JSDOM();
+const {
+ closest, matches, querySelector, querySelectorAll
+} = new DOMSelector(window);
+```
+
+<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
+
+### matches(selector, node, opt)
+
+matches - equivalent to [Element.matches()][64]
+
+#### Parameters
+
+- `selector` **[string][59]** CSS selector
+- `node` **[object][60]** Element node
+- `opt` **[object][60]?** options
+ - `opt.noexcept` **[boolean][61]?** no exception
+ - `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
+
+Returns **[boolean][61]** `true` if matched, `false` otherwise
+
+
+### closest(selector, node, opt)
+
+closest - equivalent to [Element.closest()][65]
+
+#### Parameters
+
+- `selector` **[string][59]** CSS selector
+- `node` **[object][60]** Element node
+- `opt` **[object][60]?** options
+ - `opt.noexcept` **[boolean][61]?** no exception
+ - `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
+
+Returns **[object][60]?** matched node
+
+
+### querySelector(selector, node, opt)
+
+querySelector - equivalent to [Document.querySelector()][66], [DocumentFragment.querySelector()][67] and [Element.querySelector()][68]
+
+#### Parameters
+
+- `selector` **[string][59]** CSS selector
+- `node` **[object][60]** Document, DocumentFragment or Element node
+- `opt` **[object][60]?** options
+ - `opt.noexcept` **[boolean][61]?** no exception
+ - `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
+
+Returns **[object][60]?** matched node
+
+
+### querySelectorAll(selector, node, opt)
+
+querySelectorAll - equivalent to [Document.querySelectorAll()][69], [DocumentFragment.querySelectorAll()][70] and [Element.querySelectorAll()][71]
+**NOTE**: returns Array, not NodeList
+
+#### Parameters
+
+- `selector` **[string][59]** CSS selector
+- `node` **[object][60]** Document, DocumentFragment or Element node
+- `opt` **[object][60]?** options
+ - `opt.noexcept` **[boolean][61]?** no exception
+ - `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
+
+Returns **[Array][62]<([object][60] \| [undefined][63])>** array of matched nodes
+
+
+## Monkey patch jsdom
+
+``` javascript
+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);
+ };
+ }
+});
+```
+
+
+## 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|✓| |
+|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<br>E:closed|Partially supported|Matching with <select>, e.g. `select:open`, is not supported.|
+|E:popover-open|✓| |
+|E:enabled<br>E:disabled|✓| |
+|E:read‑write<br>E:read‑only|✓| |
+|E:placeholder‑shown|✓| |
+|E:default|✓| |
+|E:checked|✓| |
+|E:indeterminate|✓| |
+|E:blank|Unsupported| |
+|E:valid<br>E:invalid|✓| |
+|E:in-range<br>E:out-of-range|✓| |
+|E:required<br>E:optional|✓| |
+|E:user‑valid<br>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.
+
+``` javascript
+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](https://github.com/asamuzaK/domSelector/actions/workflows/benchmark.yml) for the latest results.
+
+
+## Acknowledgments
+
+The following resources have been of great help in the development of the DOM Selector.
+
+- [CSSTree](https://github.com/csstree/csstree)
+- [selery](https://github.com/danburzo/selery)
+- [jsdom](https://github.com/jsdom/jsdom)
+- [nwsapi](https://github.com/dperini/nwsapi)
+
+---
+Copyright (c) 2023 [asamuzaK (Kazz)](https://github.com/asamuzaK/)
+
+
+[1]: #matches
+[2]: #parameters
+[3]: #closest
+[4]: #parameters-1
+[5]: #queryselector
+[6]: #parameters-2
+[7]: #queryselectorall
+[8]: #parameters-3
+[59]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
+[60]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
+[61]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
+[62]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
+[63]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined
+[64]: https://developer.mozilla.org/docs/Web/API/Element/matches
+[65]: https://developer.mozilla.org/docs/Web/API/Element/closest
+[66]: https://developer.mozilla.org/docs/Web/API/Document/querySelector
+[67]: https://developer.mozilla.org/docs/Web/API/DocumentFragment/querySelector
+[68]: https://developer.mozilla.org/docs/Web/API/Element/querySelector
+[69]: https://developer.mozilla.org/docs/Web/API/Document/querySelectorAll
+[70]: https://developer.mozilla.org/docs/Web/API/DocumentFragment/querySelectorAll
+[71]: https://developer.mozilla.org/docs/Web/API/Element/querySelectorAll
|
