aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/@asamuzakjp/dom-selector
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-14 14:46:37 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-14 14:46:37 -0800
commitafa87af01c79a9baa539f2992d32154d2a4739bd (patch)
tree92c7416db734270a2fee1d72ee9cc119379ff8e1 /vanilla/node_modules/@asamuzakjp/dom-selector
parent3b927e84d200402281f68181cd4253bc77e5528d (diff)
downloadneko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.gz
neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.bz2
neko-afa87af01c79a9baa539f2992d32154d2a4739bd.zip
task: delete vanilla js prototype\n\n- Removed vanilla/ directory and web/dist/vanilla directory\n- Updated Makefile, Dockerfile, and CI workflow to remove vanilla references\n- Cleaned up web/web.go to remove vanilla embed and routes\n- Verified build and tests pass\n\nCloses NK-2tcnmq
Diffstat (limited to 'vanilla/node_modules/@asamuzakjp/dom-selector')
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/LICENSE21
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/README.md324
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs4622
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs.map1
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.d.cts16
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/package.json81
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/index.js353
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/js/constant.js129
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/js/finder.js3122
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/js/matcher.js587
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/js/parser.js431
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/src/js/utility.js1107
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/index.d.ts14
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/js/constant.d.ts77
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/js/finder.d.ts63
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/js/matcher.d.ts16
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/js/parser.d.ts14
-rw-r--r--vanilla/node_modules/@asamuzakjp/dom-selector/types/js/utility.d.ts30
18 files changed, 0 insertions, 11008 deletions
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/LICENSE b/vanilla/node_modules/@asamuzakjp/dom-selector/LICENSE
deleted file mode 100644
index f3f97a3..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 asamuzaK (Kazz)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/README.md b/vanilla/node_modules/@asamuzakjp/dom-selector/README.md
deleted file mode 100644
index f4f2296..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/README.md
+++ /dev/null
@@ -1,324 +0,0 @@
-# DOM Selector
-
-[![build](https://github.com/asamuzaK/domSelector/actions/workflows/node.js.yml/badge.svg)](https://github.com/asamuzaK/domSelector/actions/workflows/node.js.yml)
-[![CodeQL](https://github.com/asamuzaK/domSelector/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/asamuzaK/domSelector/actions/workflows/github-code-scanning/codeql)
-[![npm (scoped)](https://img.shields.io/npm/v/@asamuzakjp/dom-selector)](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]&lt;([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&nbsp;F|✓| |
-|E > F|✓| |
-|E + F|✓| |
-|E ~ F|✓| |
-|F \|\| E|Unsupported| |
-|E.warning|✓| |
-|E#myid|✓| |
-|E\[foo\]|✓| |
-|E\[foo="bar"\]|✓| |
-|E\[foo="bar"&nbsp;i\]|✓| |
-|E\[foo="bar"&nbsp;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&#8209;link|✓| |
-|E:link|✓| |
-|E:visited|✓|Returns `false` or `null` to prevent fingerprinting.|
-|E:local&#8209;link|✓| |
-|E:target|✓| |
-|E:target&#8209;within|✓| |
-|E:scope|✓| |
-|E:hover|✓| |
-|E:active|✓| |
-|E:focus|✓| |
-|E:focus&#8209;visible|✓| |
-|E:focus&#8209;within|✓| |
-|E:current|Unsupported| |
-|E:current(s)|Unsupported| |
-|E:past|Unsupported| |
-|E:future|Unsupported| |
-|E:open<br>E:closed|Partially supported|Matching with &lt;select&gt;, e.g. `select:open`, is not supported.|
-|E:popover-open|✓| |
-|E:enabled<br>E:disabled|✓| |
-|E:read&#8209;write<br>E:read&#8209;only|✓| |
-|E:placeholder&#8209;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&#8209;valid<br>E:user&#8209;invalid|Unsupported| |
-|E:root|✓| |
-|E:empty|✓| |
-|E:nth&#8209;child(n&nbsp;[of&nbsp;S]?)|✓| |
-|E:nth&#8209;last&#8209;child(n&nbsp;[of&nbsp;S]?)|✓| |
-|E:first&#8209;child|✓| |
-|E:last&#8209;child|✓| |
-|E:only&#8209;child|✓| |
-|E:nth&#8209;of&#8209;type(n)|✓| |
-|E:nth&#8209;last&#8209;of&#8209;type(n)|✓| |
-|E:first&#8209;of&#8209;type|✓| |
-|E:last&#8209;of&#8209;type|✓| |
-|E:only&#8209;of&#8209;type|✓| |
-|E:nth&#8209;col(n)|Unsupported| |
-|E:nth&#8209;last&#8209;col(n)|Unsupported| |
-|CE:state(v)|✓|*1|
-|:host|✓| |
-|:host(s)|✓| |
-|:host(:state(v))|✓|*1|
-|:host:has(rs1, rs2, ...)|✓| |
-|:host(s):has(rs1, rs2, ...)|✓| |
-|:host&#8209;context(s)|✓| |
-|:host&#8209;context(s):has(rs1, rs2, ...)|✓| |
-|&amp;|✓|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
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs b/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs
deleted file mode 100644
index 9505dd3..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs
+++ /dev/null
@@ -1,4622 +0,0 @@
-var __create = Object.create;
-var __defProp = Object.defineProperty;
-var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
-var __getOwnPropNames = Object.getOwnPropertyNames;
-var __getProtoOf = Object.getPrototypeOf;
-var __hasOwnProp = Object.prototype.hasOwnProperty;
-var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
-};
-var __copyProps = (to, from, except, desc) => {
- if (from && typeof from === "object" || typeof from === "function") {
- for (let key of __getOwnPropNames(from))
- if (!__hasOwnProp.call(to, key) && key !== except)
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
- }
- return to;
-};
-var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
- // If the importer is in node compatibility mode or this is not an ESM
- // file that has been converted to a CommonJS file using a Babel-
- // compatible transform (i.e. "__esModule" has not been set), then set
- // "default" to the CommonJS "module.exports" for node compatibility.
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
- mod
-));
-var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
-
-// src/index.js
-var index_exports = {};
-__export(index_exports, {
- DOMSelector: () => DOMSelector
-});
-module.exports = __toCommonJS(index_exports);
-var import_lru_cache = require("lru-cache");
-
-// src/js/parser.js
-var cssTree2 = __toESM(require("css-tree"), 1);
-
-// src/js/utility.js
-var import_nwsapi = __toESM(require("@asamuzakjp/nwsapi"), 1);
-var import_bidi_js = __toESM(require("bidi-js"), 1);
-var cssTree = __toESM(require("css-tree"), 1);
-var import_is_potential_custom_element_name = __toESM(require("is-potential-custom-element-name"), 1);
-
-// src/js/constant.js
-var ATTR_SELECTOR = "AttributeSelector";
-var CLASS_SELECTOR = "ClassSelector";
-var COMBINATOR = "Combinator";
-var IDENT = "Identifier";
-var ID_SELECTOR = "IdSelector";
-var NOT_SUPPORTED_ERR = "NotSupportedError";
-var NTH = "Nth";
-var PS_CLASS_SELECTOR = "PseudoClassSelector";
-var PS_ELEMENT_SELECTOR = "PseudoElementSelector";
-var SELECTOR = "Selector";
-var STRING = "String";
-var SYNTAX_ERR = "SyntaxError";
-var TARGET_ALL = "all";
-var TARGET_FIRST = "first";
-var TARGET_LINEAL = "lineal";
-var TARGET_SELF = "self";
-var TYPE_SELECTOR = "TypeSelector";
-var BIT_01 = 1;
-var BIT_02 = 2;
-var BIT_04 = 4;
-var BIT_08 = 8;
-var BIT_16 = 16;
-var BIT_32 = 32;
-var BIT_FFFF = 65535;
-var DUO = 2;
-var HEX = 16;
-var TYPE_FROM = 8;
-var TYPE_TO = -1;
-var ELEMENT_NODE = 1;
-var TEXT_NODE = 3;
-var DOCUMENT_NODE = 9;
-var DOCUMENT_FRAGMENT_NODE = 11;
-var DOCUMENT_POSITION_PRECEDING = 2;
-var DOCUMENT_POSITION_CONTAINS = 8;
-var SHOW_ALL = 4294967295;
-var SHOW_CONTAINER = 1281;
-var ALPHA_NUM = "[A-Z\\d]+";
-var CHILD_IDX = "(?:first|last|only)-(?:child|of-type)";
-var DIGIT = "(?:0|[1-9]\\d*)";
-var LANG_PART = `(?:-${ALPHA_NUM})*`;
-var PSEUDO_CLASS = `(?:any-)?link|${CHILD_IDX}|checked|empty|indeterminate|read-(?:only|write)|target`;
-var ANB = `[+-]?(?:${DIGIT}n?|n)|(?:[+-]?${DIGIT})?n\\s*[+-]\\s*${DIGIT}`;
-var COMBO = "\\s?[\\s>~+]\\s?";
-var DESCEND = "\\s?[\\s>]\\s?";
-var SIBLING = "\\s?[+~]\\s?";
-var LOGIC_IS = `:is\\(\\s*[^)]+\\s*\\)`;
-var N_TH = `nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|${ANB})\\s*\\)`;
-var SUB_TYPE = "\\[[^|\\]]+\\]|[#.:][\\w-]+";
-var SUB_TYPE_WO_PSEUDO = "\\[[^|\\]]+\\]|[#.][\\w-]+";
-var TAG_TYPE = "\\*|[A-Za-z][\\w-]*";
-var TAG_TYPE_I = "\\*|[A-Z][\\w-]*";
-var COMPOUND = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE})+)`;
-var COMPOUND_L = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${LOGIC_IS})+)`;
-var COMPOUND_I = `(?:${TAG_TYPE_I}|(?:${TAG_TYPE_I})?(?:${SUB_TYPE})+)`;
-var COMPOUND_WO_PSEUDO = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE_WO_PSEUDO})+)`;
-var COMPLEX = `${COMPOUND}(?:${COMBO}${COMPOUND})*`;
-var COMPLEX_L = `${COMPOUND_L}(?:${COMBO}${COMPOUND_L})*`;
-var HAS_COMPOUND = `has\\([\\s>]?\\s*${COMPOUND_WO_PSEUDO}\\s*\\)`;
-var LOGIC_COMPOUND = `(?:is|not)\\(\\s*${COMPOUND_L}(?:\\s*,\\s*${COMPOUND_L})*\\s*\\)`;
-var LOGIC_COMPLEX = `(?:is|not)\\(\\s*${COMPLEX_L}(?:\\s*,\\s*${COMPLEX_L})*\\s*\\)`;
-var FORM_PARTS = Object.freeze([
- "button",
- "input",
- "select",
- "textarea"
-]);
-var INPUT_BUTTON = Object.freeze(["button", "reset", "submit"]);
-var INPUT_CHECK = Object.freeze(["checkbox", "radio"]);
-var INPUT_DATE = Object.freeze([
- "date",
- "datetime-local",
- "month",
- "time",
- "week"
-]);
-var INPUT_TEXT = Object.freeze([
- "email",
- "password",
- "search",
- "tel",
- "text",
- "url"
-]);
-var INPUT_EDIT = Object.freeze([
- ...INPUT_DATE,
- ...INPUT_TEXT,
- "number"
-]);
-var INPUT_LTR = Object.freeze([
- ...INPUT_CHECK,
- "color",
- "date",
- "image",
- "number",
- "range",
- "time"
-]);
-var KEYS_LOGICAL = /* @__PURE__ */ new Set(["has", "is", "not", "where"]);
-
-// src/js/utility.js
-var KEYS_DIR_AUTO = /* @__PURE__ */ new Set([...INPUT_BUTTON, ...INPUT_TEXT, "hidden"]);
-var KEYS_DIR_LTR = new Set(INPUT_LTR);
-var KEYS_INPUT_EDIT = new Set(INPUT_EDIT);
-var KEYS_NODE_DIR_EXCLUDE = /* @__PURE__ */ new Set(["bdi", "script", "style", "textarea"]);
-var KEYS_NODE_FOCUSABLE = /* @__PURE__ */ new Set(["button", "select", "textarea"]);
-var KEYS_NODE_FOCUSABLE_SVG = /* @__PURE__ */ new Set([
- "clipPath",
- "defs",
- "desc",
- "linearGradient",
- "marker",
- "mask",
- "metadata",
- "pattern",
- "radialGradient",
- "script",
- "style",
- "symbol",
- "title"
-]);
-var REG_EXCLUDE_BASIC = /[|\\]|::|[^\u0021-\u007F\s]|\[\s*[\w$*=^|~-]+(?:(?:"[\w$*=^|~\s'-]+"|'[\w$*=^|~\s"-]+')?(?:\s+[\w$*=^|~-]+)+|"[^"\]]{1,255}|'[^'\]]{1,255})\s*\]|:(?:is|where)\(\s*\)/;
-var REG_COMPLEX = new RegExp(`${COMPOUND_I}${COMBO}${COMPOUND_I}`, "i");
-var REG_DESCEND = new RegExp(`${COMPOUND_I}${DESCEND}${COMPOUND_I}`, "i");
-var REG_SIBLING = new RegExp(`${COMPOUND_I}${SIBLING}${COMPOUND_I}`, "i");
-var REG_LOGIC_COMPLEX = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPLEX})`
-);
-var REG_LOGIC_COMPOUND = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND})`
-);
-var REG_LOGIC_HAS_COMPOUND = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND}|${HAS_COMPOUND})`
-);
-var REG_END_WITH_HAS = new RegExp(`:${HAS_COMPOUND}$`);
-var REG_WO_LOGICAL = new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH})`);
-var REG_IS_HTML = /^(?:application\/xhtml\+x|text\/ht)ml$/;
-var REG_IS_XML = /^(?:application\/(?:[\w\-.]+\+)?|image\/[\w\-.]+\+|text\/)xml$/;
-var getType = (o) => Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);
-var generateException = (msg, name, globalObject = globalThis) => {
- return new globalObject.DOMException(msg, name);
-};
-var findNestedHas = (leaf) => {
- return leaf.name === "has";
-};
-var findLogicalWithNestedHas = (leaf) => {
- if (KEYS_LOGICAL.has(leaf.name) && cssTree.find(leaf, findNestedHas)) {
- return leaf;
- }
- return null;
-};
-var filterNodesByAnB = (nodes, anb) => {
- const { a, b, reverse } = anb;
- const processedNodes = reverse ? [...nodes].reverse() : nodes;
- const l = nodes.length;
- const matched = [];
- if (a === 0) {
- if (b > 0 && b <= l) {
- matched.push(processedNodes[b - 1]);
- }
- return matched;
- }
- let startIndex = b - 1;
- if (a > 0) {
- while (startIndex < 0) {
- startIndex += a;
- }
- for (let i = startIndex; i < l; i += a) {
- matched.push(processedNodes[i]);
- }
- } else if (startIndex >= 0) {
- for (let i = startIndex; i >= 0; i += a) {
- matched.push(processedNodes[i]);
- }
- return matched.reverse();
- }
- return matched;
-};
-var resolveContent = (node) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- let document;
- let root;
- let shadow;
- switch (node.nodeType) {
- case DOCUMENT_NODE: {
- document = node;
- root = node;
- break;
- }
- case DOCUMENT_FRAGMENT_NODE: {
- const { host, mode, ownerDocument } = node;
- document = ownerDocument;
- root = node;
- shadow = host && (mode === "close" || mode === "open");
- break;
- }
- case ELEMENT_NODE: {
- document = node.ownerDocument;
- let refNode = node;
- while (refNode) {
- const { host, mode, nodeType, parentNode } = refNode;
- if (nodeType === DOCUMENT_FRAGMENT_NODE) {
- shadow = host && (mode === "close" || mode === "open");
- break;
- } else if (parentNode) {
- refNode = parentNode;
- } else {
- break;
- }
- }
- root = refNode;
- break;
- }
- default: {
- throw new TypeError(`Unexpected node ${node.nodeName}`);
- }
- }
- return [document, root, !!shadow];
-};
-var traverseNode = (node, walker, force = false) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (!walker) {
- return null;
- }
- let refNode = walker.currentNode;
- if (refNode === node) {
- return refNode;
- } else if (force || refNode.contains(node)) {
- refNode = walker.nextNode();
- while (refNode) {
- if (refNode === node) {
- break;
- }
- refNode = walker.nextNode();
- }
- return refNode;
- } else {
- if (refNode !== walker.root) {
- let bool;
- while (refNode) {
- if (refNode === node) {
- bool = true;
- break;
- } else if (refNode === walker.root || refNode.contains(node)) {
- break;
- }
- refNode = walker.parentNode();
- }
- if (bool) {
- return refNode;
- }
- }
- if (node.nodeType === ELEMENT_NODE) {
- let bool;
- while (refNode) {
- if (refNode === node) {
- bool = true;
- break;
- }
- refNode = walker.nextNode();
- }
- if (bool) {
- return refNode;
- }
- }
- }
- return null;
-};
-var isCustomElement = (node, opt = {}) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const { localName, ownerDocument } = node;
- const { formAssociated } = opt;
- const window = ownerDocument.defaultView;
- let elmConstructor;
- const attr = node.getAttribute("is");
- if (attr) {
- elmConstructor = (0, import_is_potential_custom_element_name.default)(attr) && window.customElements.get(attr);
- } else {
- elmConstructor = (0, import_is_potential_custom_element_name.default)(localName) && window.customElements.get(localName);
- }
- if (elmConstructor) {
- if (formAssociated) {
- return !!elmConstructor.formAssociated;
- }
- return true;
- }
- return false;
-};
-var getSlottedTextContent = (node) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (typeof node.assignedNodes !== "function") {
- return null;
- }
- const nodes = node.assignedNodes();
- if (nodes.length) {
- let text = "";
- const l = nodes.length;
- for (let i = 0; i < l; i++) {
- const item = nodes[i];
- text = item.textContent.trim();
- if (text) {
- break;
- }
- }
- return text;
- }
- return node.textContent.trim();
-};
-var getDirectionality = (node) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { dir: dirAttr, localName, parentNode } = node;
- const { getEmbeddingLevels } = (0, import_bidi_js.default)();
- if (dirAttr === "ltr" || dirAttr === "rtl") {
- return dirAttr;
- } else if (dirAttr === "auto") {
- let text = "";
- switch (localName) {
- case "input": {
- if (!node.type || KEYS_DIR_AUTO.has(node.type)) {
- text = node.value;
- } else if (KEYS_DIR_LTR.has(node.type)) {
- return "ltr";
- }
- break;
- }
- case "slot": {
- text = getSlottedTextContent(node);
- break;
- }
- case "textarea": {
- text = node.value;
- break;
- }
- default: {
- const items = [].slice.call(node.childNodes);
- for (const item of items) {
- const {
- dir: itemDir,
- localName: itemLocalName,
- nodeType: itemNodeType,
- textContent: itemTextContent
- } = item;
- if (itemNodeType === TEXT_NODE) {
- text = itemTextContent.trim();
- } else if (itemNodeType === ELEMENT_NODE && !KEYS_NODE_DIR_EXCLUDE.has(itemLocalName) && (!itemDir || itemDir !== "ltr" && itemDir !== "rtl")) {
- if (itemLocalName === "slot") {
- text = getSlottedTextContent(item);
- } else {
- text = itemTextContent.trim();
- }
- }
- if (text) {
- break;
- }
- }
- }
- }
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return "rtl";
- }
- } else if (parentNode) {
- const { nodeType: parentNodeType } = parentNode;
- if (parentNodeType === ELEMENT_NODE) {
- return getDirectionality(parentNode);
- }
- }
- } else if (localName === "input" && node.type === "tel") {
- return "ltr";
- } else if (localName === "bdi") {
- const text = node.textContent.trim();
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return "rtl";
- }
- }
- } else if (parentNode) {
- if (localName === "slot") {
- const text = getSlottedTextContent(node);
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return "rtl";
- }
- return "ltr";
- }
- }
- const { nodeType: parentNodeType } = parentNode;
- if (parentNodeType === ELEMENT_NODE) {
- return getDirectionality(parentNode);
- }
- }
- return "ltr";
-};
-var getLanguageAttribute = (node) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { contentType } = node.ownerDocument;
- const isHtml = REG_IS_HTML.test(contentType);
- const isXml = REG_IS_XML.test(contentType);
- let isShadow = false;
- let current = node;
- while (current) {
- switch (current.nodeType) {
- case ELEMENT_NODE: {
- if (isHtml && current.hasAttribute("lang")) {
- return current.getAttribute("lang");
- } else if (isXml && current.hasAttribute("xml:lang")) {
- return current.getAttribute("xml:lang");
- }
- break;
- }
- case DOCUMENT_FRAGMENT_NODE: {
- if (current.host) {
- isShadow = true;
- }
- break;
- }
- case DOCUMENT_NODE:
- default: {
- return null;
- }
- }
- if (isShadow) {
- current = current.host;
- isShadow = false;
- } else if (current.parentNode) {
- current = current.parentNode;
- } else {
- break;
- }
- }
- return null;
-};
-var isContentEditable = (node) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (typeof node.isContentEditable === "boolean") {
- return node.isContentEditable;
- } else if (node.ownerDocument.designMode === "on") {
- return true;
- } else {
- let attr;
- if (node.hasAttribute("contenteditable")) {
- attr = node.getAttribute("contenteditable");
- } else {
- attr = "inherit";
- }
- switch (attr) {
- case "":
- case "true": {
- return true;
- }
- case "plaintext-only": {
- return true;
- }
- case "false": {
- return false;
- }
- default: {
- if (node?.parentNode?.nodeType === ELEMENT_NODE) {
- return isContentEditable(node.parentNode);
- }
- return false;
- }
- }
- }
-};
-var isVisible = (node) => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const window = node.ownerDocument.defaultView;
- const { display, visibility } = window.getComputedStyle(node);
- if (display !== "none" && visibility === "visible") {
- return true;
- }
- return false;
-};
-var isFocusVisible = (node) => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const { localName, type } = node;
- switch (localName) {
- case "input": {
- if (!type || KEYS_INPUT_EDIT.has(type)) {
- return true;
- }
- return false;
- }
- case "textarea": {
- return true;
- }
- default: {
- return isContentEditable(node);
- }
- }
-};
-var isFocusableArea = (node) => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (!node.isConnected) {
- return false;
- }
- const window = node.ownerDocument.defaultView;
- if (node instanceof window.HTMLElement) {
- if (Number.isInteger(parseInt(node.getAttribute("tabindex")))) {
- return true;
- }
- if (isContentEditable(node)) {
- return true;
- }
- const { localName, parentNode } = node;
- switch (localName) {
- case "a": {
- if (node.href || node.hasAttribute("href")) {
- return true;
- }
- return false;
- }
- case "iframe": {
- return true;
- }
- case "input": {
- if (node.disabled || node.hasAttribute("disabled") || node.hidden || node.hasAttribute("hidden")) {
- return false;
- }
- return true;
- }
- case "summary": {
- if (parentNode.localName === "details") {
- let child = parentNode.firstElementChild;
- let bool = false;
- while (child) {
- if (child.localName === "summary") {
- bool = child === node;
- break;
- }
- child = child.nextElementSibling;
- }
- return bool;
- }
- return false;
- }
- default: {
- if (KEYS_NODE_FOCUSABLE.has(localName) && !(node.disabled || node.hasAttribute("disabled"))) {
- return true;
- }
- }
- }
- } else if (node instanceof window.SVGElement) {
- if (Number.isInteger(parseInt(node.getAttributeNS(null, "tabindex")))) {
- const ns = "http://www.w3.org/2000/svg";
- let bool;
- let refNode = node;
- while (refNode.namespaceURI === ns) {
- bool = KEYS_NODE_FOCUSABLE_SVG.has(refNode.localName);
- if (bool) {
- break;
- }
- if (refNode?.parentNode?.namespaceURI === ns) {
- refNode = refNode.parentNode;
- } else {
- break;
- }
- }
- if (bool) {
- return false;
- }
- return true;
- }
- if (node.localName === "a" && (node.href || node.hasAttributeNS(null, "href"))) {
- return true;
- }
- }
- return false;
-};
-var getNamespaceURI = (ns, node) => {
- if (typeof ns !== "string") {
- throw new TypeError(`Unexpected type ${getType(ns)}`);
- } else if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (!ns || node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { attributes } = node;
- let res;
- for (const attr of attributes) {
- const { name, namespaceURI, prefix, value } = attr;
- if (name === `xmlns:${ns}`) {
- res = value;
- } else if (prefix === ns) {
- res = namespaceURI;
- }
- if (res) {
- break;
- }
- }
- return res ?? null;
-};
-var isNamespaceDeclared = (ns = "", node = {}) => {
- if (!ns || typeof ns !== "string" || node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (node.lookupNamespaceURI(ns)) {
- return true;
- }
- const root = node.ownerDocument.documentElement;
- let parent = node;
- let res;
- while (parent) {
- res = getNamespaceURI(ns, parent);
- if (res || parent === root) {
- break;
- }
- parent = parent.parentNode;
- }
- return !!res;
-};
-var isPreceding = (nodeA, nodeB) => {
- if (!nodeA?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(nodeA)}`);
- } else if (!nodeB?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(nodeB)}`);
- }
- if (nodeA.nodeType !== ELEMENT_NODE || nodeB.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const posBit = nodeB.compareDocumentPosition(nodeA);
- const res = posBit & DOCUMENT_POSITION_PRECEDING || posBit & DOCUMENT_POSITION_CONTAINS;
- return !!res;
-};
-var compareNodes = (a, b) => {
- if (isPreceding(b, a)) {
- return 1;
- }
- return -1;
-};
-var sortNodes = (nodes = []) => {
- const arr = [...nodes];
- if (arr.length > 1) {
- arr.sort(compareNodes);
- }
- return arr;
-};
-var initNwsapi = (window, document) => {
- if (!window?.DOMException) {
- throw new TypeError(`Unexpected global object ${getType(window)}`);
- }
- if (document?.nodeType !== DOCUMENT_NODE) {
- document = window.document;
- }
- const nw = (0, import_nwsapi.default)({
- document,
- DOMException: window.DOMException
- });
- nw.configure({
- LOGERRORS: false
- });
- return nw;
-};
-var filterSelector = (selector, target) => {
- const isQuerySelectorType = target === TARGET_FIRST || target === TARGET_ALL;
- if (!selector || typeof selector !== "string" || /null|undefined/.test(selector)) {
- return false;
- }
- if (selector.includes("[")) {
- const index = selector.lastIndexOf("[");
- const sel = selector.substring(index);
- if (sel.indexOf("]") < 0) {
- return false;
- }
- }
- if (selector.includes("/") || REG_EXCLUDE_BASIC.test(selector)) {
- return false;
- }
- if (selector.includes(":")) {
- let complex = false;
- if (target !== isQuerySelectorType) {
- complex = REG_COMPLEX.test(selector);
- }
- if (isQuerySelectorType && REG_DESCEND.test(selector) && !REG_SIBLING.test(selector)) {
- return false;
- } else if (!isQuerySelectorType && /:has\(/.test(selector)) {
- if (!complex || REG_LOGIC_HAS_COMPOUND.test(selector)) {
- return false;
- }
- return REG_END_WITH_HAS.test(selector);
- } else if (/:(?:is|not)\(/.test(selector)) {
- if (complex) {
- return !REG_LOGIC_COMPLEX.test(selector);
- } else {
- return !REG_LOGIC_COMPOUND.test(selector);
- }
- } else {
- return !REG_WO_LOGICAL.test(selector);
- }
- }
- return true;
-};
-
-// src/js/parser.js
-var import_css_tree = require("css-tree");
-var AST_SORT_ORDER = /* @__PURE__ */ new Map([
- [PS_ELEMENT_SELECTOR, BIT_01],
- [ID_SELECTOR, BIT_02],
- [CLASS_SELECTOR, BIT_04],
- [TYPE_SELECTOR, BIT_08],
- [ATTR_SELECTOR, BIT_16],
- [PS_CLASS_SELECTOR, BIT_32]
-]);
-var KEYS_PS_CLASS_STATE = /* @__PURE__ */ new Set([
- "checked",
- "closed",
- "disabled",
- "empty",
- "enabled",
- "in-range",
- "indeterminate",
- "invalid",
- "open",
- "out-of-range",
- "placeholder-shown",
- "read-only",
- "read-write",
- "valid"
-]);
-var KEYS_SHADOW_HOST = /* @__PURE__ */ new Set(["host", "host-context"]);
-var REG_EMPTY_PS_FUNC = /(?<=:(?:dir|has|host(?:-context)?|is|lang|not|nth-(?:last-)?(?:child|of-type)|where))\(\s+\)/g;
-var REG_SHADOW_PS_ELEMENT = /^part|slotted$/;
-var U_FFFD = "\uFFFD";
-var unescapeSelector = (selector = "") => {
- if (typeof selector === "string" && selector.indexOf("\\", 0) >= 0) {
- const arr = selector.split("\\");
- const selectorItems = [arr[0]];
- const l = arr.length;
- for (let i = 1; i < l; i++) {
- const item = arr[i];
- if (item === "" && i === l - 1) {
- selectorItems.push(U_FFFD);
- } else {
- const hexExists = /^([\da-f]{1,6}\s?)/i.exec(item);
- if (hexExists) {
- const [, hex] = hexExists;
- let str;
- try {
- const low = parseInt("D800", HEX);
- const high = parseInt("DFFF", HEX);
- const deci = parseInt(hex, HEX);
- if (deci === 0 || deci >= low && deci <= high) {
- str = U_FFFD;
- } else {
- str = String.fromCodePoint(deci);
- }
- } catch (e) {
- str = U_FFFD;
- }
- let postStr = "";
- if (item.length > hex.length) {
- postStr = item.substring(hex.length);
- }
- selectorItems.push(`${str}${postStr}`);
- } else if (/^[\n\r\f]/.test(item)) {
- selectorItems.push(`\\${item}`);
- } else {
- selectorItems.push(item);
- }
- }
- }
- return selectorItems.join("");
- }
- return selector;
-};
-var preprocess = (value) => {
- if (typeof value !== "string") {
- if (value === void 0 || value === null) {
- return getType(value).toLowerCase();
- } else if (Array.isArray(value)) {
- return value.join(",");
- } else if (Object.hasOwn(value, "toString")) {
- return value.toString();
- } else {
- throw new DOMException(`Invalid selector ${value}`, SYNTAX_ERR);
- }
- }
- let selector = value;
- let index = 0;
- while (index >= 0) {
- index = selector.indexOf("#", index);
- if (index < 0) {
- break;
- }
- const preHash = selector.substring(0, index + 1);
- let postHash = selector.substring(index + 1);
- const codePoint = postHash.codePointAt(0);
- if (codePoint > BIT_FFFF) {
- const str = `\\${codePoint.toString(HEX)} `;
- if (postHash.length === DUO) {
- postHash = str;
- } else {
- postHash = `${str}${postHash.substring(DUO)}`;
- }
- }
- selector = `${preHash}${postHash}`;
- index++;
- }
- return selector.replace(/\f|\r\n?/g, "\n").replace(/[\0\uD800-\uDFFF]|\\$/g, U_FFFD).replace(/\x26/g, ":scope");
-};
-var parseSelector = (sel) => {
- const selector = preprocess(sel);
- if (/^$|^\s*>|,\s*$/.test(selector)) {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- try {
- const ast = cssTree2.parse(selector, {
- context: "selectorList",
- parseCustomProperty: true
- });
- return cssTree2.toPlainObject(ast);
- } catch (e) {
- const { message } = e;
- if (/^(?:"\]"|Attribute selector [()\s,=~^$*|]+) is expected$/.test(
- message
- ) && !selector.endsWith("]")) {
- const index = selector.lastIndexOf("[");
- const selPart = selector.substring(index);
- if (selPart.includes('"')) {
- const quotes = selPart.match(/"/g).length;
- if (quotes % 2) {
- return parseSelector(`${selector}"]`);
- }
- return parseSelector(`${selector}]`);
- }
- return parseSelector(`${selector}]`);
- } else if (message === '")" is expected') {
- if (REG_EMPTY_PS_FUNC.test(selector)) {
- return parseSelector(`${selector.replaceAll(REG_EMPTY_PS_FUNC, "()")}`);
- } else if (!selector.endsWith(")")) {
- return parseSelector(`${selector})`);
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- }
-};
-var walkAST = (ast = {}) => {
- const branches = /* @__PURE__ */ new Set();
- const info = {
- hasForgivenPseudoFunc: false,
- hasHasPseudoFunc: false,
- hasLogicalPseudoFunc: false,
- hasNotPseudoFunc: false,
- hasNthChildOfSelector: false,
- hasNestedSelector: false,
- hasStatePseudoClass: false
- };
- const opt = {
- enter(node) {
- switch (node.type) {
- case CLASS_SELECTOR: {
- if (/^-?\d/.test(node.name)) {
- throw new DOMException(
- `Invalid selector .${node.name}`,
- SYNTAX_ERR
- );
- }
- break;
- }
- case ID_SELECTOR: {
- if (/^-?\d/.test(node.name)) {
- throw new DOMException(
- `Invalid selector #${node.name}`,
- SYNTAX_ERR
- );
- }
- break;
- }
- case PS_CLASS_SELECTOR: {
- if (KEYS_LOGICAL.has(node.name)) {
- info.hasNestedSelector = true;
- info.hasLogicalPseudoFunc = true;
- if (node.name === "has") {
- info.hasHasPseudoFunc = true;
- } else if (node.name === "not") {
- info.hasNotPseudoFunc = true;
- } else {
- info.hasForgivenPseudoFunc = true;
- }
- } else if (KEYS_PS_CLASS_STATE.has(node.name)) {
- info.hasStatePseudoClass = true;
- } else if (KEYS_SHADOW_HOST.has(node.name) && Array.isArray(node.children) && node.children.length) {
- info.hasNestedSelector = true;
- }
- break;
- }
- case PS_ELEMENT_SELECTOR: {
- if (REG_SHADOW_PS_ELEMENT.test(node.name)) {
- info.hasNestedSelector = true;
- }
- break;
- }
- case NTH: {
- if (node.selector) {
- info.hasNestedSelector = true;
- info.hasNthChildOfSelector = true;
- }
- break;
- }
- case SELECTOR: {
- branches.add(node.children);
- break;
- }
- default:
- }
- }
- };
- cssTree2.walk(ast, opt);
- if (info.hasNestedSelector === true) {
- cssTree2.findAll(ast, (node, item, list) => {
- if (list) {
- if (node.type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(node.name)) {
- const itemList = list.filter((i) => {
- const { name, type } = i;
- return type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(name);
- });
- for (const { children } of itemList) {
- for (const { children: grandChildren } of children) {
- for (const { children: greatGrandChildren } of grandChildren) {
- if (branches.has(greatGrandChildren)) {
- branches.delete(greatGrandChildren);
- }
- }
- }
- }
- } else if (node.type === PS_CLASS_SELECTOR && KEYS_SHADOW_HOST.has(node.name) && Array.isArray(node.children) && node.children.length) {
- const itemList = list.filter((i) => {
- const { children, name, type } = i;
- const res = type === PS_CLASS_SELECTOR && KEYS_SHADOW_HOST.has(name) && Array.isArray(children) && children.length;
- return res;
- });
- for (const { children } of itemList) {
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- } else if (node.type === PS_ELEMENT_SELECTOR && REG_SHADOW_PS_ELEMENT.test(node.name)) {
- const itemList = list.filter((i) => {
- const { name, type } = i;
- const res = type === PS_ELEMENT_SELECTOR && REG_SHADOW_PS_ELEMENT.test(name);
- return res;
- });
- for (const { children } of itemList) {
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- } else if (node.type === NTH && node.selector) {
- const itemList = list.filter((i) => {
- const { selector, type } = i;
- const res = type === NTH && selector;
- return res;
- });
- for (const { selector } of itemList) {
- const { children } = selector;
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- }
- }
- });
- }
- return {
- info,
- branches: [...branches]
- };
-};
-var compareASTNodes = (a, b) => {
- const bitA = AST_SORT_ORDER.get(a.type);
- const bitB = AST_SORT_ORDER.get(b.type);
- if (bitA === bitB) {
- return 0;
- } else if (bitA > bitB) {
- return 1;
- } else {
- return -1;
- }
-};
-var sortAST = (asts) => {
- const arr = [...asts];
- if (arr.length > 1) {
- arr.sort(compareASTNodes);
- }
- return arr;
-};
-var parseAstName = (selector) => {
- let prefix;
- let localName;
- if (selector && typeof selector === "string") {
- if (selector.indexOf("|") > -1) {
- [prefix, localName] = selector.split("|");
- } else {
- prefix = "*";
- localName = selector;
- }
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- return {
- prefix,
- localName
- };
-};
-
-// src/js/matcher.js
-var KEYS_FORM_PS_DISABLED = /* @__PURE__ */ new Set([
- ...FORM_PARTS,
- "fieldset",
- "optgroup",
- "option"
-]);
-var KEYS_INPUT_EDIT2 = new Set(INPUT_EDIT);
-var REG_LANG_VALID = new RegExp(`^(?:\\*-)?${ALPHA_NUM}${LANG_PART}$`, "i");
-var REG_TAG_NAME = /[A-Z][\\w-]*/i;
-var matchPseudoElementSelector = (astName, astType, opt = {}) => {
- const { forgive, globalObject, warn } = opt;
- if (astType !== PS_ELEMENT_SELECTOR) {
- throw new TypeError(`Unexpected ast type ${getType(astType)}`);
- }
- switch (astName) {
- case "after":
- case "backdrop":
- case "before":
- case "cue":
- case "cue-region":
- case "first-letter":
- case "first-line":
- case "file-selector-button":
- case "marker":
- case "placeholder":
- case "selection":
- case "target-text": {
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- break;
- }
- case "part":
- case "slotted": {
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}()`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- break;
- }
- default: {
- if (astName.startsWith("-webkit-")) {
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- } else if (!forgive) {
- throw generateException(
- `Unknown pseudo-element ::${astName}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- }
- }
-};
-var matchDirectionPseudoClass = (ast, node) => {
- const { name } = ast;
- if (!name) {
- const type = name === "" ? "(empty String)" : getType(name);
- throw new TypeError(`Unexpected ast type ${type}`);
- }
- const dir = getDirectionality(node);
- return name === dir;
-};
-var matchLanguagePseudoClass = (ast, node) => {
- const { name, type, value } = ast;
- let langPattern;
- if (type === STRING && value) {
- langPattern = value;
- } else if (type === IDENT && name) {
- langPattern = unescapeSelector(name);
- }
- if (typeof langPattern !== "string") {
- return false;
- }
- const elementLang = getLanguageAttribute(node);
- if (elementLang === null) {
- return false;
- }
- if (langPattern === "*") {
- return elementLang !== "";
- }
- if (!REG_LANG_VALID.test(langPattern)) {
- return false;
- }
- let matcherRegex;
- if (langPattern.indexOf("-") > -1) {
- const [langMain, langSub, ...langRest] = langPattern.split("-");
- const extendedMain = langMain === "*" ? `${ALPHA_NUM}${LANG_PART}` : `${langMain}${LANG_PART}`;
- const extendedSub = `-${langSub}${LANG_PART}`;
- let extendedRest = "";
- for (let i = 0; i < langRest.length; i++) {
- extendedRest += `-${langRest[i]}${LANG_PART}`;
- }
- matcherRegex = new RegExp(
- `^${extendedMain}${extendedSub}${extendedRest}$`,
- "i"
- );
- } else {
- matcherRegex = new RegExp(`^${langPattern}${LANG_PART}$`, "i");
- }
- return matcherRegex.test(elementLang);
-};
-var matchDisabledPseudoClass = (astName, node) => {
- const { localName, parentNode } = node;
- if (!KEYS_FORM_PS_DISABLED.has(localName) && !isCustomElement(node, { formAssociated: true })) {
- return false;
- }
- let isDisabled = false;
- if (node.disabled || node.hasAttribute("disabled")) {
- isDisabled = true;
- } else if (localName === "option") {
- if (parentNode && parentNode.localName === "optgroup" && (parentNode.disabled || parentNode.hasAttribute("disabled"))) {
- isDisabled = true;
- }
- } else if (localName !== "optgroup") {
- let current = parentNode;
- while (current) {
- if (current.localName === "fieldset" && (current.disabled || current.hasAttribute("disabled"))) {
- let legend;
- let element = current.firstElementChild;
- while (element) {
- if (element.localName === "legend") {
- legend = element;
- break;
- }
- element = element.nextElementSibling;
- }
- if (!legend || !legend.contains(node)) {
- isDisabled = true;
- }
- break;
- }
- current = current.parentNode;
- }
- }
- if (astName === "disabled") {
- return isDisabled;
- }
- return !isDisabled;
-};
-var matchReadOnlyPseudoClass = (astName, node) => {
- const { localName } = node;
- let isReadOnly = false;
- switch (localName) {
- case "textarea":
- case "input": {
- const isEditableInput = !node.type || KEYS_INPUT_EDIT2.has(node.type);
- if (localName === "textarea" || isEditableInput) {
- isReadOnly = node.readOnly || node.hasAttribute("readonly") || node.disabled || node.hasAttribute("disabled");
- } else {
- isReadOnly = true;
- }
- break;
- }
- default: {
- isReadOnly = !isContentEditable(node);
- }
- }
- if (astName === "read-only") {
- return isReadOnly;
- }
- return !isReadOnly;
-};
-var matchAttributeSelector = (ast, node, opt = {}) => {
- const {
- flags: astFlags,
- matcher: astMatcher,
- name: astName,
- value: astValue
- } = ast;
- const { check, forgive, globalObject } = opt;
- if (typeof astFlags === "string" && !/^[is]$/i.test(astFlags) && !forgive) {
- const css = (0, import_css_tree.generate)(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- const { attributes } = node;
- if (!attributes || !attributes.length) {
- return false;
- }
- const contentType = node.ownerDocument.contentType;
- let caseInsensitive;
- if (contentType === "text/html") {
- if (typeof astFlags === "string" && /^s$/i.test(astFlags)) {
- caseInsensitive = false;
- } else {
- caseInsensitive = true;
- }
- } else if (typeof astFlags === "string" && /^i$/i.test(astFlags)) {
- caseInsensitive = true;
- } else {
- caseInsensitive = false;
- }
- let astAttrName = unescapeSelector(astName.name);
- if (caseInsensitive) {
- astAttrName = astAttrName.toLowerCase();
- }
- const attrValues = /* @__PURE__ */ new Set();
- if (astAttrName.indexOf("|") > -1) {
- const { prefix: astPrefix, localName: astLocalName } = parseAstName(astAttrName);
- for (const item of attributes) {
- let { name: itemName, value: itemValue } = item;
- if (caseInsensitive) {
- itemName = itemName.toLowerCase();
- itemValue = itemValue.toLowerCase();
- }
- switch (astPrefix) {
- case "": {
- if (astLocalName === itemName) {
- attrValues.add(itemValue);
- }
- break;
- }
- case "*": {
- if (itemName.indexOf(":") > -1) {
- const [, ...restItemName] = itemName.split(":");
- const itemLocalName = restItemName.join(":").replace(/^:/, "");
- if (itemLocalName === astLocalName) {
- attrValues.add(itemValue);
- }
- } else if (astLocalName === itemName) {
- attrValues.add(itemValue);
- }
- break;
- }
- default: {
- if (!check) {
- if (forgive) {
- return false;
- }
- const css = (0, import_css_tree.generate)(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- if (itemName.indexOf(":") > -1) {
- const [itemPrefix, ...restItemName] = itemName.split(":");
- const itemLocalName = restItemName.join(":").replace(/^:/, "");
- if (itemPrefix === "xml" && itemLocalName === "lang") {
- continue;
- } else if (astPrefix === itemPrefix && astLocalName === itemLocalName) {
- const namespaceDeclared = isNamespaceDeclared(astPrefix, node);
- if (namespaceDeclared) {
- attrValues.add(itemValue);
- }
- }
- }
- }
- }
- }
- } else {
- for (let { name: itemName, value: itemValue } of attributes) {
- if (caseInsensitive) {
- itemName = itemName.toLowerCase();
- itemValue = itemValue.toLowerCase();
- }
- if (itemName.indexOf(":") > -1) {
- const [itemPrefix, ...restItemName] = itemName.split(":");
- const itemLocalName = restItemName.join(":").replace(/^:/, "");
- if (!itemPrefix && astAttrName === `:${itemLocalName}`) {
- attrValues.add(itemValue);
- } else if (itemPrefix === "xml" && itemLocalName === "lang") {
- continue;
- } else if (astAttrName === itemLocalName) {
- attrValues.add(itemValue);
- }
- } else if (astAttrName === itemName) {
- attrValues.add(itemValue);
- }
- }
- }
- if (!attrValues.size) {
- return false;
- }
- const { name: astIdentValue, value: astStringValue } = astValue ?? {};
- let attrValue;
- if (astIdentValue) {
- if (caseInsensitive) {
- attrValue = astIdentValue.toLowerCase();
- } else {
- attrValue = astIdentValue;
- }
- } else if (astStringValue) {
- if (caseInsensitive) {
- attrValue = astStringValue.toLowerCase();
- } else {
- attrValue = astStringValue;
- }
- } else if (astStringValue === "") {
- attrValue = astStringValue;
- }
- switch (astMatcher) {
- case "=": {
- return typeof attrValue === "string" && attrValues.has(attrValue);
- }
- case "~=": {
- if (attrValue && typeof attrValue === "string") {
- for (const value of attrValues) {
- const item = new Set(value.split(/\s+/));
- if (item.has(attrValue)) {
- return true;
- }
- }
- }
- return false;
- }
- case "|=": {
- if (attrValue && typeof attrValue === "string") {
- for (const value of attrValues) {
- if (value === attrValue || value.startsWith(`${attrValue}-`)) {
- return true;
- }
- }
- }
- return false;
- }
- case "^=": {
- if (attrValue && typeof attrValue === "string") {
- for (const value of attrValues) {
- if (value.startsWith(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case "$=": {
- if (attrValue && typeof attrValue === "string") {
- for (const value of attrValues) {
- if (value.endsWith(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case "*=": {
- if (attrValue && typeof attrValue === "string") {
- for (const value of attrValues) {
- if (value.includes(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case null:
- default: {
- return true;
- }
- }
-};
-var matchTypeSelector = (ast, node, opt = {}) => {
- const astName = unescapeSelector(ast.name);
- const { localName, namespaceURI, prefix } = node;
- const { check, forgive, globalObject } = opt;
- let { prefix: astPrefix, localName: astLocalName } = parseAstName(
- astName,
- node
- );
- if (node.ownerDocument.contentType === "text/html" && (!namespaceURI || namespaceURI === "http://www.w3.org/1999/xhtml") && REG_TAG_NAME.test(localName)) {
- astPrefix = astPrefix.toLowerCase();
- astLocalName = astLocalName.toLowerCase();
- }
- let nodePrefix;
- let nodeLocalName;
- if (localName.indexOf(":") > -1) {
- [nodePrefix, nodeLocalName] = localName.split(":");
- } else {
- nodePrefix = prefix || "";
- nodeLocalName = localName;
- }
- switch (astPrefix) {
- case "": {
- if (!nodePrefix && !namespaceURI && (astLocalName === "*" || astLocalName === nodeLocalName)) {
- return true;
- }
- return false;
- }
- case "*": {
- if (astLocalName === "*" || astLocalName === nodeLocalName) {
- return true;
- }
- return false;
- }
- default: {
- if (!check) {
- if (forgive) {
- return false;
- }
- const css = (0, import_css_tree.generate)(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- const astNS = node.lookupNamespaceURI(astPrefix);
- const nodeNS = node.lookupNamespaceURI(nodePrefix);
- if (astNS === nodeNS && astPrefix === nodePrefix) {
- if (astLocalName === "*" || astLocalName === nodeLocalName) {
- return true;
- }
- return false;
- } else if (!forgive && !astNS) {
- throw generateException(
- `Undeclared namespace ${astPrefix}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- return false;
- }
- }
-};
-
-// src/js/finder.js
-var DIR_NEXT = "next";
-var DIR_PREV = "prev";
-var KEYS_FORM = /* @__PURE__ */ new Set([...FORM_PARTS, "fieldset", "form"]);
-var KEYS_FORM_PS_VALID = /* @__PURE__ */ new Set([...FORM_PARTS, "form"]);
-var KEYS_INPUT_CHECK = new Set(INPUT_CHECK);
-var KEYS_INPUT_PLACEHOLDER = /* @__PURE__ */ new Set([...INPUT_TEXT, "number"]);
-var KEYS_INPUT_RANGE = /* @__PURE__ */ new Set([...INPUT_DATE, "number", "range"]);
-var KEYS_INPUT_REQUIRED = /* @__PURE__ */ new Set([...INPUT_CHECK, ...INPUT_EDIT, "file"]);
-var KEYS_INPUT_RESET = /* @__PURE__ */ new Set(["button", "reset"]);
-var KEYS_INPUT_SUBMIT = /* @__PURE__ */ new Set(["image", "submit"]);
-var KEYS_MODIFIER = /* @__PURE__ */ new Set([
- "Alt",
- "AltGraph",
- "CapsLock",
- "Control",
- "Fn",
- "FnLock",
- "Hyper",
- "Meta",
- "NumLock",
- "ScrollLock",
- "Shift",
- "Super",
- "Symbol",
- "SymbolLock"
-]);
-var KEYS_PS_UNCACHE = /* @__PURE__ */ new Set([
- "any-link",
- "defined",
- "dir",
- "link",
- "scope"
-]);
-var KEYS_PS_NTH_OF_TYPE = /* @__PURE__ */ new Set([
- "first-of-type",
- "last-of-type",
- "only-of-type"
-]);
-var Finder = class {
- /* private fields */
- #ast;
- #astCache;
- #check;
- #descendant;
- #document;
- #documentCache;
- #documentURL;
- #event;
- #eventHandlers;
- #focus;
- #invalidate;
- #invalidateResults;
- #lastFocusVisible;
- #node;
- #nodeWalker;
- #nodes;
- #noexcept;
- #pseudoElement;
- #results;
- #root;
- #rootWalker;
- #scoped;
- #selector;
- #shadow;
- #verifyShadowHost;
- #walkers;
- #warn;
- #window;
- /**
- * constructor
- * @param {object} window - The window object.
- */
- constructor(window) {
- this.#window = window;
- this.#astCache = /* @__PURE__ */ new WeakMap();
- this.#documentCache = /* @__PURE__ */ new WeakMap();
- this.#event = null;
- this.#focus = null;
- this.#lastFocusVisible = null;
- this.#eventHandlers = /* @__PURE__ */ new Set([
- {
- keys: ["focus", "focusin"],
- handler: this._handleFocusEvent
- },
- {
- keys: ["keydown", "keyup"],
- handler: this._handleKeyboardEvent
- },
- {
- keys: ["mouseover", "mousedown", "mouseup", "click", "mouseout"],
- handler: this._handleMouseEvent
- }
- ]);
- this._registerEventListeners();
- this.clearResults(true);
- }
- /**
- * Handles errors.
- * @param {Error} e - The error object.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.
- * @throws {Error} Throws an error.
- * @returns {void}
- */
- onError = (e, opt = {}) => {
- const noexcept = opt.noexcept ?? this.#noexcept;
- if (noexcept) {
- return;
- }
- const isDOMException = e instanceof DOMException || e instanceof this.#window.DOMException;
- if (isDOMException) {
- if (e.name === NOT_SUPPORTED_ERR) {
- if (this.#warn) {
- console.warn(e.message);
- }
- return;
- }
- throw new this.#window.DOMException(e.message, e.name);
- }
- if (e.name in this.#window) {
- throw new this.#window[e.name](e.message, { cause: e });
- }
- throw e;
- };
- /**
- * Sets up the finder.
- * @param {string} selector - The CSS selector.
- * @param {object} node - Document, DocumentFragment, or Element.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.check] - Indicates if running in internal check().
- * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.
- * @param {boolean} [opt.warn] - If true, console warnings are enabled.
- * @returns {object} The finder instance.
- */
- setup = (selector, node, opt = {}) => {
- const { check, noexcept, warn } = opt;
- this.#check = !!check;
- this.#noexcept = !!noexcept;
- this.#warn = !!warn;
- [this.#document, this.#root, this.#shadow] = resolveContent(node);
- this.#documentURL = null;
- this.#node = node;
- this.#scoped = this.#node !== this.#root && this.#node.nodeType === ELEMENT_NODE;
- this.#selector = selector;
- [this.#ast, this.#nodes] = this._correspond(selector);
- this.#pseudoElement = [];
- this.#walkers = /* @__PURE__ */ new WeakMap();
- this.#nodeWalker = null;
- this.#rootWalker = null;
- this.#verifyShadowHost = null;
- this.clearResults();
- return this;
- };
- /**
- * Clear cached results.
- * @param {boolean} all - clear all results
- * @returns {void}
- */
- clearResults = (all = false) => {
- this.#invalidateResults = /* @__PURE__ */ new WeakMap();
- if (all) {
- this.#results = /* @__PURE__ */ new WeakMap();
- }
- };
- /**
- * Handles focus events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleFocusEvent = (evt) => {
- this.#focus = evt;
- };
- /**
- * Handles keyboard events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleKeyboardEvent = (evt) => {
- const { key } = evt;
- if (!KEYS_MODIFIER.has(key)) {
- this.#event = evt;
- }
- };
- /**
- * Handles mouse events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleMouseEvent = (evt) => {
- this.#event = evt;
- };
- /**
- * Registers event listeners.
- * @private
- * @returns {Array.<void>} An array of return values from addEventListener.
- */
- _registerEventListeners = () => {
- const opt = {
- capture: true,
- passive: true
- };
- const func = [];
- for (const eventHandler of this.#eventHandlers) {
- const { keys, handler } = eventHandler;
- const l = keys.length;
- for (let i = 0; i < l; i++) {
- const key = keys[i];
- func.push(this.#window.addEventListener(key, handler, opt));
- }
- }
- return func;
- };
- /**
- * Processes selector branches into the internal AST structure.
- * @private
- * @param {Array.<Array.<object>>} branches - The branches from walkAST.
- * @param {string} selector - The original selector for error reporting.
- * @returns {{ast: Array, descendant: boolean}}
- * An object with the AST, descendant flag.
- */
- _processSelectorBranches = (branches, selector) => {
- let descendant = false;
- const ast = [];
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const items = [...branches[i]];
- const branch = [];
- let item = items.shift();
- if (item && item.type !== COMBINATOR) {
- const leaves = /* @__PURE__ */ new Set();
- while (item) {
- if (item.type === COMBINATOR) {
- const [nextItem] = items;
- if (!nextItem || nextItem.type === COMBINATOR) {
- const msg = `Invalid selector ${selector}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- return { ast: [], descendant: false, invalidate: false };
- }
- if (item.name === " " || item.name === ">") {
- descendant = true;
- }
- branch.push({ combo: item, leaves: sortAST(leaves) });
- leaves.clear();
- } else {
- if (item.name && typeof item.name === "string") {
- const unescapedName = unescapeSelector(item.name);
- if (unescapedName !== item.name) {
- item.name = unescapedName;
- }
- if (/[|:]/.test(unescapedName)) {
- item.namespace = true;
- }
- }
- leaves.add(item);
- }
- if (items.length) {
- item = items.shift();
- } else {
- branch.push({ combo: null, leaves: sortAST(leaves) });
- leaves.clear();
- break;
- }
- }
- }
- ast.push({ branch, dir: null, filtered: false, find: false });
- }
- return { ast, descendant };
- };
- /**
- * Corresponds AST and nodes.
- * @private
- * @param {string} selector - The CSS selector.
- * @returns {Array.<Array.<object>>} An array with the AST and nodes.
- */
- _correspond = (selector) => {
- const nodes = [];
- this.#descendant = false;
- this.#invalidate = false;
- let ast;
- if (this.#documentCache.has(this.#document)) {
- const cachedItem = this.#documentCache.get(this.#document);
- if (cachedItem && cachedItem.has(`${selector}`)) {
- const item = cachedItem.get(`${selector}`);
- ast = item.ast;
- this.#descendant = item.descendant;
- this.#invalidate = item.invalidate;
- }
- }
- if (ast) {
- const l = ast.length;
- for (let i = 0; i < l; i++) {
- ast[i].dir = null;
- ast[i].filtered = false;
- ast[i].find = false;
- nodes[i] = [];
- }
- } else {
- let cssAst;
- try {
- cssAst = parseSelector(selector);
- } catch (e) {
- return this.onError(e);
- }
- const { branches, info } = walkAST(cssAst);
- const {
- hasHasPseudoFunc,
- hasLogicalPseudoFunc,
- hasNthChildOfSelector,
- hasStatePseudoClass
- } = info;
- this.#invalidate = hasHasPseudoFunc || hasStatePseudoClass || !!(hasLogicalPseudoFunc && hasNthChildOfSelector);
- const processed = this._processSelectorBranches(branches, selector);
- ast = processed.ast;
- this.#descendant = processed.descendant;
- let cachedItem;
- if (this.#documentCache.has(this.#document)) {
- cachedItem = this.#documentCache.get(this.#document);
- } else {
- cachedItem = /* @__PURE__ */ new Map();
- }
- cachedItem.set(`${selector}`, {
- ast,
- descendant: this.#descendant,
- invalidate: this.#invalidate
- });
- this.#documentCache.set(this.#document, cachedItem);
- for (let i = 0; i < ast.length; i++) {
- nodes[i] = [];
- }
- }
- return [ast, nodes];
- };
- /**
- * Creates a TreeWalker.
- * @private
- * @param {object} node - The Document, DocumentFragment, or Element node.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.force] - Force creation of a new TreeWalker.
- * @param {number} [opt.whatToShow] - The NodeFilter whatToShow value.
- * @returns {object} The TreeWalker object.
- */
- _createTreeWalker = (node, opt = {}) => {
- const { force = false, whatToShow = SHOW_CONTAINER } = opt;
- if (force) {
- return this.#document.createTreeWalker(node, whatToShow);
- } else if (this.#walkers.has(node)) {
- return this.#walkers.get(node);
- }
- const walker = this.#document.createTreeWalker(node, whatToShow);
- this.#walkers.set(node, walker);
- return walker;
- };
- /**
- * Gets selector branches from cache or parses them.
- * @private
- * @param {object} selector - The AST.
- * @returns {Array.<Array.<object>>} The selector branches.
- */
- _getSelectorBranches = (selector) => {
- if (this.#astCache.has(selector)) {
- return this.#astCache.get(selector);
- }
- const { branches } = walkAST(selector);
- this.#astCache.set(selector, branches);
- return branches;
- };
- /**
- * Gets the children of a node, optionally filtered by a selector.
- * @private
- * @param {object} parentNode - The parent element.
- * @param {Array.<Array.<object>>} selectorBranches - The selector branches.
- * @param {object} [opt] - Options.
- * @returns {Array.<object>} An array of child nodes.
- */
- _getFilteredChildren = (parentNode, selectorBranches, opt = {}) => {
- const children = [];
- const walker = this._createTreeWalker(parentNode, { force: true });
- let childNode = walker.firstChild();
- while (childNode) {
- if (selectorBranches) {
- if (isVisible(childNode)) {
- let isMatch = false;
- const l = selectorBranches.length;
- for (let i = 0; i < l; i++) {
- const leaves = selectorBranches[i];
- if (this._matchLeaves(leaves, childNode, opt)) {
- isMatch = true;
- break;
- }
- }
- if (isMatch) {
- children.push(childNode);
- }
- }
- } else {
- children.push(childNode);
- }
- childNode = walker.nextSibling();
- }
- return children;
- };
- /**
- * Collects nth-child nodes.
- * @private
- * @param {object} anb - An+B options.
- * @param {number} anb.a - The 'a' value.
- * @param {number} anb.b - The 'b' value.
- * @param {boolean} [anb.reverse] - If true, reverses the order.
- * @param {object} [anb.selector] - The AST.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _collectNthChild = (anb, node, opt = {}) => {
- const { a, b, selector } = anb;
- const { parentNode } = node;
- if (!parentNode) {
- const matchedNode = /* @__PURE__ */ new Set();
- if (node === this.#root && a * 1 + b * 1 === 1) {
- if (selector) {
- const selectorBranches2 = this._getSelectorBranches(selector);
- const l = selectorBranches2.length;
- for (let i = 0; i < l; i++) {
- const leaves = selectorBranches2[i];
- if (this._matchLeaves(leaves, node, opt)) {
- matchedNode.add(node);
- break;
- }
- }
- } else {
- matchedNode.add(node);
- }
- }
- return matchedNode;
- }
- const selectorBranches = selector ? this._getSelectorBranches(selector) : null;
- const children = this._getFilteredChildren(
- parentNode,
- selectorBranches,
- opt
- );
- const matchedNodes = filterNodesByAnB(children, anb);
- return new Set(matchedNodes);
- };
- /**
- * Collects nth-of-type nodes.
- * @private
- * @param {object} anb - An+B options.
- * @param {number} anb.a - The 'a' value.
- * @param {number} anb.b - The 'b' value.
- * @param {boolean} [anb.reverse] - If true, reverses the order.
- * @param {object} node - The Element node.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _collectNthOfType = (anb, node) => {
- const { parentNode } = node;
- if (!parentNode) {
- if (node === this.#root && anb.a * 1 + anb.b * 1 === 1) {
- return /* @__PURE__ */ new Set([node]);
- }
- return /* @__PURE__ */ new Set();
- }
- const typedSiblings = [];
- const walker = this._createTreeWalker(parentNode, { force: true });
- let sibling = walker.firstChild();
- while (sibling) {
- if (sibling.localName === node.localName && sibling.namespaceURI === node.namespaceURI && sibling.prefix === node.prefix) {
- typedSiblings.push(sibling);
- }
- sibling = walker.nextSibling();
- }
- const matchedNodes = filterNodesByAnB(typedSiblings, anb);
- return new Set(matchedNodes);
- };
- /**
- * Matches An+B.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Element node.
- * @param {string} nthName - The name of the nth pseudo-class.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchAnPlusB = (ast, node, nthName, opt = {}) => {
- const {
- nth: { a, b, name: nthIdentName },
- selector
- } = ast;
- const anbMap = /* @__PURE__ */ new Map();
- if (nthIdentName) {
- if (nthIdentName === "even") {
- anbMap.set("a", 2);
- anbMap.set("b", 0);
- } else if (nthIdentName === "odd") {
- anbMap.set("a", 2);
- anbMap.set("b", 1);
- }
- if (nthName.indexOf("last") > -1) {
- anbMap.set("reverse", true);
- }
- } else {
- if (typeof a === "string" && /-?\d+/.test(a)) {
- anbMap.set("a", a * 1);
- } else {
- anbMap.set("a", 0);
- }
- if (typeof b === "string" && /-?\d+/.test(b)) {
- anbMap.set("b", b * 1);
- } else {
- anbMap.set("b", 0);
- }
- if (nthName.indexOf("last") > -1) {
- anbMap.set("reverse", true);
- }
- }
- if (nthName === "nth-child" || nthName === "nth-last-child") {
- if (selector) {
- anbMap.set("selector", selector);
- }
- const anb = Object.fromEntries(anbMap);
- const nodes = this._collectNthChild(anb, node, opt);
- return nodes;
- } else if (nthName === "nth-of-type" || nthName === "nth-last-of-type") {
- const anb = Object.fromEntries(anbMap);
- const nodes = this._collectNthOfType(anb, node);
- return nodes;
- }
- return /* @__PURE__ */ new Set();
- };
- /**
- * Matches the :has() pseudo-class function.
- * @private
- * @param {Array.<object>} astLeaves - The AST leaves.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {boolean} The result.
- */
- _matchHasPseudoFunc = (astLeaves, node, opt = {}) => {
- if (Array.isArray(astLeaves) && astLeaves.length) {
- const leaves = [...astLeaves];
- const [leaf] = leaves;
- const { type: leafType } = leaf;
- let combo;
- if (leafType === COMBINATOR) {
- combo = leaves.shift();
- } else {
- combo = {
- name: " ",
- type: COMBINATOR
- };
- }
- const twigLeaves = [];
- while (leaves.length) {
- const [item] = leaves;
- const { type: itemType } = item;
- if (itemType === COMBINATOR) {
- break;
- } else {
- twigLeaves.push(leaves.shift());
- }
- }
- const twig = {
- combo,
- leaves: twigLeaves
- };
- opt.dir = DIR_NEXT;
- const nodes = this._matchCombinator(twig, node, opt);
- if (nodes.size) {
- if (leaves.length) {
- let bool = false;
- for (const nextNode of nodes) {
- bool = this._matchHasPseudoFunc(leaves, nextNode, opt);
- if (bool) {
- break;
- }
- }
- return bool;
- }
- return true;
- }
- }
- return false;
- };
- /**
- * Evaluates the :has() pseudo-class.
- * @private
- * @param {object} astData - The AST data.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {?object} The matched node.
- */
- _evaluateHasPseudo = (astData, node, opt) => {
- const { branches } = astData;
- let bool = false;
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const leaves = branches[i];
- bool = this._matchHasPseudoFunc(leaves, node, opt);
- if (bool) {
- break;
- }
- }
- if (!bool) {
- return null;
- }
- if ((opt.isShadowRoot || this.#shadow) && node.nodeType === DOCUMENT_FRAGMENT_NODE) {
- return this.#verifyShadowHost ? node : null;
- }
- return node;
- };
- /**
- * Matches logical pseudo-class functions.
- * @private
- * @param {object} astData - The AST data.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {?object} The matched node.
- */
- _matchLogicalPseudoFunc = (astData, node, opt = {}) => {
- const { astName, branches, twigBranches } = astData;
- if (astName === "has") {
- return this._evaluateHasPseudo(astData, node, opt);
- }
- const isShadowRoot = (opt.isShadowRoot || this.#shadow) && node.nodeType === DOCUMENT_FRAGMENT_NODE;
- if (isShadowRoot) {
- let invalid = false;
- for (const branch of branches) {
- if (branch.length > 1) {
- invalid = true;
- break;
- } else if (astName === "not") {
- const [{ type: childAstType }] = branch;
- if (childAstType !== PS_CLASS_SELECTOR) {
- invalid = true;
- break;
- }
- }
- }
- if (invalid) {
- return null;
- }
- }
- opt.forgive = astName === "is" || astName === "where";
- const l = twigBranches.length;
- let bool;
- for (let i = 0; i < l; i++) {
- const branch = twigBranches[i];
- const lastIndex = branch.length - 1;
- const { leaves } = branch[lastIndex];
- bool = this._matchLeaves(leaves, node, opt);
- if (bool && lastIndex > 0) {
- let nextNodes = /* @__PURE__ */ new Set([node]);
- for (let j = lastIndex - 1; j >= 0; j--) {
- const twig = branch[j];
- const arr = [];
- opt.dir = DIR_PREV;
- for (const nextNode of nextNodes) {
- const m = this._matchCombinator(twig, nextNode, opt);
- if (m.size) {
- arr.push(...m);
- }
- }
- if (arr.length) {
- if (j === 0) {
- bool = true;
- } else {
- nextNodes = new Set(arr);
- }
- } else {
- bool = false;
- break;
- }
- }
- }
- if (bool) {
- break;
- }
- }
- if (astName === "not") {
- if (bool) {
- return null;
- }
- return node;
- } else if (bool) {
- return node;
- }
- return null;
- };
- /**
- * match pseudo-class selector
- * @private
- * @see https://html.spec.whatwg.org/#pseudo-classes
- * @param {object} ast - AST
- * @param {object} node - Element node
- * @param {object} [opt] - options
- * @returns {Set.<object>} - collection of matched nodes
- */
- _matchPseudoClassSelector(ast, node, opt = {}) {
- const { children: astChildren, name: astName } = ast;
- const { localName, parentNode } = node;
- const { forgive, warn = this.#warn } = opt;
- const matched = /* @__PURE__ */ new Set();
- if (Array.isArray(astChildren) && KEYS_LOGICAL.has(astName)) {
- if (!astChildren.length && astName !== "is" && astName !== "where") {
- const css = (0, import_css_tree.generate)(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- let astData;
- if (this.#astCache.has(ast)) {
- astData = this.#astCache.get(ast);
- } else {
- const { branches } = walkAST(ast);
- if (astName === "has") {
- let forgiven = false;
- const l = astChildren.length;
- for (let i = 0; i < l; i++) {
- const child = astChildren[i];
- const item = (0, import_css_tree.find)(child, findLogicalWithNestedHas);
- if (item) {
- const itemName = item.name;
- if (itemName === "is" || itemName === "where") {
- forgiven = true;
- break;
- } else {
- const css = (0, import_css_tree.generate)(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(
- generateException(msg, SYNTAX_ERR, this.#window)
- );
- }
- }
- }
- if (forgiven) {
- return matched;
- }
- astData = {
- astName,
- branches
- };
- } else {
- const twigBranches = [];
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const [...leaves] = branches[i];
- const branch = [];
- const leavesSet = /* @__PURE__ */ new Set();
- let item = leaves.shift();
- while (item) {
- if (item.type === COMBINATOR) {
- branch.push({
- combo: item,
- leaves: [...leavesSet]
- });
- leavesSet.clear();
- } else if (item) {
- leavesSet.add(item);
- }
- if (leaves.length) {
- item = leaves.shift();
- } else {
- branch.push({
- combo: null,
- leaves: [...leavesSet]
- });
- leavesSet.clear();
- break;
- }
- }
- twigBranches.push(branch);
- }
- astData = {
- astName,
- branches,
- twigBranches
- };
- this.#astCache.set(ast, astData);
- }
- }
- const res = this._matchLogicalPseudoFunc(astData, node, opt);
- if (res) {
- matched.add(res);
- }
- } else if (Array.isArray(astChildren)) {
- if (/^nth-(?:last-)?(?:child|of-type)$/.test(astName)) {
- if (astChildren.length !== 1) {
- const css = (0, import_css_tree.generate)(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- const [branch] = astChildren;
- const nodes = this._matchAnPlusB(branch, node, astName, opt);
- return nodes;
- } else {
- switch (astName) {
- // :dir()
- case "dir": {
- if (astChildren.length !== 1) {
- const css = (0, import_css_tree.generate)(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- const [astChild] = astChildren;
- const res = matchDirectionPseudoClass(astChild, node);
- if (res) {
- matched.add(node);
- }
- break;
- }
- // :lang()
- case "lang": {
- if (!astChildren.length) {
- const css = (0, import_css_tree.generate)(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- let bool;
- for (const astChild of astChildren) {
- bool = matchLanguagePseudoClass(astChild, node);
- if (bool) {
- break;
- }
- }
- if (bool) {
- matched.add(node);
- }
- break;
- }
- // :state()
- case "state": {
- if (isCustomElement(node)) {
- const [{ value: stateValue }] = astChildren;
- if (stateValue) {
- if (node[stateValue]) {
- matched.add(node);
- } else {
- for (const i in node) {
- const prop = node[i];
- if (prop instanceof this.#window.ElementInternals) {
- if (prop?.states?.has(stateValue)) {
- matched.add(node);
- }
- break;
- }
- }
- }
- }
- }
- break;
- }
- case "current":
- case "heading":
- case "nth-col":
- case "nth-last-col": {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}()`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- // Ignore :host() and :host-context().
- case "host":
- case "host-context": {
- break;
- }
- // Deprecated in CSS Selectors 3.
- case "contains": {
- if (warn) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}()`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- default: {
- if (!forgive) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}()`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- }
- }
- }
- } else if (KEYS_PS_NTH_OF_TYPE.has(astName)) {
- if (node === this.#root) {
- matched.add(node);
- } else if (parentNode) {
- switch (astName) {
- case "first-of-type": {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1
- },
- node
- );
- if (node1) {
- matched.add(node1);
- }
- break;
- }
- case "last-of-type": {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1,
- reverse: true
- },
- node
- );
- if (node1) {
- matched.add(node1);
- }
- break;
- }
- // 'only-of-type' is handled by default.
- default: {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1
- },
- node
- );
- if (node1 === node) {
- const [node2] = this._collectNthOfType(
- {
- a: 0,
- b: 1,
- reverse: true
- },
- node
- );
- if (node2 === node) {
- matched.add(node);
- }
- }
- }
- }
- }
- } else {
- switch (astName) {
- case "disabled":
- case "enabled": {
- const isMatch = matchDisabledPseudoClass(astName, node);
- if (isMatch) {
- matched.add(node);
- }
- break;
- }
- case "read-only":
- case "read-write": {
- const isMatch = matchReadOnlyPseudoClass(astName, node);
- if (isMatch) {
- matched.add(node);
- }
- break;
- }
- case "any-link":
- case "link": {
- if ((localName === "a" || localName === "area") && node.hasAttribute("href")) {
- matched.add(node);
- }
- break;
- }
- case "local-link": {
- if ((localName === "a" || localName === "area") && node.hasAttribute("href")) {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { href, origin, pathname } = this.#documentURL;
- const attrURL = new URL(node.getAttribute("href"), href);
- if (attrURL.origin === origin && attrURL.pathname === pathname) {
- matched.add(node);
- }
- }
- break;
- }
- case "visited": {
- break;
- }
- case "hover": {
- const { target, type } = this.#event ?? {};
- if (/^(?:click|mouse(?:down|over|up))$/.test(type) && node.contains(target)) {
- matched.add(node);
- }
- break;
- }
- case "active": {
- const { buttons, target, type } = this.#event ?? {};
- if (type === "mousedown" && buttons & 1 && node.contains(target)) {
- matched.add(node);
- }
- break;
- }
- case "target": {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { hash } = this.#documentURL;
- if (node.id && hash === `#${node.id}` && this.#document.contains(node)) {
- matched.add(node);
- }
- break;
- }
- case "target-within": {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { hash } = this.#documentURL;
- if (hash) {
- const id = hash.replace(/^#/, "");
- let current = this.#document.getElementById(id);
- while (current) {
- if (current === node) {
- matched.add(node);
- break;
- }
- current = current.parentNode;
- }
- }
- break;
- }
- case "scope": {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (!this.#shadow && node === this.#node) {
- matched.add(node);
- }
- } else if (node === this.#document.documentElement) {
- matched.add(node);
- }
- break;
- }
- case "focus": {
- const activeElement = this.#document.activeElement;
- if (node === activeElement && isFocusableArea(node)) {
- matched.add(node);
- } else if (activeElement.shadowRoot) {
- const activeShadowElement = activeElement.shadowRoot.activeElement;
- let current = activeShadowElement;
- while (current) {
- if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {
- const { host } = current;
- if (host === activeElement) {
- if (isFocusableArea(node)) {
- matched.add(node);
- } else {
- matched.add(host);
- }
- }
- break;
- } else {
- current = current.parentNode;
- }
- }
- }
- break;
- }
- case "focus-visible": {
- if (node === this.#document.activeElement && isFocusableArea(node)) {
- let bool;
- if (isFocusVisible(node)) {
- bool = true;
- } else if (this.#focus) {
- const { relatedTarget, target: focusTarget } = this.#focus;
- if (focusTarget === node) {
- if (isFocusVisible(relatedTarget)) {
- bool = true;
- } else if (this.#event) {
- const {
- altKey: eventAltKey,
- ctrlKey: eventCtrlKey,
- key: eventKey,
- metaKey: eventMetaKey,
- target: eventTarget,
- type: eventType
- } = this.#event;
- if (eventTarget === relatedTarget) {
- if (this.#lastFocusVisible === null) {
- bool = true;
- } else if (focusTarget === this.#lastFocusVisible) {
- bool = true;
- }
- } else if (eventKey === "Tab") {
- if (eventType === "keydown" && eventTarget !== node || eventType === "keyup" && eventTarget === node) {
- if (eventTarget === focusTarget) {
- if (this.#lastFocusVisible === null) {
- bool = true;
- } else if (eventTarget === this.#lastFocusVisible && relatedTarget === null) {
- bool = true;
- }
- } else {
- bool = true;
- }
- }
- } else if (eventKey) {
- if ((eventType === "keydown" || eventType === "keyup") && !eventAltKey && !eventCtrlKey && !eventMetaKey && eventTarget === node) {
- bool = true;
- }
- }
- } else if (relatedTarget === null || relatedTarget === this.#lastFocusVisible) {
- bool = true;
- }
- }
- }
- if (bool) {
- this.#lastFocusVisible = node;
- matched.add(node);
- } else if (this.#lastFocusVisible === node) {
- this.#lastFocusVisible = null;
- }
- }
- break;
- }
- case "focus-within": {
- const activeElement = this.#document.activeElement;
- if (node.contains(activeElement) && isFocusableArea(activeElement)) {
- matched.add(node);
- } else if (activeElement.shadowRoot) {
- const activeShadowElement = activeElement.shadowRoot.activeElement;
- if (node.contains(activeShadowElement)) {
- matched.add(node);
- } else {
- let current = activeShadowElement;
- while (current) {
- if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {
- const { host } = current;
- if (host === activeElement && node.contains(host)) {
- matched.add(node);
- }
- break;
- } else {
- current = current.parentNode;
- }
- }
- }
- }
- break;
- }
- case "open":
- case "closed": {
- if (localName === "details" || localName === "dialog") {
- if (node.hasAttribute("open")) {
- if (astName === "open") {
- matched.add(node);
- }
- } else if (astName === "closed") {
- matched.add(node);
- }
- }
- break;
- }
- case "placeholder-shown": {
- let placeholder;
- if (node.placeholder) {
- placeholder = node.placeholder;
- } else if (node.hasAttribute("placeholder")) {
- placeholder = node.getAttribute("placeholder");
- }
- if (typeof placeholder === "string" && !/[\r\n]/.test(placeholder)) {
- let targetNode;
- if (localName === "textarea") {
- targetNode = node;
- } else if (localName === "input") {
- if (node.hasAttribute("type")) {
- if (KEYS_INPUT_PLACEHOLDER.has(node.getAttribute("type"))) {
- targetNode = node;
- }
- } else {
- targetNode = node;
- }
- }
- if (targetNode && node.value === "") {
- matched.add(node);
- }
- }
- break;
- }
- case "checked": {
- const attrType = node.getAttribute("type");
- if (node.checked && localName === "input" && (attrType === "checkbox" || attrType === "radio") || node.selected && localName === "option") {
- matched.add(node);
- }
- break;
- }
- case "indeterminate": {
- if (node.indeterminate && localName === "input" && node.type === "checkbox" || localName === "progress" && !node.hasAttribute("value")) {
- matched.add(node);
- } else if (localName === "input" && node.type === "radio" && !node.hasAttribute("checked")) {
- const nodeName = node.name;
- let parent = node.parentNode;
- while (parent) {
- if (parent.localName === "form") {
- break;
- }
- parent = parent.parentNode;
- }
- if (!parent) {
- parent = this.#document.documentElement;
- }
- const walker = this._createTreeWalker(parent);
- let refNode = traverseNode(parent, walker);
- refNode = walker.firstChild();
- let checked;
- while (refNode) {
- if (refNode.localName === "input" && refNode.getAttribute("type") === "radio") {
- if (refNode.hasAttribute("name")) {
- if (refNode.getAttribute("name") === nodeName) {
- checked = !!refNode.checked;
- }
- } else {
- checked = !!refNode.checked;
- }
- if (checked) {
- break;
- }
- }
- refNode = walker.nextNode();
- }
- if (!checked) {
- matched.add(node);
- }
- }
- break;
- }
- case "default": {
- const attrType = node.getAttribute("type");
- if (localName === "button" && !(node.hasAttribute("type") && KEYS_INPUT_RESET.has(attrType)) || localName === "input" && node.hasAttribute("type") && KEYS_INPUT_SUBMIT.has(attrType)) {
- let form = node.parentNode;
- while (form) {
- if (form.localName === "form") {
- break;
- }
- form = form.parentNode;
- }
- if (form) {
- const walker = this._createTreeWalker(form);
- let refNode = traverseNode(form, walker);
- refNode = walker.firstChild();
- while (refNode) {
- const nodeName = refNode.localName;
- const nodeAttrType = refNode.getAttribute("type");
- let m;
- if (nodeName === "button") {
- m = !(refNode.hasAttribute("type") && KEYS_INPUT_RESET.has(nodeAttrType));
- } else if (nodeName === "input") {
- m = refNode.hasAttribute("type") && KEYS_INPUT_SUBMIT.has(nodeAttrType);
- }
- if (m) {
- if (refNode === node) {
- matched.add(node);
- }
- break;
- }
- refNode = walker.nextNode();
- }
- }
- } else if (localName === "input" && node.hasAttribute("type") && node.hasAttribute("checked") && KEYS_INPUT_CHECK.has(attrType)) {
- matched.add(node);
- } else if (localName === "option" && node.hasAttribute("selected")) {
- matched.add(node);
- }
- break;
- }
- case "valid":
- case "invalid": {
- if (KEYS_FORM_PS_VALID.has(localName)) {
- let valid;
- if (node.checkValidity()) {
- if (node.maxLength >= 0) {
- if (node.maxLength >= node.value.length) {
- valid = true;
- }
- } else {
- valid = true;
- }
- }
- if (valid) {
- if (astName === "valid") {
- matched.add(node);
- }
- } else if (astName === "invalid") {
- matched.add(node);
- }
- } else if (localName === "fieldset") {
- const walker = this._createTreeWalker(node);
- let refNode = traverseNode(node, walker);
- refNode = walker.firstChild();
- let valid;
- if (!refNode) {
- valid = true;
- } else {
- while (refNode) {
- if (KEYS_FORM_PS_VALID.has(refNode.localName)) {
- if (refNode.checkValidity()) {
- if (refNode.maxLength >= 0) {
- valid = refNode.maxLength >= refNode.value.length;
- } else {
- valid = true;
- }
- } else {
- valid = false;
- }
- if (!valid) {
- break;
- }
- }
- refNode = walker.nextNode();
- }
- }
- if (valid) {
- if (astName === "valid") {
- matched.add(node);
- }
- } else if (astName === "invalid") {
- matched.add(node);
- }
- }
- break;
- }
- case "in-range":
- case "out-of-range": {
- const attrType = node.getAttribute("type");
- if (localName === "input" && !(node.readonly || node.hasAttribute("readonly")) && !(node.disabled || node.hasAttribute("disabled")) && KEYS_INPUT_RANGE.has(attrType)) {
- const flowed = node.validity.rangeUnderflow || node.validity.rangeOverflow;
- if (astName === "out-of-range" && flowed) {
- matched.add(node);
- } else if (astName === "in-range" && !flowed && (node.hasAttribute("min") || node.hasAttribute("max") || attrType === "range")) {
- matched.add(node);
- }
- }
- break;
- }
- case "required":
- case "optional": {
- let required;
- let optional;
- if (localName === "select" || localName === "textarea") {
- if (node.required || node.hasAttribute("required")) {
- required = true;
- } else {
- optional = true;
- }
- } else if (localName === "input") {
- if (node.hasAttribute("type")) {
- const attrType = node.getAttribute("type");
- if (KEYS_INPUT_REQUIRED.has(attrType)) {
- if (node.required || node.hasAttribute("required")) {
- required = true;
- } else {
- optional = true;
- }
- } else {
- optional = true;
- }
- } else if (node.required || node.hasAttribute("required")) {
- required = true;
- } else {
- optional = true;
- }
- }
- if (astName === "required" && required) {
- matched.add(node);
- } else if (astName === "optional" && optional) {
- matched.add(node);
- }
- break;
- }
- case "root": {
- if (node === this.#document.documentElement) {
- matched.add(node);
- }
- break;
- }
- case "empty": {
- if (node.hasChildNodes()) {
- const walker = this._createTreeWalker(node, {
- force: true,
- whatToShow: SHOW_ALL
- });
- let refNode = walker.firstChild();
- let bool;
- while (refNode) {
- bool = refNode.nodeType !== ELEMENT_NODE && refNode.nodeType !== TEXT_NODE;
- if (!bool) {
- break;
- }
- refNode = walker.nextSibling();
- }
- if (bool) {
- matched.add(node);
- }
- } else {
- matched.add(node);
- }
- break;
- }
- case "first-child": {
- if (parentNode && node === parentNode.firstElementChild || node === this.#root) {
- matched.add(node);
- }
- break;
- }
- case "last-child": {
- if (parentNode && node === parentNode.lastElementChild || node === this.#root) {
- matched.add(node);
- }
- break;
- }
- case "only-child": {
- if (parentNode && node === parentNode.firstElementChild && node === parentNode.lastElementChild || node === this.#root) {
- matched.add(node);
- }
- break;
- }
- case "defined": {
- if (node.hasAttribute("is") || localName.includes("-")) {
- if (isCustomElement(node)) {
- matched.add(node);
- }
- } else if (node instanceof this.#window.HTMLElement || node instanceof this.#window.SVGElement) {
- matched.add(node);
- }
- break;
- }
- case "popover-open": {
- if (node.popover && isVisible(node)) {
- matched.add(node);
- }
- break;
- }
- // Ignore :host.
- case "host": {
- break;
- }
- // Legacy pseudo-elements.
- case "after":
- case "before":
- case "first-letter":
- case "first-line": {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- // Not supported.
- case "autofill":
- case "blank":
- case "buffering":
- case "current":
- case "fullscreen":
- case "future":
- case "has-slotted":
- case "heading":
- case "modal":
- case "muted":
- case "past":
- case "paused":
- case "picture-in-picture":
- case "playing":
- case "seeking":
- case "stalled":
- case "user-invalid":
- case "user-valid":
- case "volume-locked":
- case "-webkit-autofill": {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- default: {
- if (astName.startsWith("-webkit-")) {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- } else if (!forgive) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- }
- }
- }
- return matched;
- }
- /**
- * Evaluates the :host() pseudo-class.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} host - The host element.
- * @param {object} ast - The original AST for error reporting.
- * @returns {boolean} True if matched.
- */
- _evaluateHostPseudo = (leaves, host, ast) => {
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- if (leaf.type === COMBINATOR) {
- const css = (0, import_css_tree.generate)(ast);
- const msg = `Invalid selector ${css}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- return false;
- }
- if (!this._matchSelector(leaf, host).has(host)) {
- return false;
- }
- }
- return true;
- };
- /**
- * Evaluates the :host-context() pseudo-class.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} host - The host element.
- * @param {object} ast - The original AST for error reporting.
- * @returns {boolean} True if matched.
- */
- _evaluateHostContextPseudo = (leaves, host, ast) => {
- let parent = host;
- while (parent) {
- let bool;
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- if (leaf.type === COMBINATOR) {
- const css = (0, import_css_tree.generate)(ast);
- const msg = `Invalid selector ${css}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- return false;
- }
- bool = this._matchSelector(leaf, parent).has(parent);
- if (!bool) {
- break;
- }
- }
- if (bool) {
- return true;
- }
- parent = parent.parentNode;
- }
- return false;
- };
- /**
- * Matches shadow host pseudo-classes.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The DocumentFragment node.
- * @returns {?object} The matched node.
- */
- _matchShadowHostPseudoClass = (ast, node) => {
- const { children: astChildren, name: astName } = ast;
- if (!Array.isArray(astChildren)) {
- if (astName === "host") {
- return node;
- }
- const msg = `Invalid selector :${astName}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- if (astName !== "host" && astName !== "host-context") {
- const msg = `Invalid selector :${astName}()`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- if (astChildren.length !== 1) {
- const css = (0, import_css_tree.generate)(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- const { host } = node;
- const { branches } = walkAST(astChildren[0]);
- const [branch] = branches;
- const [...leaves] = branch;
- let isMatch = false;
- if (astName === "host") {
- isMatch = this._evaluateHostPseudo(leaves, host, ast);
- } else {
- isMatch = this._evaluateHostContextPseudo(leaves, host, ast);
- }
- return isMatch ? node : null;
- };
- /**
- * Matches a selector for element nodes.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelectorForElement = (ast, node, opt = {}) => {
- const { type: astType } = ast;
- const astName = unescapeSelector(ast.name);
- const matched = /* @__PURE__ */ new Set();
- switch (astType) {
- case ATTR_SELECTOR: {
- if (matchAttributeSelector(ast, node, opt)) {
- matched.add(node);
- }
- break;
- }
- case ID_SELECTOR: {
- if (node.id === astName) {
- matched.add(node);
- }
- break;
- }
- case CLASS_SELECTOR: {
- if (node.classList.contains(astName)) {
- matched.add(node);
- }
- break;
- }
- case PS_CLASS_SELECTOR: {
- return this._matchPseudoClassSelector(ast, node, opt);
- }
- case TYPE_SELECTOR: {
- if (matchTypeSelector(ast, node, opt)) {
- matched.add(node);
- }
- break;
- }
- // PS_ELEMENT_SELECTOR is handled by default.
- default: {
- try {
- if (opt.check) {
- const css = (0, import_css_tree.generate)(ast);
- this.#pseudoElement.push(css);
- matched.add(node);
- } else {
- matchPseudoElementSelector(astName, astType, opt);
- }
- } catch (e) {
- this.onError(e);
- }
- }
- }
- return matched;
- };
- /**
- * Matches a selector for a shadow root.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The DocumentFragment node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelectorForShadowRoot = (ast, node, opt = {}) => {
- const { name: astName } = ast;
- if (KEYS_LOGICAL.has(astName)) {
- opt.isShadowRoot = true;
- return this._matchPseudoClassSelector(ast, node, opt);
- }
- const matched = /* @__PURE__ */ new Set();
- if (astName === "host" || astName === "host-context") {
- const res = this._matchShadowHostPseudoClass(ast, node, opt);
- if (res) {
- this.#verifyShadowHost = true;
- matched.add(res);
- }
- }
- return matched;
- };
- /**
- * Matches a selector.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Document, DocumentFragment, or Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelector = (ast, node, opt = {}) => {
- if (node.nodeType === ELEMENT_NODE) {
- return this._matchSelectorForElement(ast, node, opt);
- }
- if (this.#shadow && node.nodeType === DOCUMENT_FRAGMENT_NODE && ast.type === PS_CLASS_SELECTOR) {
- return this._matchSelectorForShadowRoot(ast, node, opt);
- }
- return /* @__PURE__ */ new Set();
- };
- /**
- * Matches leaves.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node.
- * @param {object} [opt] - Options.
- * @returns {boolean} The result.
- */
- _matchLeaves = (leaves, node, opt = {}) => {
- const results = this.#invalidate ? this.#invalidateResults : this.#results;
- let result = results.get(leaves);
- if (result && result.has(node)) {
- const { matched } = result.get(node);
- return matched;
- }
- let cacheable = true;
- if (node.nodeType === ELEMENT_NODE && KEYS_FORM.has(node.localName)) {
- cacheable = false;
- }
- let bool;
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- switch (leaf.type) {
- case ATTR_SELECTOR:
- case ID_SELECTOR: {
- cacheable = false;
- break;
- }
- case PS_CLASS_SELECTOR: {
- if (KEYS_PS_UNCACHE.has(leaf.name)) {
- cacheable = false;
- }
- break;
- }
- default: {
- }
- }
- bool = this._matchSelector(leaf, node, opt).has(node);
- if (!bool) {
- break;
- }
- }
- if (cacheable) {
- if (!result) {
- result = /* @__PURE__ */ new WeakMap();
- }
- result.set(node, {
- matched: bool
- });
- results.set(leaves, result);
- }
- return bool;
- };
- /**
- * Traverses all descendant nodes and collects matches.
- * @private
- * @param {object} baseNode - The base Element node or Element.shadowRoot.
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _traverseAllDescendants = (baseNode, leaves, opt = {}) => {
- const walker = this._createTreeWalker(baseNode);
- traverseNode(baseNode, walker);
- let currentNode = walker.firstChild();
- const nodes = /* @__PURE__ */ new Set();
- while (currentNode) {
- if (this._matchLeaves(leaves, currentNode, opt)) {
- nodes.add(currentNode);
- }
- currentNode = walker.nextNode();
- }
- return nodes;
- };
- /**
- * Finds descendant nodes.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} baseNode - The base Element node or Element.shadowRoot.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _findDescendantNodes = (leaves, baseNode, opt = {}) => {
- const [leaf, ...filterLeaves] = leaves;
- const { type: leafType } = leaf;
- switch (leafType) {
- case ID_SELECTOR: {
- const canUseGetElementById = !this.#shadow && baseNode.nodeType === ELEMENT_NODE && this.#root.nodeType !== ELEMENT_NODE;
- if (canUseGetElementById) {
- const leafName = unescapeSelector(leaf.name);
- const nodes = /* @__PURE__ */ new Set();
- const foundNode = this.#root.getElementById(leafName);
- if (foundNode && foundNode !== baseNode && baseNode.contains(foundNode)) {
- const isCompoundSelector = filterLeaves.length > 0;
- if (!isCompoundSelector || this._matchLeaves(filterLeaves, foundNode, opt)) {
- nodes.add(foundNode);
- }
- }
- return nodes;
- }
- return this._traverseAllDescendants(baseNode, leaves, opt);
- }
- case PS_ELEMENT_SELECTOR: {
- const leafName = unescapeSelector(leaf.name);
- matchPseudoElementSelector(leafName, leafType, opt);
- return /* @__PURE__ */ new Set();
- }
- default: {
- return this._traverseAllDescendants(baseNode, leaves, opt);
- }
- }
- };
- /**
- * Matches the descendant combinator ' '.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchDescendantCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { parentNode } = node;
- const { dir } = opt;
- if (dir === DIR_NEXT) {
- return this._findDescendantNodes(leaves, node, opt);
- }
- const ancestors = [];
- let refNode = parentNode;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- ancestors.push(refNode);
- }
- refNode = refNode.parentNode;
- }
- if (ancestors.length) {
- return new Set(ancestors.reverse());
- }
- return /* @__PURE__ */ new Set();
- };
- /**
- * Matches the child combinator '>'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchChildCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const { parentNode } = node;
- const matched = /* @__PURE__ */ new Set();
- if (dir === DIR_NEXT) {
- let refNode = node.firstElementChild;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- refNode = refNode.nextElementSibling;
- }
- } else {
- if (parentNode && this._matchLeaves(leaves, parentNode, opt)) {
- matched.add(parentNode);
- }
- }
- return matched;
- };
- /**
- * Matches the adjacent sibling combinator '+'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchAdjacentSiblingCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const matched = /* @__PURE__ */ new Set();
- const refNode = dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;
- if (refNode && this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- return matched;
- };
- /**
- * Matches the general sibling combinator '~'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchGeneralSiblingCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const matched = /* @__PURE__ */ new Set();
- let refNode = dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- refNode = dir === DIR_NEXT ? refNode.nextElementSibling : refNode.previousElementSibling;
- }
- return matched;
- };
- /**
- * Matches a combinator.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchCombinator = (twig, node, opt = {}) => {
- const {
- combo: { name: comboName }
- } = twig;
- switch (comboName) {
- case "+": {
- return this._matchAdjacentSiblingCombinator(twig, node, opt);
- }
- case "~": {
- return this._matchGeneralSiblingCombinator(twig, node, opt);
- }
- case ">": {
- return this._matchChildCombinator(twig, node, opt);
- }
- case " ":
- default: {
- return this._matchDescendantCombinator(twig, node, opt);
- }
- }
- };
- /**
- * Traverses with a TreeWalker and collects nodes matching the leaves.
- * @private
- * @param {TreeWalker} walker - The TreeWalker instance to use.
- * @param {Array} leaves - The AST leaves to match against.
- * @param {object} options - Traversal options.
- * @param {Node} options.startNode - The node to start traversal from.
- * @param {string} options.targetType - The type of target ('all' or 'first').
- * @param {Node} [options.boundaryNode] - The node to stop traversal at.
- * @param {boolean} [options.force] - Force traversal to the next node.
- * @returns {Array.<Node>} An array of matched nodes.
- */
- _traverseAndCollectNodes = (walker, leaves, options) => {
- const { boundaryNode, force, startNode, targetType } = options;
- const collectedNodes = [];
- let currentNode = traverseNode(startNode, walker, !!force);
- if (!currentNode) {
- return [];
- }
- if (currentNode.nodeType !== ELEMENT_NODE) {
- currentNode = walker.nextNode();
- } else if (currentNode === startNode && currentNode !== this.#root) {
- currentNode = walker.nextNode();
- }
- const matchOpt = {
- warn: this.#warn
- };
- while (currentNode) {
- if (boundaryNode) {
- if (currentNode === boundaryNode) {
- break;
- } else if (targetType === TARGET_ALL && !boundaryNode.contains(currentNode)) {
- break;
- }
- }
- if (this._matchLeaves(leaves, currentNode, matchOpt) && currentNode !== this.#node) {
- collectedNodes.push(currentNode);
- if (targetType !== TARGET_ALL) {
- break;
- }
- }
- currentNode = walker.nextNode();
- }
- return collectedNodes;
- };
- /**
- * Finds matched node(s) preceding this.#node.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node to start from.
- * @param {object} opt - Options.
- * @param {boolean} [opt.force] - If true, traverses only to the next node.
- * @param {string} [opt.targetType] - The target type.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _findPrecede = (leaves, node, opt = {}) => {
- const { force, targetType } = opt;
- if (!this.#rootWalker) {
- this.#rootWalker = this._createTreeWalker(this.#root);
- }
- return this._traverseAndCollectNodes(this.#rootWalker, leaves, {
- force,
- targetType,
- boundaryNode: this.#node,
- startNode: node
- });
- };
- /**
- * Finds matched node(s) in #nodeWalker.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node to start from.
- * @param {object} opt - Options.
- * @param {boolean} [opt.precede] - If true, finds preceding nodes.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _findNodeWalker = (leaves, node, opt = {}) => {
- const { precede, ...traversalOpts } = opt;
- if (precede) {
- const precedeNodes = this._findPrecede(leaves, this.#root, opt);
- if (precedeNodes.length) {
- return precedeNodes;
- }
- }
- if (!this.#nodeWalker) {
- this.#nodeWalker = this._createTreeWalker(this.#node);
- }
- return this._traverseAndCollectNodes(this.#nodeWalker, leaves, {
- startNode: node,
- ...traversalOpts
- });
- };
- /**
- * Matches the node itself.
- * @private
- * @param {Array} leaves - The AST leaves.
- * @param {boolean} check - Indicates if running in internal check().
- * @returns {Array} An array containing [nodes, filtered, pseudoElement].
- */
- _matchSelf = (leaves, check = false) => {
- const options = { check, warn: this.#warn };
- const matched = this._matchLeaves(leaves, this.#node, options);
- const nodes = matched ? [this.#node] : [];
- return [nodes, matched, this.#pseudoElement];
- };
- /**
- * Finds lineal nodes (self and ancestors).
- * @private
- * @param {Array} leaves - The AST leaves.
- * @param {object} opt - Options.
- * @returns {Array} An array containing [nodes, filtered].
- */
- _findLineal = (leaves, opt) => {
- const { complex } = opt;
- const nodes = [];
- const options = { warn: this.#warn };
- const selfMatched = this._matchLeaves(leaves, this.#node, options);
- if (selfMatched) {
- nodes.push(this.#node);
- }
- if (!selfMatched || complex) {
- let currentNode = this.#node.parentNode;
- while (currentNode) {
- if (this._matchLeaves(leaves, currentNode, options)) {
- nodes.push(currentNode);
- }
- currentNode = currentNode.parentNode;
- }
- }
- const filtered = nodes.length > 0;
- return [nodes, filtered];
- };
- /**
- * Finds entry nodes for pseudo-element selectors.
- * @private
- * @param {object} leaf - The pseudo-element leaf from the AST.
- * @param {Array.<object>} filterLeaves - Leaves for compound selectors.
- * @param {string} targetType - The type of target to find.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForPseudoElement = (leaf, filterLeaves, targetType) => {
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF && this.#check) {
- const css = (0, import_css_tree.generate)(leaf);
- this.#pseudoElement.push(css);
- if (filterLeaves.length) {
- [nodes, filtered] = this._matchSelf(filterLeaves, this.#check);
- } else {
- nodes.push(this.#node);
- filtered = true;
- }
- } else {
- matchPseudoElementSelector(leaf.name, leaf.type, { warn: this.#warn });
- }
- return { nodes, filtered, pending: false };
- };
- /**
- * Finds entry nodes for ID selectors.
- * @private
- * @param {object} twig - The current twig from the AST branch.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForId = (twig, targetType, opt) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else if (targetType === TARGET_FIRST && this.#root.nodeType !== ELEMENT_NODE) {
- const node = this.#root.getElementById(leaf.name);
- if (node) {
- if (filterLeaves.length) {
- if (this._matchLeaves(filterLeaves, node, { warn: this.#warn })) {
- nodes.push(node);
- filtered = true;
- }
- } else {
- nodes.push(node);
- filtered = true;
- }
- }
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
- /**
- * Finds entry nodes for class selectors.
- * @private
- * @param {Array.<object>} leaves - The AST leaves for the selector.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForClass = (leaves, targetType, opt) => {
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
- /**
- * Finds entry nodes for type selectors.
- * @private
- * @param {Array.<object>} leaves - The AST leaves for the selector.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForType = (leaves, targetType, opt) => {
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
- /**
- * Finds entry nodes for other selector types (default case).
- * @private
- * @param {object} twig - The current twig from the AST branch.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForOther = (twig, targetType, opt) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- let pending = false;
- if (targetType !== TARGET_LINEAL && /host(?:-context)?/.test(leaf.name)) {
- let shadowRoot = null;
- if (this.#shadow && this.#node.nodeType === DOCUMENT_FRAGMENT_NODE) {
- shadowRoot = this._matchShadowHostPseudoClass(leaf, this.#node);
- } else if (filterLeaves.length && this.#node.nodeType === ELEMENT_NODE) {
- shadowRoot = this._matchShadowHostPseudoClass(
- leaf,
- this.#node.shadowRoot
- );
- }
- if (shadowRoot) {
- let bool = true;
- const l = filterLeaves.length;
- for (let i = 0; i < l; i++) {
- const filterLeaf = filterLeaves[i];
- switch (filterLeaf.name) {
- case "host":
- case "host-context": {
- const matchedNode = this._matchShadowHostPseudoClass(
- filterLeaf,
- shadowRoot
- );
- bool = matchedNode === shadowRoot;
- break;
- }
- case "has": {
- bool = this._matchPseudoClassSelector(
- filterLeaf,
- shadowRoot,
- {}
- ).has(shadowRoot);
- break;
- }
- default: {
- bool = false;
- }
- }
- if (!bool) {
- break;
- }
- }
- if (bool) {
- nodes.push(shadowRoot);
- filtered = true;
- }
- }
- } else if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else if (targetType === TARGET_FIRST) {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- } else {
- pending = true;
- }
- return { nodes, filtered, pending };
- };
- /**
- * Finds entry nodes.
- * @private
- * @param {object} twig - The twig object.
- * @param {string} targetType - The target type.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.complex] - If true, the selector is complex.
- * @param {string} [opt.dir] - The find direction.
- * @returns {object} An object with nodes and their state.
- */
- _findEntryNodes = (twig, targetType, opt = {}) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex = false, dir = DIR_PREV } = opt;
- const precede = dir === DIR_NEXT && this.#node.nodeType === ELEMENT_NODE && this.#node !== this.#root;
- let result;
- switch (leaf.type) {
- case PS_ELEMENT_SELECTOR: {
- result = this._findEntryNodesForPseudoElement(
- leaf,
- filterLeaves,
- targetType
- );
- break;
- }
- case ID_SELECTOR: {
- result = this._findEntryNodesForId(twig, targetType, {
- complex,
- precede
- });
- break;
- }
- case CLASS_SELECTOR: {
- result = this._findEntryNodesForClass(leaves, targetType, {
- complex,
- precede
- });
- break;
- }
- case TYPE_SELECTOR: {
- result = this._findEntryNodesForType(leaves, targetType, {
- complex,
- precede
- });
- break;
- }
- default: {
- result = this._findEntryNodesForOther(twig, targetType, {
- complex,
- precede
- });
- }
- }
- return {
- compound: filterLeaves.length > 0,
- filtered: result.filtered,
- nodes: result.nodes,
- pending: result.pending
- };
- };
- /**
- * Determines the direction and starting twig for a selector branch.
- * @private
- * @param {Array.<object>} branch - The AST branch.
- * @param {string} targetType - The type of target to find.
- * @returns {object} An object with the direction and starting twig.
- */
- _determineTraversalStrategy = (branch, targetType) => {
- const branchLen = branch.length;
- const firstTwig = branch[0];
- const lastTwig = branch[branchLen - 1];
- if (branchLen === 1) {
- return { dir: DIR_PREV, twig: firstTwig };
- }
- const {
- leaves: [{ name: firstName, type: firstType }]
- } = firstTwig;
- const {
- leaves: [{ name: lastName, type: lastType }]
- } = lastTwig;
- const { combo: firstCombo } = firstTwig;
- if (this.#selector.includes(":scope") || lastType === PS_ELEMENT_SELECTOR || lastType === ID_SELECTOR) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- if (firstType === ID_SELECTOR) {
- return { dir: DIR_NEXT, twig: firstTwig };
- }
- if (firstName === "*" && firstType === TYPE_SELECTOR) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- if (lastName === "*" && lastType === TYPE_SELECTOR) {
- return { dir: DIR_NEXT, twig: firstTwig };
- }
- if (branchLen === 2) {
- if (targetType === TARGET_FIRST) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- const { name: comboName } = firstCombo;
- if (comboName === "+" || comboName === "~") {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- } else if (branchLen > 2 && this.#scoped && targetType === TARGET_FIRST) {
- if (lastType === TYPE_SELECTOR) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- let isChildOrDescendant = false;
- for (const { combo } of branch) {
- if (combo) {
- const { name: comboName } = combo;
- isChildOrDescendant = comboName === ">" || comboName === " ";
- if (!isChildOrDescendant) {
- break;
- }
- }
- }
- if (isChildOrDescendant) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- }
- return { dir: DIR_NEXT, twig: firstTwig };
- };
- /**
- * Processes pending items not resolved with a direct strategy.
- * @private
- * @param {Set.<Map>} pendingItems - The set of pending items.
- */
- _processPendingItems = (pendingItems) => {
- if (!pendingItems.size) {
- return;
- }
- if (!this.#rootWalker) {
- this.#rootWalker = this._createTreeWalker(this.#root);
- }
- const walker = this.#rootWalker;
- let node = this.#root;
- if (this.#scoped) {
- node = this.#node;
- }
- let nextNode = traverseNode(node, walker);
- while (nextNode) {
- const isWithinScope = this.#node.nodeType !== ELEMENT_NODE || nextNode === this.#node || this.#node.contains(nextNode);
- if (isWithinScope) {
- for (const pendingItem of pendingItems) {
- const { leaves } = pendingItem.get("twig");
- if (this._matchLeaves(leaves, nextNode, { warn: this.#warn })) {
- const index = pendingItem.get("index");
- this.#ast[index].filtered = true;
- this.#ast[index].find = true;
- this.#nodes[index].push(nextNode);
- }
- }
- } else if (this.#scoped) {
- break;
- }
- nextNode = walker.nextNode();
- }
- };
- /**
- * Collects nodes.
- * @private
- * @param {string} targetType - The target type.
- * @returns {Array.<Array.<object>>} An array containing the AST and nodes.
- */
- _collectNodes = (targetType) => {
- const ast = this.#ast.values();
- if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {
- const pendingItems = /* @__PURE__ */ new Set();
- let i = 0;
- for (const { branch } of ast) {
- const complex = branch.length > 1;
- const { dir, twig } = this._determineTraversalStrategy(
- branch,
- targetType
- );
- const { compound, filtered, nodes, pending } = this._findEntryNodes(
- twig,
- targetType,
- { complex, dir }
- );
- if (nodes.length) {
- this.#ast[i].find = true;
- this.#nodes[i] = nodes;
- } else if (pending) {
- pendingItems.add(
- /* @__PURE__ */ new Map([
- ["index", i],
- ["twig", twig]
- ])
- );
- }
- this.#ast[i].dir = dir;
- this.#ast[i].filtered = filtered || !compound;
- i++;
- }
- this._processPendingItems(pendingItems);
- } else {
- let i = 0;
- for (const { branch } of ast) {
- const twig = branch[branch.length - 1];
- const complex = branch.length > 1;
- const dir = DIR_PREV;
- const { compound, filtered, nodes } = this._findEntryNodes(
- twig,
- targetType,
- { complex, dir }
- );
- if (nodes.length) {
- this.#ast[i].find = true;
- this.#nodes[i] = nodes;
- }
- this.#ast[i].dir = dir;
- this.#ast[i].filtered = filtered || !compound;
- i++;
- }
- }
- return [this.#ast, this.#nodes];
- };
- /**
- * Gets combined nodes.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} nodes - A collection of nodes.
- * @param {string} dir - The direction.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _getCombinedNodes = (twig, nodes, dir) => {
- const arr = [];
- const options = {
- dir,
- warn: this.#warn
- };
- for (const node of nodes) {
- const matched = this._matchCombinator(twig, node, options);
- if (matched.size) {
- arr.push(...matched);
- }
- }
- return arr;
- };
- /**
- * Matches a node in the 'next' direction.
- * @private
- * @param {Array} branch - The branch.
- * @param {Set.<object>} nodes - A collection of Element nodes.
- * @param {object} opt - Options.
- * @param {object} opt.combo - The combo object.
- * @param {number} opt.index - The index.
- * @returns {?object} The matched node.
- */
- _matchNodeNext = (branch, nodes, opt) => {
- const { combo, index } = opt;
- const { combo: nextCombo, leaves } = branch[index];
- const twig = {
- combo,
- leaves
- };
- const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_NEXT));
- if (nextNodes.size) {
- if (index === branch.length - 1) {
- const [nextNode] = sortNodes(nextNodes);
- return nextNode;
- }
- return this._matchNodeNext(branch, nextNodes, {
- combo: nextCombo,
- index: index + 1
- });
- }
- return null;
- };
- /**
- * Matches a node in the 'previous' direction.
- * @private
- * @param {Array} branch - The branch.
- * @param {object} node - The Element node.
- * @param {object} opt - Options.
- * @param {number} opt.index - The index.
- * @returns {?object} The node.
- */
- _matchNodePrev = (branch, node, opt) => {
- const { index } = opt;
- const twig = branch[index];
- const nodes = /* @__PURE__ */ new Set([node]);
- const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_PREV));
- if (nextNodes.size) {
- if (index === 0) {
- return node;
- }
- let matched;
- for (const nextNode of nextNodes) {
- matched = this._matchNodePrev(branch, nextNode, {
- index: index - 1
- });
- if (matched) {
- break;
- }
- }
- if (matched) {
- return node;
- }
- }
- return null;
- };
- /**
- * Processes a complex selector branch to find all matching nodes.
- * @private
- * @param {Array} branch - The selector branch from the AST.
- * @param {Array} entryNodes - The initial set of nodes to start from.
- * @param {string} dir - The direction of traversal ('next' or 'prev').
- * @returns {Set.<object>} A set of all matched nodes.
- */
- _processComplexBranchAll = (branch, entryNodes, dir) => {
- const matchedNodes = /* @__PURE__ */ new Set();
- const branchLen = branch.length;
- const lastIndex = branchLen - 1;
- if (dir === DIR_NEXT) {
- const { combo: firstCombo } = branch[0];
- for (const node of entryNodes) {
- let combo = firstCombo;
- let nextNodes = /* @__PURE__ */ new Set([node]);
- for (let j = 1; j < branchLen; j++) {
- const { combo: nextCombo, leaves } = branch[j];
- const twig = { combo, leaves };
- const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);
- if (nodesArr.length) {
- if (j === lastIndex) {
- for (const nextNode of nodesArr) {
- matchedNodes.add(nextNode);
- }
- }
- combo = nextCombo;
- nextNodes = new Set(nodesArr);
- } else {
- nextNodes.clear();
- break;
- }
- }
- }
- } else {
- for (const node of entryNodes) {
- let nextNodes = /* @__PURE__ */ new Set([node]);
- for (let j = lastIndex - 1; j >= 0; j--) {
- const twig = branch[j];
- const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);
- if (nodesArr.length) {
- if (j === 0) {
- matchedNodes.add(node);
- }
- nextNodes = new Set(nodesArr);
- } else {
- nextNodes.clear();
- break;
- }
- }
- }
- }
- return matchedNodes;
- };
- /**
- * Processes a complex selector branch to find the first matching node.
- * @private
- * @param {Array} branch - The selector branch from the AST.
- * @param {Array} entryNodes - The initial set of nodes to start from.
- * @param {string} dir - The direction of traversal ('next' or 'prev').
- * @param {string} targetType - The type of search (e.g., 'first').
- * @returns {?object} The first matched node, or null.
- */
- _processComplexBranchFirst = (branch, entryNodes, dir, targetType) => {
- const branchLen = branch.length;
- const lastIndex = branchLen - 1;
- if (dir === DIR_NEXT) {
- const { combo: entryCombo } = branch[0];
- for (const node of entryNodes) {
- const matchedNode = this._matchNodeNext(branch, /* @__PURE__ */ new Set([node]), {
- combo: entryCombo,
- index: 1
- });
- if (matchedNode) {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (matchedNode !== this.#node && this.#node.contains(matchedNode)) {
- return matchedNode;
- }
- } else {
- return matchedNode;
- }
- }
- }
- const { leaves: entryLeaves } = branch[0];
- const [entryNode] = entryNodes;
- if (this.#node.contains(entryNode)) {
- let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {
- targetType
- });
- while (refNode) {
- const matchedNode = this._matchNodeNext(branch, /* @__PURE__ */ new Set([refNode]), {
- combo: entryCombo,
- index: 1
- });
- if (matchedNode) {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (matchedNode !== this.#node && this.#node.contains(matchedNode)) {
- return matchedNode;
- }
- } else {
- return matchedNode;
- }
- }
- [refNode] = this._findNodeWalker(entryLeaves, refNode, {
- targetType,
- force: true
- });
- }
- }
- } else {
- for (const node of entryNodes) {
- const matchedNode = this._matchNodePrev(branch, node, {
- index: lastIndex - 1
- });
- if (matchedNode) {
- return matchedNode;
- }
- }
- if (targetType === TARGET_FIRST) {
- const { leaves: entryLeaves } = branch[lastIndex];
- const [entryNode] = entryNodes;
- let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {
- targetType
- });
- while (refNode) {
- const matchedNode = this._matchNodePrev(branch, refNode, {
- index: lastIndex - 1
- });
- if (matchedNode) {
- return refNode;
- }
- [refNode] = this._findNodeWalker(entryLeaves, refNode, {
- targetType,
- force: true
- });
- }
- }
- }
- return null;
- };
- /**
- * Finds matched nodes.
- * @param {string} targetType - The target type.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- find = (targetType) => {
- const [[...branches], collectedNodes] = this._collectNodes(targetType);
- const l = branches.length;
- let sort = l > 1 && targetType === TARGET_ALL && this.#selector.includes(":scope");
- let nodes = /* @__PURE__ */ new Set();
- for (let i = 0; i < l; i++) {
- const { branch, dir, find: find3 } = branches[i];
- if (!branch.length || !find3) {
- continue;
- }
- const entryNodes = collectedNodes[i];
- const lastIndex = branch.length - 1;
- if (lastIndex === 0) {
- if ((targetType === TARGET_ALL || targetType === TARGET_FIRST) && this.#node.nodeType === ELEMENT_NODE) {
- for (const node of entryNodes) {
- if (node !== this.#node && this.#node.contains(node)) {
- nodes.add(node);
- if (targetType === TARGET_FIRST) {
- break;
- }
- }
- }
- } else if (targetType === TARGET_ALL) {
- if (nodes.size) {
- for (const node of entryNodes) {
- nodes.add(node);
- }
- sort = true;
- } else {
- nodes = new Set(entryNodes);
- }
- } else {
- if (entryNodes.length) {
- nodes.add(entryNodes[0]);
- }
- }
- } else {
- if (targetType === TARGET_ALL) {
- const newNodes = this._processComplexBranchAll(
- branch,
- entryNodes,
- dir
- );
- if (nodes.size) {
- for (const newNode of newNodes) {
- nodes.add(newNode);
- }
- sort = true;
- } else {
- nodes = newNodes;
- }
- } else {
- const matchedNode = this._processComplexBranchFirst(
- branch,
- entryNodes,
- dir,
- targetType
- );
- if (matchedNode) {
- nodes.add(matchedNode);
- }
- }
- }
- }
- if (this.#check) {
- const match = !!nodes.size;
- let pseudoElement;
- if (this.#pseudoElement.length) {
- pseudoElement = this.#pseudoElement.join("");
- } else {
- pseudoElement = null;
- }
- return { match, pseudoElement };
- }
- if (targetType === TARGET_FIRST || targetType === TARGET_ALL) {
- nodes.delete(this.#node);
- }
- if ((sort || targetType === TARGET_FIRST) && nodes.size > 1) {
- return new Set(sortNodes(nodes));
- }
- return nodes;
- };
-};
-
-// src/index.js
-var MAX_CACHE = 1024;
-var DOMSelector = class {
- /* private fields */
- #window;
- #document;
- #finder;
- #idlUtils;
- #nwsapi;
- #cache;
- /**
- * Creates an instance of DOMSelector.
- * @param {Window} window - The window object.
- * @param {Document} document - The document object.
- * @param {object} [opt] - Options.
- */
- constructor(window, document, opt = {}) {
- const { idlUtils } = opt;
- this.#window = window;
- this.#document = document ?? window.document;
- this.#finder = new Finder(window);
- this.#idlUtils = idlUtils;
- this.#nwsapi = initNwsapi(window, document);
- this.#cache = new import_lru_cache.LRUCache({
- max: MAX_CACHE
- });
- }
- /**
- * Clears the internal cache of finder results.
- * @returns {void}
- */
- clear = () => {
- this.#finder.clearResults(true);
- };
- /**
- * Checks if an element matches a CSS selector.
- * @param {string} selector - The CSS selector to check against.
- * @param {Element} node - The element node to check.
- * @param {object} [opt] - Optional parameters.
- * @returns {CheckResult} An object containing the check result.
- */
- check = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (document === this.#document && document.contentType === "text/html" && document.documentElement && node.parentNode) {
- const cacheKey = `check_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_SELF);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const match = this.#nwsapi.match(selector, n);
- return {
- match,
- pseudoElement: null
- };
- } catch (e) {
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- opt.check = true;
- opt.noexept = true;
- opt.warn = false;
- this.#finder.setup(selector, node, opt);
- res = this.#finder.find(TARGET_SELF);
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res;
- };
- /**
- * Returns true if the element matches the selector.
- * @param {string} selector - The CSS selector to match against.
- * @param {Element} node - The element node to test.
- * @param {object} [opt] - Optional parameters.
- * @returns {boolean} `true` if the element matches, or `false` otherwise.
- */
- matches = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (document === this.#document && document.contentType === "text/html" && document.documentElement && node.parentNode) {
- const cacheKey = `matches_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_SELF);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res2 = this.#nwsapi.match(selector, n);
- return res2;
- } catch (e) {
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_SELF);
- res = nodes.size;
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return !!res;
- };
- /**
- * Traverses up the DOM tree to find the first node that matches the selector.
- * @param {string} selector - The CSS selector to match against.
- * @param {Element} node - The element from which to start traversing.
- * @param {object} [opt] - Optional parameters.
- * @returns {?Element} The first matching ancestor element, or `null`.
- */
- closest = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (document === this.#document && document.contentType === "text/html" && document.documentElement && node.parentNode) {
- const cacheKey = `closest_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_LINEAL);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res2 = this.#nwsapi.closest(selector, n);
- return res2;
- } catch (e) {
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_LINEAL);
- if (nodes.size) {
- let refNode = node;
- while (refNode) {
- if (nodes.has(refNode)) {
- res = refNode;
- break;
- }
- refNode = refNode.parentNode;
- }
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? null;
- };
- /**
- * Returns the first element within the subtree that matches the selector.
- * @param {string} selector - The CSS selector to match.
- * @param {Document|DocumentFragment|Element} node - The node to find within.
- * @param {object} [opt] - Optional parameters.
- * @returns {?Element} The first matching element, or `null`.
- */
- querySelector = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_FIRST);
- if (nodes.size) {
- [res] = [...nodes];
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? null;
- };
- /**
- * Returns an array of elements within the subtree that match the selector.
- * Note: This method returns an Array, not a NodeList.
- * @param {string} selector - The CSS selector to match.
- * @param {Document|DocumentFragment|Element} node - The node to find within.
- * @param {object} [opt] - Optional parameters.
- * @returns {Array<Element>} An array of elements, or an empty array.
- */
- querySelectorAll = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;
- if (document === this.#document && document.contentType === "text/html" && document.documentElement && (node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)) {
- const cacheKey = `querySelectorAll_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_ALL);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res2 = this.#nwsapi.select(selector, n);
- return res2;
- } catch (e) {
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_ALL);
- if (nodes.size) {
- res = [...nodes];
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? [];
- };
-};
-// Annotate the CommonJS export names for ESM import in node:
-0 && (module.exports = {
- DOMSelector
-});
-/*!
- * DOM Selector - A CSS selector engine.
- * @license MIT
- * @copyright asamuzaK (Kazz)
- * @see {@link https://github.com/asamuzaK/domSelector/blob/main/LICENSE}
- */
-//# sourceMappingURL=index.cjs.map \ No newline at end of file
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs.map b/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs.map
deleted file mode 100644
index e8327b1..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.cjs.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../../src/index.js","../../src/js/parser.js","../../src/js/utility.js","../../src/js/constant.js","../../src/js/matcher.js","../../src/js/finder.js"],"sourcesContent":["/*!\n * DOM Selector - A CSS selector engine.\n * @license MIT\n * @copyright asamuzaK (Kazz)\n * @see {@link https://github.com/asamuzaK/domSelector/blob/main/LICENSE}\n */\n\n/* import */\nimport { LRUCache } from 'lru-cache';\nimport { Finder } from './js/finder.js';\nimport { filterSelector, getType, initNwsapi } from './js/utility.js';\n\n/* constants */\nimport {\n DOCUMENT_NODE,\n DOCUMENT_FRAGMENT_NODE,\n ELEMENT_NODE,\n TARGET_ALL,\n TARGET_FIRST,\n TARGET_LINEAL,\n TARGET_SELF\n} from './js/constant.js';\nconst MAX_CACHE = 1024;\n\n/**\n * @typedef {object} CheckResult\n * @property {boolean} match - The match result.\n * @property {string?} pseudoElement - The pseudo-element, if any.\n */\n\n/* DOMSelector */\nexport class DOMSelector {\n /* private fields */\n #window;\n #document;\n #finder;\n #idlUtils;\n #nwsapi;\n #cache;\n\n /**\n * Creates an instance of DOMSelector.\n * @param {Window} window - The window object.\n * @param {Document} document - The document object.\n * @param {object} [opt] - Options.\n */\n constructor(window, document, opt = {}) {\n const { idlUtils } = opt;\n this.#window = window;\n this.#document = document ?? window.document;\n this.#finder = new Finder(window);\n this.#idlUtils = idlUtils;\n this.#nwsapi = initNwsapi(window, document);\n this.#cache = new LRUCache({\n max: MAX_CACHE\n });\n }\n\n /**\n * Clears the internal cache of finder results.\n * @returns {void}\n */\n clear = () => {\n this.#finder.clearResults(true);\n };\n\n /**\n * Checks if an element matches a CSS selector.\n * @param {string} selector - The CSS selector to check against.\n * @param {Element} node - The element node to check.\n * @param {object} [opt] - Optional parameters.\n * @returns {CheckResult} An object containing the check result.\n */\n check = (selector, node, opt = {}) => {\n if (!node?.nodeType) {\n const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);\n return this.#finder.onError(e, opt);\n } else if (node.nodeType !== ELEMENT_NODE) {\n const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);\n return this.#finder.onError(e, opt);\n }\n const document = node.ownerDocument;\n if (\n document === this.#document &&\n document.contentType === 'text/html' &&\n document.documentElement &&\n node.parentNode\n ) {\n const cacheKey = `check_${selector}`;\n let filterMatches = false;\n if (this.#cache.has(cacheKey)) {\n filterMatches = this.#cache.get(cacheKey);\n } else {\n filterMatches = filterSelector(selector, TARGET_SELF);\n this.#cache.set(cacheKey, filterMatches);\n }\n if (filterMatches) {\n try {\n const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;\n const match = this.#nwsapi.match(selector, n);\n return {\n match,\n pseudoElement: null\n };\n } catch (e) {\n // fall through\n }\n }\n }\n let res;\n try {\n if (this.#idlUtils) {\n node = this.#idlUtils.wrapperForImpl(node);\n }\n opt.check = true;\n opt.noexept = true;\n opt.warn = false;\n this.#finder.setup(selector, node, opt);\n res = this.#finder.find(TARGET_SELF);\n } catch (e) {\n this.#finder.onError(e, opt);\n }\n return res;\n };\n\n /**\n * Returns true if the element matches the selector.\n * @param {string} selector - The CSS selector to match against.\n * @param {Element} node - The element node to test.\n * @param {object} [opt] - Optional parameters.\n * @returns {boolean} `true` if the element matches, or `false` otherwise.\n */\n matches = (selector, node, opt = {}) => {\n if (!node?.nodeType) {\n const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);\n return this.#finder.onError(e, opt);\n } else if (node.nodeType !== ELEMENT_NODE) {\n const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);\n return this.#finder.onError(e, opt);\n }\n const document = node.ownerDocument;\n if (\n document === this.#document &&\n document.contentType === 'text/html' &&\n document.documentElement &&\n node.parentNode\n ) {\n const cacheKey = `matches_${selector}`;\n let filterMatches = false;\n if (this.#cache.has(cacheKey)) {\n filterMatches = this.#cache.get(cacheKey);\n } else {\n filterMatches = filterSelector(selector, TARGET_SELF);\n this.#cache.set(cacheKey, filterMatches);\n }\n if (filterMatches) {\n try {\n const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;\n const res = this.#nwsapi.match(selector, n);\n return res;\n } catch (e) {\n // fall through\n }\n }\n }\n let res;\n try {\n if (this.#idlUtils) {\n node = this.#idlUtils.wrapperForImpl(node);\n }\n this.#finder.setup(selector, node, opt);\n const nodes = this.#finder.find(TARGET_SELF);\n res = nodes.size;\n } catch (e) {\n this.#finder.onError(e, opt);\n }\n return !!res;\n };\n\n /**\n * Traverses up the DOM tree to find the first node that matches the selector.\n * @param {string} selector - The CSS selector to match against.\n * @param {Element} node - The element from which to start traversing.\n * @param {object} [opt] - Optional parameters.\n * @returns {?Element} The first matching ancestor element, or `null`.\n */\n closest = (selector, node, opt = {}) => {\n if (!node?.nodeType) {\n const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);\n return this.#finder.onError(e, opt);\n } else if (node.nodeType !== ELEMENT_NODE) {\n const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);\n return this.#finder.onError(e, opt);\n }\n const document = node.ownerDocument;\n if (\n document === this.#document &&\n document.contentType === 'text/html' &&\n document.documentElement &&\n node.parentNode\n ) {\n const cacheKey = `closest_${selector}`;\n let filterMatches = false;\n if (this.#cache.has(cacheKey)) {\n filterMatches = this.#cache.get(cacheKey);\n } else {\n filterMatches = filterSelector(selector, TARGET_LINEAL);\n this.#cache.set(cacheKey, filterMatches);\n }\n if (filterMatches) {\n try {\n const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;\n const res = this.#nwsapi.closest(selector, n);\n return res;\n } catch (e) {\n // fall through\n }\n }\n }\n let res;\n try {\n if (this.#idlUtils) {\n node = this.#idlUtils.wrapperForImpl(node);\n }\n this.#finder.setup(selector, node, opt);\n const nodes = this.#finder.find(TARGET_LINEAL);\n if (nodes.size) {\n let refNode = node;\n while (refNode) {\n if (nodes.has(refNode)) {\n res = refNode;\n break;\n }\n refNode = refNode.parentNode;\n }\n }\n } catch (e) {\n this.#finder.onError(e, opt);\n }\n return res ?? null;\n };\n\n /**\n * Returns the first element within the subtree that matches the selector.\n * @param {string} selector - The CSS selector to match.\n * @param {Document|DocumentFragment|Element} node - The node to find within.\n * @param {object} [opt] - Optional parameters.\n * @returns {?Element} The first matching element, or `null`.\n */\n querySelector = (selector, node, opt = {}) => {\n if (!node?.nodeType) {\n const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);\n return this.#finder.onError(e, opt);\n }\n /*\n const document =\n node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;\n if (\n document === this.#document &&\n document.contentType === 'text/html' &&\n document.documentElement &&\n (node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)\n ) {\n const cacheKey = `querySelector_${selector}`;\n let filterMatches = false;\n if (this.#cache.has(cacheKey)) {\n filterMatches = this.#cache.get(cacheKey);\n } else {\n filterMatches = filterSelector(selector, TARGET_FIRST);\n this.#cache.set(cacheKey, filterMatches);\n }\n if (filterMatches) {\n try {\n const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;\n const res = this.#nwsapi.first(selector, n);\n return res;\n } catch (e) {\n // fall through\n }\n }\n }\n */\n let res;\n try {\n if (this.#idlUtils) {\n node = this.#idlUtils.wrapperForImpl(node);\n }\n this.#finder.setup(selector, node, opt);\n const nodes = this.#finder.find(TARGET_FIRST);\n if (nodes.size) {\n [res] = [...nodes];\n }\n } catch (e) {\n this.#finder.onError(e, opt);\n }\n return res ?? null;\n };\n\n /**\n * Returns an array of elements within the subtree that match the selector.\n * Note: This method returns an Array, not a NodeList.\n * @param {string} selector - The CSS selector to match.\n * @param {Document|DocumentFragment|Element} node - The node to find within.\n * @param {object} [opt] - Optional parameters.\n * @returns {Array<Element>} An array of elements, or an empty array.\n */\n querySelectorAll = (selector, node, opt = {}) => {\n if (!node?.nodeType) {\n const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);\n return this.#finder.onError(e, opt);\n }\n const document =\n node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;\n if (\n document === this.#document &&\n document.contentType === 'text/html' &&\n document.documentElement &&\n (node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)\n ) {\n const cacheKey = `querySelectorAll_${selector}`;\n let filterMatches = false;\n if (this.#cache.has(cacheKey)) {\n filterMatches = this.#cache.get(cacheKey);\n } else {\n filterMatches = filterSelector(selector, TARGET_ALL);\n this.#cache.set(cacheKey, filterMatches);\n }\n if (filterMatches) {\n try {\n const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;\n const res = this.#nwsapi.select(selector, n);\n return res;\n } catch (e) {\n // fall through\n }\n }\n }\n let res;\n try {\n if (this.#idlUtils) {\n node = this.#idlUtils.wrapperForImpl(node);\n }\n this.#finder.setup(selector, node, opt);\n const nodes = this.#finder.find(TARGET_ALL);\n if (nodes.size) {\n res = [...nodes];\n }\n } catch (e) {\n this.#finder.onError(e, opt);\n }\n return res ?? [];\n };\n}\n","/**\n * parser.js\n */\n\n/* import */\nimport * as cssTree from 'css-tree';\nimport { getType } from './utility.js';\n\n/* constants */\nimport {\n ATTR_SELECTOR,\n BIT_01,\n BIT_02,\n BIT_04,\n BIT_08,\n BIT_16,\n BIT_32,\n BIT_FFFF,\n CLASS_SELECTOR,\n DUO,\n HEX,\n ID_SELECTOR,\n KEYS_LOGICAL,\n NTH,\n PS_CLASS_SELECTOR,\n PS_ELEMENT_SELECTOR,\n SELECTOR,\n SYNTAX_ERR,\n TYPE_SELECTOR\n} from './constant.js';\nconst AST_SORT_ORDER = new Map([\n [PS_ELEMENT_SELECTOR, BIT_01],\n [ID_SELECTOR, BIT_02],\n [CLASS_SELECTOR, BIT_04],\n [TYPE_SELECTOR, BIT_08],\n [ATTR_SELECTOR, BIT_16],\n [PS_CLASS_SELECTOR, BIT_32]\n]);\nconst KEYS_PS_CLASS_STATE = new Set([\n 'checked',\n 'closed',\n 'disabled',\n 'empty',\n 'enabled',\n 'in-range',\n 'indeterminate',\n 'invalid',\n 'open',\n 'out-of-range',\n 'placeholder-shown',\n 'read-only',\n 'read-write',\n 'valid'\n]);\nconst KEYS_SHADOW_HOST = new Set(['host', 'host-context']);\nconst REG_EMPTY_PS_FUNC =\n /(?<=:(?:dir|has|host(?:-context)?|is|lang|not|nth-(?:last-)?(?:child|of-type)|where))\\(\\s+\\)/g;\nconst REG_SHADOW_PS_ELEMENT = /^part|slotted$/;\nconst U_FFFD = '\\uFFFD';\n\n/**\n * Unescapes a CSS selector string.\n * @param {string} selector - The CSS selector to unescape.\n * @returns {string} The unescaped selector string.\n */\nexport const unescapeSelector = (selector = '') => {\n if (typeof selector === 'string' && selector.indexOf('\\\\', 0) >= 0) {\n const arr = selector.split('\\\\');\n const selectorItems = [arr[0]];\n const l = arr.length;\n for (let i = 1; i < l; i++) {\n const item = arr[i];\n if (item === '' && i === l - 1) {\n selectorItems.push(U_FFFD);\n } else {\n const hexExists = /^([\\da-f]{1,6}\\s?)/i.exec(item);\n if (hexExists) {\n const [, hex] = hexExists;\n let str;\n try {\n const low = parseInt('D800', HEX);\n const high = parseInt('DFFF', HEX);\n const deci = parseInt(hex, HEX);\n if (deci === 0 || (deci >= low && deci <= high)) {\n str = U_FFFD;\n } else {\n str = String.fromCodePoint(deci);\n }\n } catch (e) {\n str = U_FFFD;\n }\n let postStr = '';\n if (item.length > hex.length) {\n postStr = item.substring(hex.length);\n }\n selectorItems.push(`${str}${postStr}`);\n // whitespace\n } else if (/^[\\n\\r\\f]/.test(item)) {\n selectorItems.push(`\\\\${item}`);\n } else {\n selectorItems.push(item);\n }\n }\n }\n return selectorItems.join('');\n }\n return selector;\n};\n\n/**\n * Preprocesses a selector string according to the specification.\n * @see https://drafts.csswg.org/css-syntax-3/#input-preprocessing\n * @param {string} value - The value to preprocess.\n * @returns {string} The preprocessed selector string.\n */\nexport const preprocess = value => {\n // Non-string values will be converted to string.\n if (typeof value !== 'string') {\n if (value === undefined || value === null) {\n return getType(value).toLowerCase();\n } else if (Array.isArray(value)) {\n return value.join(',');\n } else if (Object.hasOwn(value, 'toString')) {\n return value.toString();\n } else {\n throw new DOMException(`Invalid selector ${value}`, SYNTAX_ERR);\n }\n }\n let selector = value;\n let index = 0;\n while (index >= 0) {\n // @see https://drafts.csswg.org/selectors/#id-selectors\n index = selector.indexOf('#', index);\n if (index < 0) {\n break;\n }\n const preHash = selector.substring(0, index + 1);\n let postHash = selector.substring(index + 1);\n const codePoint = postHash.codePointAt(0);\n if (codePoint > BIT_FFFF) {\n const str = `\\\\${codePoint.toString(HEX)} `;\n if (postHash.length === DUO) {\n postHash = str;\n } else {\n postHash = `${str}${postHash.substring(DUO)}`;\n }\n }\n selector = `${preHash}${postHash}`;\n index++;\n }\n return selector\n .replace(/\\f|\\r\\n?/g, '\\n')\n .replace(/[\\0\\uD800-\\uDFFF]|\\\\$/g, U_FFFD)\n .replace(/\\x26/g, ':scope');\n};\n\n/**\n * Creates an Abstract Syntax Tree (AST) from a CSS selector string.\n * @param {string} sel - The CSS selector string.\n * @returns {object} The parsed AST object.\n */\nexport const parseSelector = sel => {\n const selector = preprocess(sel);\n // invalid selectors\n if (/^$|^\\s*>|,\\s*$/.test(selector)) {\n throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);\n }\n try {\n const ast = cssTree.parse(selector, {\n context: 'selectorList',\n parseCustomProperty: true\n });\n return cssTree.toPlainObject(ast);\n } catch (e) {\n const { message } = e;\n if (\n /^(?:\"\\]\"|Attribute selector [()\\s,=~^$*|]+) is expected$/.test(\n message\n ) &&\n !selector.endsWith(']')\n ) {\n const index = selector.lastIndexOf('[');\n const selPart = selector.substring(index);\n if (selPart.includes('\"')) {\n const quotes = selPart.match(/\"/g).length;\n if (quotes % 2) {\n return parseSelector(`${selector}\"]`);\n }\n return parseSelector(`${selector}]`);\n }\n return parseSelector(`${selector}]`);\n } else if (message === '\")\" is expected') {\n // workaround for https://github.com/csstree/csstree/issues/283\n if (REG_EMPTY_PS_FUNC.test(selector)) {\n return parseSelector(`${selector.replaceAll(REG_EMPTY_PS_FUNC, '()')}`);\n } else if (!selector.endsWith(')')) {\n return parseSelector(`${selector})`);\n } else {\n throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);\n }\n } else {\n throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);\n }\n }\n};\n\n/**\n * Walks the provided AST to collect selector branches and gather information\n * about its contents.\n * @param {object} ast - The AST to traverse.\n * @returns {{branches: Array<object>, info: object}} An object containing the selector branches and info.\n */\nexport const walkAST = (ast = {}) => {\n const branches = new Set();\n const info = {\n hasForgivenPseudoFunc: false,\n hasHasPseudoFunc: false,\n hasLogicalPseudoFunc: false,\n hasNotPseudoFunc: false,\n hasNthChildOfSelector: false,\n hasNestedSelector: false,\n hasStatePseudoClass: false\n };\n const opt = {\n enter(node) {\n switch (node.type) {\n case CLASS_SELECTOR: {\n if (/^-?\\d/.test(node.name)) {\n throw new DOMException(\n `Invalid selector .${node.name}`,\n SYNTAX_ERR\n );\n }\n break;\n }\n case ID_SELECTOR: {\n if (/^-?\\d/.test(node.name)) {\n throw new DOMException(\n `Invalid selector #${node.name}`,\n SYNTAX_ERR\n );\n }\n break;\n }\n case PS_CLASS_SELECTOR: {\n if (KEYS_LOGICAL.has(node.name)) {\n info.hasNestedSelector = true;\n info.hasLogicalPseudoFunc = true;\n if (node.name === 'has') {\n info.hasHasPseudoFunc = true;\n } else if (node.name === 'not') {\n info.hasNotPseudoFunc = true;\n } else {\n info.hasForgivenPseudoFunc = true;\n }\n } else if (KEYS_PS_CLASS_STATE.has(node.name)) {\n info.hasStatePseudoClass = true;\n } else if (\n KEYS_SHADOW_HOST.has(node.name) &&\n Array.isArray(node.children) &&\n node.children.length\n ) {\n info.hasNestedSelector = true;\n }\n break;\n }\n case PS_ELEMENT_SELECTOR: {\n if (REG_SHADOW_PS_ELEMENT.test(node.name)) {\n info.hasNestedSelector = true;\n }\n break;\n }\n case NTH: {\n if (node.selector) {\n info.hasNestedSelector = true;\n info.hasNthChildOfSelector = true;\n }\n break;\n }\n case SELECTOR: {\n branches.add(node.children);\n break;\n }\n default:\n }\n }\n };\n cssTree.walk(ast, opt);\n if (info.hasNestedSelector === true) {\n cssTree.findAll(ast, (node, item, list) => {\n if (list) {\n if (node.type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(node.name)) {\n const itemList = list.filter(i => {\n const { name, type } = i;\n return type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(name);\n });\n for (const { children } of itemList) {\n // SelectorList\n for (const { children: grandChildren } of children) {\n // Selector\n for (const { children: greatGrandChildren } of grandChildren) {\n if (branches.has(greatGrandChildren)) {\n branches.delete(greatGrandChildren);\n }\n }\n }\n }\n } else if (\n node.type === PS_CLASS_SELECTOR &&\n KEYS_SHADOW_HOST.has(node.name) &&\n Array.isArray(node.children) &&\n node.children.length\n ) {\n const itemList = list.filter(i => {\n const { children, name, type } = i;\n const res =\n type === PS_CLASS_SELECTOR &&\n KEYS_SHADOW_HOST.has(name) &&\n Array.isArray(children) &&\n children.length;\n return res;\n });\n for (const { children } of itemList) {\n // Selector\n for (const { children: grandChildren } of children) {\n if (branches.has(grandChildren)) {\n branches.delete(grandChildren);\n }\n }\n }\n } else if (\n node.type === PS_ELEMENT_SELECTOR &&\n REG_SHADOW_PS_ELEMENT.test(node.name)\n ) {\n const itemList = list.filter(i => {\n const { name, type } = i;\n const res =\n type === PS_ELEMENT_SELECTOR && REG_SHADOW_PS_ELEMENT.test(name);\n return res;\n });\n for (const { children } of itemList) {\n // Selector\n for (const { children: grandChildren } of children) {\n if (branches.has(grandChildren)) {\n branches.delete(grandChildren);\n }\n }\n }\n } else if (node.type === NTH && node.selector) {\n const itemList = list.filter(i => {\n const { selector, type } = i;\n const res = type === NTH && selector;\n return res;\n });\n for (const { selector } of itemList) {\n const { children } = selector;\n // Selector\n for (const { children: grandChildren } of children) {\n if (branches.has(grandChildren)) {\n branches.delete(grandChildren);\n }\n }\n }\n }\n }\n });\n }\n return {\n info,\n branches: [...branches]\n };\n};\n\n/**\n * Comparison function for sorting AST nodes based on specificity.\n * @param {object} a - The first AST node.\n * @param {object} b - The second AST node.\n * @returns {number} -1, 0 or 1, depending on the sort order.\n */\nexport const compareASTNodes = (a, b) => {\n const bitA = AST_SORT_ORDER.get(a.type);\n const bitB = AST_SORT_ORDER.get(b.type);\n if (bitA === bitB) {\n return 0;\n } else if (bitA > bitB) {\n return 1;\n } else {\n return -1;\n }\n};\n\n/**\n * Sorts a collection of AST nodes based on CSS specificity rules.\n * @param {Array<object>} asts - A collection of AST nodes to sort.\n * @returns {Array<object>} A new array containing the sorted AST nodes.\n */\nexport const sortAST = asts => {\n const arr = [...asts];\n if (arr.length > 1) {\n arr.sort(compareASTNodes);\n }\n return arr;\n};\n\n/**\n * Parses a type selector's name, which may include a namespace prefix.\n * @param {string} selector - The type selector name (e.g., 'ns|E' or 'E').\n * @returns {{prefix: string, localName: string}} An object with `prefix` and\n * `localName` properties.\n */\nexport const parseAstName = selector => {\n let prefix;\n let localName;\n if (selector && typeof selector === 'string') {\n if (selector.indexOf('|') > -1) {\n [prefix, localName] = selector.split('|');\n } else {\n prefix = '*';\n localName = selector;\n }\n } else {\n throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);\n }\n return {\n prefix,\n localName\n };\n};\n\n/* Re-exported from css-tree. */\nexport { find as findAST, generate as generateCSS } from 'css-tree';\n","/**\n * utility.js\n */\n\n/* import */\nimport nwsapi from '@asamuzakjp/nwsapi';\nimport bidiFactory from 'bidi-js';\nimport * as cssTree from 'css-tree';\nimport isCustomElementName from 'is-potential-custom-element-name';\n\n/* constants */\nimport {\n ATRULE,\n COMBO,\n COMPOUND_I,\n DESCEND,\n DOCUMENT_FRAGMENT_NODE,\n DOCUMENT_NODE,\n DOCUMENT_POSITION_CONTAINS,\n DOCUMENT_POSITION_PRECEDING,\n ELEMENT_NODE,\n HAS_COMPOUND,\n INPUT_BUTTON,\n INPUT_EDIT,\n INPUT_LTR,\n INPUT_TEXT,\n KEYS_LOGICAL,\n LOGIC_COMPLEX,\n LOGIC_COMPOUND,\n N_TH,\n PSEUDO_CLASS,\n RULE,\n SCOPE,\n SELECTOR_LIST,\n SIBLING,\n TARGET_ALL,\n TARGET_FIRST,\n TEXT_NODE,\n TYPE_FROM,\n TYPE_TO\n} from './constant.js';\nconst KEYS_DIR_AUTO = new Set([...INPUT_BUTTON, ...INPUT_TEXT, 'hidden']);\nconst KEYS_DIR_LTR = new Set(INPUT_LTR);\nconst KEYS_INPUT_EDIT = new Set(INPUT_EDIT);\nconst KEYS_NODE_DIR_EXCLUDE = new Set(['bdi', 'script', 'style', 'textarea']);\nconst KEYS_NODE_FOCUSABLE = new Set(['button', 'select', 'textarea']);\nconst KEYS_NODE_FOCUSABLE_SVG = new Set([\n 'clipPath',\n 'defs',\n 'desc',\n 'linearGradient',\n 'marker',\n 'mask',\n 'metadata',\n 'pattern',\n 'radialGradient',\n 'script',\n 'style',\n 'symbol',\n 'title'\n]);\nconst REG_EXCLUDE_BASIC =\n /[|\\\\]|::|[^\\u0021-\\u007F\\s]|\\[\\s*[\\w$*=^|~-]+(?:(?:\"[\\w$*=^|~\\s'-]+\"|'[\\w$*=^|~\\s\"-]+')?(?:\\s+[\\w$*=^|~-]+)+|\"[^\"\\]]{1,255}|'[^'\\]]{1,255})\\s*\\]|:(?:is|where)\\(\\s*\\)/;\nconst REG_COMPLEX = new RegExp(`${COMPOUND_I}${COMBO}${COMPOUND_I}`, 'i');\nconst REG_DESCEND = new RegExp(`${COMPOUND_I}${DESCEND}${COMPOUND_I}`, 'i');\nconst REG_SIBLING = new RegExp(`${COMPOUND_I}${SIBLING}${COMPOUND_I}`, 'i');\nconst REG_LOGIC_COMPLEX = new RegExp(\n `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPLEX})`\n);\nconst REG_LOGIC_COMPOUND = new RegExp(\n `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND})`\n);\nconst REG_LOGIC_HAS_COMPOUND = new RegExp(\n `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND}|${HAS_COMPOUND})`\n);\nconst REG_END_WITH_HAS = new RegExp(`:${HAS_COMPOUND}$`);\nconst REG_WO_LOGICAL = new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH})`);\nconst REG_IS_HTML = /^(?:application\\/xhtml\\+x|text\\/ht)ml$/;\nconst REG_IS_XML =\n /^(?:application\\/(?:[\\w\\-.]+\\+)?|image\\/[\\w\\-.]+\\+|text\\/)xml$/;\n\n/**\n * Manages state for extracting nested selectors from a CSS AST.\n */\nclass SelectorExtractor {\n constructor() {\n this.selectors = [];\n this.isScoped = false;\n }\n\n /**\n * Walker enter function.\n * @param {object} node - The AST node.\n */\n enter(node) {\n switch (node.type) {\n case ATRULE: {\n if (node.name === 'scope') {\n this.isScoped = true;\n }\n break;\n }\n case SCOPE: {\n const { children, type } = node.root;\n const arr = [];\n if (type === SELECTOR_LIST) {\n for (const child of children) {\n const selector = cssTree.generate(child);\n arr.push(selector);\n }\n this.selectors.push(arr);\n }\n break;\n }\n case RULE: {\n const { children, type } = node.prelude;\n const arr = [];\n if (type === SELECTOR_LIST) {\n let hasAmp = false;\n for (const child of children) {\n const selector = cssTree.generate(child);\n if (this.isScoped && !hasAmp) {\n hasAmp = /\\x26/.test(selector);\n }\n arr.push(selector);\n }\n if (this.isScoped) {\n if (hasAmp) {\n this.selectors.push(arr);\n /* FIXME:\n } else {\n this.selectors = arr;\n this.isScoped = false;\n */\n }\n } else {\n this.selectors.push(arr);\n }\n }\n }\n }\n }\n\n /**\n * Walker leave function.\n * @param {object} node - The AST node.\n */\n leave(node) {\n if (node.type === ATRULE) {\n if (node.name === 'scope') {\n this.isScoped = false;\n }\n }\n }\n}\n\n/**\n * Get type of an object.\n * @param {object} o - Object to check.\n * @returns {string} - Type of the object.\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * Verify array contents.\n * @param {Array} arr - The array.\n * @param {string} type - Expected type, e.g. 'String'.\n * @throws {TypeError} - Throws if array or its items are of unexpected type.\n * @returns {Array} - The verified array.\n */\nexport const verifyArray = (arr, type) => {\n if (!Array.isArray(arr)) {\n throw new TypeError(`Unexpected type ${getType(arr)}`);\n }\n if (typeof type !== 'string') {\n throw new TypeError(`Unexpected type ${getType(type)}`);\n }\n for (const item of arr) {\n if (getType(item) !== type) {\n throw new TypeError(`Unexpected type ${getType(item)}`);\n }\n }\n return arr;\n};\n\n/**\n * Generate a DOMException.\n * @param {string} msg - The error message.\n * @param {string} name - The error name.\n * @param {object} globalObject - The global object (e.g., window).\n * @returns {DOMException} The generated DOMException object.\n */\nexport const generateException = (msg, name, globalObject = globalThis) => {\n return new globalObject.DOMException(msg, name);\n};\n\n/**\n * Find a nested :has() pseudo-class.\n * @param {object} leaf - The AST leaf to check.\n * @returns {?object} The leaf if it's :has, otherwise null.\n */\nexport const findNestedHas = leaf => {\n return leaf.name === 'has';\n};\n\n/**\n * Find a logical pseudo-class that contains a nested :has().\n * @param {object} leaf - The AST leaf to check.\n * @returns {?object} The leaf if it matches, otherwise null.\n */\nexport const findLogicalWithNestedHas = leaf => {\n if (KEYS_LOGICAL.has(leaf.name) && cssTree.find(leaf, findNestedHas)) {\n return leaf;\n }\n return null;\n};\n\n/**\n * Filter a list of nodes based on An+B logic\n * @param {Array.<object>} nodes - array of nodes to filter\n * @param {object} anb - An+B options\n * @param {number} anb.a - a\n * @param {number} anb.b - b\n * @param {boolean} [anb.reverse] - reverse order\n * @returns {Array.<object>} - array of matched nodes\n */\nexport const filterNodesByAnB = (nodes, anb) => {\n const { a, b, reverse } = anb;\n const processedNodes = reverse ? [...nodes].reverse() : nodes;\n const l = nodes.length;\n const matched = [];\n if (a === 0) {\n if (b > 0 && b <= l) {\n matched.push(processedNodes[b - 1]);\n }\n return matched;\n }\n let startIndex = b - 1;\n if (a > 0) {\n while (startIndex < 0) {\n startIndex += a;\n }\n for (let i = startIndex; i < l; i += a) {\n matched.push(processedNodes[i]);\n }\n } else if (startIndex >= 0) {\n for (let i = startIndex; i >= 0; i += a) {\n matched.push(processedNodes[i]);\n }\n return matched.reverse();\n }\n return matched;\n};\n\n/**\n * Resolve content document, root node, and check if it's in a shadow DOM.\n * @param {object} node - Document, DocumentFragment, or Element node.\n * @returns {Array.<object|boolean>} - [document, root, isInShadow].\n */\nexport const resolveContent = node => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n let document;\n let root;\n let shadow;\n switch (node.nodeType) {\n case DOCUMENT_NODE: {\n document = node;\n root = node;\n break;\n }\n case DOCUMENT_FRAGMENT_NODE: {\n const { host, mode, ownerDocument } = node;\n document = ownerDocument;\n root = node;\n shadow = host && (mode === 'close' || mode === 'open');\n break;\n }\n case ELEMENT_NODE: {\n document = node.ownerDocument;\n let refNode = node;\n while (refNode) {\n const { host, mode, nodeType, parentNode } = refNode;\n if (nodeType === DOCUMENT_FRAGMENT_NODE) {\n shadow = host && (mode === 'close' || mode === 'open');\n break;\n } else if (parentNode) {\n refNode = parentNode;\n } else {\n break;\n }\n }\n root = refNode;\n break;\n }\n default: {\n throw new TypeError(`Unexpected node ${node.nodeName}`);\n }\n }\n return [document, root, !!shadow];\n};\n\n/**\n * Traverse node tree with a TreeWalker.\n * @param {object} node - The target node.\n * @param {object} walker - The TreeWalker instance.\n * @param {boolean} [force] - Traverse only to the next node.\n * @returns {?object} - The current node if found, otherwise null.\n */\nexport const traverseNode = (node, walker, force = false) => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (!walker) {\n return null;\n }\n let refNode = walker.currentNode;\n if (refNode === node) {\n return refNode;\n } else if (force || refNode.contains(node)) {\n refNode = walker.nextNode();\n while (refNode) {\n if (refNode === node) {\n break;\n }\n refNode = walker.nextNode();\n }\n return refNode;\n } else {\n if (refNode !== walker.root) {\n let bool;\n while (refNode) {\n if (refNode === node) {\n bool = true;\n break;\n } else if (refNode === walker.root || refNode.contains(node)) {\n break;\n }\n refNode = walker.parentNode();\n }\n if (bool) {\n return refNode;\n }\n }\n if (node.nodeType === ELEMENT_NODE) {\n let bool;\n while (refNode) {\n if (refNode === node) {\n bool = true;\n break;\n }\n refNode = walker.nextNode();\n }\n if (bool) {\n return refNode;\n }\n }\n }\n return null;\n};\n\n/**\n * Check if a node is a custom element.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {boolean} - True if it's a custom element.\n */\nexport const isCustomElement = (node, opt = {}) => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (node.nodeType !== ELEMENT_NODE) {\n return false;\n }\n const { localName, ownerDocument } = node;\n const { formAssociated } = opt;\n const window = ownerDocument.defaultView;\n let elmConstructor;\n const attr = node.getAttribute('is');\n if (attr) {\n elmConstructor =\n isCustomElementName(attr) && window.customElements.get(attr);\n } else {\n elmConstructor =\n isCustomElementName(localName) && window.customElements.get(localName);\n }\n if (elmConstructor) {\n if (formAssociated) {\n return !!elmConstructor.formAssociated;\n }\n return true;\n }\n return false;\n};\n\n/**\n * Get slotted text content.\n * @param {object} node - The Element node (likely a <slot>).\n * @returns {?string} - The text content.\n */\nexport const getSlottedTextContent = node => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (typeof node.assignedNodes !== 'function') {\n return null;\n }\n const nodes = node.assignedNodes();\n if (nodes.length) {\n let text = '';\n const l = nodes.length;\n for (let i = 0; i < l; i++) {\n const item = nodes[i];\n text = item.textContent.trim();\n if (text) {\n break;\n }\n }\n return text;\n }\n return node.textContent.trim();\n};\n\n/**\n * Get directionality of a node.\n * @see https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute\n * @param {object} node - The Element node.\n * @returns {?string} - 'ltr' or 'rtl'.\n */\nexport const getDirectionality = node => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (node.nodeType !== ELEMENT_NODE) {\n return null;\n }\n const { dir: dirAttr, localName, parentNode } = node;\n const { getEmbeddingLevels } = bidiFactory();\n if (dirAttr === 'ltr' || dirAttr === 'rtl') {\n return dirAttr;\n } else if (dirAttr === 'auto') {\n let text = '';\n switch (localName) {\n case 'input': {\n if (!node.type || KEYS_DIR_AUTO.has(node.type)) {\n text = node.value;\n } else if (KEYS_DIR_LTR.has(node.type)) {\n return 'ltr';\n }\n break;\n }\n case 'slot': {\n text = getSlottedTextContent(node);\n break;\n }\n case 'textarea': {\n text = node.value;\n break;\n }\n default: {\n const items = [].slice.call(node.childNodes);\n for (const item of items) {\n const {\n dir: itemDir,\n localName: itemLocalName,\n nodeType: itemNodeType,\n textContent: itemTextContent\n } = item;\n if (itemNodeType === TEXT_NODE) {\n text = itemTextContent.trim();\n } else if (\n itemNodeType === ELEMENT_NODE &&\n !KEYS_NODE_DIR_EXCLUDE.has(itemLocalName) &&\n (!itemDir || (itemDir !== 'ltr' && itemDir !== 'rtl'))\n ) {\n if (itemLocalName === 'slot') {\n text = getSlottedTextContent(item);\n } else {\n text = itemTextContent.trim();\n }\n }\n if (text) {\n break;\n }\n }\n }\n }\n if (text) {\n const {\n paragraphs: [{ level }]\n } = getEmbeddingLevels(text);\n if (level % 2 === 1) {\n return 'rtl';\n }\n } else if (parentNode) {\n const { nodeType: parentNodeType } = parentNode;\n if (parentNodeType === ELEMENT_NODE) {\n return getDirectionality(parentNode);\n }\n }\n } else if (localName === 'input' && node.type === 'tel') {\n return 'ltr';\n } else if (localName === 'bdi') {\n const text = node.textContent.trim();\n if (text) {\n const {\n paragraphs: [{ level }]\n } = getEmbeddingLevels(text);\n if (level % 2 === 1) {\n return 'rtl';\n }\n }\n } else if (parentNode) {\n if (localName === 'slot') {\n const text = getSlottedTextContent(node);\n if (text) {\n const {\n paragraphs: [{ level }]\n } = getEmbeddingLevels(text);\n if (level % 2 === 1) {\n return 'rtl';\n }\n return 'ltr';\n }\n }\n const { nodeType: parentNodeType } = parentNode;\n if (parentNodeType === ELEMENT_NODE) {\n return getDirectionality(parentNode);\n }\n }\n return 'ltr';\n};\n\n/**\n * Traverses up the DOM tree to find the language attribute for a node.\n * It checks for 'lang' in HTML and 'xml:lang' in XML contexts.\n * @param {object} node - The starting element node.\n * @returns {string|null} The language attribute value, or null if not found.\n */\nexport const getLanguageAttribute = node => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (node.nodeType !== ELEMENT_NODE) {\n return null;\n }\n const { contentType } = node.ownerDocument;\n const isHtml = REG_IS_HTML.test(contentType);\n const isXml = REG_IS_XML.test(contentType);\n let isShadow = false;\n // Traverse up from the current node to the root.\n let current = node;\n while (current) {\n // Check if the current node is an element.\n switch (current.nodeType) {\n case ELEMENT_NODE: {\n // Check for and return the language attribute if present.\n if (isHtml && current.hasAttribute('lang')) {\n return current.getAttribute('lang');\n } else if (isXml && current.hasAttribute('xml:lang')) {\n return current.getAttribute('xml:lang');\n }\n break;\n }\n case DOCUMENT_FRAGMENT_NODE: {\n // Continue traversal if the current node is a shadow root.\n if (current.host) {\n isShadow = true;\n }\n break;\n }\n case DOCUMENT_NODE:\n default: {\n // Stop if we reach the root document node.\n return null;\n }\n }\n if (isShadow) {\n current = current.host;\n isShadow = false;\n } else if (current.parentNode) {\n current = current.parentNode;\n } else {\n break;\n }\n }\n // No language attribute was found in the hierarchy.\n return null;\n};\n\n/**\n * Check if content is editable.\n * NOTE: Not implemented in jsdom https://github.com/jsdom/jsdom/issues/1670\n * @param {object} node - The Element node.\n * @returns {boolean} - True if content is editable.\n */\nexport const isContentEditable = node => {\n if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (node.nodeType !== ELEMENT_NODE) {\n return false;\n }\n if (typeof node.isContentEditable === 'boolean') {\n return node.isContentEditable;\n } else if (node.ownerDocument.designMode === 'on') {\n return true;\n } else {\n let attr;\n if (node.hasAttribute('contenteditable')) {\n attr = node.getAttribute('contenteditable');\n } else {\n attr = 'inherit';\n }\n switch (attr) {\n case '':\n case 'true': {\n return true;\n }\n case 'plaintext-only': {\n // FIXME:\n // @see https://github.com/w3c/editing/issues/470\n // @see https://github.com/whatwg/html/issues/10651\n return true;\n }\n case 'false': {\n return false;\n }\n default: {\n if (node?.parentNode?.nodeType === ELEMENT_NODE) {\n return isContentEditable(node.parentNode);\n }\n return false;\n }\n }\n }\n};\n\n/**\n * Check if a node is visible.\n * @param {object} node - The Element node.\n * @returns {boolean} - True if the node is visible.\n */\nexport const isVisible = node => {\n if (node?.nodeType !== ELEMENT_NODE) {\n return false;\n }\n const window = node.ownerDocument.defaultView;\n const { display, visibility } = window.getComputedStyle(node);\n if (display !== 'none' && visibility === 'visible') {\n return true;\n }\n return false;\n};\n\n/**\n * Check if focus is visible on the node.\n * @param {object} node - The Element node.\n * @returns {boolean} - True if focus is visible.\n */\nexport const isFocusVisible = node => {\n if (node?.nodeType !== ELEMENT_NODE) {\n return false;\n }\n const { localName, type } = node;\n switch (localName) {\n case 'input': {\n if (!type || KEYS_INPUT_EDIT.has(type)) {\n return true;\n }\n return false;\n }\n case 'textarea': {\n return true;\n }\n default: {\n return isContentEditable(node);\n }\n }\n};\n\n/**\n * Check if an area is focusable.\n * @param {object} node - The Element node.\n * @returns {boolean} - True if the area is focusable.\n */\nexport const isFocusableArea = node => {\n if (node?.nodeType !== ELEMENT_NODE) {\n return false;\n }\n if (!node.isConnected) {\n return false;\n }\n const window = node.ownerDocument.defaultView;\n if (node instanceof window.HTMLElement) {\n if (Number.isInteger(parseInt(node.getAttribute('tabindex')))) {\n return true;\n }\n if (isContentEditable(node)) {\n return true;\n }\n const { localName, parentNode } = node;\n switch (localName) {\n case 'a': {\n if (node.href || node.hasAttribute('href')) {\n return true;\n }\n return false;\n }\n case 'iframe': {\n return true;\n }\n case 'input': {\n if (\n node.disabled ||\n node.hasAttribute('disabled') ||\n node.hidden ||\n node.hasAttribute('hidden')\n ) {\n return false;\n }\n return true;\n }\n case 'summary': {\n if (parentNode.localName === 'details') {\n let child = parentNode.firstElementChild;\n let bool = false;\n while (child) {\n if (child.localName === 'summary') {\n bool = child === node;\n break;\n }\n child = child.nextElementSibling;\n }\n return bool;\n }\n return false;\n }\n default: {\n if (\n KEYS_NODE_FOCUSABLE.has(localName) &&\n !(node.disabled || node.hasAttribute('disabled'))\n ) {\n return true;\n }\n }\n }\n } else if (node instanceof window.SVGElement) {\n if (Number.isInteger(parseInt(node.getAttributeNS(null, 'tabindex')))) {\n const ns = 'http://www.w3.org/2000/svg';\n let bool;\n let refNode = node;\n while (refNode.namespaceURI === ns) {\n bool = KEYS_NODE_FOCUSABLE_SVG.has(refNode.localName);\n if (bool) {\n break;\n }\n if (refNode?.parentNode?.namespaceURI === ns) {\n refNode = refNode.parentNode;\n } else {\n break;\n }\n }\n if (bool) {\n return false;\n }\n return true;\n }\n if (\n node.localName === 'a' &&\n (node.href || node.hasAttributeNS(null, 'href'))\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a node is focusable.\n * NOTE: Not applied, needs fix in jsdom itself.\n * @see https://github.com/whatwg/html/pull/8392\n * @see https://phabricator.services.mozilla.com/D156219\n * @see https://github.com/jsdom/jsdom/issues/3029\n * @see https://github.com/jsdom/jsdom/issues/3464\n * @param {object} node - The Element node.\n * @returns {boolean} - True if the node is focusable.\n */\nexport const isFocusable = node => {\n if (node?.nodeType !== ELEMENT_NODE) {\n return false;\n }\n const window = node.ownerDocument.defaultView;\n let refNode = node;\n let res = true;\n while (refNode) {\n if (refNode.disabled || refNode.hasAttribute('disabled')) {\n res = false;\n break;\n }\n if (refNode.hidden || refNode.hasAttribute('hidden')) {\n res = false;\n }\n const { contentVisibility, display, visibility } =\n window.getComputedStyle(refNode);\n if (\n display === 'none' ||\n visibility !== 'visible' ||\n (contentVisibility === 'hidden' && refNode !== node)\n ) {\n res = false;\n } else {\n res = true;\n }\n if (res && refNode?.parentNode?.nodeType === ELEMENT_NODE) {\n refNode = refNode.parentNode;\n } else {\n break;\n }\n }\n return res;\n};\n\n/**\n * Get namespace URI.\n * @param {string} ns - The namespace prefix.\n * @param {object} node - The Element node.\n * @returns {?string} - The namespace URI.\n */\nexport const getNamespaceURI = (ns, node) => {\n if (typeof ns !== 'string') {\n throw new TypeError(`Unexpected type ${getType(ns)}`);\n } else if (!node?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(node)}`);\n }\n if (!ns || node.nodeType !== ELEMENT_NODE) {\n return null;\n }\n const { attributes } = node;\n let res;\n for (const attr of attributes) {\n const { name, namespaceURI, prefix, value } = attr;\n if (name === `xmlns:${ns}`) {\n res = value;\n } else if (prefix === ns) {\n res = namespaceURI;\n }\n if (res) {\n break;\n }\n }\n return res ?? null;\n};\n\n/**\n * Check if a namespace is declared.\n * @param {string} ns - The namespace.\n * @param {object} node - The Element node.\n * @returns {boolean} - True if the namespace is declared.\n */\nexport const isNamespaceDeclared = (ns = '', node = {}) => {\n if (!ns || typeof ns !== 'string' || node?.nodeType !== ELEMENT_NODE) {\n return false;\n }\n if (node.lookupNamespaceURI(ns)) {\n return true;\n }\n const root = node.ownerDocument.documentElement;\n let parent = node;\n let res;\n while (parent) {\n res = getNamespaceURI(ns, parent);\n if (res || parent === root) {\n break;\n }\n parent = parent.parentNode;\n }\n return !!res;\n};\n\n/**\n * Check if nodeA precedes and/or contains nodeB.\n * @param {object} nodeA - The first Element node.\n * @param {object} nodeB - The second Element node.\n * @returns {boolean} - True if nodeA precedes nodeB.\n */\nexport const isPreceding = (nodeA, nodeB) => {\n if (!nodeA?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(nodeA)}`);\n } else if (!nodeB?.nodeType) {\n throw new TypeError(`Unexpected type ${getType(nodeB)}`);\n }\n if (nodeA.nodeType !== ELEMENT_NODE || nodeB.nodeType !== ELEMENT_NODE) {\n return false;\n }\n const posBit = nodeB.compareDocumentPosition(nodeA);\n const res =\n posBit & DOCUMENT_POSITION_PRECEDING || posBit & DOCUMENT_POSITION_CONTAINS;\n return !!res;\n};\n\n/**\n * Comparison function for sorting nodes based on document position.\n * @param {object} a - The first node.\n * @param {object} b - The second node.\n * @returns {number} - Sort order.\n */\nexport const compareNodes = (a, b) => {\n if (isPreceding(b, a)) {\n return 1;\n }\n return -1;\n};\n\n/**\n * Sort a collection of nodes.\n * @param {Array.<object>|Set.<object>} nodes - Collection of nodes.\n * @returns {Array.<object>} - Collection of sorted nodes.\n */\nexport const sortNodes = (nodes = []) => {\n const arr = [...nodes];\n if (arr.length > 1) {\n arr.sort(compareNodes);\n }\n return arr;\n};\n\n/**\n * Concat an array of nested selectors into an equivalent single selector.\n * @param {Array.<Array.<string>>} selectors - [parents, children, ...].\n * @returns {string} - The concatenated selector.\n */\nexport const concatNestedSelectors = selectors => {\n if (!Array.isArray(selectors)) {\n throw new TypeError(`Unexpected type ${getType(selectors)}`);\n }\n let selector = '';\n if (selectors.length) {\n const revSelectors = selectors.toReversed();\n let child = verifyArray(revSelectors.shift(), 'String');\n if (child.length === 1) {\n [child] = child;\n }\n while (revSelectors.length) {\n const parentArr = verifyArray(revSelectors.shift(), 'String');\n if (!parentArr.length) {\n continue;\n }\n let parent;\n if (parentArr.length === 1) {\n [parent] = parentArr;\n if (!/^[>~+]/.test(parent) && /[\\s>~+]/.test(parent)) {\n parent = `:is(${parent})`;\n }\n } else {\n parent = `:is(${parentArr.join(', ')})`;\n }\n if (selector.includes('\\x26')) {\n selector = selector.replace(/\\x26/g, parent);\n }\n if (Array.isArray(child)) {\n const items = [];\n for (let item of child) {\n if (item.includes('\\x26')) {\n if (/^[>~+]/.test(item)) {\n item = `${parent} ${item.replace(/\\x26/g, parent)} ${selector}`;\n } else {\n item = `${item.replace(/\\x26/g, parent)} ${selector}`;\n }\n } else {\n item = `${parent} ${item} ${selector}`;\n }\n items.push(item.trim());\n }\n selector = items.join(', ');\n } else if (revSelectors.length) {\n selector = `${child} ${selector}`;\n } else {\n if (child.includes('\\x26')) {\n if (/^[>~+]/.test(child)) {\n selector = `${parent} ${child.replace(/\\x26/g, parent)} ${selector}`;\n } else {\n selector = `${child.replace(/\\x26/g, parent)} ${selector}`;\n }\n } else {\n selector = `${parent} ${child} ${selector}`;\n }\n }\n selector = selector.trim();\n if (revSelectors.length) {\n child = parentArr.length > 1 ? parentArr : parent;\n } else {\n break;\n }\n }\n selector = selector.replace(/\\x26/g, ':scope').trim();\n }\n return selector;\n};\n\n/**\n * Extract nested selectors from CSSRule.cssText.\n * @param {string} css - CSSRule.cssText.\n * @returns {Array.<Array.<string>>} - Array of nested selectors.\n */\nexport const extractNestedSelectors = css => {\n const ast = cssTree.parse(css, {\n context: 'rule'\n });\n const extractor = new SelectorExtractor();\n cssTree.walk(ast, {\n enter: extractor.enter.bind(extractor),\n leave: extractor.leave.bind(extractor)\n });\n return extractor.selectors;\n};\n\n/**\n * Initialize nwsapi.\n * @param {object} window - The Window object.\n * @param {object} document - The Document object.\n * @returns {object} - The nwsapi instance.\n */\nexport const initNwsapi = (window, document) => {\n if (!window?.DOMException) {\n throw new TypeError(`Unexpected global object ${getType(window)}`);\n }\n if (document?.nodeType !== DOCUMENT_NODE) {\n document = window.document;\n }\n const nw = nwsapi({\n document,\n DOMException: window.DOMException\n });\n nw.configure({\n LOGERRORS: false\n });\n return nw;\n};\n\n/**\n * Filter a selector for use with nwsapi.\n * @param {string} selector - The selector string.\n * @param {string} target - The target type.\n * @returns {boolean} - True if the selector is valid for nwsapi.\n */\nexport const filterSelector = (selector, target) => {\n const isQuerySelectorType = target === TARGET_FIRST || target === TARGET_ALL;\n if (\n !selector ||\n typeof selector !== 'string' ||\n /null|undefined/.test(selector)\n ) {\n return false;\n }\n // Exclude missing close square bracket.\n if (selector.includes('[')) {\n const index = selector.lastIndexOf('[');\n const sel = selector.substring(index);\n if (sel.indexOf(']') < 0) {\n return false;\n }\n }\n // Exclude various complex or unsupported selectors.\n // - selectors containing '/'\n // - namespaced selectors\n // - escaped selectors\n // - pseudo-element selectors\n // - selectors containing non-ASCII\n // - selectors containing control character other than whitespace\n // - attribute selectors with case flag, e.g. [attr i]\n // - attribute selectors with unclosed quotes\n // - empty :is() or :where()\n if (selector.includes('/') || REG_EXCLUDE_BASIC.test(selector)) {\n return false;\n }\n // Include pseudo-classes that are known to work correctly.\n if (selector.includes(':')) {\n let complex = false;\n if (target !== isQuerySelectorType) {\n complex = REG_COMPLEX.test(selector);\n }\n if (\n isQuerySelectorType &&\n REG_DESCEND.test(selector) &&\n !REG_SIBLING.test(selector)\n ) {\n return false;\n } else if (!isQuerySelectorType && /:has\\(/.test(selector)) {\n if (!complex || REG_LOGIC_HAS_COMPOUND.test(selector)) {\n return false;\n }\n return REG_END_WITH_HAS.test(selector);\n } else if (/:(?:is|not)\\(/.test(selector)) {\n if (complex) {\n return !REG_LOGIC_COMPLEX.test(selector);\n } else {\n return !REG_LOGIC_COMPOUND.test(selector);\n }\n } else {\n return !REG_WO_LOGICAL.test(selector);\n }\n }\n return true;\n};\n","/**\n * constant.js\n */\n\n/* string */\nexport const ATRULE = 'Atrule';\nexport const ATTR_SELECTOR = 'AttributeSelector';\nexport const CLASS_SELECTOR = 'ClassSelector';\nexport const COMBINATOR = 'Combinator';\nexport const IDENT = 'Identifier';\nexport const ID_SELECTOR = 'IdSelector';\nexport const NOT_SUPPORTED_ERR = 'NotSupportedError';\nexport const NTH = 'Nth';\nexport const OPERATOR = 'Operator';\nexport const PS_CLASS_SELECTOR = 'PseudoClassSelector';\nexport const PS_ELEMENT_SELECTOR = 'PseudoElementSelector';\nexport const RULE = 'Rule';\nexport const SCOPE = 'Scope';\nexport const SELECTOR = 'Selector';\nexport const SELECTOR_LIST = 'SelectorList';\nexport const STRING = 'String';\nexport const SYNTAX_ERR = 'SyntaxError';\nexport const TARGET_ALL = 'all';\nexport const TARGET_FIRST = 'first';\nexport const TARGET_LINEAL = 'lineal';\nexport const TARGET_SELF = 'self';\nexport const TYPE_SELECTOR = 'TypeSelector';\n\n/* numeric */\nexport const BIT_01 = 1;\nexport const BIT_02 = 2;\nexport const BIT_04 = 4;\nexport const BIT_08 = 8;\nexport const BIT_16 = 0x10;\nexport const BIT_32 = 0x20;\nexport const BIT_FFFF = 0xffff;\nexport const DUO = 2;\nexport const HEX = 16;\nexport const TYPE_FROM = 8;\nexport const TYPE_TO = -1;\n\n/* Node */\nexport const ELEMENT_NODE = 1;\nexport const TEXT_NODE = 3;\nexport const DOCUMENT_NODE = 9;\nexport const DOCUMENT_FRAGMENT_NODE = 11;\nexport const DOCUMENT_POSITION_PRECEDING = 2;\nexport const DOCUMENT_POSITION_CONTAINS = 8;\nexport const DOCUMENT_POSITION_CONTAINED_BY = 0x10;\n\n/* NodeFilter */\nexport const SHOW_ALL = 0xffffffff;\nexport const SHOW_CONTAINER = 0x501;\nexport const SHOW_DOCUMENT = 0x100;\nexport const SHOW_DOCUMENT_FRAGMENT = 0x400;\nexport const SHOW_ELEMENT = 1;\n\n/* selectors */\nexport const ALPHA_NUM = '[A-Z\\\\d]+';\nexport const CHILD_IDX = '(?:first|last|only)-(?:child|of-type)';\nexport const DIGIT = '(?:0|[1-9]\\\\d*)';\nexport const LANG_PART = `(?:-${ALPHA_NUM})*`;\nexport const PSEUDO_CLASS = `(?:any-)?link|${CHILD_IDX}|checked|empty|indeterminate|read-(?:only|write)|target`;\nexport const ANB = `[+-]?(?:${DIGIT}n?|n)|(?:[+-]?${DIGIT})?n\\\\s*[+-]\\\\s*${DIGIT}`;\n// combinators\nexport const COMBO = '\\\\s?[\\\\s>~+]\\\\s?';\nexport const DESCEND = '\\\\s?[\\\\s>]\\\\s?';\nexport const SIBLING = '\\\\s?[+~]\\\\s?';\n// LOGIC_IS: :is()\nexport const LOGIC_IS = `:is\\\\(\\\\s*[^)]+\\\\s*\\\\)`;\n// N_TH: excludes An+B with selector list, e.g. :nth-child(2n+1 of .foo)\nexport const N_TH = `nth-(?:last-)?(?:child|of-type)\\\\(\\\\s*(?:even|odd|${ANB})\\\\s*\\\\)`;\n// SUB_TYPE: attr, id, class, pseudo-class, note that [foo|=bar] is excluded\nexport const SUB_TYPE = '\\\\[[^|\\\\]]+\\\\]|[#.:][\\\\w-]+';\nexport const SUB_TYPE_WO_PSEUDO = '\\\\[[^|\\\\]]+\\\\]|[#.][\\\\w-]+';\n// TAG_TYPE: *, tag\nexport const TAG_TYPE = '\\\\*|[A-Za-z][\\\\w-]*';\nexport const TAG_TYPE_I = '\\\\*|[A-Z][\\\\w-]*';\nexport const COMPOUND = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE})+)`;\nexport const COMPOUND_L = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${LOGIC_IS})+)`;\nexport const COMPOUND_I = `(?:${TAG_TYPE_I}|(?:${TAG_TYPE_I})?(?:${SUB_TYPE})+)`;\nexport const COMPOUND_WO_PSEUDO = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE_WO_PSEUDO})+)`;\nexport const COMPLEX = `${COMPOUND}(?:${COMBO}${COMPOUND})*`;\nexport const COMPLEX_L = `${COMPOUND_L}(?:${COMBO}${COMPOUND_L})*`;\nexport const HAS_COMPOUND = `has\\\\([\\\\s>]?\\\\s*${COMPOUND_WO_PSEUDO}\\\\s*\\\\)`;\nexport const LOGIC_COMPOUND = `(?:is|not)\\\\(\\\\s*${COMPOUND_L}(?:\\\\s*,\\\\s*${COMPOUND_L})*\\\\s*\\\\)`;\nexport const LOGIC_COMPLEX = `(?:is|not)\\\\(\\\\s*${COMPLEX_L}(?:\\\\s*,\\\\s*${COMPLEX_L})*\\\\s*\\\\)`;\n\n/* forms and input types */\nexport const FORM_PARTS = Object.freeze([\n 'button',\n 'input',\n 'select',\n 'textarea'\n]);\nexport const INPUT_BUTTON = Object.freeze(['button', 'reset', 'submit']);\nexport const INPUT_CHECK = Object.freeze(['checkbox', 'radio']);\nexport const INPUT_DATE = Object.freeze([\n 'date',\n 'datetime-local',\n 'month',\n 'time',\n 'week'\n]);\nexport const INPUT_TEXT = Object.freeze([\n 'email',\n 'password',\n 'search',\n 'tel',\n 'text',\n 'url'\n]);\nexport const INPUT_EDIT = Object.freeze([\n ...INPUT_DATE,\n ...INPUT_TEXT,\n 'number'\n]);\nexport const INPUT_LTR = Object.freeze([\n ...INPUT_CHECK,\n 'color',\n 'date',\n 'image',\n 'number',\n 'range',\n 'time'\n]);\n\n/* logical combination pseudo-classes */\nexport const KEYS_LOGICAL = new Set(['has', 'is', 'not', 'where']);\n","/**\n * matcher.js\n */\n\n/* import */\nimport { generateCSS, parseAstName, unescapeSelector } from './parser.js';\nimport {\n generateException,\n getDirectionality,\n getLanguageAttribute,\n getType,\n isContentEditable,\n isCustomElement,\n isNamespaceDeclared\n} from './utility.js';\n\n/* constants */\nimport {\n ALPHA_NUM,\n FORM_PARTS,\n IDENT,\n INPUT_EDIT,\n LANG_PART,\n NOT_SUPPORTED_ERR,\n PS_ELEMENT_SELECTOR,\n STRING,\n SYNTAX_ERR\n} from './constant.js';\nconst KEYS_FORM_PS_DISABLED = new Set([\n ...FORM_PARTS,\n 'fieldset',\n 'optgroup',\n 'option'\n]);\nconst KEYS_INPUT_EDIT = new Set(INPUT_EDIT);\nconst REG_LANG_VALID = new RegExp(`^(?:\\\\*-)?${ALPHA_NUM}${LANG_PART}$`, 'i');\nconst REG_TAG_NAME = /[A-Z][\\\\w-]*/i;\n\n/**\n * Validates a pseudo-element selector.\n * @param {string} astName - The name of the pseudo-element from the AST.\n * @param {string} astType - The type of the selector from the AST.\n * @param {object} [opt] - Optional parameters.\n * @param {boolean} [opt.forgive] - If true, ignores unknown pseudo-elements.\n * @param {boolean} [opt.warn] - If true, throws an error for unsupported ones.\n * @throws {DOMException} If the selector is invalid or unsupported.\n * @returns {void}\n */\nexport const matchPseudoElementSelector = (astName, astType, opt = {}) => {\n const { forgive, globalObject, warn } = opt;\n if (astType !== PS_ELEMENT_SELECTOR) {\n // Ensure the AST node is a pseudo-element selector.\n throw new TypeError(`Unexpected ast type ${getType(astType)}`);\n }\n switch (astName) {\n case 'after':\n case 'backdrop':\n case 'before':\n case 'cue':\n case 'cue-region':\n case 'first-letter':\n case 'first-line':\n case 'file-selector-button':\n case 'marker':\n case 'placeholder':\n case 'selection':\n case 'target-text': {\n // Warn if the pseudo-element is known but unsupported.\n if (warn) {\n throw generateException(\n `Unsupported pseudo-element ::${astName}`,\n NOT_SUPPORTED_ERR,\n globalObject\n );\n }\n break;\n }\n case 'part':\n case 'slotted': {\n // Warn if the functional pseudo-element is known but unsupported.\n if (warn) {\n throw generateException(\n `Unsupported pseudo-element ::${astName}()`,\n NOT_SUPPORTED_ERR,\n globalObject\n );\n }\n break;\n }\n default: {\n // Handle vendor-prefixed or unknown pseudo-elements.\n if (astName.startsWith('-webkit-')) {\n if (warn) {\n throw generateException(\n `Unsupported pseudo-element ::${astName}`,\n NOT_SUPPORTED_ERR,\n globalObject\n );\n }\n // Throw an error for unknown pseudo-elements if not forgiven.\n } else if (!forgive) {\n throw generateException(\n `Unknown pseudo-element ::${astName}`,\n SYNTAX_ERR,\n globalObject\n );\n }\n }\n }\n};\n\n/**\n * Matches the :dir() pseudo-class against an element's directionality.\n * @param {object} ast - The AST object for the pseudo-class.\n * @param {object} node - The element node to match against.\n * @throws {TypeError} If the AST does not contain a valid direction value.\n * @returns {boolean} - True if the directionality matches, otherwise false.\n */\nexport const matchDirectionPseudoClass = (ast, node) => {\n const { name } = ast;\n // The :dir() pseudo-class requires a direction argument (e.g., \"ltr\").\n if (!name) {\n const type = name === '' ? '(empty String)' : getType(name);\n throw new TypeError(`Unexpected ast type ${type}`);\n }\n // Get the computed directionality of the element.\n const dir = getDirectionality(node);\n // Compare the expected direction with the element's actual direction.\n return name === dir;\n};\n\n/**\n * Matches the :lang() pseudo-class against an element's language.\n * @see https://datatracker.ietf.org/doc/html/rfc4647#section-3.3.1\n * @param {object} ast - The AST object for the pseudo-class.\n * @param {object} node - The element node to match against.\n * @returns {boolean} - True if the language matches, otherwise false.\n */\nexport const matchLanguagePseudoClass = (ast, node) => {\n const { name, type, value } = ast;\n let langPattern;\n // Determine the language pattern from the AST.\n if (type === STRING && value) {\n langPattern = value;\n } else if (type === IDENT && name) {\n langPattern = unescapeSelector(name);\n }\n // If no valid language pattern is provided, it cannot match.\n if (typeof langPattern !== 'string') {\n return false;\n }\n // Get the effective language attribute for the current node.\n const elementLang = getLanguageAttribute(node);\n // If the element has no language, it cannot match a specific pattern.\n if (elementLang === null) {\n return false;\n }\n // Handle the universal selector '*' for :lang.\n if (langPattern === '*') {\n // It matches any language unless attribute is not empty.\n return elementLang !== '';\n }\n // Validate the provided language pattern structure.\n if (!REG_LANG_VALID.test(langPattern)) {\n return false;\n }\n // Build a regex for extended language range matching.\n let matcherRegex;\n if (langPattern.indexOf('-') > -1) {\n // Handle complex patterns with wildcards and sub-tags (e.g., '*-US').\n const [langMain, langSub, ...langRest] = langPattern.split('-');\n const extendedMain =\n langMain === '*' ? `${ALPHA_NUM}${LANG_PART}` : `${langMain}${LANG_PART}`;\n const extendedSub = `-${langSub}${LANG_PART}`;\n let extendedRest = '';\n // Use a standard for loop for performance as per the rules.\n for (let i = 0; i < langRest.length; i++) {\n extendedRest += `-${langRest[i]}${LANG_PART}`;\n }\n matcherRegex = new RegExp(\n `^${extendedMain}${extendedSub}${extendedRest}$`,\n 'i'\n );\n } else {\n // Handle simple language patterns (e.g., 'en').\n matcherRegex = new RegExp(`^${langPattern}${LANG_PART}$`, 'i');\n }\n // Test the element's language against the constructed regex.\n return matcherRegex.test(elementLang);\n};\n\n/**\n * Matches the :disabled and :enabled pseudo-classes.\n * @param {string} astName - pseudo-class name\n * @param {object} node - Element node\n * @returns {boolean} - True if matched\n */\nexport const matchDisabledPseudoClass = (astName, node) => {\n const { localName, parentNode } = node;\n if (\n !KEYS_FORM_PS_DISABLED.has(localName) &&\n !isCustomElement(node, { formAssociated: true })\n ) {\n return false;\n }\n let isDisabled = false;\n if (node.disabled || node.hasAttribute('disabled')) {\n isDisabled = true;\n } else if (localName === 'option') {\n if (\n parentNode &&\n parentNode.localName === 'optgroup' &&\n (parentNode.disabled || parentNode.hasAttribute('disabled'))\n ) {\n isDisabled = true;\n }\n } else if (localName !== 'optgroup') {\n let current = parentNode;\n while (current) {\n if (\n current.localName === 'fieldset' &&\n (current.disabled || current.hasAttribute('disabled'))\n ) {\n // The first <legend> in a disabled <fieldset> is not disabled.\n let legend;\n let element = current.firstElementChild;\n while (element) {\n if (element.localName === 'legend') {\n legend = element;\n break;\n }\n element = element.nextElementSibling;\n }\n if (!legend || !legend.contains(node)) {\n isDisabled = true;\n }\n // Found the containing fieldset, stop searching up.\n break;\n }\n current = current.parentNode;\n }\n }\n if (astName === 'disabled') {\n return isDisabled;\n }\n return !isDisabled;\n};\n\n/**\n * Match the :read-only and :read-write pseudo-classes\n * @param {string} astName - pseudo-class name\n * @param {object} node - Element node\n * @returns {boolean} - True if matched\n */\nexport const matchReadOnlyPseudoClass = (astName, node) => {\n const { localName } = node;\n let isReadOnly = false;\n switch (localName) {\n case 'textarea':\n case 'input': {\n const isEditableInput = !node.type || KEYS_INPUT_EDIT.has(node.type);\n if (localName === 'textarea' || isEditableInput) {\n isReadOnly =\n node.readOnly ||\n node.hasAttribute('readonly') ||\n node.disabled ||\n node.hasAttribute('disabled');\n } else {\n // Non-editable input types are always read-only\n isReadOnly = true;\n }\n break;\n }\n default: {\n isReadOnly = !isContentEditable(node);\n }\n }\n if (astName === 'read-only') {\n return isReadOnly;\n }\n return !isReadOnly;\n};\n\n/**\n * Matches an attribute selector against an element.\n * This function handles various attribute matchers like '=', '~=', '^=', etc.,\n * and considers namespaces and case sensitivity based on document type.\n * @param {object} ast - The AST for the attribute selector.\n * @param {object} node - The element node to match against.\n * @param {object} [opt] - Optional parameters.\n * @param {boolean} [opt.check] - True if running in an internal check.\n * @param {boolean} [opt.forgive] - True to forgive certain syntax errors.\n * @returns {boolean} - True if the attribute selector matches, otherwise false.\n */\nexport const matchAttributeSelector = (ast, node, opt = {}) => {\n const {\n flags: astFlags,\n matcher: astMatcher,\n name: astName,\n value: astValue\n } = ast;\n const { check, forgive, globalObject } = opt;\n // Validate selector flags ('i' or 's').\n if (typeof astFlags === 'string' && !/^[is]$/i.test(astFlags) && !forgive) {\n const css = generateCSS(ast);\n throw generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n globalObject\n );\n }\n const { attributes } = node;\n // An element with no attributes cannot match.\n if (!attributes || !attributes.length) {\n return false;\n }\n // Determine case sensitivity based on document type and flags.\n const contentType = node.ownerDocument.contentType;\n let caseInsensitive;\n if (contentType === 'text/html') {\n if (typeof astFlags === 'string' && /^s$/i.test(astFlags)) {\n caseInsensitive = false;\n } else {\n caseInsensitive = true;\n }\n } else if (typeof astFlags === 'string' && /^i$/i.test(astFlags)) {\n caseInsensitive = true;\n } else {\n caseInsensitive = false;\n }\n // Prepare the attribute name from the selector for matching.\n let astAttrName = unescapeSelector(astName.name);\n if (caseInsensitive) {\n astAttrName = astAttrName.toLowerCase();\n }\n // A set to store the values of attributes whose names match.\n const attrValues = new Set();\n // Handle namespaced attribute names (e.g., [*|attr], [ns|attr]).\n if (astAttrName.indexOf('|') > -1) {\n const { prefix: astPrefix, localName: astLocalName } =\n parseAstName(astAttrName);\n for (const item of attributes) {\n let { name: itemName, value: itemValue } = item;\n if (caseInsensitive) {\n itemName = itemName.toLowerCase();\n itemValue = itemValue.toLowerCase();\n }\n switch (astPrefix) {\n case '': {\n if (astLocalName === itemName) {\n attrValues.add(itemValue);\n }\n break;\n }\n case '*': {\n if (itemName.indexOf(':') > -1) {\n const [, ...restItemName] = itemName.split(':');\n const itemLocalName = restItemName.join(':').replace(/^:/, '');\n if (itemLocalName === astLocalName) {\n attrValues.add(itemValue);\n }\n } else if (astLocalName === itemName) {\n attrValues.add(itemValue);\n }\n break;\n }\n default: {\n if (!check) {\n if (forgive) {\n return false;\n }\n const css = generateCSS(ast);\n throw generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n globalObject\n );\n }\n if (itemName.indexOf(':') > -1) {\n const [itemPrefix, ...restItemName] = itemName.split(':');\n const itemLocalName = restItemName.join(':').replace(/^:/, '');\n // Ignore the 'xml:lang' attribute.\n if (itemPrefix === 'xml' && itemLocalName === 'lang') {\n continue;\n } else if (\n astPrefix === itemPrefix &&\n astLocalName === itemLocalName\n ) {\n const namespaceDeclared = isNamespaceDeclared(astPrefix, node);\n if (namespaceDeclared) {\n attrValues.add(itemValue);\n }\n }\n }\n }\n }\n }\n // Handle non-namespaced attribute names.\n } else {\n for (let { name: itemName, value: itemValue } of attributes) {\n if (caseInsensitive) {\n itemName = itemName.toLowerCase();\n itemValue = itemValue.toLowerCase();\n }\n if (itemName.indexOf(':') > -1) {\n const [itemPrefix, ...restItemName] = itemName.split(':');\n const itemLocalName = restItemName.join(':').replace(/^:/, '');\n // The attribute is starting with ':'.\n if (!itemPrefix && astAttrName === `:${itemLocalName}`) {\n attrValues.add(itemValue);\n // Ignore the 'xml:lang' attribute.\n } else if (itemPrefix === 'xml' && itemLocalName === 'lang') {\n continue;\n } else if (astAttrName === itemLocalName) {\n attrValues.add(itemValue);\n }\n } else if (astAttrName === itemName) {\n attrValues.add(itemValue);\n }\n }\n }\n if (!attrValues.size) {\n return false;\n }\n // Prepare the value from the selector's RHS for comparison.\n const { name: astIdentValue, value: astStringValue } = astValue ?? {};\n let attrValue;\n if (astIdentValue) {\n if (caseInsensitive) {\n attrValue = astIdentValue.toLowerCase();\n } else {\n attrValue = astIdentValue;\n }\n } else if (astStringValue) {\n if (caseInsensitive) {\n attrValue = astStringValue.toLowerCase();\n } else {\n attrValue = astStringValue;\n }\n } else if (astStringValue === '') {\n attrValue = astStringValue;\n }\n // Perform the final match based on the specified matcher.\n switch (astMatcher) {\n case '=': {\n return typeof attrValue === 'string' && attrValues.has(attrValue);\n }\n case '~=': {\n if (attrValue && typeof attrValue === 'string') {\n for (const value of attrValues) {\n const item = new Set(value.split(/\\s+/));\n if (item.has(attrValue)) {\n return true;\n }\n }\n }\n return false;\n }\n case '|=': {\n if (attrValue && typeof attrValue === 'string') {\n for (const value of attrValues) {\n if (value === attrValue || value.startsWith(`${attrValue}-`)) {\n return true;\n }\n }\n }\n return false;\n }\n case '^=': {\n if (attrValue && typeof attrValue === 'string') {\n for (const value of attrValues) {\n if (value.startsWith(`${attrValue}`)) {\n return true;\n }\n }\n }\n return false;\n }\n case '$=': {\n if (attrValue && typeof attrValue === 'string') {\n for (const value of attrValues) {\n if (value.endsWith(`${attrValue}`)) {\n return true;\n }\n }\n }\n return false;\n }\n case '*=': {\n if (attrValue && typeof attrValue === 'string') {\n for (const value of attrValues) {\n if (value.includes(`${attrValue}`)) {\n return true;\n }\n }\n }\n return false;\n }\n case null:\n default: {\n // This case handles attribute existence checks (e.g., '[disabled]').\n return true;\n }\n }\n};\n\n/**\n * match type selector\n * @param {object} ast - AST\n * @param {object} node - Element node\n * @param {object} [opt] - options\n * @param {boolean} [opt.check] - running in internal check()\n * @param {boolean} [opt.forgive] - forgive undeclared namespace\n * @returns {boolean} - result\n */\nexport const matchTypeSelector = (ast, node, opt = {}) => {\n const astName = unescapeSelector(ast.name);\n const { localName, namespaceURI, prefix } = node;\n const { check, forgive, globalObject } = opt;\n let { prefix: astPrefix, localName: astLocalName } = parseAstName(\n astName,\n node\n );\n if (\n node.ownerDocument.contentType === 'text/html' &&\n (!namespaceURI || namespaceURI === 'http://www.w3.org/1999/xhtml') &&\n REG_TAG_NAME.test(localName)\n ) {\n astPrefix = astPrefix.toLowerCase();\n astLocalName = astLocalName.toLowerCase();\n }\n let nodePrefix;\n let nodeLocalName;\n // just in case that the namespaced content is parsed as text/html\n if (localName.indexOf(':') > -1) {\n [nodePrefix, nodeLocalName] = localName.split(':');\n } else {\n nodePrefix = prefix || '';\n nodeLocalName = localName;\n }\n switch (astPrefix) {\n case '': {\n if (\n !nodePrefix &&\n !namespaceURI &&\n (astLocalName === '*' || astLocalName === nodeLocalName)\n ) {\n return true;\n }\n return false;\n }\n case '*': {\n if (astLocalName === '*' || astLocalName === nodeLocalName) {\n return true;\n }\n return false;\n }\n default: {\n if (!check) {\n if (forgive) {\n return false;\n }\n const css = generateCSS(ast);\n throw generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n globalObject\n );\n }\n const astNS = node.lookupNamespaceURI(astPrefix);\n const nodeNS = node.lookupNamespaceURI(nodePrefix);\n if (astNS === nodeNS && astPrefix === nodePrefix) {\n if (astLocalName === '*' || astLocalName === nodeLocalName) {\n return true;\n }\n return false;\n } else if (!forgive && !astNS) {\n throw generateException(\n `Undeclared namespace ${astPrefix}`,\n SYNTAX_ERR,\n globalObject\n );\n }\n return false;\n }\n }\n};\n","/**\n * finder.js\n */\n\n/* import */\nimport {\n matchAttributeSelector,\n matchDirectionPseudoClass,\n matchDisabledPseudoClass,\n matchLanguagePseudoClass,\n matchPseudoElementSelector,\n matchReadOnlyPseudoClass,\n matchTypeSelector\n} from './matcher.js';\nimport {\n findAST,\n generateCSS,\n parseSelector,\n sortAST,\n unescapeSelector,\n walkAST\n} from './parser.js';\nimport {\n filterNodesByAnB,\n findLogicalWithNestedHas,\n generateException,\n isCustomElement,\n isFocusVisible,\n isFocusableArea,\n isVisible,\n resolveContent,\n sortNodes,\n traverseNode\n} from './utility.js';\n\n/* constants */\nimport {\n ATTR_SELECTOR,\n CLASS_SELECTOR,\n COMBINATOR,\n DOCUMENT_FRAGMENT_NODE,\n ELEMENT_NODE,\n FORM_PARTS,\n ID_SELECTOR,\n INPUT_CHECK,\n INPUT_DATE,\n INPUT_EDIT,\n INPUT_TEXT,\n KEYS_LOGICAL,\n NOT_SUPPORTED_ERR,\n PS_CLASS_SELECTOR,\n PS_ELEMENT_SELECTOR,\n SHOW_ALL,\n SHOW_CONTAINER,\n SYNTAX_ERR,\n TARGET_ALL,\n TARGET_FIRST,\n TARGET_LINEAL,\n TARGET_SELF,\n TEXT_NODE,\n TYPE_SELECTOR\n} from './constant.js';\nconst DIR_NEXT = 'next';\nconst DIR_PREV = 'prev';\nconst KEYS_FORM = new Set([...FORM_PARTS, 'fieldset', 'form']);\nconst KEYS_FORM_PS_VALID = new Set([...FORM_PARTS, 'form']);\nconst KEYS_INPUT_CHECK = new Set(INPUT_CHECK);\nconst KEYS_INPUT_PLACEHOLDER = new Set([...INPUT_TEXT, 'number']);\nconst KEYS_INPUT_RANGE = new Set([...INPUT_DATE, 'number', 'range']);\nconst KEYS_INPUT_REQUIRED = new Set([...INPUT_CHECK, ...INPUT_EDIT, 'file']);\nconst KEYS_INPUT_RESET = new Set(['button', 'reset']);\nconst KEYS_INPUT_SUBMIT = new Set(['image', 'submit']);\nconst KEYS_MODIFIER = new Set([\n 'Alt',\n 'AltGraph',\n 'CapsLock',\n 'Control',\n 'Fn',\n 'FnLock',\n 'Hyper',\n 'Meta',\n 'NumLock',\n 'ScrollLock',\n 'Shift',\n 'Super',\n 'Symbol',\n 'SymbolLock'\n]);\nconst KEYS_PS_UNCACHE = new Set([\n 'any-link',\n 'defined',\n 'dir',\n 'link',\n 'scope'\n]);\nconst KEYS_PS_NTH_OF_TYPE = new Set([\n 'first-of-type',\n 'last-of-type',\n 'only-of-type'\n]);\n\n/**\n * Finder\n * NOTE: #ast[i] corresponds to #nodes[i]\n */\nexport class Finder {\n /* private fields */\n #ast;\n #astCache;\n #check;\n #descendant;\n #document;\n #documentCache;\n #documentURL;\n #event;\n #eventHandlers;\n #focus;\n #invalidate;\n #invalidateResults;\n #lastFocusVisible;\n #node;\n #nodeWalker;\n #nodes;\n #noexcept;\n #pseudoElement;\n #results;\n #root;\n #rootWalker;\n #scoped;\n #selector;\n #shadow;\n #verifyShadowHost;\n #walkers;\n #warn;\n #window;\n\n /**\n * constructor\n * @param {object} window - The window object.\n */\n constructor(window) {\n this.#window = window;\n this.#astCache = new WeakMap();\n this.#documentCache = new WeakMap();\n this.#event = null;\n this.#focus = null;\n this.#lastFocusVisible = null;\n this.#eventHandlers = new Set([\n {\n keys: ['focus', 'focusin'],\n handler: this._handleFocusEvent\n },\n {\n keys: ['keydown', 'keyup'],\n handler: this._handleKeyboardEvent\n },\n {\n keys: ['mouseover', 'mousedown', 'mouseup', 'click', 'mouseout'],\n handler: this._handleMouseEvent\n }\n ]);\n this._registerEventListeners();\n this.clearResults(true);\n }\n\n /**\n * Handles errors.\n * @param {Error} e - The error object.\n * @param {object} [opt] - Options.\n * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.\n * @throws {Error} Throws an error.\n * @returns {void}\n */\n onError = (e, opt = {}) => {\n const noexcept = opt.noexcept ?? this.#noexcept;\n if (noexcept) {\n return;\n }\n const isDOMException =\n e instanceof DOMException || e instanceof this.#window.DOMException;\n if (isDOMException) {\n if (e.name === NOT_SUPPORTED_ERR) {\n if (this.#warn) {\n console.warn(e.message);\n }\n return;\n }\n throw new this.#window.DOMException(e.message, e.name);\n }\n if (e.name in this.#window) {\n throw new this.#window[e.name](e.message, { cause: e });\n }\n throw e;\n };\n\n /**\n * Sets up the finder.\n * @param {string} selector - The CSS selector.\n * @param {object} node - Document, DocumentFragment, or Element.\n * @param {object} [opt] - Options.\n * @param {boolean} [opt.check] - Indicates if running in internal check().\n * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.\n * @param {boolean} [opt.warn] - If true, console warnings are enabled.\n * @returns {object} The finder instance.\n */\n setup = (selector, node, opt = {}) => {\n const { check, noexcept, warn } = opt;\n this.#check = !!check;\n this.#noexcept = !!noexcept;\n this.#warn = !!warn;\n [this.#document, this.#root, this.#shadow] = resolveContent(node);\n this.#documentURL = null;\n this.#node = node;\n this.#scoped =\n this.#node !== this.#root && this.#node.nodeType === ELEMENT_NODE;\n this.#selector = selector;\n [this.#ast, this.#nodes] = this._correspond(selector);\n this.#pseudoElement = [];\n this.#walkers = new WeakMap();\n this.#nodeWalker = null;\n this.#rootWalker = null;\n this.#verifyShadowHost = null;\n this.clearResults();\n return this;\n };\n\n /**\n * Clear cached results.\n * @param {boolean} all - clear all results\n * @returns {void}\n */\n clearResults = (all = false) => {\n this.#invalidateResults = new WeakMap();\n if (all) {\n this.#results = new WeakMap();\n }\n };\n\n /**\n * Handles focus events.\n * @private\n * @param {Event} evt - The event object.\n * @returns {void}\n */\n _handleFocusEvent = evt => {\n this.#focus = evt;\n };\n\n /**\n * Handles keyboard events.\n * @private\n * @param {Event} evt - The event object.\n * @returns {void}\n */\n _handleKeyboardEvent = evt => {\n const { key } = evt;\n if (!KEYS_MODIFIER.has(key)) {\n this.#event = evt;\n }\n };\n\n /**\n * Handles mouse events.\n * @private\n * @param {Event} evt - The event object.\n * @returns {void}\n */\n _handleMouseEvent = evt => {\n this.#event = evt;\n };\n\n /**\n * Registers event listeners.\n * @private\n * @returns {Array.<void>} An array of return values from addEventListener.\n */\n _registerEventListeners = () => {\n const opt = {\n capture: true,\n passive: true\n };\n const func = [];\n for (const eventHandler of this.#eventHandlers) {\n const { keys, handler } = eventHandler;\n const l = keys.length;\n for (let i = 0; i < l; i++) {\n const key = keys[i];\n func.push(this.#window.addEventListener(key, handler, opt));\n }\n }\n return func;\n };\n\n /**\n * Processes selector branches into the internal AST structure.\n * @private\n * @param {Array.<Array.<object>>} branches - The branches from walkAST.\n * @param {string} selector - The original selector for error reporting.\n * @returns {{ast: Array, descendant: boolean}}\n * An object with the AST, descendant flag.\n */\n _processSelectorBranches = (branches, selector) => {\n let descendant = false;\n const ast = [];\n const l = branches.length;\n for (let i = 0; i < l; i++) {\n const items = [...branches[i]];\n const branch = [];\n let item = items.shift();\n if (item && item.type !== COMBINATOR) {\n const leaves = new Set();\n while (item) {\n if (item.type === COMBINATOR) {\n const [nextItem] = items;\n if (!nextItem || nextItem.type === COMBINATOR) {\n const msg = `Invalid selector ${selector}`;\n this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n // Stop processing on invalid selector.\n return { ast: [], descendant: false, invalidate: false };\n }\n if (item.name === ' ' || item.name === '>') {\n descendant = true;\n }\n branch.push({ combo: item, leaves: sortAST(leaves) });\n leaves.clear();\n } else {\n if (item.name && typeof item.name === 'string') {\n const unescapedName = unescapeSelector(item.name);\n if (unescapedName !== item.name) {\n item.name = unescapedName;\n }\n if (/[|:]/.test(unescapedName)) {\n item.namespace = true;\n }\n }\n leaves.add(item);\n }\n if (items.length) {\n item = items.shift();\n } else {\n branch.push({ combo: null, leaves: sortAST(leaves) });\n leaves.clear();\n break;\n }\n }\n }\n ast.push({ branch, dir: null, filtered: false, find: false });\n }\n return { ast, descendant };\n };\n\n /**\n * Corresponds AST and nodes.\n * @private\n * @param {string} selector - The CSS selector.\n * @returns {Array.<Array.<object>>} An array with the AST and nodes.\n */\n _correspond = selector => {\n const nodes = [];\n this.#descendant = false;\n this.#invalidate = false;\n let ast;\n if (this.#documentCache.has(this.#document)) {\n const cachedItem = this.#documentCache.get(this.#document);\n if (cachedItem && cachedItem.has(`${selector}`)) {\n const item = cachedItem.get(`${selector}`);\n ast = item.ast;\n this.#descendant = item.descendant;\n this.#invalidate = item.invalidate;\n }\n }\n if (ast) {\n const l = ast.length;\n for (let i = 0; i < l; i++) {\n ast[i].dir = null;\n ast[i].filtered = false;\n ast[i].find = false;\n nodes[i] = [];\n }\n } else {\n let cssAst;\n try {\n cssAst = parseSelector(selector);\n } catch (e) {\n return this.onError(e);\n }\n const { branches, info } = walkAST(cssAst);\n const {\n hasHasPseudoFunc,\n hasLogicalPseudoFunc,\n hasNthChildOfSelector,\n hasStatePseudoClass\n } = info;\n this.#invalidate =\n hasHasPseudoFunc ||\n hasStatePseudoClass ||\n !!(hasLogicalPseudoFunc && hasNthChildOfSelector);\n const processed = this._processSelectorBranches(branches, selector);\n ast = processed.ast;\n this.#descendant = processed.descendant;\n let cachedItem;\n if (this.#documentCache.has(this.#document)) {\n cachedItem = this.#documentCache.get(this.#document);\n } else {\n cachedItem = new Map();\n }\n cachedItem.set(`${selector}`, {\n ast,\n descendant: this.#descendant,\n invalidate: this.#invalidate\n });\n this.#documentCache.set(this.#document, cachedItem);\n // Initialize nodes array for each branch.\n for (let i = 0; i < ast.length; i++) {\n nodes[i] = [];\n }\n }\n return [ast, nodes];\n };\n\n /**\n * Creates a TreeWalker.\n * @private\n * @param {object} node - The Document, DocumentFragment, or Element node.\n * @param {object} [opt] - Options.\n * @param {boolean} [opt.force] - Force creation of a new TreeWalker.\n * @param {number} [opt.whatToShow] - The NodeFilter whatToShow value.\n * @returns {object} The TreeWalker object.\n */\n _createTreeWalker = (node, opt = {}) => {\n const { force = false, whatToShow = SHOW_CONTAINER } = opt;\n if (force) {\n return this.#document.createTreeWalker(node, whatToShow);\n } else if (this.#walkers.has(node)) {\n return this.#walkers.get(node);\n }\n const walker = this.#document.createTreeWalker(node, whatToShow);\n this.#walkers.set(node, walker);\n return walker;\n };\n\n /**\n * Gets selector branches from cache or parses them.\n * @private\n * @param {object} selector - The AST.\n * @returns {Array.<Array.<object>>} The selector branches.\n */\n _getSelectorBranches = selector => {\n if (this.#astCache.has(selector)) {\n return this.#astCache.get(selector);\n }\n const { branches } = walkAST(selector);\n this.#astCache.set(selector, branches);\n return branches;\n };\n\n /**\n * Gets the children of a node, optionally filtered by a selector.\n * @private\n * @param {object} parentNode - The parent element.\n * @param {Array.<Array.<object>>} selectorBranches - The selector branches.\n * @param {object} [opt] - Options.\n * @returns {Array.<object>} An array of child nodes.\n */\n _getFilteredChildren = (parentNode, selectorBranches, opt = {}) => {\n const children = [];\n const walker = this._createTreeWalker(parentNode, { force: true });\n let childNode = walker.firstChild();\n while (childNode) {\n if (selectorBranches) {\n if (isVisible(childNode)) {\n let isMatch = false;\n const l = selectorBranches.length;\n for (let i = 0; i < l; i++) {\n const leaves = selectorBranches[i];\n if (this._matchLeaves(leaves, childNode, opt)) {\n isMatch = true;\n break;\n }\n }\n if (isMatch) {\n children.push(childNode);\n }\n }\n } else {\n children.push(childNode);\n }\n childNode = walker.nextSibling();\n }\n return children;\n };\n\n /**\n * Collects nth-child nodes.\n * @private\n * @param {object} anb - An+B options.\n * @param {number} anb.a - The 'a' value.\n * @param {number} anb.b - The 'b' value.\n * @param {boolean} [anb.reverse] - If true, reverses the order.\n * @param {object} [anb.selector] - The AST.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _collectNthChild = (anb, node, opt = {}) => {\n const { a, b, selector } = anb;\n const { parentNode } = node;\n if (!parentNode) {\n const matchedNode = new Set();\n if (node === this.#root && a * 1 + b * 1 === 1) {\n if (selector) {\n const selectorBranches = this._getSelectorBranches(selector);\n const l = selectorBranches.length;\n for (let i = 0; i < l; i++) {\n const leaves = selectorBranches[i];\n if (this._matchLeaves(leaves, node, opt)) {\n matchedNode.add(node);\n break;\n }\n }\n } else {\n matchedNode.add(node);\n }\n }\n return matchedNode;\n }\n const selectorBranches = selector\n ? this._getSelectorBranches(selector)\n : null;\n const children = this._getFilteredChildren(\n parentNode,\n selectorBranches,\n opt\n );\n const matchedNodes = filterNodesByAnB(children, anb);\n return new Set(matchedNodes);\n };\n\n /**\n * Collects nth-of-type nodes.\n * @private\n * @param {object} anb - An+B options.\n * @param {number} anb.a - The 'a' value.\n * @param {number} anb.b - The 'b' value.\n * @param {boolean} [anb.reverse] - If true, reverses the order.\n * @param {object} node - The Element node.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _collectNthOfType = (anb, node) => {\n const { parentNode } = node;\n if (!parentNode) {\n if (node === this.#root && anb.a * 1 + anb.b * 1 === 1) {\n return new Set([node]);\n }\n return new Set();\n }\n const typedSiblings = [];\n const walker = this._createTreeWalker(parentNode, { force: true });\n let sibling = walker.firstChild();\n while (sibling) {\n if (\n sibling.localName === node.localName &&\n sibling.namespaceURI === node.namespaceURI &&\n sibling.prefix === node.prefix\n ) {\n typedSiblings.push(sibling);\n }\n sibling = walker.nextSibling();\n }\n const matchedNodes = filterNodesByAnB(typedSiblings, anb);\n return new Set(matchedNodes);\n };\n\n /**\n * Matches An+B.\n * @private\n * @param {object} ast - The AST.\n * @param {object} node - The Element node.\n * @param {string} nthName - The name of the nth pseudo-class.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchAnPlusB = (ast, node, nthName, opt = {}) => {\n const {\n nth: { a, b, name: nthIdentName },\n selector\n } = ast;\n const anbMap = new Map();\n if (nthIdentName) {\n if (nthIdentName === 'even') {\n anbMap.set('a', 2);\n anbMap.set('b', 0);\n } else if (nthIdentName === 'odd') {\n anbMap.set('a', 2);\n anbMap.set('b', 1);\n }\n if (nthName.indexOf('last') > -1) {\n anbMap.set('reverse', true);\n }\n } else {\n if (typeof a === 'string' && /-?\\d+/.test(a)) {\n anbMap.set('a', a * 1);\n } else {\n anbMap.set('a', 0);\n }\n if (typeof b === 'string' && /-?\\d+/.test(b)) {\n anbMap.set('b', b * 1);\n } else {\n anbMap.set('b', 0);\n }\n if (nthName.indexOf('last') > -1) {\n anbMap.set('reverse', true);\n }\n }\n if (nthName === 'nth-child' || nthName === 'nth-last-child') {\n if (selector) {\n anbMap.set('selector', selector);\n }\n const anb = Object.fromEntries(anbMap);\n const nodes = this._collectNthChild(anb, node, opt);\n return nodes;\n } else if (nthName === 'nth-of-type' || nthName === 'nth-last-of-type') {\n const anb = Object.fromEntries(anbMap);\n const nodes = this._collectNthOfType(anb, node);\n return nodes;\n }\n return new Set();\n };\n\n /**\n * Matches the :has() pseudo-class function.\n * @private\n * @param {Array.<object>} astLeaves - The AST leaves.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {boolean} The result.\n */\n _matchHasPseudoFunc = (astLeaves, node, opt = {}) => {\n if (Array.isArray(astLeaves) && astLeaves.length) {\n // Prepare a copy to avoid astLeaves being consumed.\n const leaves = [...astLeaves];\n const [leaf] = leaves;\n const { type: leafType } = leaf;\n let combo;\n if (leafType === COMBINATOR) {\n combo = leaves.shift();\n } else {\n combo = {\n name: ' ',\n type: COMBINATOR\n };\n }\n const twigLeaves = [];\n while (leaves.length) {\n const [item] = leaves;\n const { type: itemType } = item;\n if (itemType === COMBINATOR) {\n break;\n } else {\n twigLeaves.push(leaves.shift());\n }\n }\n const twig = {\n combo,\n leaves: twigLeaves\n };\n opt.dir = DIR_NEXT;\n const nodes = this._matchCombinator(twig, node, opt);\n if (nodes.size) {\n if (leaves.length) {\n let bool = false;\n for (const nextNode of nodes) {\n bool = this._matchHasPseudoFunc(leaves, nextNode, opt);\n if (bool) {\n break;\n }\n }\n return bool;\n }\n return true;\n }\n }\n return false;\n };\n\n /**\n * Evaluates the :has() pseudo-class.\n * @private\n * @param {object} astData - The AST data.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {?object} The matched node.\n */\n _evaluateHasPseudo = (astData, node, opt) => {\n const { branches } = astData;\n let bool = false;\n const l = branches.length;\n for (let i = 0; i < l; i++) {\n const leaves = branches[i];\n bool = this._matchHasPseudoFunc(leaves, node, opt);\n if (bool) {\n break;\n }\n }\n if (!bool) {\n return null;\n }\n if (\n (opt.isShadowRoot || this.#shadow) &&\n node.nodeType === DOCUMENT_FRAGMENT_NODE\n ) {\n return this.#verifyShadowHost ? node : null;\n }\n return node;\n };\n\n /**\n * Matches logical pseudo-class functions.\n * @private\n * @param {object} astData - The AST data.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {?object} The matched node.\n */\n _matchLogicalPseudoFunc = (astData, node, opt = {}) => {\n const { astName, branches, twigBranches } = astData;\n // Handle :has().\n if (astName === 'has') {\n return this._evaluateHasPseudo(astData, node, opt);\n }\n // Handle :is(), :not(), :where().\n const isShadowRoot =\n (opt.isShadowRoot || this.#shadow) &&\n node.nodeType === DOCUMENT_FRAGMENT_NODE;\n // Check for invalid shadow root.\n if (isShadowRoot) {\n let invalid = false;\n for (const branch of branches) {\n if (branch.length > 1) {\n invalid = true;\n break;\n } else if (astName === 'not') {\n const [{ type: childAstType }] = branch;\n if (childAstType !== PS_CLASS_SELECTOR) {\n invalid = true;\n break;\n }\n }\n }\n if (invalid) {\n return null;\n }\n }\n opt.forgive = astName === 'is' || astName === 'where';\n const l = twigBranches.length;\n let bool;\n for (let i = 0; i < l; i++) {\n const branch = twigBranches[i];\n const lastIndex = branch.length - 1;\n const { leaves } = branch[lastIndex];\n bool = this._matchLeaves(leaves, node, opt);\n if (bool && lastIndex > 0) {\n let nextNodes = new Set([node]);\n for (let j = lastIndex - 1; j >= 0; j--) {\n const twig = branch[j];\n const arr = [];\n opt.dir = DIR_PREV;\n for (const nextNode of nextNodes) {\n const m = this._matchCombinator(twig, nextNode, opt);\n if (m.size) {\n arr.push(...m);\n }\n }\n if (arr.length) {\n if (j === 0) {\n bool = true;\n } else {\n nextNodes = new Set(arr);\n }\n } else {\n bool = false;\n break;\n }\n }\n }\n if (bool) {\n break;\n }\n }\n if (astName === 'not') {\n if (bool) {\n return null;\n }\n return node;\n } else if (bool) {\n return node;\n }\n return null;\n };\n\n /**\n * match pseudo-class selector\n * @private\n * @see https://html.spec.whatwg.org/#pseudo-classes\n * @param {object} ast - AST\n * @param {object} node - Element node\n * @param {object} [opt] - options\n * @returns {Set.<object>} - collection of matched nodes\n */\n _matchPseudoClassSelector(ast, node, opt = {}) {\n const { children: astChildren, name: astName } = ast;\n const { localName, parentNode } = node;\n const { forgive, warn = this.#warn } = opt;\n const matched = new Set();\n // :has(), :is(), :not(), :where()\n if (Array.isArray(astChildren) && KEYS_LOGICAL.has(astName)) {\n if (!astChildren.length && astName !== 'is' && astName !== 'where') {\n const css = generateCSS(ast);\n const msg = `Invalid selector ${css}`;\n return this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n }\n let astData;\n if (this.#astCache.has(ast)) {\n astData = this.#astCache.get(ast);\n } else {\n const { branches } = walkAST(ast);\n if (astName === 'has') {\n // Check for nested :has().\n let forgiven = false;\n const l = astChildren.length;\n for (let i = 0; i < l; i++) {\n const child = astChildren[i];\n const item = findAST(child, findLogicalWithNestedHas);\n if (item) {\n const itemName = item.name;\n if (itemName === 'is' || itemName === 'where') {\n forgiven = true;\n break;\n } else {\n const css = generateCSS(ast);\n const msg = `Invalid selector ${css}`;\n return this.onError(\n generateException(msg, SYNTAX_ERR, this.#window)\n );\n }\n }\n }\n if (forgiven) {\n return matched;\n }\n astData = {\n astName,\n branches\n };\n } else {\n const twigBranches = [];\n const l = branches.length;\n for (let i = 0; i < l; i++) {\n const [...leaves] = branches[i];\n const branch = [];\n const leavesSet = new Set();\n let item = leaves.shift();\n while (item) {\n if (item.type === COMBINATOR) {\n branch.push({\n combo: item,\n leaves: [...leavesSet]\n });\n leavesSet.clear();\n } else if (item) {\n leavesSet.add(item);\n }\n if (leaves.length) {\n item = leaves.shift();\n } else {\n branch.push({\n combo: null,\n leaves: [...leavesSet]\n });\n leavesSet.clear();\n break;\n }\n }\n twigBranches.push(branch);\n }\n astData = {\n astName,\n branches,\n twigBranches\n };\n this.#astCache.set(ast, astData);\n }\n }\n const res = this._matchLogicalPseudoFunc(astData, node, opt);\n if (res) {\n matched.add(res);\n }\n } else if (Array.isArray(astChildren)) {\n // :nth-child(), :nth-last-child(), nth-of-type(), :nth-last-of-type()\n if (/^nth-(?:last-)?(?:child|of-type)$/.test(astName)) {\n if (astChildren.length !== 1) {\n const css = generateCSS(ast);\n return this.onError(\n generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n this.#window\n )\n );\n }\n const [branch] = astChildren;\n const nodes = this._matchAnPlusB(branch, node, astName, opt);\n return nodes;\n } else {\n switch (astName) {\n // :dir()\n case 'dir': {\n if (astChildren.length !== 1) {\n const css = generateCSS(ast);\n return this.onError(\n generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n this.#window\n )\n );\n }\n const [astChild] = astChildren;\n const res = matchDirectionPseudoClass(astChild, node);\n if (res) {\n matched.add(node);\n }\n break;\n }\n // :lang()\n case 'lang': {\n if (!astChildren.length) {\n const css = generateCSS(ast);\n return this.onError(\n generateException(\n `Invalid selector ${css}`,\n SYNTAX_ERR,\n this.#window\n )\n );\n }\n let bool;\n for (const astChild of astChildren) {\n bool = matchLanguagePseudoClass(astChild, node);\n if (bool) {\n break;\n }\n }\n if (bool) {\n matched.add(node);\n }\n break;\n }\n // :state()\n case 'state': {\n if (isCustomElement(node)) {\n const [{ value: stateValue }] = astChildren;\n if (stateValue) {\n if (node[stateValue]) {\n matched.add(node);\n } else {\n for (const i in node) {\n const prop = node[i];\n if (prop instanceof this.#window.ElementInternals) {\n if (prop?.states?.has(stateValue)) {\n matched.add(node);\n }\n break;\n }\n }\n }\n }\n }\n break;\n }\n case 'current':\n case 'heading':\n case 'nth-col':\n case 'nth-last-col': {\n if (warn) {\n this.onError(\n generateException(\n `Unsupported pseudo-class :${astName}()`,\n NOT_SUPPORTED_ERR,\n this.#window\n )\n );\n }\n break;\n }\n // Ignore :host() and :host-context().\n case 'host':\n case 'host-context': {\n break;\n }\n // Deprecated in CSS Selectors 3.\n case 'contains': {\n if (warn) {\n this.onError(\n generateException(\n `Unknown pseudo-class :${astName}()`,\n NOT_SUPPORTED_ERR,\n this.#window\n )\n );\n }\n break;\n }\n default: {\n if (!forgive) {\n this.onError(\n generateException(\n `Unknown pseudo-class :${astName}()`,\n SYNTAX_ERR,\n this.#window\n )\n );\n }\n }\n }\n }\n } else if (KEYS_PS_NTH_OF_TYPE.has(astName)) {\n if (node === this.#root) {\n matched.add(node);\n } else if (parentNode) {\n switch (astName) {\n case 'first-of-type': {\n const [node1] = this._collectNthOfType(\n {\n a: 0,\n b: 1\n },\n node\n );\n if (node1) {\n matched.add(node1);\n }\n break;\n }\n case 'last-of-type': {\n const [node1] = this._collectNthOfType(\n {\n a: 0,\n b: 1,\n reverse: true\n },\n node\n );\n if (node1) {\n matched.add(node1);\n }\n break;\n }\n // 'only-of-type' is handled by default.\n default: {\n const [node1] = this._collectNthOfType(\n {\n a: 0,\n b: 1\n },\n node\n );\n if (node1 === node) {\n const [node2] = this._collectNthOfType(\n {\n a: 0,\n b: 1,\n reverse: true\n },\n node\n );\n if (node2 === node) {\n matched.add(node);\n }\n }\n }\n }\n }\n } else {\n switch (astName) {\n case 'disabled':\n case 'enabled': {\n const isMatch = matchDisabledPseudoClass(astName, node);\n if (isMatch) {\n matched.add(node);\n }\n break;\n }\n case 'read-only':\n case 'read-write': {\n const isMatch = matchReadOnlyPseudoClass(astName, node);\n if (isMatch) {\n matched.add(node);\n }\n break;\n }\n case 'any-link':\n case 'link': {\n if (\n (localName === 'a' || localName === 'area') &&\n node.hasAttribute('href')\n ) {\n matched.add(node);\n }\n break;\n }\n case 'local-link': {\n if (\n (localName === 'a' || localName === 'area') &&\n node.hasAttribute('href')\n ) {\n if (!this.#documentURL) {\n this.#documentURL = new URL(this.#document.URL);\n }\n const { href, origin, pathname } = this.#documentURL;\n const attrURL = new URL(node.getAttribute('href'), href);\n if (attrURL.origin === origin && attrURL.pathname === pathname) {\n matched.add(node);\n }\n }\n break;\n }\n case 'visited': {\n // prevent fingerprinting\n break;\n }\n case 'hover': {\n const { target, type } = this.#event ?? {};\n if (\n /^(?:click|mouse(?:down|over|up))$/.test(type) &&\n node.contains(target)\n ) {\n matched.add(node);\n }\n break;\n }\n case 'active': {\n const { buttons, target, type } = this.#event ?? {};\n if (type === 'mousedown' && buttons & 1 && node.contains(target)) {\n matched.add(node);\n }\n break;\n }\n case 'target': {\n if (!this.#documentURL) {\n this.#documentURL = new URL(this.#document.URL);\n }\n const { hash } = this.#documentURL;\n if (\n node.id &&\n hash === `#${node.id}` &&\n this.#document.contains(node)\n ) {\n matched.add(node);\n }\n break;\n }\n case 'target-within': {\n if (!this.#documentURL) {\n this.#documentURL = new URL(this.#document.URL);\n }\n const { hash } = this.#documentURL;\n if (hash) {\n const id = hash.replace(/^#/, '');\n let current = this.#document.getElementById(id);\n while (current) {\n if (current === node) {\n matched.add(node);\n break;\n }\n current = current.parentNode;\n }\n }\n break;\n }\n case 'scope': {\n if (this.#node.nodeType === ELEMENT_NODE) {\n if (!this.#shadow && node === this.#node) {\n matched.add(node);\n }\n } else if (node === this.#document.documentElement) {\n matched.add(node);\n }\n break;\n }\n case 'focus': {\n const activeElement = this.#document.activeElement;\n if (node === activeElement && isFocusableArea(node)) {\n matched.add(node);\n } else if (activeElement.shadowRoot) {\n const activeShadowElement = activeElement.shadowRoot.activeElement;\n let current = activeShadowElement;\n while (current) {\n if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {\n const { host } = current;\n if (host === activeElement) {\n if (isFocusableArea(node)) {\n matched.add(node);\n } else {\n matched.add(host);\n }\n }\n break;\n } else {\n current = current.parentNode;\n }\n }\n }\n break;\n }\n case 'focus-visible': {\n if (node === this.#document.activeElement && isFocusableArea(node)) {\n let bool;\n if (isFocusVisible(node)) {\n bool = true;\n } else if (this.#focus) {\n const { relatedTarget, target: focusTarget } = this.#focus;\n if (focusTarget === node) {\n if (isFocusVisible(relatedTarget)) {\n bool = true;\n } else if (this.#event) {\n const {\n altKey: eventAltKey,\n ctrlKey: eventCtrlKey,\n key: eventKey,\n metaKey: eventMetaKey,\n target: eventTarget,\n type: eventType\n } = this.#event;\n // this.#event is irrelevant if eventTarget === relatedTarget\n if (eventTarget === relatedTarget) {\n if (this.#lastFocusVisible === null) {\n bool = true;\n } else if (focusTarget === this.#lastFocusVisible) {\n bool = true;\n }\n } else if (eventKey === 'Tab') {\n if (\n (eventType === 'keydown' && eventTarget !== node) ||\n (eventType === 'keyup' && eventTarget === node)\n ) {\n if (eventTarget === focusTarget) {\n if (this.#lastFocusVisible === null) {\n bool = true;\n } else if (\n eventTarget === this.#lastFocusVisible &&\n relatedTarget === null\n ) {\n bool = true;\n }\n } else {\n bool = true;\n }\n }\n } else if (eventKey) {\n if (\n (eventType === 'keydown' || eventType === 'keyup') &&\n !eventAltKey &&\n !eventCtrlKey &&\n !eventMetaKey &&\n eventTarget === node\n ) {\n bool = true;\n }\n }\n } else if (\n relatedTarget === null ||\n relatedTarget === this.#lastFocusVisible\n ) {\n bool = true;\n }\n }\n }\n if (bool) {\n this.#lastFocusVisible = node;\n matched.add(node);\n } else if (this.#lastFocusVisible === node) {\n this.#lastFocusVisible = null;\n }\n }\n break;\n }\n case 'focus-within': {\n const activeElement = this.#document.activeElement;\n if (node.contains(activeElement) && isFocusableArea(activeElement)) {\n matched.add(node);\n } else if (activeElement.shadowRoot) {\n const activeShadowElement = activeElement.shadowRoot.activeElement;\n if (node.contains(activeShadowElement)) {\n matched.add(node);\n } else {\n let current = activeShadowElement;\n while (current) {\n if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {\n const { host } = current;\n if (host === activeElement && node.contains(host)) {\n matched.add(node);\n }\n break;\n } else {\n current = current.parentNode;\n }\n }\n }\n }\n break;\n }\n case 'open':\n case 'closed': {\n if (localName === 'details' || localName === 'dialog') {\n if (node.hasAttribute('open')) {\n if (astName === 'open') {\n matched.add(node);\n }\n } else if (astName === 'closed') {\n matched.add(node);\n }\n }\n break;\n }\n case 'placeholder-shown': {\n let placeholder;\n if (node.placeholder) {\n placeholder = node.placeholder;\n } else if (node.hasAttribute('placeholder')) {\n placeholder = node.getAttribute('placeholder');\n }\n if (typeof placeholder === 'string' && !/[\\r\\n]/.test(placeholder)) {\n let targetNode;\n if (localName === 'textarea') {\n targetNode = node;\n } else if (localName === 'input') {\n if (node.hasAttribute('type')) {\n if (KEYS_INPUT_PLACEHOLDER.has(node.getAttribute('type'))) {\n targetNode = node;\n }\n } else {\n targetNode = node;\n }\n }\n if (targetNode && node.value === '') {\n matched.add(node);\n }\n }\n break;\n }\n case 'checked': {\n const attrType = node.getAttribute('type');\n if (\n (node.checked &&\n localName === 'input' &&\n (attrType === 'checkbox' || attrType === 'radio')) ||\n (node.selected && localName === 'option')\n ) {\n matched.add(node);\n }\n break;\n }\n case 'indeterminate': {\n if (\n (node.indeterminate &&\n localName === 'input' &&\n node.type === 'checkbox') ||\n (localName === 'progress' && !node.hasAttribute('value'))\n ) {\n matched.add(node);\n } else if (\n localName === 'input' &&\n node.type === 'radio' &&\n !node.hasAttribute('checked')\n ) {\n const nodeName = node.name;\n let parent = node.parentNode;\n while (parent) {\n if (parent.localName === 'form') {\n break;\n }\n parent = parent.parentNode;\n }\n if (!parent) {\n parent = this.#document.documentElement;\n }\n const walker = this._createTreeWalker(parent);\n let refNode = traverseNode(parent, walker);\n refNode = walker.firstChild();\n let checked;\n while (refNode) {\n if (\n refNode.localName === 'input' &&\n refNode.getAttribute('type') === 'radio'\n ) {\n if (refNode.hasAttribute('name')) {\n if (refNode.getAttribute('name') === nodeName) {\n checked = !!refNode.checked;\n }\n } else {\n checked = !!refNode.checked;\n }\n if (checked) {\n break;\n }\n }\n refNode = walker.nextNode();\n }\n if (!checked) {\n matched.add(node);\n }\n }\n break;\n }\n case 'default': {\n // button[type=\"submit\"], input[type=\"submit\"], input[type=\"image\"]\n const attrType = node.getAttribute('type');\n if (\n (localName === 'button' &&\n !(node.hasAttribute('type') && KEYS_INPUT_RESET.has(attrType))) ||\n (localName === 'input' &&\n node.hasAttribute('type') &&\n KEYS_INPUT_SUBMIT.has(attrType))\n ) {\n let form = node.parentNode;\n while (form) {\n if (form.localName === 'form') {\n break;\n }\n form = form.parentNode;\n }\n if (form) {\n const walker = this._createTreeWalker(form);\n let refNode = traverseNode(form, walker);\n refNode = walker.firstChild();\n while (refNode) {\n const nodeName = refNode.localName;\n const nodeAttrType = refNode.getAttribute('type');\n let m;\n if (nodeName === 'button') {\n m = !(\n refNode.hasAttribute('type') &&\n KEYS_INPUT_RESET.has(nodeAttrType)\n );\n } else if (nodeName === 'input') {\n m =\n refNode.hasAttribute('type') &&\n KEYS_INPUT_SUBMIT.has(nodeAttrType);\n }\n if (m) {\n if (refNode === node) {\n matched.add(node);\n }\n break;\n }\n refNode = walker.nextNode();\n }\n }\n // input[type=\"checkbox\"], input[type=\"radio\"]\n } else if (\n localName === 'input' &&\n node.hasAttribute('type') &&\n node.hasAttribute('checked') &&\n KEYS_INPUT_CHECK.has(attrType)\n ) {\n matched.add(node);\n // option\n } else if (localName === 'option' && node.hasAttribute('selected')) {\n matched.add(node);\n }\n break;\n }\n case 'valid':\n case 'invalid': {\n if (KEYS_FORM_PS_VALID.has(localName)) {\n let valid;\n if (node.checkValidity()) {\n if (node.maxLength >= 0) {\n if (node.maxLength >= node.value.length) {\n valid = true;\n }\n } else {\n valid = true;\n }\n }\n if (valid) {\n if (astName === 'valid') {\n matched.add(node);\n }\n } else if (astName === 'invalid') {\n matched.add(node);\n }\n } else if (localName === 'fieldset') {\n const walker = this._createTreeWalker(node);\n let refNode = traverseNode(node, walker);\n refNode = walker.firstChild();\n let valid;\n if (!refNode) {\n valid = true;\n } else {\n while (refNode) {\n if (KEYS_FORM_PS_VALID.has(refNode.localName)) {\n if (refNode.checkValidity()) {\n if (refNode.maxLength >= 0) {\n valid = refNode.maxLength >= refNode.value.length;\n } else {\n valid = true;\n }\n } else {\n valid = false;\n }\n if (!valid) {\n break;\n }\n }\n refNode = walker.nextNode();\n }\n }\n if (valid) {\n if (astName === 'valid') {\n matched.add(node);\n }\n } else if (astName === 'invalid') {\n matched.add(node);\n }\n }\n break;\n }\n case 'in-range':\n case 'out-of-range': {\n const attrType = node.getAttribute('type');\n if (\n localName === 'input' &&\n !(node.readonly || node.hasAttribute('readonly')) &&\n !(node.disabled || node.hasAttribute('disabled')) &&\n KEYS_INPUT_RANGE.has(attrType)\n ) {\n const flowed =\n node.validity.rangeUnderflow || node.validity.rangeOverflow;\n if (astName === 'out-of-range' && flowed) {\n matched.add(node);\n } else if (\n astName === 'in-range' &&\n !flowed &&\n (node.hasAttribute('min') ||\n node.hasAttribute('max') ||\n attrType === 'range')\n ) {\n matched.add(node);\n }\n }\n break;\n }\n case 'required':\n case 'optional': {\n let required;\n let optional;\n if (localName === 'select' || localName === 'textarea') {\n if (node.required || node.hasAttribute('required')) {\n required = true;\n } else {\n optional = true;\n }\n } else if (localName === 'input') {\n if (node.hasAttribute('type')) {\n const attrType = node.getAttribute('type');\n if (KEYS_INPUT_REQUIRED.has(attrType)) {\n if (node.required || node.hasAttribute('required')) {\n required = true;\n } else {\n optional = true;\n }\n } else {\n optional = true;\n }\n } else if (node.required || node.hasAttribute('required')) {\n required = true;\n } else {\n optional = true;\n }\n }\n if (astName === 'required' && required) {\n matched.add(node);\n } else if (astName === 'optional' && optional) {\n matched.add(node);\n }\n break;\n }\n case 'root': {\n if (node === this.#document.documentElement) {\n matched.add(node);\n }\n break;\n }\n case 'empty': {\n if (node.hasChildNodes()) {\n const walker = this._createTreeWalker(node, {\n force: true,\n whatToShow: SHOW_ALL\n });\n let refNode = walker.firstChild();\n let bool;\n while (refNode) {\n bool =\n refNode.nodeType !== ELEMENT_NODE &&\n refNode.nodeType !== TEXT_NODE;\n if (!bool) {\n break;\n }\n refNode = walker.nextSibling();\n }\n if (bool) {\n matched.add(node);\n }\n } else {\n matched.add(node);\n }\n break;\n }\n case 'first-child': {\n if (\n (parentNode && node === parentNode.firstElementChild) ||\n node === this.#root\n ) {\n matched.add(node);\n }\n break;\n }\n case 'last-child': {\n if (\n (parentNode && node === parentNode.lastElementChild) ||\n node === this.#root\n ) {\n matched.add(node);\n }\n break;\n }\n case 'only-child': {\n if (\n (parentNode &&\n node === parentNode.firstElementChild &&\n node === parentNode.lastElementChild) ||\n node === this.#root\n ) {\n matched.add(node);\n }\n break;\n }\n case 'defined': {\n if (node.hasAttribute('is') || localName.includes('-')) {\n if (isCustomElement(node)) {\n matched.add(node);\n }\n // NOTE: MathMLElement is not implemented in jsdom.\n } else if (\n node instanceof this.#window.HTMLElement ||\n node instanceof this.#window.SVGElement\n ) {\n matched.add(node);\n }\n break;\n }\n case 'popover-open': {\n if (node.popover && isVisible(node)) {\n matched.add(node);\n }\n break;\n }\n // Ignore :host.\n case 'host': {\n break;\n }\n // Legacy pseudo-elements.\n case 'after':\n case 'before':\n case 'first-letter':\n case 'first-line': {\n if (warn) {\n this.onError(\n generateException(\n `Unsupported pseudo-element ::${astName}`,\n NOT_SUPPORTED_ERR,\n this.#window\n )\n );\n }\n break;\n }\n // Not supported.\n case 'autofill':\n case 'blank':\n case 'buffering':\n case 'current':\n case 'fullscreen':\n case 'future':\n case 'has-slotted':\n case 'heading':\n case 'modal':\n case 'muted':\n case 'past':\n case 'paused':\n case 'picture-in-picture':\n case 'playing':\n case 'seeking':\n case 'stalled':\n case 'user-invalid':\n case 'user-valid':\n case 'volume-locked':\n case '-webkit-autofill': {\n if (warn) {\n this.onError(\n generateException(\n `Unsupported pseudo-class :${astName}`,\n NOT_SUPPORTED_ERR,\n this.#window\n )\n );\n }\n break;\n }\n default: {\n if (astName.startsWith('-webkit-')) {\n if (warn) {\n this.onError(\n generateException(\n `Unsupported pseudo-class :${astName}`,\n NOT_SUPPORTED_ERR,\n this.#window\n )\n );\n }\n } else if (!forgive) {\n this.onError(\n generateException(\n `Unknown pseudo-class :${astName}`,\n SYNTAX_ERR,\n this.#window\n )\n );\n }\n }\n }\n }\n return matched;\n }\n\n /**\n * Evaluates the :host() pseudo-class.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} host - The host element.\n * @param {object} ast - The original AST for error reporting.\n * @returns {boolean} True if matched.\n */\n _evaluateHostPseudo = (leaves, host, ast) => {\n const l = leaves.length;\n for (let i = 0; i < l; i++) {\n const leaf = leaves[i];\n if (leaf.type === COMBINATOR) {\n const css = generateCSS(ast);\n const msg = `Invalid selector ${css}`;\n this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n return false;\n }\n if (!this._matchSelector(leaf, host).has(host)) {\n return false;\n }\n }\n return true;\n };\n\n /**\n * Evaluates the :host-context() pseudo-class.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} host - The host element.\n * @param {object} ast - The original AST for error reporting.\n * @returns {boolean} True if matched.\n */\n _evaluateHostContextPseudo = (leaves, host, ast) => {\n let parent = host;\n while (parent) {\n let bool;\n const l = leaves.length;\n for (let i = 0; i < l; i++) {\n const leaf = leaves[i];\n if (leaf.type === COMBINATOR) {\n const css = generateCSS(ast);\n const msg = `Invalid selector ${css}`;\n this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n return false;\n }\n bool = this._matchSelector(leaf, parent).has(parent);\n if (!bool) {\n break;\n }\n }\n if (bool) {\n return true;\n }\n parent = parent.parentNode;\n }\n return false;\n };\n\n /**\n * Matches shadow host pseudo-classes.\n * @private\n * @param {object} ast - The AST.\n * @param {object} node - The DocumentFragment node.\n * @returns {?object} The matched node.\n */\n _matchShadowHostPseudoClass = (ast, node) => {\n const { children: astChildren, name: astName } = ast;\n // Handle simple pseudo-class (no arguments).\n if (!Array.isArray(astChildren)) {\n if (astName === 'host') {\n return node;\n }\n const msg = `Invalid selector :${astName}`;\n return this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n }\n // Handle functional pseudo-class like :host(...).\n if (astName !== 'host' && astName !== 'host-context') {\n const msg = `Invalid selector :${astName}()`;\n return this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n }\n if (astChildren.length !== 1) {\n const css = generateCSS(ast);\n const msg = `Invalid selector ${css}`;\n return this.onError(generateException(msg, SYNTAX_ERR, this.#window));\n }\n const { host } = node;\n const { branches } = walkAST(astChildren[0]);\n const [branch] = branches;\n const [...leaves] = branch;\n let isMatch = false;\n if (astName === 'host') {\n isMatch = this._evaluateHostPseudo(leaves, host, ast);\n // astName === 'host-context'.\n } else {\n isMatch = this._evaluateHostContextPseudo(leaves, host, ast);\n }\n return isMatch ? node : null;\n };\n\n /**\n * Matches a selector for element nodes.\n * @private\n * @param {object} ast - The AST.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchSelectorForElement = (ast, node, opt = {}) => {\n const { type: astType } = ast;\n const astName = unescapeSelector(ast.name);\n const matched = new Set();\n switch (astType) {\n case ATTR_SELECTOR: {\n if (matchAttributeSelector(ast, node, opt)) {\n matched.add(node);\n }\n break;\n }\n case ID_SELECTOR: {\n if (node.id === astName) {\n matched.add(node);\n }\n break;\n }\n case CLASS_SELECTOR: {\n if (node.classList.contains(astName)) {\n matched.add(node);\n }\n break;\n }\n case PS_CLASS_SELECTOR: {\n return this._matchPseudoClassSelector(ast, node, opt);\n }\n case TYPE_SELECTOR: {\n if (matchTypeSelector(ast, node, opt)) {\n matched.add(node);\n }\n break;\n }\n // PS_ELEMENT_SELECTOR is handled by default.\n default: {\n try {\n if (opt.check) {\n const css = generateCSS(ast);\n this.#pseudoElement.push(css);\n matched.add(node);\n } else {\n matchPseudoElementSelector(astName, astType, opt);\n }\n } catch (e) {\n this.onError(e);\n }\n }\n }\n return matched;\n };\n\n /**\n * Matches a selector for a shadow root.\n * @private\n * @param {object} ast - The AST.\n * @param {object} node - The DocumentFragment node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchSelectorForShadowRoot = (ast, node, opt = {}) => {\n const { name: astName } = ast;\n if (KEYS_LOGICAL.has(astName)) {\n opt.isShadowRoot = true;\n return this._matchPseudoClassSelector(ast, node, opt);\n }\n const matched = new Set();\n if (astName === 'host' || astName === 'host-context') {\n const res = this._matchShadowHostPseudoClass(ast, node, opt);\n if (res) {\n this.#verifyShadowHost = true;\n matched.add(res);\n }\n }\n return matched;\n };\n\n /**\n * Matches a selector.\n * @private\n * @param {object} ast - The AST.\n * @param {object} node - The Document, DocumentFragment, or Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchSelector = (ast, node, opt = {}) => {\n if (node.nodeType === ELEMENT_NODE) {\n return this._matchSelectorForElement(ast, node, opt);\n }\n if (\n this.#shadow &&\n node.nodeType === DOCUMENT_FRAGMENT_NODE &&\n ast.type === PS_CLASS_SELECTOR\n ) {\n return this._matchSelectorForShadowRoot(ast, node, opt);\n }\n return new Set();\n };\n\n /**\n * Matches leaves.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} node - The node.\n * @param {object} [opt] - Options.\n * @returns {boolean} The result.\n */\n _matchLeaves = (leaves, node, opt = {}) => {\n const results = this.#invalidate ? this.#invalidateResults : this.#results;\n let result = results.get(leaves);\n if (result && result.has(node)) {\n const { matched } = result.get(node);\n return matched;\n }\n let cacheable = true;\n if (node.nodeType === ELEMENT_NODE && KEYS_FORM.has(node.localName)) {\n cacheable = false;\n }\n let bool;\n const l = leaves.length;\n for (let i = 0; i < l; i++) {\n const leaf = leaves[i];\n switch (leaf.type) {\n case ATTR_SELECTOR:\n case ID_SELECTOR: {\n cacheable = false;\n break;\n }\n case PS_CLASS_SELECTOR: {\n if (KEYS_PS_UNCACHE.has(leaf.name)) {\n cacheable = false;\n }\n break;\n }\n default: {\n // No action needed for other types.\n }\n }\n bool = this._matchSelector(leaf, node, opt).has(node);\n if (!bool) {\n break;\n }\n }\n if (cacheable) {\n if (!result) {\n result = new WeakMap();\n }\n result.set(node, {\n matched: bool\n });\n results.set(leaves, result);\n }\n return bool;\n };\n\n /**\n * Traverses all descendant nodes and collects matches.\n * @private\n * @param {object} baseNode - The base Element node or Element.shadowRoot.\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _traverseAllDescendants = (baseNode, leaves, opt = {}) => {\n const walker = this._createTreeWalker(baseNode);\n traverseNode(baseNode, walker);\n let currentNode = walker.firstChild();\n const nodes = new Set();\n while (currentNode) {\n if (this._matchLeaves(leaves, currentNode, opt)) {\n nodes.add(currentNode);\n }\n currentNode = walker.nextNode();\n }\n return nodes;\n };\n\n /**\n * Finds descendant nodes.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} baseNode - The base Element node or Element.shadowRoot.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _findDescendantNodes = (leaves, baseNode, opt = {}) => {\n const [leaf, ...filterLeaves] = leaves;\n const { type: leafType } = leaf;\n switch (leafType) {\n case ID_SELECTOR: {\n const canUseGetElementById =\n !this.#shadow &&\n baseNode.nodeType === ELEMENT_NODE &&\n this.#root.nodeType !== ELEMENT_NODE;\n if (canUseGetElementById) {\n const leafName = unescapeSelector(leaf.name);\n const nodes = new Set();\n const foundNode = this.#root.getElementById(leafName);\n if (\n foundNode &&\n foundNode !== baseNode &&\n baseNode.contains(foundNode)\n ) {\n const isCompoundSelector = filterLeaves.length > 0;\n if (\n !isCompoundSelector ||\n this._matchLeaves(filterLeaves, foundNode, opt)\n ) {\n nodes.add(foundNode);\n }\n }\n return nodes;\n }\n // Fallback to default traversal if fast path is not applicable.\n return this._traverseAllDescendants(baseNode, leaves, opt);\n }\n case PS_ELEMENT_SELECTOR: {\n const leafName = unescapeSelector(leaf.name);\n matchPseudoElementSelector(leafName, leafType, opt);\n return new Set();\n }\n default: {\n return this._traverseAllDescendants(baseNode, leaves, opt);\n }\n }\n };\n\n /**\n * Matches the descendant combinator ' '.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchDescendantCombinator = (twig, node, opt = {}) => {\n const { leaves } = twig;\n const { parentNode } = node;\n const { dir } = opt;\n if (dir === DIR_NEXT) {\n return this._findDescendantNodes(leaves, node, opt);\n }\n // DIR_PREV\n const ancestors = [];\n let refNode = parentNode;\n while (refNode) {\n if (this._matchLeaves(leaves, refNode, opt)) {\n ancestors.push(refNode);\n }\n refNode = refNode.parentNode;\n }\n if (ancestors.length) {\n // Reverse to maintain document order.\n return new Set(ancestors.reverse());\n }\n return new Set();\n };\n\n /**\n * Matches the child combinator '>'.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchChildCombinator = (twig, node, opt = {}) => {\n const { leaves } = twig;\n const { dir } = opt;\n const { parentNode } = node;\n const matched = new Set();\n if (dir === DIR_NEXT) {\n let refNode = node.firstElementChild;\n while (refNode) {\n if (this._matchLeaves(leaves, refNode, opt)) {\n matched.add(refNode);\n }\n refNode = refNode.nextElementSibling;\n }\n } else {\n // DIR_PREV\n if (parentNode && this._matchLeaves(leaves, parentNode, opt)) {\n matched.add(parentNode);\n }\n }\n return matched;\n };\n\n /**\n * Matches the adjacent sibling combinator '+'.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchAdjacentSiblingCombinator = (twig, node, opt = {}) => {\n const { leaves } = twig;\n const { dir } = opt;\n const matched = new Set();\n const refNode =\n dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;\n if (refNode && this._matchLeaves(leaves, refNode, opt)) {\n matched.add(refNode);\n }\n return matched;\n };\n\n /**\n * Matches the general sibling combinator '~'.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchGeneralSiblingCombinator = (twig, node, opt = {}) => {\n const { leaves } = twig;\n const { dir } = opt;\n const matched = new Set();\n let refNode =\n dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;\n while (refNode) {\n if (this._matchLeaves(leaves, refNode, opt)) {\n matched.add(refNode);\n }\n refNode =\n dir === DIR_NEXT\n ? refNode.nextElementSibling\n : refNode.previousElementSibling;\n }\n return matched;\n };\n\n /**\n * Matches a combinator.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} node - The Element node.\n * @param {object} [opt] - Options.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n _matchCombinator = (twig, node, opt = {}) => {\n const {\n combo: { name: comboName }\n } = twig;\n switch (comboName) {\n case '+': {\n return this._matchAdjacentSiblingCombinator(twig, node, opt);\n }\n case '~': {\n return this._matchGeneralSiblingCombinator(twig, node, opt);\n }\n case '>': {\n return this._matchChildCombinator(twig, node, opt);\n }\n case ' ':\n default: {\n return this._matchDescendantCombinator(twig, node, opt);\n }\n }\n };\n\n /**\n * Traverses with a TreeWalker and collects nodes matching the leaves.\n * @private\n * @param {TreeWalker} walker - The TreeWalker instance to use.\n * @param {Array} leaves - The AST leaves to match against.\n * @param {object} options - Traversal options.\n * @param {Node} options.startNode - The node to start traversal from.\n * @param {string} options.targetType - The type of target ('all' or 'first').\n * @param {Node} [options.boundaryNode] - The node to stop traversal at.\n * @param {boolean} [options.force] - Force traversal to the next node.\n * @returns {Array.<Node>} An array of matched nodes.\n */\n _traverseAndCollectNodes = (walker, leaves, options) => {\n const { boundaryNode, force, startNode, targetType } = options;\n const collectedNodes = [];\n let currentNode = traverseNode(startNode, walker, !!force);\n if (!currentNode) {\n return [];\n }\n // Adjust starting node.\n if (currentNode.nodeType !== ELEMENT_NODE) {\n currentNode = walker.nextNode();\n } else if (currentNode === startNode && currentNode !== this.#root) {\n currentNode = walker.nextNode();\n }\n const matchOpt = {\n warn: this.#warn\n };\n while (currentNode) {\n // Stop when we reach the boundary.\n if (boundaryNode) {\n if (currentNode === boundaryNode) {\n break;\n } else if (\n targetType === TARGET_ALL &&\n !boundaryNode.contains(currentNode)\n ) {\n break;\n }\n }\n if (\n this._matchLeaves(leaves, currentNode, matchOpt) &&\n currentNode !== this.#node\n ) {\n collectedNodes.push(currentNode);\n // Stop after the first match if not collecting all.\n if (targetType !== TARGET_ALL) {\n break;\n }\n }\n currentNode = walker.nextNode();\n }\n return collectedNodes;\n };\n\n /**\n * Finds matched node(s) preceding this.#node.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} node - The node to start from.\n * @param {object} opt - Options.\n * @param {boolean} [opt.force] - If true, traverses only to the next node.\n * @param {string} [opt.targetType] - The target type.\n * @returns {Array.<object>} A collection of matched nodes.\n */\n _findPrecede = (leaves, node, opt = {}) => {\n const { force, targetType } = opt;\n if (!this.#rootWalker) {\n this.#rootWalker = this._createTreeWalker(this.#root);\n }\n return this._traverseAndCollectNodes(this.#rootWalker, leaves, {\n force,\n targetType,\n boundaryNode: this.#node,\n startNode: node\n });\n };\n\n /**\n * Finds matched node(s) in #nodeWalker.\n * @private\n * @param {Array.<object>} leaves - The AST leaves.\n * @param {object} node - The node to start from.\n * @param {object} opt - Options.\n * @param {boolean} [opt.precede] - If true, finds preceding nodes.\n * @returns {Array.<object>} A collection of matched nodes.\n */\n _findNodeWalker = (leaves, node, opt = {}) => {\n const { precede, ...traversalOpts } = opt;\n if (precede) {\n const precedeNodes = this._findPrecede(leaves, this.#root, opt);\n if (precedeNodes.length) {\n return precedeNodes;\n }\n }\n if (!this.#nodeWalker) {\n this.#nodeWalker = this._createTreeWalker(this.#node);\n }\n return this._traverseAndCollectNodes(this.#nodeWalker, leaves, {\n startNode: node,\n ...traversalOpts\n });\n };\n\n /**\n * Matches the node itself.\n * @private\n * @param {Array} leaves - The AST leaves.\n * @param {boolean} check - Indicates if running in internal check().\n * @returns {Array} An array containing [nodes, filtered, pseudoElement].\n */\n _matchSelf = (leaves, check = false) => {\n const options = { check, warn: this.#warn };\n const matched = this._matchLeaves(leaves, this.#node, options);\n const nodes = matched ? [this.#node] : [];\n return [nodes, matched, this.#pseudoElement];\n };\n\n /**\n * Finds lineal nodes (self and ancestors).\n * @private\n * @param {Array} leaves - The AST leaves.\n * @param {object} opt - Options.\n * @returns {Array} An array containing [nodes, filtered].\n */\n _findLineal = (leaves, opt) => {\n const { complex } = opt;\n const nodes = [];\n const options = { warn: this.#warn };\n const selfMatched = this._matchLeaves(leaves, this.#node, options);\n if (selfMatched) {\n nodes.push(this.#node);\n }\n if (!selfMatched || complex) {\n let currentNode = this.#node.parentNode;\n while (currentNode) {\n if (this._matchLeaves(leaves, currentNode, options)) {\n nodes.push(currentNode);\n }\n currentNode = currentNode.parentNode;\n }\n }\n const filtered = nodes.length > 0;\n return [nodes, filtered];\n };\n\n /**\n * Finds entry nodes for pseudo-element selectors.\n * @private\n * @param {object} leaf - The pseudo-element leaf from the AST.\n * @param {Array.<object>} filterLeaves - Leaves for compound selectors.\n * @param {string} targetType - The type of target to find.\n * @returns {object} The result { nodes, filtered, pending }.\n */\n _findEntryNodesForPseudoElement = (leaf, filterLeaves, targetType) => {\n let nodes = [];\n let filtered = false;\n if (targetType === TARGET_SELF && this.#check) {\n const css = generateCSS(leaf);\n this.#pseudoElement.push(css);\n if (filterLeaves.length) {\n [nodes, filtered] = this._matchSelf(filterLeaves, this.#check);\n } else {\n nodes.push(this.#node);\n filtered = true;\n }\n } else {\n matchPseudoElementSelector(leaf.name, leaf.type, { warn: this.#warn });\n }\n return { nodes, filtered, pending: false };\n };\n\n /**\n * Finds entry nodes for ID selectors.\n * @private\n * @param {object} twig - The current twig from the AST branch.\n * @param {string} targetType - The type of target to find.\n * @param {object} opt - Additional options for finding nodes.\n * @returns {object} The result { nodes, filtered, pending }.\n */\n _findEntryNodesForId = (twig, targetType, opt) => {\n const { leaves } = twig;\n const [leaf, ...filterLeaves] = leaves;\n const { complex, precede } = opt;\n let nodes = [];\n let filtered = false;\n if (targetType === TARGET_SELF) {\n [nodes, filtered] = this._matchSelf(leaves);\n } else if (targetType === TARGET_LINEAL) {\n [nodes, filtered] = this._findLineal(leaves, { complex });\n } else if (\n targetType === TARGET_FIRST &&\n this.#root.nodeType !== ELEMENT_NODE\n ) {\n const node = this.#root.getElementById(leaf.name);\n if (node) {\n if (filterLeaves.length) {\n if (this._matchLeaves(filterLeaves, node, { warn: this.#warn })) {\n nodes.push(node);\n filtered = true;\n }\n } else {\n nodes.push(node);\n filtered = true;\n }\n }\n } else {\n nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });\n filtered = nodes.length > 0;\n }\n return { nodes, filtered, pending: false };\n };\n\n /**\n * Finds entry nodes for class selectors.\n * @private\n * @param {Array.<object>} leaves - The AST leaves for the selector.\n * @param {string} targetType - The type of target to find.\n * @param {object} opt - Additional options for finding nodes.\n * @returns {object} The result { nodes, filtered, pending }.\n */\n _findEntryNodesForClass = (leaves, targetType, opt) => {\n const { complex, precede } = opt;\n let nodes = [];\n let filtered = false;\n if (targetType === TARGET_SELF) {\n [nodes, filtered] = this._matchSelf(leaves);\n } else if (targetType === TARGET_LINEAL) {\n [nodes, filtered] = this._findLineal(leaves, { complex });\n } else {\n nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });\n filtered = nodes.length > 0;\n }\n return { nodes, filtered, pending: false };\n };\n\n /**\n * Finds entry nodes for type selectors.\n * @private\n * @param {Array.<object>} leaves - The AST leaves for the selector.\n * @param {string} targetType - The type of target to find.\n * @param {object} opt - Additional options for finding nodes.\n * @returns {object} The result { nodes, filtered, pending }.\n */\n _findEntryNodesForType = (leaves, targetType, opt) => {\n const { complex, precede } = opt;\n let nodes = [];\n let filtered = false;\n if (targetType === TARGET_SELF) {\n [nodes, filtered] = this._matchSelf(leaves);\n } else if (targetType === TARGET_LINEAL) {\n [nodes, filtered] = this._findLineal(leaves, { complex });\n } else {\n nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });\n filtered = nodes.length > 0;\n }\n return { nodes, filtered, pending: false };\n };\n\n /**\n * Finds entry nodes for other selector types (default case).\n * @private\n * @param {object} twig - The current twig from the AST branch.\n * @param {string} targetType - The type of target to find.\n * @param {object} opt - Additional options for finding nodes.\n * @returns {object} The result { nodes, filtered, pending }.\n */\n _findEntryNodesForOther = (twig, targetType, opt) => {\n const { leaves } = twig;\n const [leaf, ...filterLeaves] = leaves;\n const { complex, precede } = opt;\n let nodes = [];\n let filtered = false;\n let pending = false;\n if (targetType !== TARGET_LINEAL && /host(?:-context)?/.test(leaf.name)) {\n let shadowRoot = null;\n if (this.#shadow && this.#node.nodeType === DOCUMENT_FRAGMENT_NODE) {\n shadowRoot = this._matchShadowHostPseudoClass(leaf, this.#node);\n } else if (filterLeaves.length && this.#node.nodeType === ELEMENT_NODE) {\n shadowRoot = this._matchShadowHostPseudoClass(\n leaf,\n this.#node.shadowRoot\n );\n }\n if (shadowRoot) {\n let bool = true;\n const l = filterLeaves.length;\n for (let i = 0; i < l; i++) {\n const filterLeaf = filterLeaves[i];\n switch (filterLeaf.name) {\n case 'host':\n case 'host-context': {\n const matchedNode = this._matchShadowHostPseudoClass(\n filterLeaf,\n shadowRoot\n );\n bool = matchedNode === shadowRoot;\n break;\n }\n case 'has': {\n bool = this._matchPseudoClassSelector(\n filterLeaf,\n shadowRoot,\n {}\n ).has(shadowRoot);\n break;\n }\n default: {\n bool = false;\n }\n }\n if (!bool) {\n break;\n }\n }\n if (bool) {\n nodes.push(shadowRoot);\n filtered = true;\n }\n }\n } else if (targetType === TARGET_SELF) {\n [nodes, filtered] = this._matchSelf(leaves);\n } else if (targetType === TARGET_LINEAL) {\n [nodes, filtered] = this._findLineal(leaves, { complex });\n } else if (targetType === TARGET_FIRST) {\n nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });\n filtered = nodes.length > 0;\n } else {\n pending = true;\n }\n return { nodes, filtered, pending };\n };\n\n /**\n * Finds entry nodes.\n * @private\n * @param {object} twig - The twig object.\n * @param {string} targetType - The target type.\n * @param {object} [opt] - Options.\n * @param {boolean} [opt.complex] - If true, the selector is complex.\n * @param {string} [opt.dir] - The find direction.\n * @returns {object} An object with nodes and their state.\n */\n _findEntryNodes = (twig, targetType, opt = {}) => {\n const { leaves } = twig;\n const [leaf, ...filterLeaves] = leaves;\n const { complex = false, dir = DIR_PREV } = opt;\n const precede =\n dir === DIR_NEXT &&\n this.#node.nodeType === ELEMENT_NODE &&\n this.#node !== this.#root;\n let result;\n switch (leaf.type) {\n case PS_ELEMENT_SELECTOR: {\n result = this._findEntryNodesForPseudoElement(\n leaf,\n filterLeaves,\n targetType\n );\n break;\n }\n case ID_SELECTOR: {\n result = this._findEntryNodesForId(twig, targetType, {\n complex,\n precede\n });\n break;\n }\n case CLASS_SELECTOR: {\n result = this._findEntryNodesForClass(leaves, targetType, {\n complex,\n precede\n });\n break;\n }\n case TYPE_SELECTOR: {\n result = this._findEntryNodesForType(leaves, targetType, {\n complex,\n precede\n });\n break;\n }\n default: {\n result = this._findEntryNodesForOther(twig, targetType, {\n complex,\n precede\n });\n }\n }\n return {\n compound: filterLeaves.length > 0,\n filtered: result.filtered,\n nodes: result.nodes,\n pending: result.pending\n };\n };\n\n /**\n * Determines the direction and starting twig for a selector branch.\n * @private\n * @param {Array.<object>} branch - The AST branch.\n * @param {string} targetType - The type of target to find.\n * @returns {object} An object with the direction and starting twig.\n */\n _determineTraversalStrategy = (branch, targetType) => {\n const branchLen = branch.length;\n const firstTwig = branch[0];\n const lastTwig = branch[branchLen - 1];\n if (branchLen === 1) {\n return { dir: DIR_PREV, twig: firstTwig };\n }\n // Complex selector (branchLen > 1).\n const {\n leaves: [{ name: firstName, type: firstType }]\n } = firstTwig;\n const {\n leaves: [{ name: lastName, type: lastType }]\n } = lastTwig;\n const { combo: firstCombo } = firstTwig;\n if (\n this.#selector.includes(':scope') ||\n lastType === PS_ELEMENT_SELECTOR ||\n lastType === ID_SELECTOR\n ) {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n if (firstType === ID_SELECTOR) {\n return { dir: DIR_NEXT, twig: firstTwig };\n }\n if (firstName === '*' && firstType === TYPE_SELECTOR) {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n if (lastName === '*' && lastType === TYPE_SELECTOR) {\n return { dir: DIR_NEXT, twig: firstTwig };\n }\n if (branchLen === 2) {\n if (targetType === TARGET_FIRST) {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n const { name: comboName } = firstCombo;\n if (comboName === '+' || comboName === '~') {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n } else if (branchLen > 2 && this.#scoped && targetType === TARGET_FIRST) {\n if (lastType === TYPE_SELECTOR) {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n let isChildOrDescendant = false;\n for (const { combo } of branch) {\n if (combo) {\n const { name: comboName } = combo;\n isChildOrDescendant = comboName === '>' || comboName === ' ';\n if (!isChildOrDescendant) {\n break;\n }\n }\n }\n if (isChildOrDescendant) {\n return { dir: DIR_PREV, twig: lastTwig };\n }\n }\n // Default strategy for complex selectors.\n return { dir: DIR_NEXT, twig: firstTwig };\n };\n\n /**\n * Processes pending items not resolved with a direct strategy.\n * @private\n * @param {Set.<Map>} pendingItems - The set of pending items.\n */\n _processPendingItems = pendingItems => {\n if (!pendingItems.size) {\n return;\n }\n if (!this.#rootWalker) {\n this.#rootWalker = this._createTreeWalker(this.#root);\n }\n const walker = this.#rootWalker;\n let node = this.#root;\n if (this.#scoped) {\n node = this.#node;\n }\n let nextNode = traverseNode(node, walker);\n while (nextNode) {\n const isWithinScope =\n this.#node.nodeType !== ELEMENT_NODE ||\n nextNode === this.#node ||\n this.#node.contains(nextNode);\n if (isWithinScope) {\n for (const pendingItem of pendingItems) {\n const { leaves } = pendingItem.get('twig');\n if (this._matchLeaves(leaves, nextNode, { warn: this.#warn })) {\n const index = pendingItem.get('index');\n this.#ast[index].filtered = true;\n this.#ast[index].find = true;\n this.#nodes[index].push(nextNode);\n }\n }\n } else if (this.#scoped) {\n break;\n }\n nextNode = walker.nextNode();\n }\n };\n\n /**\n * Collects nodes.\n * @private\n * @param {string} targetType - The target type.\n * @returns {Array.<Array.<object>>} An array containing the AST and nodes.\n */\n _collectNodes = targetType => {\n const ast = this.#ast.values();\n if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {\n const pendingItems = new Set();\n let i = 0;\n for (const { branch } of ast) {\n const complex = branch.length > 1;\n const { dir, twig } = this._determineTraversalStrategy(\n branch,\n targetType\n );\n const { compound, filtered, nodes, pending } = this._findEntryNodes(\n twig,\n targetType,\n { complex, dir }\n );\n if (nodes.length) {\n this.#ast[i].find = true;\n this.#nodes[i] = nodes;\n } else if (pending) {\n pendingItems.add(\n new Map([\n ['index', i],\n ['twig', twig]\n ])\n );\n }\n this.#ast[i].dir = dir;\n this.#ast[i].filtered = filtered || !compound;\n i++;\n }\n this._processPendingItems(pendingItems);\n } else {\n let i = 0;\n for (const { branch } of ast) {\n const twig = branch[branch.length - 1];\n const complex = branch.length > 1;\n const dir = DIR_PREV;\n const { compound, filtered, nodes } = this._findEntryNodes(\n twig,\n targetType,\n { complex, dir }\n );\n if (nodes.length) {\n this.#ast[i].find = true;\n this.#nodes[i] = nodes;\n }\n this.#ast[i].dir = dir;\n this.#ast[i].filtered = filtered || !compound;\n i++;\n }\n }\n return [this.#ast, this.#nodes];\n };\n\n /**\n * Gets combined nodes.\n * @private\n * @param {object} twig - The twig object.\n * @param {object} nodes - A collection of nodes.\n * @param {string} dir - The direction.\n * @returns {Array.<object>} A collection of matched nodes.\n */\n _getCombinedNodes = (twig, nodes, dir) => {\n const arr = [];\n const options = {\n dir,\n warn: this.#warn\n };\n for (const node of nodes) {\n const matched = this._matchCombinator(twig, node, options);\n if (matched.size) {\n arr.push(...matched);\n }\n }\n return arr;\n };\n\n /**\n * Matches a node in the 'next' direction.\n * @private\n * @param {Array} branch - The branch.\n * @param {Set.<object>} nodes - A collection of Element nodes.\n * @param {object} opt - Options.\n * @param {object} opt.combo - The combo object.\n * @param {number} opt.index - The index.\n * @returns {?object} The matched node.\n */\n _matchNodeNext = (branch, nodes, opt) => {\n const { combo, index } = opt;\n const { combo: nextCombo, leaves } = branch[index];\n const twig = {\n combo,\n leaves\n };\n const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_NEXT));\n if (nextNodes.size) {\n if (index === branch.length - 1) {\n const [nextNode] = sortNodes(nextNodes);\n return nextNode;\n }\n return this._matchNodeNext(branch, nextNodes, {\n combo: nextCombo,\n index: index + 1\n });\n }\n return null;\n };\n\n /**\n * Matches a node in the 'previous' direction.\n * @private\n * @param {Array} branch - The branch.\n * @param {object} node - The Element node.\n * @param {object} opt - Options.\n * @param {number} opt.index - The index.\n * @returns {?object} The node.\n */\n _matchNodePrev = (branch, node, opt) => {\n const { index } = opt;\n const twig = branch[index];\n const nodes = new Set([node]);\n const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_PREV));\n if (nextNodes.size) {\n if (index === 0) {\n return node;\n }\n let matched;\n for (const nextNode of nextNodes) {\n matched = this._matchNodePrev(branch, nextNode, {\n index: index - 1\n });\n if (matched) {\n break;\n }\n }\n if (matched) {\n return node;\n }\n }\n return null;\n };\n\n /**\n * Processes a complex selector branch to find all matching nodes.\n * @private\n * @param {Array} branch - The selector branch from the AST.\n * @param {Array} entryNodes - The initial set of nodes to start from.\n * @param {string} dir - The direction of traversal ('next' or 'prev').\n * @returns {Set.<object>} A set of all matched nodes.\n */\n _processComplexBranchAll = (branch, entryNodes, dir) => {\n const matchedNodes = new Set();\n const branchLen = branch.length;\n const lastIndex = branchLen - 1;\n\n if (dir === DIR_NEXT) {\n const { combo: firstCombo } = branch[0];\n for (const node of entryNodes) {\n let combo = firstCombo;\n let nextNodes = new Set([node]);\n for (let j = 1; j < branchLen; j++) {\n const { combo: nextCombo, leaves } = branch[j];\n const twig = { combo, leaves };\n const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);\n if (nodesArr.length) {\n if (j === lastIndex) {\n for (const nextNode of nodesArr) {\n matchedNodes.add(nextNode);\n }\n }\n combo = nextCombo;\n nextNodes = new Set(nodesArr);\n } else {\n // No further matches down this path.\n nextNodes.clear();\n break;\n }\n }\n }\n // DIR_PREV\n } else {\n for (const node of entryNodes) {\n let nextNodes = new Set([node]);\n for (let j = lastIndex - 1; j >= 0; j--) {\n const twig = branch[j];\n const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);\n if (nodesArr.length) {\n // The entry node is the final match\n if (j === 0) {\n matchedNodes.add(node);\n }\n nextNodes = new Set(nodesArr);\n } else {\n // No further matches down this path.\n nextNodes.clear();\n break;\n }\n }\n }\n }\n return matchedNodes;\n };\n\n /**\n * Processes a complex selector branch to find the first matching node.\n * @private\n * @param {Array} branch - The selector branch from the AST.\n * @param {Array} entryNodes - The initial set of nodes to start from.\n * @param {string} dir - The direction of traversal ('next' or 'prev').\n * @param {string} targetType - The type of search (e.g., 'first').\n * @returns {?object} The first matched node, or null.\n */\n _processComplexBranchFirst = (branch, entryNodes, dir, targetType) => {\n const branchLen = branch.length;\n const lastIndex = branchLen - 1;\n // DIR_NEXT logic for finding the first match.\n if (dir === DIR_NEXT) {\n const { combo: entryCombo } = branch[0];\n for (const node of entryNodes) {\n const matchedNode = this._matchNodeNext(branch, new Set([node]), {\n combo: entryCombo,\n index: 1\n });\n if (matchedNode) {\n if (this.#node.nodeType === ELEMENT_NODE) {\n if (\n matchedNode !== this.#node &&\n this.#node.contains(matchedNode)\n ) {\n return matchedNode;\n }\n } else {\n return matchedNode;\n }\n }\n }\n // Fallback logic if no direct match found.\n const { leaves: entryLeaves } = branch[0];\n const [entryNode] = entryNodes;\n if (this.#node.contains(entryNode)) {\n let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {\n targetType\n });\n while (refNode) {\n const matchedNode = this._matchNodeNext(branch, new Set([refNode]), {\n combo: entryCombo,\n index: 1\n });\n if (matchedNode) {\n if (this.#node.nodeType === ELEMENT_NODE) {\n if (\n matchedNode !== this.#node &&\n this.#node.contains(matchedNode)\n ) {\n return matchedNode;\n }\n } else {\n return matchedNode;\n }\n }\n [refNode] = this._findNodeWalker(entryLeaves, refNode, {\n targetType,\n force: true\n });\n }\n }\n // DIR_PREV logic for finding the first match.\n } else {\n for (const node of entryNodes) {\n const matchedNode = this._matchNodePrev(branch, node, {\n index: lastIndex - 1\n });\n if (matchedNode) {\n return matchedNode;\n }\n }\n // Fallback for TARGET_FIRST.\n if (targetType === TARGET_FIRST) {\n const { leaves: entryLeaves } = branch[lastIndex];\n const [entryNode] = entryNodes;\n let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {\n targetType\n });\n while (refNode) {\n const matchedNode = this._matchNodePrev(branch, refNode, {\n index: lastIndex - 1\n });\n if (matchedNode) {\n return refNode;\n }\n [refNode] = this._findNodeWalker(entryLeaves, refNode, {\n targetType,\n force: true\n });\n }\n }\n }\n return null;\n };\n\n /**\n * Finds matched nodes.\n * @param {string} targetType - The target type.\n * @returns {Set.<object>} A collection of matched nodes.\n */\n find = targetType => {\n const [[...branches], collectedNodes] = this._collectNodes(targetType);\n const l = branches.length;\n let sort =\n l > 1 && targetType === TARGET_ALL && this.#selector.includes(':scope');\n let nodes = new Set();\n for (let i = 0; i < l; i++) {\n const { branch, dir, find } = branches[i];\n if (!branch.length || !find) {\n continue;\n }\n const entryNodes = collectedNodes[i];\n const lastIndex = branch.length - 1;\n // Handle simple selectors (no combinators).\n if (lastIndex === 0) {\n if (\n (targetType === TARGET_ALL || targetType === TARGET_FIRST) &&\n this.#node.nodeType === ELEMENT_NODE\n ) {\n for (const node of entryNodes) {\n if (node !== this.#node && this.#node.contains(node)) {\n nodes.add(node);\n if (targetType === TARGET_FIRST) {\n break;\n }\n }\n }\n } else if (targetType === TARGET_ALL) {\n if (nodes.size) {\n for (const node of entryNodes) {\n nodes.add(node);\n }\n sort = true;\n } else {\n nodes = new Set(entryNodes);\n }\n } else {\n if (entryNodes.length) {\n nodes.add(entryNodes[0]);\n }\n }\n // Handle complex selectors.\n } else {\n if (targetType === TARGET_ALL) {\n const newNodes = this._processComplexBranchAll(\n branch,\n entryNodes,\n dir\n );\n if (nodes.size) {\n for (const newNode of newNodes) {\n nodes.add(newNode);\n }\n sort = true;\n } else {\n nodes = newNodes;\n }\n } else {\n const matchedNode = this._processComplexBranchFirst(\n branch,\n entryNodes,\n dir,\n targetType\n );\n if (matchedNode) {\n nodes.add(matchedNode);\n }\n }\n }\n }\n if (this.#check) {\n const match = !!nodes.size;\n let pseudoElement;\n if (this.#pseudoElement.length) {\n pseudoElement = this.#pseudoElement.join('');\n } else {\n pseudoElement = null;\n }\n return { match, pseudoElement };\n }\n if (targetType === TARGET_FIRST || targetType === TARGET_ALL) {\n nodes.delete(this.#node);\n }\n if ((sort || targetType === TARGET_FIRST) && nodes.size > 1) {\n return new Set(sortNodes(nodes));\n }\n return nodes;\n };\n}\n"],"mappings":"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","names":["cssTree","isCustomElementName","bidiFactory","nwsapi","KEYS_INPUT_EDIT","selectorBranches","find","res"]} \ No newline at end of file
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.d.cts b/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.d.cts
deleted file mode 100644
index a5a8b10..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/dist/cjs/index.d.cts
+++ /dev/null
@@ -1,16 +0,0 @@
-declare class DOMSelector {
- constructor(window: Window, document: Document, opt?: object);
- clear: () => void;
- check: (selector: string, node: Element, opt?: object) => CheckResult;
- matches: (selector: string, node: Element, opt?: object) => boolean;
- closest: (selector: string, node: Element, opt?: object) => Element | null;
- querySelector: (selector: string, node: Document | DocumentFragment | Element, opt?: object) => Element | null;
- querySelectorAll: (selector: string, node: Document | DocumentFragment | Element, opt?: object) => Array<Element>;
- #private;
-}
-type CheckResult = {
- match: boolean;
- pseudoElement: string | null;
-};
-
-export { type CheckResult, DOMSelector };
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/package.json b/vanilla/node_modules/@asamuzakjp/dom-selector/package.json
deleted file mode 100644
index 4e8736f..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/package.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "name": "@asamuzakjp/dom-selector",
- "description": "A CSS selector engine.",
- "author": "asamuzaK",
- "license": "MIT",
- "homepage": "https://github.com/asamuzaK/domSelector#readme",
- "bugs": {
- "url": "https://github.com/asamuzaK/domSelector/issues"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/asamuzaK/domSelector.git"
- },
- "files": [
- "dist",
- "src",
- "types"
- ],
- "type": "module",
- "exports": {
- "import": {
- "types": "./types/index.d.ts",
- "default": "./src/index.js"
- },
- "require": {
- "types": "./dist/cjs/index.d.cts",
- "default": "./dist/cjs/index.cjs"
- },
- "default": {
- "types": "./dist/cjs/types/index.d.cts",
- "default": "./dist/cjs/index.cjs"
- }
- },
- "types": "types/index.d.ts",
- "dependencies": {
- "@asamuzakjp/nwsapi": "^2.3.9",
- "bidi-js": "^1.0.3",
- "css-tree": "^3.1.0",
- "is-potential-custom-element-name": "^1.0.1",
- "lru-cache": "^11.2.5"
- },
- "devDependencies": {
- "@types/css-tree": "^2.3.11",
- "benchmark": "^2.1.4",
- "c8": "^10.1.3",
- "chai": "^6.2.2",
- "commander": "^14.0.3",
- "esbuild": "^0.27.2",
- "eslint": "^9.39.2",
- "eslint-config-prettier": "^10.1.8",
- "eslint-plugin-jsdoc": "^62.5.0",
- "eslint-plugin-prettier": "^5.5.5",
- "eslint-plugin-regexp": "^3.0.0",
- "eslint-plugin-unicorn": "^62.0.0",
- "globals": "^17.2.0",
- "jsdom": "^27.4.0",
- "mocha": "^11.7.5",
- "neostandard": "^0.12.2",
- "prettier": "^3.8.1",
- "sinon": "^21.0.1",
- "tsup": "^8.5.1",
- "typescript": "^5.9.3",
- "wpt-runner": "^6.1.0"
- },
- "overrides": {
- "jsdom": "$jsdom"
- },
- "scripts": {
- "bench": "node benchmark/bench.js",
- "bench:sizzle": "node benchmark/bench-sizzle.js",
- "build": "npm run tsc && npm run lint && npm test && npm run bundle && npm run test:cjs",
- "bundle": "tsup src/index.js --format=cjs --platform=node --outDir=dist/cjs/ --sourcemap --dts",
- "lint": "eslint --fix .",
- "test": "c8 --reporter=text mocha --parallel --exit test/**/*.test.js",
- "test:cjs": "mocha --exit test/index.test.cjs",
- "test:wpt": "node test/wpt/wpt-runner.js",
- "tsc": "node scripts/index clean --dir=types -i && npx tsc",
- "update:wpt": "git submodule update --init --recursive --remote"
- },
- "version": "6.7.8"
-}
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/index.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/index.js
deleted file mode 100644
index 8ec7b67..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/index.js
+++ /dev/null
@@ -1,353 +0,0 @@
-/*!
- * DOM Selector - A CSS selector engine.
- * @license MIT
- * @copyright asamuzaK (Kazz)
- * @see {@link https://github.com/asamuzaK/domSelector/blob/main/LICENSE}
- */
-
-/* import */
-import { LRUCache } from 'lru-cache';
-import { Finder } from './js/finder.js';
-import { filterSelector, getType, initNwsapi } from './js/utility.js';
-
-/* constants */
-import {
- DOCUMENT_NODE,
- DOCUMENT_FRAGMENT_NODE,
- ELEMENT_NODE,
- TARGET_ALL,
- TARGET_FIRST,
- TARGET_LINEAL,
- TARGET_SELF
-} from './js/constant.js';
-const MAX_CACHE = 1024;
-
-/**
- * @typedef {object} CheckResult
- * @property {boolean} match - The match result.
- * @property {string?} pseudoElement - The pseudo-element, if any.
- */
-
-/* DOMSelector */
-export class DOMSelector {
- /* private fields */
- #window;
- #document;
- #finder;
- #idlUtils;
- #nwsapi;
- #cache;
-
- /**
- * Creates an instance of DOMSelector.
- * @param {Window} window - The window object.
- * @param {Document} document - The document object.
- * @param {object} [opt] - Options.
- */
- constructor(window, document, opt = {}) {
- const { idlUtils } = opt;
- this.#window = window;
- this.#document = document ?? window.document;
- this.#finder = new Finder(window);
- this.#idlUtils = idlUtils;
- this.#nwsapi = initNwsapi(window, document);
- this.#cache = new LRUCache({
- max: MAX_CACHE
- });
- }
-
- /**
- * Clears the internal cache of finder results.
- * @returns {void}
- */
- clear = () => {
- this.#finder.clearResults(true);
- };
-
- /**
- * Checks if an element matches a CSS selector.
- * @param {string} selector - The CSS selector to check against.
- * @param {Element} node - The element node to check.
- * @param {object} [opt] - Optional parameters.
- * @returns {CheckResult} An object containing the check result.
- */
- check = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (
- document === this.#document &&
- document.contentType === 'text/html' &&
- document.documentElement &&
- node.parentNode
- ) {
- const cacheKey = `check_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_SELF);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const match = this.#nwsapi.match(selector, n);
- return {
- match,
- pseudoElement: null
- };
- } catch (e) {
- // fall through
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- opt.check = true;
- opt.noexept = true;
- opt.warn = false;
- this.#finder.setup(selector, node, opt);
- res = this.#finder.find(TARGET_SELF);
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res;
- };
-
- /**
- * Returns true if the element matches the selector.
- * @param {string} selector - The CSS selector to match against.
- * @param {Element} node - The element node to test.
- * @param {object} [opt] - Optional parameters.
- * @returns {boolean} `true` if the element matches, or `false` otherwise.
- */
- matches = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (
- document === this.#document &&
- document.contentType === 'text/html' &&
- document.documentElement &&
- node.parentNode
- ) {
- const cacheKey = `matches_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_SELF);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res = this.#nwsapi.match(selector, n);
- return res;
- } catch (e) {
- // fall through
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_SELF);
- res = nodes.size;
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return !!res;
- };
-
- /**
- * Traverses up the DOM tree to find the first node that matches the selector.
- * @param {string} selector - The CSS selector to match against.
- * @param {Element} node - The element from which to start traversing.
- * @param {object} [opt] - Optional parameters.
- * @returns {?Element} The first matching ancestor element, or `null`.
- */
- closest = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- } else if (node.nodeType !== ELEMENT_NODE) {
- const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
- return this.#finder.onError(e, opt);
- }
- const document = node.ownerDocument;
- if (
- document === this.#document &&
- document.contentType === 'text/html' &&
- document.documentElement &&
- node.parentNode
- ) {
- const cacheKey = `closest_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_LINEAL);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res = this.#nwsapi.closest(selector, n);
- return res;
- } catch (e) {
- // fall through
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_LINEAL);
- if (nodes.size) {
- let refNode = node;
- while (refNode) {
- if (nodes.has(refNode)) {
- res = refNode;
- break;
- }
- refNode = refNode.parentNode;
- }
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? null;
- };
-
- /**
- * Returns the first element within the subtree that matches the selector.
- * @param {string} selector - The CSS selector to match.
- * @param {Document|DocumentFragment|Element} node - The node to find within.
- * @param {object} [opt] - Optional parameters.
- * @returns {?Element} The first matching element, or `null`.
- */
- querySelector = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- }
- /*
- const document =
- node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;
- if (
- document === this.#document &&
- document.contentType === 'text/html' &&
- document.documentElement &&
- (node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)
- ) {
- const cacheKey = `querySelector_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_FIRST);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res = this.#nwsapi.first(selector, n);
- return res;
- } catch (e) {
- // fall through
- }
- }
- }
- */
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_FIRST);
- if (nodes.size) {
- [res] = [...nodes];
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? null;
- };
-
- /**
- * Returns an array of elements within the subtree that match the selector.
- * Note: This method returns an Array, not a NodeList.
- * @param {string} selector - The CSS selector to match.
- * @param {Document|DocumentFragment|Element} node - The node to find within.
- * @param {object} [opt] - Optional parameters.
- * @returns {Array<Element>} An array of elements, or an empty array.
- */
- querySelectorAll = (selector, node, opt = {}) => {
- if (!node?.nodeType) {
- const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
- return this.#finder.onError(e, opt);
- }
- const document =
- node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;
- if (
- document === this.#document &&
- document.contentType === 'text/html' &&
- document.documentElement &&
- (node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)
- ) {
- const cacheKey = `querySelectorAll_${selector}`;
- let filterMatches = false;
- if (this.#cache.has(cacheKey)) {
- filterMatches = this.#cache.get(cacheKey);
- } else {
- filterMatches = filterSelector(selector, TARGET_ALL);
- this.#cache.set(cacheKey, filterMatches);
- }
- if (filterMatches) {
- try {
- const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
- const res = this.#nwsapi.select(selector, n);
- return res;
- } catch (e) {
- // fall through
- }
- }
- }
- let res;
- try {
- if (this.#idlUtils) {
- node = this.#idlUtils.wrapperForImpl(node);
- }
- this.#finder.setup(selector, node, opt);
- const nodes = this.#finder.find(TARGET_ALL);
- if (nodes.size) {
- res = [...nodes];
- }
- } catch (e) {
- this.#finder.onError(e, opt);
- }
- return res ?? [];
- };
-}
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/constant.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/constant.js
deleted file mode 100644
index 02986ec..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/constant.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * constant.js
- */
-
-/* string */
-export const ATRULE = 'Atrule';
-export const ATTR_SELECTOR = 'AttributeSelector';
-export const CLASS_SELECTOR = 'ClassSelector';
-export const COMBINATOR = 'Combinator';
-export const IDENT = 'Identifier';
-export const ID_SELECTOR = 'IdSelector';
-export const NOT_SUPPORTED_ERR = 'NotSupportedError';
-export const NTH = 'Nth';
-export const OPERATOR = 'Operator';
-export const PS_CLASS_SELECTOR = 'PseudoClassSelector';
-export const PS_ELEMENT_SELECTOR = 'PseudoElementSelector';
-export const RULE = 'Rule';
-export const SCOPE = 'Scope';
-export const SELECTOR = 'Selector';
-export const SELECTOR_LIST = 'SelectorList';
-export const STRING = 'String';
-export const SYNTAX_ERR = 'SyntaxError';
-export const TARGET_ALL = 'all';
-export const TARGET_FIRST = 'first';
-export const TARGET_LINEAL = 'lineal';
-export const TARGET_SELF = 'self';
-export const TYPE_SELECTOR = 'TypeSelector';
-
-/* numeric */
-export const BIT_01 = 1;
-export const BIT_02 = 2;
-export const BIT_04 = 4;
-export const BIT_08 = 8;
-export const BIT_16 = 0x10;
-export const BIT_32 = 0x20;
-export const BIT_FFFF = 0xffff;
-export const DUO = 2;
-export const HEX = 16;
-export const TYPE_FROM = 8;
-export const TYPE_TO = -1;
-
-/* Node */
-export const ELEMENT_NODE = 1;
-export const TEXT_NODE = 3;
-export const DOCUMENT_NODE = 9;
-export const DOCUMENT_FRAGMENT_NODE = 11;
-export const DOCUMENT_POSITION_PRECEDING = 2;
-export const DOCUMENT_POSITION_CONTAINS = 8;
-export const DOCUMENT_POSITION_CONTAINED_BY = 0x10;
-
-/* NodeFilter */
-export const SHOW_ALL = 0xffffffff;
-export const SHOW_CONTAINER = 0x501;
-export const SHOW_DOCUMENT = 0x100;
-export const SHOW_DOCUMENT_FRAGMENT = 0x400;
-export const SHOW_ELEMENT = 1;
-
-/* selectors */
-export const ALPHA_NUM = '[A-Z\\d]+';
-export const CHILD_IDX = '(?:first|last|only)-(?:child|of-type)';
-export const DIGIT = '(?:0|[1-9]\\d*)';
-export const LANG_PART = `(?:-${ALPHA_NUM})*`;
-export const PSEUDO_CLASS = `(?:any-)?link|${CHILD_IDX}|checked|empty|indeterminate|read-(?:only|write)|target`;
-export const ANB = `[+-]?(?:${DIGIT}n?|n)|(?:[+-]?${DIGIT})?n\\s*[+-]\\s*${DIGIT}`;
-// combinators
-export const COMBO = '\\s?[\\s>~+]\\s?';
-export const DESCEND = '\\s?[\\s>]\\s?';
-export const SIBLING = '\\s?[+~]\\s?';
-// LOGIC_IS: :is()
-export const LOGIC_IS = `:is\\(\\s*[^)]+\\s*\\)`;
-// N_TH: excludes An+B with selector list, e.g. :nth-child(2n+1 of .foo)
-export const N_TH = `nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|${ANB})\\s*\\)`;
-// SUB_TYPE: attr, id, class, pseudo-class, note that [foo|=bar] is excluded
-export const SUB_TYPE = '\\[[^|\\]]+\\]|[#.:][\\w-]+';
-export const SUB_TYPE_WO_PSEUDO = '\\[[^|\\]]+\\]|[#.][\\w-]+';
-// TAG_TYPE: *, tag
-export const TAG_TYPE = '\\*|[A-Za-z][\\w-]*';
-export const TAG_TYPE_I = '\\*|[A-Z][\\w-]*';
-export const COMPOUND = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE})+)`;
-export const COMPOUND_L = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${LOGIC_IS})+)`;
-export const COMPOUND_I = `(?:${TAG_TYPE_I}|(?:${TAG_TYPE_I})?(?:${SUB_TYPE})+)`;
-export const COMPOUND_WO_PSEUDO = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE_WO_PSEUDO})+)`;
-export const COMPLEX = `${COMPOUND}(?:${COMBO}${COMPOUND})*`;
-export const COMPLEX_L = `${COMPOUND_L}(?:${COMBO}${COMPOUND_L})*`;
-export const HAS_COMPOUND = `has\\([\\s>]?\\s*${COMPOUND_WO_PSEUDO}\\s*\\)`;
-export const LOGIC_COMPOUND = `(?:is|not)\\(\\s*${COMPOUND_L}(?:\\s*,\\s*${COMPOUND_L})*\\s*\\)`;
-export const LOGIC_COMPLEX = `(?:is|not)\\(\\s*${COMPLEX_L}(?:\\s*,\\s*${COMPLEX_L})*\\s*\\)`;
-
-/* forms and input types */
-export const FORM_PARTS = Object.freeze([
- 'button',
- 'input',
- 'select',
- 'textarea'
-]);
-export const INPUT_BUTTON = Object.freeze(['button', 'reset', 'submit']);
-export const INPUT_CHECK = Object.freeze(['checkbox', 'radio']);
-export const INPUT_DATE = Object.freeze([
- 'date',
- 'datetime-local',
- 'month',
- 'time',
- 'week'
-]);
-export const INPUT_TEXT = Object.freeze([
- 'email',
- 'password',
- 'search',
- 'tel',
- 'text',
- 'url'
-]);
-export const INPUT_EDIT = Object.freeze([
- ...INPUT_DATE,
- ...INPUT_TEXT,
- 'number'
-]);
-export const INPUT_LTR = Object.freeze([
- ...INPUT_CHECK,
- 'color',
- 'date',
- 'image',
- 'number',
- 'range',
- 'time'
-]);
-
-/* logical combination pseudo-classes */
-export const KEYS_LOGICAL = new Set(['has', 'is', 'not', 'where']);
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/finder.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/finder.js
deleted file mode 100644
index 05538d7..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/finder.js
+++ /dev/null
@@ -1,3122 +0,0 @@
-/**
- * finder.js
- */
-
-/* import */
-import {
- matchAttributeSelector,
- matchDirectionPseudoClass,
- matchDisabledPseudoClass,
- matchLanguagePseudoClass,
- matchPseudoElementSelector,
- matchReadOnlyPseudoClass,
- matchTypeSelector
-} from './matcher.js';
-import {
- findAST,
- generateCSS,
- parseSelector,
- sortAST,
- unescapeSelector,
- walkAST
-} from './parser.js';
-import {
- filterNodesByAnB,
- findLogicalWithNestedHas,
- generateException,
- isCustomElement,
- isFocusVisible,
- isFocusableArea,
- isVisible,
- resolveContent,
- sortNodes,
- traverseNode
-} from './utility.js';
-
-/* constants */
-import {
- ATTR_SELECTOR,
- CLASS_SELECTOR,
- COMBINATOR,
- DOCUMENT_FRAGMENT_NODE,
- ELEMENT_NODE,
- FORM_PARTS,
- ID_SELECTOR,
- INPUT_CHECK,
- INPUT_DATE,
- INPUT_EDIT,
- INPUT_TEXT,
- KEYS_LOGICAL,
- NOT_SUPPORTED_ERR,
- PS_CLASS_SELECTOR,
- PS_ELEMENT_SELECTOR,
- SHOW_ALL,
- SHOW_CONTAINER,
- SYNTAX_ERR,
- TARGET_ALL,
- TARGET_FIRST,
- TARGET_LINEAL,
- TARGET_SELF,
- TEXT_NODE,
- TYPE_SELECTOR
-} from './constant.js';
-const DIR_NEXT = 'next';
-const DIR_PREV = 'prev';
-const KEYS_FORM = new Set([...FORM_PARTS, 'fieldset', 'form']);
-const KEYS_FORM_PS_VALID = new Set([...FORM_PARTS, 'form']);
-const KEYS_INPUT_CHECK = new Set(INPUT_CHECK);
-const KEYS_INPUT_PLACEHOLDER = new Set([...INPUT_TEXT, 'number']);
-const KEYS_INPUT_RANGE = new Set([...INPUT_DATE, 'number', 'range']);
-const KEYS_INPUT_REQUIRED = new Set([...INPUT_CHECK, ...INPUT_EDIT, 'file']);
-const KEYS_INPUT_RESET = new Set(['button', 'reset']);
-const KEYS_INPUT_SUBMIT = new Set(['image', 'submit']);
-const KEYS_MODIFIER = new Set([
- 'Alt',
- 'AltGraph',
- 'CapsLock',
- 'Control',
- 'Fn',
- 'FnLock',
- 'Hyper',
- 'Meta',
- 'NumLock',
- 'ScrollLock',
- 'Shift',
- 'Super',
- 'Symbol',
- 'SymbolLock'
-]);
-const KEYS_PS_UNCACHE = new Set([
- 'any-link',
- 'defined',
- 'dir',
- 'link',
- 'scope'
-]);
-const KEYS_PS_NTH_OF_TYPE = new Set([
- 'first-of-type',
- 'last-of-type',
- 'only-of-type'
-]);
-
-/**
- * Finder
- * NOTE: #ast[i] corresponds to #nodes[i]
- */
-export class Finder {
- /* private fields */
- #ast;
- #astCache;
- #check;
- #descendant;
- #document;
- #documentCache;
- #documentURL;
- #event;
- #eventHandlers;
- #focus;
- #invalidate;
- #invalidateResults;
- #lastFocusVisible;
- #node;
- #nodeWalker;
- #nodes;
- #noexcept;
- #pseudoElement;
- #results;
- #root;
- #rootWalker;
- #scoped;
- #selector;
- #shadow;
- #verifyShadowHost;
- #walkers;
- #warn;
- #window;
-
- /**
- * constructor
- * @param {object} window - The window object.
- */
- constructor(window) {
- this.#window = window;
- this.#astCache = new WeakMap();
- this.#documentCache = new WeakMap();
- this.#event = null;
- this.#focus = null;
- this.#lastFocusVisible = null;
- this.#eventHandlers = new Set([
- {
- keys: ['focus', 'focusin'],
- handler: this._handleFocusEvent
- },
- {
- keys: ['keydown', 'keyup'],
- handler: this._handleKeyboardEvent
- },
- {
- keys: ['mouseover', 'mousedown', 'mouseup', 'click', 'mouseout'],
- handler: this._handleMouseEvent
- }
- ]);
- this._registerEventListeners();
- this.clearResults(true);
- }
-
- /**
- * Handles errors.
- * @param {Error} e - The error object.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.
- * @throws {Error} Throws an error.
- * @returns {void}
- */
- onError = (e, opt = {}) => {
- const noexcept = opt.noexcept ?? this.#noexcept;
- if (noexcept) {
- return;
- }
- const isDOMException =
- e instanceof DOMException || e instanceof this.#window.DOMException;
- if (isDOMException) {
- if (e.name === NOT_SUPPORTED_ERR) {
- if (this.#warn) {
- console.warn(e.message);
- }
- return;
- }
- throw new this.#window.DOMException(e.message, e.name);
- }
- if (e.name in this.#window) {
- throw new this.#window[e.name](e.message, { cause: e });
- }
- throw e;
- };
-
- /**
- * Sets up the finder.
- * @param {string} selector - The CSS selector.
- * @param {object} node - Document, DocumentFragment, or Element.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.check] - Indicates if running in internal check().
- * @param {boolean} [opt.noexcept] - If true, exceptions are not thrown.
- * @param {boolean} [opt.warn] - If true, console warnings are enabled.
- * @returns {object} The finder instance.
- */
- setup = (selector, node, opt = {}) => {
- const { check, noexcept, warn } = opt;
- this.#check = !!check;
- this.#noexcept = !!noexcept;
- this.#warn = !!warn;
- [this.#document, this.#root, this.#shadow] = resolveContent(node);
- this.#documentURL = null;
- this.#node = node;
- this.#scoped =
- this.#node !== this.#root && this.#node.nodeType === ELEMENT_NODE;
- this.#selector = selector;
- [this.#ast, this.#nodes] = this._correspond(selector);
- this.#pseudoElement = [];
- this.#walkers = new WeakMap();
- this.#nodeWalker = null;
- this.#rootWalker = null;
- this.#verifyShadowHost = null;
- this.clearResults();
- return this;
- };
-
- /**
- * Clear cached results.
- * @param {boolean} all - clear all results
- * @returns {void}
- */
- clearResults = (all = false) => {
- this.#invalidateResults = new WeakMap();
- if (all) {
- this.#results = new WeakMap();
- }
- };
-
- /**
- * Handles focus events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleFocusEvent = evt => {
- this.#focus = evt;
- };
-
- /**
- * Handles keyboard events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleKeyboardEvent = evt => {
- const { key } = evt;
- if (!KEYS_MODIFIER.has(key)) {
- this.#event = evt;
- }
- };
-
- /**
- * Handles mouse events.
- * @private
- * @param {Event} evt - The event object.
- * @returns {void}
- */
- _handleMouseEvent = evt => {
- this.#event = evt;
- };
-
- /**
- * Registers event listeners.
- * @private
- * @returns {Array.<void>} An array of return values from addEventListener.
- */
- _registerEventListeners = () => {
- const opt = {
- capture: true,
- passive: true
- };
- const func = [];
- for (const eventHandler of this.#eventHandlers) {
- const { keys, handler } = eventHandler;
- const l = keys.length;
- for (let i = 0; i < l; i++) {
- const key = keys[i];
- func.push(this.#window.addEventListener(key, handler, opt));
- }
- }
- return func;
- };
-
- /**
- * Processes selector branches into the internal AST structure.
- * @private
- * @param {Array.<Array.<object>>} branches - The branches from walkAST.
- * @param {string} selector - The original selector for error reporting.
- * @returns {{ast: Array, descendant: boolean}}
- * An object with the AST, descendant flag.
- */
- _processSelectorBranches = (branches, selector) => {
- let descendant = false;
- const ast = [];
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const items = [...branches[i]];
- const branch = [];
- let item = items.shift();
- if (item && item.type !== COMBINATOR) {
- const leaves = new Set();
- while (item) {
- if (item.type === COMBINATOR) {
- const [nextItem] = items;
- if (!nextItem || nextItem.type === COMBINATOR) {
- const msg = `Invalid selector ${selector}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- // Stop processing on invalid selector.
- return { ast: [], descendant: false, invalidate: false };
- }
- if (item.name === ' ' || item.name === '>') {
- descendant = true;
- }
- branch.push({ combo: item, leaves: sortAST(leaves) });
- leaves.clear();
- } else {
- if (item.name && typeof item.name === 'string') {
- const unescapedName = unescapeSelector(item.name);
- if (unescapedName !== item.name) {
- item.name = unescapedName;
- }
- if (/[|:]/.test(unescapedName)) {
- item.namespace = true;
- }
- }
- leaves.add(item);
- }
- if (items.length) {
- item = items.shift();
- } else {
- branch.push({ combo: null, leaves: sortAST(leaves) });
- leaves.clear();
- break;
- }
- }
- }
- ast.push({ branch, dir: null, filtered: false, find: false });
- }
- return { ast, descendant };
- };
-
- /**
- * Corresponds AST and nodes.
- * @private
- * @param {string} selector - The CSS selector.
- * @returns {Array.<Array.<object>>} An array with the AST and nodes.
- */
- _correspond = selector => {
- const nodes = [];
- this.#descendant = false;
- this.#invalidate = false;
- let ast;
- if (this.#documentCache.has(this.#document)) {
- const cachedItem = this.#documentCache.get(this.#document);
- if (cachedItem && cachedItem.has(`${selector}`)) {
- const item = cachedItem.get(`${selector}`);
- ast = item.ast;
- this.#descendant = item.descendant;
- this.#invalidate = item.invalidate;
- }
- }
- if (ast) {
- const l = ast.length;
- for (let i = 0; i < l; i++) {
- ast[i].dir = null;
- ast[i].filtered = false;
- ast[i].find = false;
- nodes[i] = [];
- }
- } else {
- let cssAst;
- try {
- cssAst = parseSelector(selector);
- } catch (e) {
- return this.onError(e);
- }
- const { branches, info } = walkAST(cssAst);
- const {
- hasHasPseudoFunc,
- hasLogicalPseudoFunc,
- hasNthChildOfSelector,
- hasStatePseudoClass
- } = info;
- this.#invalidate =
- hasHasPseudoFunc ||
- hasStatePseudoClass ||
- !!(hasLogicalPseudoFunc && hasNthChildOfSelector);
- const processed = this._processSelectorBranches(branches, selector);
- ast = processed.ast;
- this.#descendant = processed.descendant;
- let cachedItem;
- if (this.#documentCache.has(this.#document)) {
- cachedItem = this.#documentCache.get(this.#document);
- } else {
- cachedItem = new Map();
- }
- cachedItem.set(`${selector}`, {
- ast,
- descendant: this.#descendant,
- invalidate: this.#invalidate
- });
- this.#documentCache.set(this.#document, cachedItem);
- // Initialize nodes array for each branch.
- for (let i = 0; i < ast.length; i++) {
- nodes[i] = [];
- }
- }
- return [ast, nodes];
- };
-
- /**
- * Creates a TreeWalker.
- * @private
- * @param {object} node - The Document, DocumentFragment, or Element node.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.force] - Force creation of a new TreeWalker.
- * @param {number} [opt.whatToShow] - The NodeFilter whatToShow value.
- * @returns {object} The TreeWalker object.
- */
- _createTreeWalker = (node, opt = {}) => {
- const { force = false, whatToShow = SHOW_CONTAINER } = opt;
- if (force) {
- return this.#document.createTreeWalker(node, whatToShow);
- } else if (this.#walkers.has(node)) {
- return this.#walkers.get(node);
- }
- const walker = this.#document.createTreeWalker(node, whatToShow);
- this.#walkers.set(node, walker);
- return walker;
- };
-
- /**
- * Gets selector branches from cache or parses them.
- * @private
- * @param {object} selector - The AST.
- * @returns {Array.<Array.<object>>} The selector branches.
- */
- _getSelectorBranches = selector => {
- if (this.#astCache.has(selector)) {
- return this.#astCache.get(selector);
- }
- const { branches } = walkAST(selector);
- this.#astCache.set(selector, branches);
- return branches;
- };
-
- /**
- * Gets the children of a node, optionally filtered by a selector.
- * @private
- * @param {object} parentNode - The parent element.
- * @param {Array.<Array.<object>>} selectorBranches - The selector branches.
- * @param {object} [opt] - Options.
- * @returns {Array.<object>} An array of child nodes.
- */
- _getFilteredChildren = (parentNode, selectorBranches, opt = {}) => {
- const children = [];
- const walker = this._createTreeWalker(parentNode, { force: true });
- let childNode = walker.firstChild();
- while (childNode) {
- if (selectorBranches) {
- if (isVisible(childNode)) {
- let isMatch = false;
- const l = selectorBranches.length;
- for (let i = 0; i < l; i++) {
- const leaves = selectorBranches[i];
- if (this._matchLeaves(leaves, childNode, opt)) {
- isMatch = true;
- break;
- }
- }
- if (isMatch) {
- children.push(childNode);
- }
- }
- } else {
- children.push(childNode);
- }
- childNode = walker.nextSibling();
- }
- return children;
- };
-
- /**
- * Collects nth-child nodes.
- * @private
- * @param {object} anb - An+B options.
- * @param {number} anb.a - The 'a' value.
- * @param {number} anb.b - The 'b' value.
- * @param {boolean} [anb.reverse] - If true, reverses the order.
- * @param {object} [anb.selector] - The AST.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _collectNthChild = (anb, node, opt = {}) => {
- const { a, b, selector } = anb;
- const { parentNode } = node;
- if (!parentNode) {
- const matchedNode = new Set();
- if (node === this.#root && a * 1 + b * 1 === 1) {
- if (selector) {
- const selectorBranches = this._getSelectorBranches(selector);
- const l = selectorBranches.length;
- for (let i = 0; i < l; i++) {
- const leaves = selectorBranches[i];
- if (this._matchLeaves(leaves, node, opt)) {
- matchedNode.add(node);
- break;
- }
- }
- } else {
- matchedNode.add(node);
- }
- }
- return matchedNode;
- }
- const selectorBranches = selector
- ? this._getSelectorBranches(selector)
- : null;
- const children = this._getFilteredChildren(
- parentNode,
- selectorBranches,
- opt
- );
- const matchedNodes = filterNodesByAnB(children, anb);
- return new Set(matchedNodes);
- };
-
- /**
- * Collects nth-of-type nodes.
- * @private
- * @param {object} anb - An+B options.
- * @param {number} anb.a - The 'a' value.
- * @param {number} anb.b - The 'b' value.
- * @param {boolean} [anb.reverse] - If true, reverses the order.
- * @param {object} node - The Element node.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _collectNthOfType = (anb, node) => {
- const { parentNode } = node;
- if (!parentNode) {
- if (node === this.#root && anb.a * 1 + anb.b * 1 === 1) {
- return new Set([node]);
- }
- return new Set();
- }
- const typedSiblings = [];
- const walker = this._createTreeWalker(parentNode, { force: true });
- let sibling = walker.firstChild();
- while (sibling) {
- if (
- sibling.localName === node.localName &&
- sibling.namespaceURI === node.namespaceURI &&
- sibling.prefix === node.prefix
- ) {
- typedSiblings.push(sibling);
- }
- sibling = walker.nextSibling();
- }
- const matchedNodes = filterNodesByAnB(typedSiblings, anb);
- return new Set(matchedNodes);
- };
-
- /**
- * Matches An+B.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Element node.
- * @param {string} nthName - The name of the nth pseudo-class.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchAnPlusB = (ast, node, nthName, opt = {}) => {
- const {
- nth: { a, b, name: nthIdentName },
- selector
- } = ast;
- const anbMap = new Map();
- if (nthIdentName) {
- if (nthIdentName === 'even') {
- anbMap.set('a', 2);
- anbMap.set('b', 0);
- } else if (nthIdentName === 'odd') {
- anbMap.set('a', 2);
- anbMap.set('b', 1);
- }
- if (nthName.indexOf('last') > -1) {
- anbMap.set('reverse', true);
- }
- } else {
- if (typeof a === 'string' && /-?\d+/.test(a)) {
- anbMap.set('a', a * 1);
- } else {
- anbMap.set('a', 0);
- }
- if (typeof b === 'string' && /-?\d+/.test(b)) {
- anbMap.set('b', b * 1);
- } else {
- anbMap.set('b', 0);
- }
- if (nthName.indexOf('last') > -1) {
- anbMap.set('reverse', true);
- }
- }
- if (nthName === 'nth-child' || nthName === 'nth-last-child') {
- if (selector) {
- anbMap.set('selector', selector);
- }
- const anb = Object.fromEntries(anbMap);
- const nodes = this._collectNthChild(anb, node, opt);
- return nodes;
- } else if (nthName === 'nth-of-type' || nthName === 'nth-last-of-type') {
- const anb = Object.fromEntries(anbMap);
- const nodes = this._collectNthOfType(anb, node);
- return nodes;
- }
- return new Set();
- };
-
- /**
- * Matches the :has() pseudo-class function.
- * @private
- * @param {Array.<object>} astLeaves - The AST leaves.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {boolean} The result.
- */
- _matchHasPseudoFunc = (astLeaves, node, opt = {}) => {
- if (Array.isArray(astLeaves) && astLeaves.length) {
- // Prepare a copy to avoid astLeaves being consumed.
- const leaves = [...astLeaves];
- const [leaf] = leaves;
- const { type: leafType } = leaf;
- let combo;
- if (leafType === COMBINATOR) {
- combo = leaves.shift();
- } else {
- combo = {
- name: ' ',
- type: COMBINATOR
- };
- }
- const twigLeaves = [];
- while (leaves.length) {
- const [item] = leaves;
- const { type: itemType } = item;
- if (itemType === COMBINATOR) {
- break;
- } else {
- twigLeaves.push(leaves.shift());
- }
- }
- const twig = {
- combo,
- leaves: twigLeaves
- };
- opt.dir = DIR_NEXT;
- const nodes = this._matchCombinator(twig, node, opt);
- if (nodes.size) {
- if (leaves.length) {
- let bool = false;
- for (const nextNode of nodes) {
- bool = this._matchHasPseudoFunc(leaves, nextNode, opt);
- if (bool) {
- break;
- }
- }
- return bool;
- }
- return true;
- }
- }
- return false;
- };
-
- /**
- * Evaluates the :has() pseudo-class.
- * @private
- * @param {object} astData - The AST data.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {?object} The matched node.
- */
- _evaluateHasPseudo = (astData, node, opt) => {
- const { branches } = astData;
- let bool = false;
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const leaves = branches[i];
- bool = this._matchHasPseudoFunc(leaves, node, opt);
- if (bool) {
- break;
- }
- }
- if (!bool) {
- return null;
- }
- if (
- (opt.isShadowRoot || this.#shadow) &&
- node.nodeType === DOCUMENT_FRAGMENT_NODE
- ) {
- return this.#verifyShadowHost ? node : null;
- }
- return node;
- };
-
- /**
- * Matches logical pseudo-class functions.
- * @private
- * @param {object} astData - The AST data.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {?object} The matched node.
- */
- _matchLogicalPseudoFunc = (astData, node, opt = {}) => {
- const { astName, branches, twigBranches } = astData;
- // Handle :has().
- if (astName === 'has') {
- return this._evaluateHasPseudo(astData, node, opt);
- }
- // Handle :is(), :not(), :where().
- const isShadowRoot =
- (opt.isShadowRoot || this.#shadow) &&
- node.nodeType === DOCUMENT_FRAGMENT_NODE;
- // Check for invalid shadow root.
- if (isShadowRoot) {
- let invalid = false;
- for (const branch of branches) {
- if (branch.length > 1) {
- invalid = true;
- break;
- } else if (astName === 'not') {
- const [{ type: childAstType }] = branch;
- if (childAstType !== PS_CLASS_SELECTOR) {
- invalid = true;
- break;
- }
- }
- }
- if (invalid) {
- return null;
- }
- }
- opt.forgive = astName === 'is' || astName === 'where';
- const l = twigBranches.length;
- let bool;
- for (let i = 0; i < l; i++) {
- const branch = twigBranches[i];
- const lastIndex = branch.length - 1;
- const { leaves } = branch[lastIndex];
- bool = this._matchLeaves(leaves, node, opt);
- if (bool && lastIndex > 0) {
- let nextNodes = new Set([node]);
- for (let j = lastIndex - 1; j >= 0; j--) {
- const twig = branch[j];
- const arr = [];
- opt.dir = DIR_PREV;
- for (const nextNode of nextNodes) {
- const m = this._matchCombinator(twig, nextNode, opt);
- if (m.size) {
- arr.push(...m);
- }
- }
- if (arr.length) {
- if (j === 0) {
- bool = true;
- } else {
- nextNodes = new Set(arr);
- }
- } else {
- bool = false;
- break;
- }
- }
- }
- if (bool) {
- break;
- }
- }
- if (astName === 'not') {
- if (bool) {
- return null;
- }
- return node;
- } else if (bool) {
- return node;
- }
- return null;
- };
-
- /**
- * match pseudo-class selector
- * @private
- * @see https://html.spec.whatwg.org/#pseudo-classes
- * @param {object} ast - AST
- * @param {object} node - Element node
- * @param {object} [opt] - options
- * @returns {Set.<object>} - collection of matched nodes
- */
- _matchPseudoClassSelector(ast, node, opt = {}) {
- const { children: astChildren, name: astName } = ast;
- const { localName, parentNode } = node;
- const { forgive, warn = this.#warn } = opt;
- const matched = new Set();
- // :has(), :is(), :not(), :where()
- if (Array.isArray(astChildren) && KEYS_LOGICAL.has(astName)) {
- if (!astChildren.length && astName !== 'is' && astName !== 'where') {
- const css = generateCSS(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- let astData;
- if (this.#astCache.has(ast)) {
- astData = this.#astCache.get(ast);
- } else {
- const { branches } = walkAST(ast);
- if (astName === 'has') {
- // Check for nested :has().
- let forgiven = false;
- const l = astChildren.length;
- for (let i = 0; i < l; i++) {
- const child = astChildren[i];
- const item = findAST(child, findLogicalWithNestedHas);
- if (item) {
- const itemName = item.name;
- if (itemName === 'is' || itemName === 'where') {
- forgiven = true;
- break;
- } else {
- const css = generateCSS(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(
- generateException(msg, SYNTAX_ERR, this.#window)
- );
- }
- }
- }
- if (forgiven) {
- return matched;
- }
- astData = {
- astName,
- branches
- };
- } else {
- const twigBranches = [];
- const l = branches.length;
- for (let i = 0; i < l; i++) {
- const [...leaves] = branches[i];
- const branch = [];
- const leavesSet = new Set();
- let item = leaves.shift();
- while (item) {
- if (item.type === COMBINATOR) {
- branch.push({
- combo: item,
- leaves: [...leavesSet]
- });
- leavesSet.clear();
- } else if (item) {
- leavesSet.add(item);
- }
- if (leaves.length) {
- item = leaves.shift();
- } else {
- branch.push({
- combo: null,
- leaves: [...leavesSet]
- });
- leavesSet.clear();
- break;
- }
- }
- twigBranches.push(branch);
- }
- astData = {
- astName,
- branches,
- twigBranches
- };
- this.#astCache.set(ast, astData);
- }
- }
- const res = this._matchLogicalPseudoFunc(astData, node, opt);
- if (res) {
- matched.add(res);
- }
- } else if (Array.isArray(astChildren)) {
- // :nth-child(), :nth-last-child(), nth-of-type(), :nth-last-of-type()
- if (/^nth-(?:last-)?(?:child|of-type)$/.test(astName)) {
- if (astChildren.length !== 1) {
- const css = generateCSS(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- const [branch] = astChildren;
- const nodes = this._matchAnPlusB(branch, node, astName, opt);
- return nodes;
- } else {
- switch (astName) {
- // :dir()
- case 'dir': {
- if (astChildren.length !== 1) {
- const css = generateCSS(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- const [astChild] = astChildren;
- const res = matchDirectionPseudoClass(astChild, node);
- if (res) {
- matched.add(node);
- }
- break;
- }
- // :lang()
- case 'lang': {
- if (!astChildren.length) {
- const css = generateCSS(ast);
- return this.onError(
- generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- let bool;
- for (const astChild of astChildren) {
- bool = matchLanguagePseudoClass(astChild, node);
- if (bool) {
- break;
- }
- }
- if (bool) {
- matched.add(node);
- }
- break;
- }
- // :state()
- case 'state': {
- if (isCustomElement(node)) {
- const [{ value: stateValue }] = astChildren;
- if (stateValue) {
- if (node[stateValue]) {
- matched.add(node);
- } else {
- for (const i in node) {
- const prop = node[i];
- if (prop instanceof this.#window.ElementInternals) {
- if (prop?.states?.has(stateValue)) {
- matched.add(node);
- }
- break;
- }
- }
- }
- }
- }
- break;
- }
- case 'current':
- case 'heading':
- case 'nth-col':
- case 'nth-last-col': {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}()`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- // Ignore :host() and :host-context().
- case 'host':
- case 'host-context': {
- break;
- }
- // Deprecated in CSS Selectors 3.
- case 'contains': {
- if (warn) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}()`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- default: {
- if (!forgive) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}()`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- }
- }
- }
- } else if (KEYS_PS_NTH_OF_TYPE.has(astName)) {
- if (node === this.#root) {
- matched.add(node);
- } else if (parentNode) {
- switch (astName) {
- case 'first-of-type': {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1
- },
- node
- );
- if (node1) {
- matched.add(node1);
- }
- break;
- }
- case 'last-of-type': {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1,
- reverse: true
- },
- node
- );
- if (node1) {
- matched.add(node1);
- }
- break;
- }
- // 'only-of-type' is handled by default.
- default: {
- const [node1] = this._collectNthOfType(
- {
- a: 0,
- b: 1
- },
- node
- );
- if (node1 === node) {
- const [node2] = this._collectNthOfType(
- {
- a: 0,
- b: 1,
- reverse: true
- },
- node
- );
- if (node2 === node) {
- matched.add(node);
- }
- }
- }
- }
- }
- } else {
- switch (astName) {
- case 'disabled':
- case 'enabled': {
- const isMatch = matchDisabledPseudoClass(astName, node);
- if (isMatch) {
- matched.add(node);
- }
- break;
- }
- case 'read-only':
- case 'read-write': {
- const isMatch = matchReadOnlyPseudoClass(astName, node);
- if (isMatch) {
- matched.add(node);
- }
- break;
- }
- case 'any-link':
- case 'link': {
- if (
- (localName === 'a' || localName === 'area') &&
- node.hasAttribute('href')
- ) {
- matched.add(node);
- }
- break;
- }
- case 'local-link': {
- if (
- (localName === 'a' || localName === 'area') &&
- node.hasAttribute('href')
- ) {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { href, origin, pathname } = this.#documentURL;
- const attrURL = new URL(node.getAttribute('href'), href);
- if (attrURL.origin === origin && attrURL.pathname === pathname) {
- matched.add(node);
- }
- }
- break;
- }
- case 'visited': {
- // prevent fingerprinting
- break;
- }
- case 'hover': {
- const { target, type } = this.#event ?? {};
- if (
- /^(?:click|mouse(?:down|over|up))$/.test(type) &&
- node.contains(target)
- ) {
- matched.add(node);
- }
- break;
- }
- case 'active': {
- const { buttons, target, type } = this.#event ?? {};
- if (type === 'mousedown' && buttons & 1 && node.contains(target)) {
- matched.add(node);
- }
- break;
- }
- case 'target': {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { hash } = this.#documentURL;
- if (
- node.id &&
- hash === `#${node.id}` &&
- this.#document.contains(node)
- ) {
- matched.add(node);
- }
- break;
- }
- case 'target-within': {
- if (!this.#documentURL) {
- this.#documentURL = new URL(this.#document.URL);
- }
- const { hash } = this.#documentURL;
- if (hash) {
- const id = hash.replace(/^#/, '');
- let current = this.#document.getElementById(id);
- while (current) {
- if (current === node) {
- matched.add(node);
- break;
- }
- current = current.parentNode;
- }
- }
- break;
- }
- case 'scope': {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (!this.#shadow && node === this.#node) {
- matched.add(node);
- }
- } else if (node === this.#document.documentElement) {
- matched.add(node);
- }
- break;
- }
- case 'focus': {
- const activeElement = this.#document.activeElement;
- if (node === activeElement && isFocusableArea(node)) {
- matched.add(node);
- } else if (activeElement.shadowRoot) {
- const activeShadowElement = activeElement.shadowRoot.activeElement;
- let current = activeShadowElement;
- while (current) {
- if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {
- const { host } = current;
- if (host === activeElement) {
- if (isFocusableArea(node)) {
- matched.add(node);
- } else {
- matched.add(host);
- }
- }
- break;
- } else {
- current = current.parentNode;
- }
- }
- }
- break;
- }
- case 'focus-visible': {
- if (node === this.#document.activeElement && isFocusableArea(node)) {
- let bool;
- if (isFocusVisible(node)) {
- bool = true;
- } else if (this.#focus) {
- const { relatedTarget, target: focusTarget } = this.#focus;
- if (focusTarget === node) {
- if (isFocusVisible(relatedTarget)) {
- bool = true;
- } else if (this.#event) {
- const {
- altKey: eventAltKey,
- ctrlKey: eventCtrlKey,
- key: eventKey,
- metaKey: eventMetaKey,
- target: eventTarget,
- type: eventType
- } = this.#event;
- // this.#event is irrelevant if eventTarget === relatedTarget
- if (eventTarget === relatedTarget) {
- if (this.#lastFocusVisible === null) {
- bool = true;
- } else if (focusTarget === this.#lastFocusVisible) {
- bool = true;
- }
- } else if (eventKey === 'Tab') {
- if (
- (eventType === 'keydown' && eventTarget !== node) ||
- (eventType === 'keyup' && eventTarget === node)
- ) {
- if (eventTarget === focusTarget) {
- if (this.#lastFocusVisible === null) {
- bool = true;
- } else if (
- eventTarget === this.#lastFocusVisible &&
- relatedTarget === null
- ) {
- bool = true;
- }
- } else {
- bool = true;
- }
- }
- } else if (eventKey) {
- if (
- (eventType === 'keydown' || eventType === 'keyup') &&
- !eventAltKey &&
- !eventCtrlKey &&
- !eventMetaKey &&
- eventTarget === node
- ) {
- bool = true;
- }
- }
- } else if (
- relatedTarget === null ||
- relatedTarget === this.#lastFocusVisible
- ) {
- bool = true;
- }
- }
- }
- if (bool) {
- this.#lastFocusVisible = node;
- matched.add(node);
- } else if (this.#lastFocusVisible === node) {
- this.#lastFocusVisible = null;
- }
- }
- break;
- }
- case 'focus-within': {
- const activeElement = this.#document.activeElement;
- if (node.contains(activeElement) && isFocusableArea(activeElement)) {
- matched.add(node);
- } else if (activeElement.shadowRoot) {
- const activeShadowElement = activeElement.shadowRoot.activeElement;
- if (node.contains(activeShadowElement)) {
- matched.add(node);
- } else {
- let current = activeShadowElement;
- while (current) {
- if (current.nodeType === DOCUMENT_FRAGMENT_NODE) {
- const { host } = current;
- if (host === activeElement && node.contains(host)) {
- matched.add(node);
- }
- break;
- } else {
- current = current.parentNode;
- }
- }
- }
- }
- break;
- }
- case 'open':
- case 'closed': {
- if (localName === 'details' || localName === 'dialog') {
- if (node.hasAttribute('open')) {
- if (astName === 'open') {
- matched.add(node);
- }
- } else if (astName === 'closed') {
- matched.add(node);
- }
- }
- break;
- }
- case 'placeholder-shown': {
- let placeholder;
- if (node.placeholder) {
- placeholder = node.placeholder;
- } else if (node.hasAttribute('placeholder')) {
- placeholder = node.getAttribute('placeholder');
- }
- if (typeof placeholder === 'string' && !/[\r\n]/.test(placeholder)) {
- let targetNode;
- if (localName === 'textarea') {
- targetNode = node;
- } else if (localName === 'input') {
- if (node.hasAttribute('type')) {
- if (KEYS_INPUT_PLACEHOLDER.has(node.getAttribute('type'))) {
- targetNode = node;
- }
- } else {
- targetNode = node;
- }
- }
- if (targetNode && node.value === '') {
- matched.add(node);
- }
- }
- break;
- }
- case 'checked': {
- const attrType = node.getAttribute('type');
- if (
- (node.checked &&
- localName === 'input' &&
- (attrType === 'checkbox' || attrType === 'radio')) ||
- (node.selected && localName === 'option')
- ) {
- matched.add(node);
- }
- break;
- }
- case 'indeterminate': {
- if (
- (node.indeterminate &&
- localName === 'input' &&
- node.type === 'checkbox') ||
- (localName === 'progress' && !node.hasAttribute('value'))
- ) {
- matched.add(node);
- } else if (
- localName === 'input' &&
- node.type === 'radio' &&
- !node.hasAttribute('checked')
- ) {
- const nodeName = node.name;
- let parent = node.parentNode;
- while (parent) {
- if (parent.localName === 'form') {
- break;
- }
- parent = parent.parentNode;
- }
- if (!parent) {
- parent = this.#document.documentElement;
- }
- const walker = this._createTreeWalker(parent);
- let refNode = traverseNode(parent, walker);
- refNode = walker.firstChild();
- let checked;
- while (refNode) {
- if (
- refNode.localName === 'input' &&
- refNode.getAttribute('type') === 'radio'
- ) {
- if (refNode.hasAttribute('name')) {
- if (refNode.getAttribute('name') === nodeName) {
- checked = !!refNode.checked;
- }
- } else {
- checked = !!refNode.checked;
- }
- if (checked) {
- break;
- }
- }
- refNode = walker.nextNode();
- }
- if (!checked) {
- matched.add(node);
- }
- }
- break;
- }
- case 'default': {
- // button[type="submit"], input[type="submit"], input[type="image"]
- const attrType = node.getAttribute('type');
- if (
- (localName === 'button' &&
- !(node.hasAttribute('type') && KEYS_INPUT_RESET.has(attrType))) ||
- (localName === 'input' &&
- node.hasAttribute('type') &&
- KEYS_INPUT_SUBMIT.has(attrType))
- ) {
- let form = node.parentNode;
- while (form) {
- if (form.localName === 'form') {
- break;
- }
- form = form.parentNode;
- }
- if (form) {
- const walker = this._createTreeWalker(form);
- let refNode = traverseNode(form, walker);
- refNode = walker.firstChild();
- while (refNode) {
- const nodeName = refNode.localName;
- const nodeAttrType = refNode.getAttribute('type');
- let m;
- if (nodeName === 'button') {
- m = !(
- refNode.hasAttribute('type') &&
- KEYS_INPUT_RESET.has(nodeAttrType)
- );
- } else if (nodeName === 'input') {
- m =
- refNode.hasAttribute('type') &&
- KEYS_INPUT_SUBMIT.has(nodeAttrType);
- }
- if (m) {
- if (refNode === node) {
- matched.add(node);
- }
- break;
- }
- refNode = walker.nextNode();
- }
- }
- // input[type="checkbox"], input[type="radio"]
- } else if (
- localName === 'input' &&
- node.hasAttribute('type') &&
- node.hasAttribute('checked') &&
- KEYS_INPUT_CHECK.has(attrType)
- ) {
- matched.add(node);
- // option
- } else if (localName === 'option' && node.hasAttribute('selected')) {
- matched.add(node);
- }
- break;
- }
- case 'valid':
- case 'invalid': {
- if (KEYS_FORM_PS_VALID.has(localName)) {
- let valid;
- if (node.checkValidity()) {
- if (node.maxLength >= 0) {
- if (node.maxLength >= node.value.length) {
- valid = true;
- }
- } else {
- valid = true;
- }
- }
- if (valid) {
- if (astName === 'valid') {
- matched.add(node);
- }
- } else if (astName === 'invalid') {
- matched.add(node);
- }
- } else if (localName === 'fieldset') {
- const walker = this._createTreeWalker(node);
- let refNode = traverseNode(node, walker);
- refNode = walker.firstChild();
- let valid;
- if (!refNode) {
- valid = true;
- } else {
- while (refNode) {
- if (KEYS_FORM_PS_VALID.has(refNode.localName)) {
- if (refNode.checkValidity()) {
- if (refNode.maxLength >= 0) {
- valid = refNode.maxLength >= refNode.value.length;
- } else {
- valid = true;
- }
- } else {
- valid = false;
- }
- if (!valid) {
- break;
- }
- }
- refNode = walker.nextNode();
- }
- }
- if (valid) {
- if (astName === 'valid') {
- matched.add(node);
- }
- } else if (astName === 'invalid') {
- matched.add(node);
- }
- }
- break;
- }
- case 'in-range':
- case 'out-of-range': {
- const attrType = node.getAttribute('type');
- if (
- localName === 'input' &&
- !(node.readonly || node.hasAttribute('readonly')) &&
- !(node.disabled || node.hasAttribute('disabled')) &&
- KEYS_INPUT_RANGE.has(attrType)
- ) {
- const flowed =
- node.validity.rangeUnderflow || node.validity.rangeOverflow;
- if (astName === 'out-of-range' && flowed) {
- matched.add(node);
- } else if (
- astName === 'in-range' &&
- !flowed &&
- (node.hasAttribute('min') ||
- node.hasAttribute('max') ||
- attrType === 'range')
- ) {
- matched.add(node);
- }
- }
- break;
- }
- case 'required':
- case 'optional': {
- let required;
- let optional;
- if (localName === 'select' || localName === 'textarea') {
- if (node.required || node.hasAttribute('required')) {
- required = true;
- } else {
- optional = true;
- }
- } else if (localName === 'input') {
- if (node.hasAttribute('type')) {
- const attrType = node.getAttribute('type');
- if (KEYS_INPUT_REQUIRED.has(attrType)) {
- if (node.required || node.hasAttribute('required')) {
- required = true;
- } else {
- optional = true;
- }
- } else {
- optional = true;
- }
- } else if (node.required || node.hasAttribute('required')) {
- required = true;
- } else {
- optional = true;
- }
- }
- if (astName === 'required' && required) {
- matched.add(node);
- } else if (astName === 'optional' && optional) {
- matched.add(node);
- }
- break;
- }
- case 'root': {
- if (node === this.#document.documentElement) {
- matched.add(node);
- }
- break;
- }
- case 'empty': {
- if (node.hasChildNodes()) {
- const walker = this._createTreeWalker(node, {
- force: true,
- whatToShow: SHOW_ALL
- });
- let refNode = walker.firstChild();
- let bool;
- while (refNode) {
- bool =
- refNode.nodeType !== ELEMENT_NODE &&
- refNode.nodeType !== TEXT_NODE;
- if (!bool) {
- break;
- }
- refNode = walker.nextSibling();
- }
- if (bool) {
- matched.add(node);
- }
- } else {
- matched.add(node);
- }
- break;
- }
- case 'first-child': {
- if (
- (parentNode && node === parentNode.firstElementChild) ||
- node === this.#root
- ) {
- matched.add(node);
- }
- break;
- }
- case 'last-child': {
- if (
- (parentNode && node === parentNode.lastElementChild) ||
- node === this.#root
- ) {
- matched.add(node);
- }
- break;
- }
- case 'only-child': {
- if (
- (parentNode &&
- node === parentNode.firstElementChild &&
- node === parentNode.lastElementChild) ||
- node === this.#root
- ) {
- matched.add(node);
- }
- break;
- }
- case 'defined': {
- if (node.hasAttribute('is') || localName.includes('-')) {
- if (isCustomElement(node)) {
- matched.add(node);
- }
- // NOTE: MathMLElement is not implemented in jsdom.
- } else if (
- node instanceof this.#window.HTMLElement ||
- node instanceof this.#window.SVGElement
- ) {
- matched.add(node);
- }
- break;
- }
- case 'popover-open': {
- if (node.popover && isVisible(node)) {
- matched.add(node);
- }
- break;
- }
- // Ignore :host.
- case 'host': {
- break;
- }
- // Legacy pseudo-elements.
- case 'after':
- case 'before':
- case 'first-letter':
- case 'first-line': {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- // Not supported.
- case 'autofill':
- case 'blank':
- case 'buffering':
- case 'current':
- case 'fullscreen':
- case 'future':
- case 'has-slotted':
- case 'heading':
- case 'modal':
- case 'muted':
- case 'past':
- case 'paused':
- case 'picture-in-picture':
- case 'playing':
- case 'seeking':
- case 'stalled':
- case 'user-invalid':
- case 'user-valid':
- case 'volume-locked':
- case '-webkit-autofill': {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- break;
- }
- default: {
- if (astName.startsWith('-webkit-')) {
- if (warn) {
- this.onError(
- generateException(
- `Unsupported pseudo-class :${astName}`,
- NOT_SUPPORTED_ERR,
- this.#window
- )
- );
- }
- } else if (!forgive) {
- this.onError(
- generateException(
- `Unknown pseudo-class :${astName}`,
- SYNTAX_ERR,
- this.#window
- )
- );
- }
- }
- }
- }
- return matched;
- }
-
- /**
- * Evaluates the :host() pseudo-class.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} host - The host element.
- * @param {object} ast - The original AST for error reporting.
- * @returns {boolean} True if matched.
- */
- _evaluateHostPseudo = (leaves, host, ast) => {
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- if (leaf.type === COMBINATOR) {
- const css = generateCSS(ast);
- const msg = `Invalid selector ${css}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- return false;
- }
- if (!this._matchSelector(leaf, host).has(host)) {
- return false;
- }
- }
- return true;
- };
-
- /**
- * Evaluates the :host-context() pseudo-class.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} host - The host element.
- * @param {object} ast - The original AST for error reporting.
- * @returns {boolean} True if matched.
- */
- _evaluateHostContextPseudo = (leaves, host, ast) => {
- let parent = host;
- while (parent) {
- let bool;
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- if (leaf.type === COMBINATOR) {
- const css = generateCSS(ast);
- const msg = `Invalid selector ${css}`;
- this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- return false;
- }
- bool = this._matchSelector(leaf, parent).has(parent);
- if (!bool) {
- break;
- }
- }
- if (bool) {
- return true;
- }
- parent = parent.parentNode;
- }
- return false;
- };
-
- /**
- * Matches shadow host pseudo-classes.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The DocumentFragment node.
- * @returns {?object} The matched node.
- */
- _matchShadowHostPseudoClass = (ast, node) => {
- const { children: astChildren, name: astName } = ast;
- // Handle simple pseudo-class (no arguments).
- if (!Array.isArray(astChildren)) {
- if (astName === 'host') {
- return node;
- }
- const msg = `Invalid selector :${astName}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- // Handle functional pseudo-class like :host(...).
- if (astName !== 'host' && astName !== 'host-context') {
- const msg = `Invalid selector :${astName}()`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- if (astChildren.length !== 1) {
- const css = generateCSS(ast);
- const msg = `Invalid selector ${css}`;
- return this.onError(generateException(msg, SYNTAX_ERR, this.#window));
- }
- const { host } = node;
- const { branches } = walkAST(astChildren[0]);
- const [branch] = branches;
- const [...leaves] = branch;
- let isMatch = false;
- if (astName === 'host') {
- isMatch = this._evaluateHostPseudo(leaves, host, ast);
- // astName === 'host-context'.
- } else {
- isMatch = this._evaluateHostContextPseudo(leaves, host, ast);
- }
- return isMatch ? node : null;
- };
-
- /**
- * Matches a selector for element nodes.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelectorForElement = (ast, node, opt = {}) => {
- const { type: astType } = ast;
- const astName = unescapeSelector(ast.name);
- const matched = new Set();
- switch (astType) {
- case ATTR_SELECTOR: {
- if (matchAttributeSelector(ast, node, opt)) {
- matched.add(node);
- }
- break;
- }
- case ID_SELECTOR: {
- if (node.id === astName) {
- matched.add(node);
- }
- break;
- }
- case CLASS_SELECTOR: {
- if (node.classList.contains(astName)) {
- matched.add(node);
- }
- break;
- }
- case PS_CLASS_SELECTOR: {
- return this._matchPseudoClassSelector(ast, node, opt);
- }
- case TYPE_SELECTOR: {
- if (matchTypeSelector(ast, node, opt)) {
- matched.add(node);
- }
- break;
- }
- // PS_ELEMENT_SELECTOR is handled by default.
- default: {
- try {
- if (opt.check) {
- const css = generateCSS(ast);
- this.#pseudoElement.push(css);
- matched.add(node);
- } else {
- matchPseudoElementSelector(astName, astType, opt);
- }
- } catch (e) {
- this.onError(e);
- }
- }
- }
- return matched;
- };
-
- /**
- * Matches a selector for a shadow root.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The DocumentFragment node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelectorForShadowRoot = (ast, node, opt = {}) => {
- const { name: astName } = ast;
- if (KEYS_LOGICAL.has(astName)) {
- opt.isShadowRoot = true;
- return this._matchPseudoClassSelector(ast, node, opt);
- }
- const matched = new Set();
- if (astName === 'host' || astName === 'host-context') {
- const res = this._matchShadowHostPseudoClass(ast, node, opt);
- if (res) {
- this.#verifyShadowHost = true;
- matched.add(res);
- }
- }
- return matched;
- };
-
- /**
- * Matches a selector.
- * @private
- * @param {object} ast - The AST.
- * @param {object} node - The Document, DocumentFragment, or Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchSelector = (ast, node, opt = {}) => {
- if (node.nodeType === ELEMENT_NODE) {
- return this._matchSelectorForElement(ast, node, opt);
- }
- if (
- this.#shadow &&
- node.nodeType === DOCUMENT_FRAGMENT_NODE &&
- ast.type === PS_CLASS_SELECTOR
- ) {
- return this._matchSelectorForShadowRoot(ast, node, opt);
- }
- return new Set();
- };
-
- /**
- * Matches leaves.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node.
- * @param {object} [opt] - Options.
- * @returns {boolean} The result.
- */
- _matchLeaves = (leaves, node, opt = {}) => {
- const results = this.#invalidate ? this.#invalidateResults : this.#results;
- let result = results.get(leaves);
- if (result && result.has(node)) {
- const { matched } = result.get(node);
- return matched;
- }
- let cacheable = true;
- if (node.nodeType === ELEMENT_NODE && KEYS_FORM.has(node.localName)) {
- cacheable = false;
- }
- let bool;
- const l = leaves.length;
- for (let i = 0; i < l; i++) {
- const leaf = leaves[i];
- switch (leaf.type) {
- case ATTR_SELECTOR:
- case ID_SELECTOR: {
- cacheable = false;
- break;
- }
- case PS_CLASS_SELECTOR: {
- if (KEYS_PS_UNCACHE.has(leaf.name)) {
- cacheable = false;
- }
- break;
- }
- default: {
- // No action needed for other types.
- }
- }
- bool = this._matchSelector(leaf, node, opt).has(node);
- if (!bool) {
- break;
- }
- }
- if (cacheable) {
- if (!result) {
- result = new WeakMap();
- }
- result.set(node, {
- matched: bool
- });
- results.set(leaves, result);
- }
- return bool;
- };
-
- /**
- * Traverses all descendant nodes and collects matches.
- * @private
- * @param {object} baseNode - The base Element node or Element.shadowRoot.
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _traverseAllDescendants = (baseNode, leaves, opt = {}) => {
- const walker = this._createTreeWalker(baseNode);
- traverseNode(baseNode, walker);
- let currentNode = walker.firstChild();
- const nodes = new Set();
- while (currentNode) {
- if (this._matchLeaves(leaves, currentNode, opt)) {
- nodes.add(currentNode);
- }
- currentNode = walker.nextNode();
- }
- return nodes;
- };
-
- /**
- * Finds descendant nodes.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} baseNode - The base Element node or Element.shadowRoot.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _findDescendantNodes = (leaves, baseNode, opt = {}) => {
- const [leaf, ...filterLeaves] = leaves;
- const { type: leafType } = leaf;
- switch (leafType) {
- case ID_SELECTOR: {
- const canUseGetElementById =
- !this.#shadow &&
- baseNode.nodeType === ELEMENT_NODE &&
- this.#root.nodeType !== ELEMENT_NODE;
- if (canUseGetElementById) {
- const leafName = unescapeSelector(leaf.name);
- const nodes = new Set();
- const foundNode = this.#root.getElementById(leafName);
- if (
- foundNode &&
- foundNode !== baseNode &&
- baseNode.contains(foundNode)
- ) {
- const isCompoundSelector = filterLeaves.length > 0;
- if (
- !isCompoundSelector ||
- this._matchLeaves(filterLeaves, foundNode, opt)
- ) {
- nodes.add(foundNode);
- }
- }
- return nodes;
- }
- // Fallback to default traversal if fast path is not applicable.
- return this._traverseAllDescendants(baseNode, leaves, opt);
- }
- case PS_ELEMENT_SELECTOR: {
- const leafName = unescapeSelector(leaf.name);
- matchPseudoElementSelector(leafName, leafType, opt);
- return new Set();
- }
- default: {
- return this._traverseAllDescendants(baseNode, leaves, opt);
- }
- }
- };
-
- /**
- * Matches the descendant combinator ' '.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchDescendantCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { parentNode } = node;
- const { dir } = opt;
- if (dir === DIR_NEXT) {
- return this._findDescendantNodes(leaves, node, opt);
- }
- // DIR_PREV
- const ancestors = [];
- let refNode = parentNode;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- ancestors.push(refNode);
- }
- refNode = refNode.parentNode;
- }
- if (ancestors.length) {
- // Reverse to maintain document order.
- return new Set(ancestors.reverse());
- }
- return new Set();
- };
-
- /**
- * Matches the child combinator '>'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchChildCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const { parentNode } = node;
- const matched = new Set();
- if (dir === DIR_NEXT) {
- let refNode = node.firstElementChild;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- refNode = refNode.nextElementSibling;
- }
- } else {
- // DIR_PREV
- if (parentNode && this._matchLeaves(leaves, parentNode, opt)) {
- matched.add(parentNode);
- }
- }
- return matched;
- };
-
- /**
- * Matches the adjacent sibling combinator '+'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchAdjacentSiblingCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const matched = new Set();
- const refNode =
- dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;
- if (refNode && this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- return matched;
- };
-
- /**
- * Matches the general sibling combinator '~'.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchGeneralSiblingCombinator = (twig, node, opt = {}) => {
- const { leaves } = twig;
- const { dir } = opt;
- const matched = new Set();
- let refNode =
- dir === DIR_NEXT ? node.nextElementSibling : node.previousElementSibling;
- while (refNode) {
- if (this._matchLeaves(leaves, refNode, opt)) {
- matched.add(refNode);
- }
- refNode =
- dir === DIR_NEXT
- ? refNode.nextElementSibling
- : refNode.previousElementSibling;
- }
- return matched;
- };
-
- /**
- * Matches a combinator.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- _matchCombinator = (twig, node, opt = {}) => {
- const {
- combo: { name: comboName }
- } = twig;
- switch (comboName) {
- case '+': {
- return this._matchAdjacentSiblingCombinator(twig, node, opt);
- }
- case '~': {
- return this._matchGeneralSiblingCombinator(twig, node, opt);
- }
- case '>': {
- return this._matchChildCombinator(twig, node, opt);
- }
- case ' ':
- default: {
- return this._matchDescendantCombinator(twig, node, opt);
- }
- }
- };
-
- /**
- * Traverses with a TreeWalker and collects nodes matching the leaves.
- * @private
- * @param {TreeWalker} walker - The TreeWalker instance to use.
- * @param {Array} leaves - The AST leaves to match against.
- * @param {object} options - Traversal options.
- * @param {Node} options.startNode - The node to start traversal from.
- * @param {string} options.targetType - The type of target ('all' or 'first').
- * @param {Node} [options.boundaryNode] - The node to stop traversal at.
- * @param {boolean} [options.force] - Force traversal to the next node.
- * @returns {Array.<Node>} An array of matched nodes.
- */
- _traverseAndCollectNodes = (walker, leaves, options) => {
- const { boundaryNode, force, startNode, targetType } = options;
- const collectedNodes = [];
- let currentNode = traverseNode(startNode, walker, !!force);
- if (!currentNode) {
- return [];
- }
- // Adjust starting node.
- if (currentNode.nodeType !== ELEMENT_NODE) {
- currentNode = walker.nextNode();
- } else if (currentNode === startNode && currentNode !== this.#root) {
- currentNode = walker.nextNode();
- }
- const matchOpt = {
- warn: this.#warn
- };
- while (currentNode) {
- // Stop when we reach the boundary.
- if (boundaryNode) {
- if (currentNode === boundaryNode) {
- break;
- } else if (
- targetType === TARGET_ALL &&
- !boundaryNode.contains(currentNode)
- ) {
- break;
- }
- }
- if (
- this._matchLeaves(leaves, currentNode, matchOpt) &&
- currentNode !== this.#node
- ) {
- collectedNodes.push(currentNode);
- // Stop after the first match if not collecting all.
- if (targetType !== TARGET_ALL) {
- break;
- }
- }
- currentNode = walker.nextNode();
- }
- return collectedNodes;
- };
-
- /**
- * Finds matched node(s) preceding this.#node.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node to start from.
- * @param {object} opt - Options.
- * @param {boolean} [opt.force] - If true, traverses only to the next node.
- * @param {string} [opt.targetType] - The target type.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _findPrecede = (leaves, node, opt = {}) => {
- const { force, targetType } = opt;
- if (!this.#rootWalker) {
- this.#rootWalker = this._createTreeWalker(this.#root);
- }
- return this._traverseAndCollectNodes(this.#rootWalker, leaves, {
- force,
- targetType,
- boundaryNode: this.#node,
- startNode: node
- });
- };
-
- /**
- * Finds matched node(s) in #nodeWalker.
- * @private
- * @param {Array.<object>} leaves - The AST leaves.
- * @param {object} node - The node to start from.
- * @param {object} opt - Options.
- * @param {boolean} [opt.precede] - If true, finds preceding nodes.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _findNodeWalker = (leaves, node, opt = {}) => {
- const { precede, ...traversalOpts } = opt;
- if (precede) {
- const precedeNodes = this._findPrecede(leaves, this.#root, opt);
- if (precedeNodes.length) {
- return precedeNodes;
- }
- }
- if (!this.#nodeWalker) {
- this.#nodeWalker = this._createTreeWalker(this.#node);
- }
- return this._traverseAndCollectNodes(this.#nodeWalker, leaves, {
- startNode: node,
- ...traversalOpts
- });
- };
-
- /**
- * Matches the node itself.
- * @private
- * @param {Array} leaves - The AST leaves.
- * @param {boolean} check - Indicates if running in internal check().
- * @returns {Array} An array containing [nodes, filtered, pseudoElement].
- */
- _matchSelf = (leaves, check = false) => {
- const options = { check, warn: this.#warn };
- const matched = this._matchLeaves(leaves, this.#node, options);
- const nodes = matched ? [this.#node] : [];
- return [nodes, matched, this.#pseudoElement];
- };
-
- /**
- * Finds lineal nodes (self and ancestors).
- * @private
- * @param {Array} leaves - The AST leaves.
- * @param {object} opt - Options.
- * @returns {Array} An array containing [nodes, filtered].
- */
- _findLineal = (leaves, opt) => {
- const { complex } = opt;
- const nodes = [];
- const options = { warn: this.#warn };
- const selfMatched = this._matchLeaves(leaves, this.#node, options);
- if (selfMatched) {
- nodes.push(this.#node);
- }
- if (!selfMatched || complex) {
- let currentNode = this.#node.parentNode;
- while (currentNode) {
- if (this._matchLeaves(leaves, currentNode, options)) {
- nodes.push(currentNode);
- }
- currentNode = currentNode.parentNode;
- }
- }
- const filtered = nodes.length > 0;
- return [nodes, filtered];
- };
-
- /**
- * Finds entry nodes for pseudo-element selectors.
- * @private
- * @param {object} leaf - The pseudo-element leaf from the AST.
- * @param {Array.<object>} filterLeaves - Leaves for compound selectors.
- * @param {string} targetType - The type of target to find.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForPseudoElement = (leaf, filterLeaves, targetType) => {
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF && this.#check) {
- const css = generateCSS(leaf);
- this.#pseudoElement.push(css);
- if (filterLeaves.length) {
- [nodes, filtered] = this._matchSelf(filterLeaves, this.#check);
- } else {
- nodes.push(this.#node);
- filtered = true;
- }
- } else {
- matchPseudoElementSelector(leaf.name, leaf.type, { warn: this.#warn });
- }
- return { nodes, filtered, pending: false };
- };
-
- /**
- * Finds entry nodes for ID selectors.
- * @private
- * @param {object} twig - The current twig from the AST branch.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForId = (twig, targetType, opt) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else if (
- targetType === TARGET_FIRST &&
- this.#root.nodeType !== ELEMENT_NODE
- ) {
- const node = this.#root.getElementById(leaf.name);
- if (node) {
- if (filterLeaves.length) {
- if (this._matchLeaves(filterLeaves, node, { warn: this.#warn })) {
- nodes.push(node);
- filtered = true;
- }
- } else {
- nodes.push(node);
- filtered = true;
- }
- }
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
-
- /**
- * Finds entry nodes for class selectors.
- * @private
- * @param {Array.<object>} leaves - The AST leaves for the selector.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForClass = (leaves, targetType, opt) => {
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
-
- /**
- * Finds entry nodes for type selectors.
- * @private
- * @param {Array.<object>} leaves - The AST leaves for the selector.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForType = (leaves, targetType, opt) => {
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- }
- return { nodes, filtered, pending: false };
- };
-
- /**
- * Finds entry nodes for other selector types (default case).
- * @private
- * @param {object} twig - The current twig from the AST branch.
- * @param {string} targetType - The type of target to find.
- * @param {object} opt - Additional options for finding nodes.
- * @returns {object} The result { nodes, filtered, pending }.
- */
- _findEntryNodesForOther = (twig, targetType, opt) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex, precede } = opt;
- let nodes = [];
- let filtered = false;
- let pending = false;
- if (targetType !== TARGET_LINEAL && /host(?:-context)?/.test(leaf.name)) {
- let shadowRoot = null;
- if (this.#shadow && this.#node.nodeType === DOCUMENT_FRAGMENT_NODE) {
- shadowRoot = this._matchShadowHostPseudoClass(leaf, this.#node);
- } else if (filterLeaves.length && this.#node.nodeType === ELEMENT_NODE) {
- shadowRoot = this._matchShadowHostPseudoClass(
- leaf,
- this.#node.shadowRoot
- );
- }
- if (shadowRoot) {
- let bool = true;
- const l = filterLeaves.length;
- for (let i = 0; i < l; i++) {
- const filterLeaf = filterLeaves[i];
- switch (filterLeaf.name) {
- case 'host':
- case 'host-context': {
- const matchedNode = this._matchShadowHostPseudoClass(
- filterLeaf,
- shadowRoot
- );
- bool = matchedNode === shadowRoot;
- break;
- }
- case 'has': {
- bool = this._matchPseudoClassSelector(
- filterLeaf,
- shadowRoot,
- {}
- ).has(shadowRoot);
- break;
- }
- default: {
- bool = false;
- }
- }
- if (!bool) {
- break;
- }
- }
- if (bool) {
- nodes.push(shadowRoot);
- filtered = true;
- }
- }
- } else if (targetType === TARGET_SELF) {
- [nodes, filtered] = this._matchSelf(leaves);
- } else if (targetType === TARGET_LINEAL) {
- [nodes, filtered] = this._findLineal(leaves, { complex });
- } else if (targetType === TARGET_FIRST) {
- nodes = this._findNodeWalker(leaves, this.#node, { precede, targetType });
- filtered = nodes.length > 0;
- } else {
- pending = true;
- }
- return { nodes, filtered, pending };
- };
-
- /**
- * Finds entry nodes.
- * @private
- * @param {object} twig - The twig object.
- * @param {string} targetType - The target type.
- * @param {object} [opt] - Options.
- * @param {boolean} [opt.complex] - If true, the selector is complex.
- * @param {string} [opt.dir] - The find direction.
- * @returns {object} An object with nodes and their state.
- */
- _findEntryNodes = (twig, targetType, opt = {}) => {
- const { leaves } = twig;
- const [leaf, ...filterLeaves] = leaves;
- const { complex = false, dir = DIR_PREV } = opt;
- const precede =
- dir === DIR_NEXT &&
- this.#node.nodeType === ELEMENT_NODE &&
- this.#node !== this.#root;
- let result;
- switch (leaf.type) {
- case PS_ELEMENT_SELECTOR: {
- result = this._findEntryNodesForPseudoElement(
- leaf,
- filterLeaves,
- targetType
- );
- break;
- }
- case ID_SELECTOR: {
- result = this._findEntryNodesForId(twig, targetType, {
- complex,
- precede
- });
- break;
- }
- case CLASS_SELECTOR: {
- result = this._findEntryNodesForClass(leaves, targetType, {
- complex,
- precede
- });
- break;
- }
- case TYPE_SELECTOR: {
- result = this._findEntryNodesForType(leaves, targetType, {
- complex,
- precede
- });
- break;
- }
- default: {
- result = this._findEntryNodesForOther(twig, targetType, {
- complex,
- precede
- });
- }
- }
- return {
- compound: filterLeaves.length > 0,
- filtered: result.filtered,
- nodes: result.nodes,
- pending: result.pending
- };
- };
-
- /**
- * Determines the direction and starting twig for a selector branch.
- * @private
- * @param {Array.<object>} branch - The AST branch.
- * @param {string} targetType - The type of target to find.
- * @returns {object} An object with the direction and starting twig.
- */
- _determineTraversalStrategy = (branch, targetType) => {
- const branchLen = branch.length;
- const firstTwig = branch[0];
- const lastTwig = branch[branchLen - 1];
- if (branchLen === 1) {
- return { dir: DIR_PREV, twig: firstTwig };
- }
- // Complex selector (branchLen > 1).
- const {
- leaves: [{ name: firstName, type: firstType }]
- } = firstTwig;
- const {
- leaves: [{ name: lastName, type: lastType }]
- } = lastTwig;
- const { combo: firstCombo } = firstTwig;
- if (
- this.#selector.includes(':scope') ||
- lastType === PS_ELEMENT_SELECTOR ||
- lastType === ID_SELECTOR
- ) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- if (firstType === ID_SELECTOR) {
- return { dir: DIR_NEXT, twig: firstTwig };
- }
- if (firstName === '*' && firstType === TYPE_SELECTOR) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- if (lastName === '*' && lastType === TYPE_SELECTOR) {
- return { dir: DIR_NEXT, twig: firstTwig };
- }
- if (branchLen === 2) {
- if (targetType === TARGET_FIRST) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- const { name: comboName } = firstCombo;
- if (comboName === '+' || comboName === '~') {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- } else if (branchLen > 2 && this.#scoped && targetType === TARGET_FIRST) {
- if (lastType === TYPE_SELECTOR) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- let isChildOrDescendant = false;
- for (const { combo } of branch) {
- if (combo) {
- const { name: comboName } = combo;
- isChildOrDescendant = comboName === '>' || comboName === ' ';
- if (!isChildOrDescendant) {
- break;
- }
- }
- }
- if (isChildOrDescendant) {
- return { dir: DIR_PREV, twig: lastTwig };
- }
- }
- // Default strategy for complex selectors.
- return { dir: DIR_NEXT, twig: firstTwig };
- };
-
- /**
- * Processes pending items not resolved with a direct strategy.
- * @private
- * @param {Set.<Map>} pendingItems - The set of pending items.
- */
- _processPendingItems = pendingItems => {
- if (!pendingItems.size) {
- return;
- }
- if (!this.#rootWalker) {
- this.#rootWalker = this._createTreeWalker(this.#root);
- }
- const walker = this.#rootWalker;
- let node = this.#root;
- if (this.#scoped) {
- node = this.#node;
- }
- let nextNode = traverseNode(node, walker);
- while (nextNode) {
- const isWithinScope =
- this.#node.nodeType !== ELEMENT_NODE ||
- nextNode === this.#node ||
- this.#node.contains(nextNode);
- if (isWithinScope) {
- for (const pendingItem of pendingItems) {
- const { leaves } = pendingItem.get('twig');
- if (this._matchLeaves(leaves, nextNode, { warn: this.#warn })) {
- const index = pendingItem.get('index');
- this.#ast[index].filtered = true;
- this.#ast[index].find = true;
- this.#nodes[index].push(nextNode);
- }
- }
- } else if (this.#scoped) {
- break;
- }
- nextNode = walker.nextNode();
- }
- };
-
- /**
- * Collects nodes.
- * @private
- * @param {string} targetType - The target type.
- * @returns {Array.<Array.<object>>} An array containing the AST and nodes.
- */
- _collectNodes = targetType => {
- const ast = this.#ast.values();
- if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {
- const pendingItems = new Set();
- let i = 0;
- for (const { branch } of ast) {
- const complex = branch.length > 1;
- const { dir, twig } = this._determineTraversalStrategy(
- branch,
- targetType
- );
- const { compound, filtered, nodes, pending } = this._findEntryNodes(
- twig,
- targetType,
- { complex, dir }
- );
- if (nodes.length) {
- this.#ast[i].find = true;
- this.#nodes[i] = nodes;
- } else if (pending) {
- pendingItems.add(
- new Map([
- ['index', i],
- ['twig', twig]
- ])
- );
- }
- this.#ast[i].dir = dir;
- this.#ast[i].filtered = filtered || !compound;
- i++;
- }
- this._processPendingItems(pendingItems);
- } else {
- let i = 0;
- for (const { branch } of ast) {
- const twig = branch[branch.length - 1];
- const complex = branch.length > 1;
- const dir = DIR_PREV;
- const { compound, filtered, nodes } = this._findEntryNodes(
- twig,
- targetType,
- { complex, dir }
- );
- if (nodes.length) {
- this.#ast[i].find = true;
- this.#nodes[i] = nodes;
- }
- this.#ast[i].dir = dir;
- this.#ast[i].filtered = filtered || !compound;
- i++;
- }
- }
- return [this.#ast, this.#nodes];
- };
-
- /**
- * Gets combined nodes.
- * @private
- * @param {object} twig - The twig object.
- * @param {object} nodes - A collection of nodes.
- * @param {string} dir - The direction.
- * @returns {Array.<object>} A collection of matched nodes.
- */
- _getCombinedNodes = (twig, nodes, dir) => {
- const arr = [];
- const options = {
- dir,
- warn: this.#warn
- };
- for (const node of nodes) {
- const matched = this._matchCombinator(twig, node, options);
- if (matched.size) {
- arr.push(...matched);
- }
- }
- return arr;
- };
-
- /**
- * Matches a node in the 'next' direction.
- * @private
- * @param {Array} branch - The branch.
- * @param {Set.<object>} nodes - A collection of Element nodes.
- * @param {object} opt - Options.
- * @param {object} opt.combo - The combo object.
- * @param {number} opt.index - The index.
- * @returns {?object} The matched node.
- */
- _matchNodeNext = (branch, nodes, opt) => {
- const { combo, index } = opt;
- const { combo: nextCombo, leaves } = branch[index];
- const twig = {
- combo,
- leaves
- };
- const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_NEXT));
- if (nextNodes.size) {
- if (index === branch.length - 1) {
- const [nextNode] = sortNodes(nextNodes);
- return nextNode;
- }
- return this._matchNodeNext(branch, nextNodes, {
- combo: nextCombo,
- index: index + 1
- });
- }
- return null;
- };
-
- /**
- * Matches a node in the 'previous' direction.
- * @private
- * @param {Array} branch - The branch.
- * @param {object} node - The Element node.
- * @param {object} opt - Options.
- * @param {number} opt.index - The index.
- * @returns {?object} The node.
- */
- _matchNodePrev = (branch, node, opt) => {
- const { index } = opt;
- const twig = branch[index];
- const nodes = new Set([node]);
- const nextNodes = new Set(this._getCombinedNodes(twig, nodes, DIR_PREV));
- if (nextNodes.size) {
- if (index === 0) {
- return node;
- }
- let matched;
- for (const nextNode of nextNodes) {
- matched = this._matchNodePrev(branch, nextNode, {
- index: index - 1
- });
- if (matched) {
- break;
- }
- }
- if (matched) {
- return node;
- }
- }
- return null;
- };
-
- /**
- * Processes a complex selector branch to find all matching nodes.
- * @private
- * @param {Array} branch - The selector branch from the AST.
- * @param {Array} entryNodes - The initial set of nodes to start from.
- * @param {string} dir - The direction of traversal ('next' or 'prev').
- * @returns {Set.<object>} A set of all matched nodes.
- */
- _processComplexBranchAll = (branch, entryNodes, dir) => {
- const matchedNodes = new Set();
- const branchLen = branch.length;
- const lastIndex = branchLen - 1;
-
- if (dir === DIR_NEXT) {
- const { combo: firstCombo } = branch[0];
- for (const node of entryNodes) {
- let combo = firstCombo;
- let nextNodes = new Set([node]);
- for (let j = 1; j < branchLen; j++) {
- const { combo: nextCombo, leaves } = branch[j];
- const twig = { combo, leaves };
- const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);
- if (nodesArr.length) {
- if (j === lastIndex) {
- for (const nextNode of nodesArr) {
- matchedNodes.add(nextNode);
- }
- }
- combo = nextCombo;
- nextNodes = new Set(nodesArr);
- } else {
- // No further matches down this path.
- nextNodes.clear();
- break;
- }
- }
- }
- // DIR_PREV
- } else {
- for (const node of entryNodes) {
- let nextNodes = new Set([node]);
- for (let j = lastIndex - 1; j >= 0; j--) {
- const twig = branch[j];
- const nodesArr = this._getCombinedNodes(twig, nextNodes, dir);
- if (nodesArr.length) {
- // The entry node is the final match
- if (j === 0) {
- matchedNodes.add(node);
- }
- nextNodes = new Set(nodesArr);
- } else {
- // No further matches down this path.
- nextNodes.clear();
- break;
- }
- }
- }
- }
- return matchedNodes;
- };
-
- /**
- * Processes a complex selector branch to find the first matching node.
- * @private
- * @param {Array} branch - The selector branch from the AST.
- * @param {Array} entryNodes - The initial set of nodes to start from.
- * @param {string} dir - The direction of traversal ('next' or 'prev').
- * @param {string} targetType - The type of search (e.g., 'first').
- * @returns {?object} The first matched node, or null.
- */
- _processComplexBranchFirst = (branch, entryNodes, dir, targetType) => {
- const branchLen = branch.length;
- const lastIndex = branchLen - 1;
- // DIR_NEXT logic for finding the first match.
- if (dir === DIR_NEXT) {
- const { combo: entryCombo } = branch[0];
- for (const node of entryNodes) {
- const matchedNode = this._matchNodeNext(branch, new Set([node]), {
- combo: entryCombo,
- index: 1
- });
- if (matchedNode) {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (
- matchedNode !== this.#node &&
- this.#node.contains(matchedNode)
- ) {
- return matchedNode;
- }
- } else {
- return matchedNode;
- }
- }
- }
- // Fallback logic if no direct match found.
- const { leaves: entryLeaves } = branch[0];
- const [entryNode] = entryNodes;
- if (this.#node.contains(entryNode)) {
- let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {
- targetType
- });
- while (refNode) {
- const matchedNode = this._matchNodeNext(branch, new Set([refNode]), {
- combo: entryCombo,
- index: 1
- });
- if (matchedNode) {
- if (this.#node.nodeType === ELEMENT_NODE) {
- if (
- matchedNode !== this.#node &&
- this.#node.contains(matchedNode)
- ) {
- return matchedNode;
- }
- } else {
- return matchedNode;
- }
- }
- [refNode] = this._findNodeWalker(entryLeaves, refNode, {
- targetType,
- force: true
- });
- }
- }
- // DIR_PREV logic for finding the first match.
- } else {
- for (const node of entryNodes) {
- const matchedNode = this._matchNodePrev(branch, node, {
- index: lastIndex - 1
- });
- if (matchedNode) {
- return matchedNode;
- }
- }
- // Fallback for TARGET_FIRST.
- if (targetType === TARGET_FIRST) {
- const { leaves: entryLeaves } = branch[lastIndex];
- const [entryNode] = entryNodes;
- let [refNode] = this._findNodeWalker(entryLeaves, entryNode, {
- targetType
- });
- while (refNode) {
- const matchedNode = this._matchNodePrev(branch, refNode, {
- index: lastIndex - 1
- });
- if (matchedNode) {
- return refNode;
- }
- [refNode] = this._findNodeWalker(entryLeaves, refNode, {
- targetType,
- force: true
- });
- }
- }
- }
- return null;
- };
-
- /**
- * Finds matched nodes.
- * @param {string} targetType - The target type.
- * @returns {Set.<object>} A collection of matched nodes.
- */
- find = targetType => {
- const [[...branches], collectedNodes] = this._collectNodes(targetType);
- const l = branches.length;
- let sort =
- l > 1 && targetType === TARGET_ALL && this.#selector.includes(':scope');
- let nodes = new Set();
- for (let i = 0; i < l; i++) {
- const { branch, dir, find } = branches[i];
- if (!branch.length || !find) {
- continue;
- }
- const entryNodes = collectedNodes[i];
- const lastIndex = branch.length - 1;
- // Handle simple selectors (no combinators).
- if (lastIndex === 0) {
- if (
- (targetType === TARGET_ALL || targetType === TARGET_FIRST) &&
- this.#node.nodeType === ELEMENT_NODE
- ) {
- for (const node of entryNodes) {
- if (node !== this.#node && this.#node.contains(node)) {
- nodes.add(node);
- if (targetType === TARGET_FIRST) {
- break;
- }
- }
- }
- } else if (targetType === TARGET_ALL) {
- if (nodes.size) {
- for (const node of entryNodes) {
- nodes.add(node);
- }
- sort = true;
- } else {
- nodes = new Set(entryNodes);
- }
- } else {
- if (entryNodes.length) {
- nodes.add(entryNodes[0]);
- }
- }
- // Handle complex selectors.
- } else {
- if (targetType === TARGET_ALL) {
- const newNodes = this._processComplexBranchAll(
- branch,
- entryNodes,
- dir
- );
- if (nodes.size) {
- for (const newNode of newNodes) {
- nodes.add(newNode);
- }
- sort = true;
- } else {
- nodes = newNodes;
- }
- } else {
- const matchedNode = this._processComplexBranchFirst(
- branch,
- entryNodes,
- dir,
- targetType
- );
- if (matchedNode) {
- nodes.add(matchedNode);
- }
- }
- }
- }
- if (this.#check) {
- const match = !!nodes.size;
- let pseudoElement;
- if (this.#pseudoElement.length) {
- pseudoElement = this.#pseudoElement.join('');
- } else {
- pseudoElement = null;
- }
- return { match, pseudoElement };
- }
- if (targetType === TARGET_FIRST || targetType === TARGET_ALL) {
- nodes.delete(this.#node);
- }
- if ((sort || targetType === TARGET_FIRST) && nodes.size > 1) {
- return new Set(sortNodes(nodes));
- }
- return nodes;
- };
-}
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/matcher.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/matcher.js
deleted file mode 100644
index 6395560..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/matcher.js
+++ /dev/null
@@ -1,587 +0,0 @@
-/**
- * matcher.js
- */
-
-/* import */
-import { generateCSS, parseAstName, unescapeSelector } from './parser.js';
-import {
- generateException,
- getDirectionality,
- getLanguageAttribute,
- getType,
- isContentEditable,
- isCustomElement,
- isNamespaceDeclared
-} from './utility.js';
-
-/* constants */
-import {
- ALPHA_NUM,
- FORM_PARTS,
- IDENT,
- INPUT_EDIT,
- LANG_PART,
- NOT_SUPPORTED_ERR,
- PS_ELEMENT_SELECTOR,
- STRING,
- SYNTAX_ERR
-} from './constant.js';
-const KEYS_FORM_PS_DISABLED = new Set([
- ...FORM_PARTS,
- 'fieldset',
- 'optgroup',
- 'option'
-]);
-const KEYS_INPUT_EDIT = new Set(INPUT_EDIT);
-const REG_LANG_VALID = new RegExp(`^(?:\\*-)?${ALPHA_NUM}${LANG_PART}$`, 'i');
-const REG_TAG_NAME = /[A-Z][\\w-]*/i;
-
-/**
- * Validates a pseudo-element selector.
- * @param {string} astName - The name of the pseudo-element from the AST.
- * @param {string} astType - The type of the selector from the AST.
- * @param {object} [opt] - Optional parameters.
- * @param {boolean} [opt.forgive] - If true, ignores unknown pseudo-elements.
- * @param {boolean} [opt.warn] - If true, throws an error for unsupported ones.
- * @throws {DOMException} If the selector is invalid or unsupported.
- * @returns {void}
- */
-export const matchPseudoElementSelector = (astName, astType, opt = {}) => {
- const { forgive, globalObject, warn } = opt;
- if (astType !== PS_ELEMENT_SELECTOR) {
- // Ensure the AST node is a pseudo-element selector.
- throw new TypeError(`Unexpected ast type ${getType(astType)}`);
- }
- switch (astName) {
- case 'after':
- case 'backdrop':
- case 'before':
- case 'cue':
- case 'cue-region':
- case 'first-letter':
- case 'first-line':
- case 'file-selector-button':
- case 'marker':
- case 'placeholder':
- case 'selection':
- case 'target-text': {
- // Warn if the pseudo-element is known but unsupported.
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- break;
- }
- case 'part':
- case 'slotted': {
- // Warn if the functional pseudo-element is known but unsupported.
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}()`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- break;
- }
- default: {
- // Handle vendor-prefixed or unknown pseudo-elements.
- if (astName.startsWith('-webkit-')) {
- if (warn) {
- throw generateException(
- `Unsupported pseudo-element ::${astName}`,
- NOT_SUPPORTED_ERR,
- globalObject
- );
- }
- // Throw an error for unknown pseudo-elements if not forgiven.
- } else if (!forgive) {
- throw generateException(
- `Unknown pseudo-element ::${astName}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- }
- }
-};
-
-/**
- * Matches the :dir() pseudo-class against an element's directionality.
- * @param {object} ast - The AST object for the pseudo-class.
- * @param {object} node - The element node to match against.
- * @throws {TypeError} If the AST does not contain a valid direction value.
- * @returns {boolean} - True if the directionality matches, otherwise false.
- */
-export const matchDirectionPseudoClass = (ast, node) => {
- const { name } = ast;
- // The :dir() pseudo-class requires a direction argument (e.g., "ltr").
- if (!name) {
- const type = name === '' ? '(empty String)' : getType(name);
- throw new TypeError(`Unexpected ast type ${type}`);
- }
- // Get the computed directionality of the element.
- const dir = getDirectionality(node);
- // Compare the expected direction with the element's actual direction.
- return name === dir;
-};
-
-/**
- * Matches the :lang() pseudo-class against an element's language.
- * @see https://datatracker.ietf.org/doc/html/rfc4647#section-3.3.1
- * @param {object} ast - The AST object for the pseudo-class.
- * @param {object} node - The element node to match against.
- * @returns {boolean} - True if the language matches, otherwise false.
- */
-export const matchLanguagePseudoClass = (ast, node) => {
- const { name, type, value } = ast;
- let langPattern;
- // Determine the language pattern from the AST.
- if (type === STRING && value) {
- langPattern = value;
- } else if (type === IDENT && name) {
- langPattern = unescapeSelector(name);
- }
- // If no valid language pattern is provided, it cannot match.
- if (typeof langPattern !== 'string') {
- return false;
- }
- // Get the effective language attribute for the current node.
- const elementLang = getLanguageAttribute(node);
- // If the element has no language, it cannot match a specific pattern.
- if (elementLang === null) {
- return false;
- }
- // Handle the universal selector '*' for :lang.
- if (langPattern === '*') {
- // It matches any language unless attribute is not empty.
- return elementLang !== '';
- }
- // Validate the provided language pattern structure.
- if (!REG_LANG_VALID.test(langPattern)) {
- return false;
- }
- // Build a regex for extended language range matching.
- let matcherRegex;
- if (langPattern.indexOf('-') > -1) {
- // Handle complex patterns with wildcards and sub-tags (e.g., '*-US').
- const [langMain, langSub, ...langRest] = langPattern.split('-');
- const extendedMain =
- langMain === '*' ? `${ALPHA_NUM}${LANG_PART}` : `${langMain}${LANG_PART}`;
- const extendedSub = `-${langSub}${LANG_PART}`;
- let extendedRest = '';
- // Use a standard for loop for performance as per the rules.
- for (let i = 0; i < langRest.length; i++) {
- extendedRest += `-${langRest[i]}${LANG_PART}`;
- }
- matcherRegex = new RegExp(
- `^${extendedMain}${extendedSub}${extendedRest}$`,
- 'i'
- );
- } else {
- // Handle simple language patterns (e.g., 'en').
- matcherRegex = new RegExp(`^${langPattern}${LANG_PART}$`, 'i');
- }
- // Test the element's language against the constructed regex.
- return matcherRegex.test(elementLang);
-};
-
-/**
- * Matches the :disabled and :enabled pseudo-classes.
- * @param {string} astName - pseudo-class name
- * @param {object} node - Element node
- * @returns {boolean} - True if matched
- */
-export const matchDisabledPseudoClass = (astName, node) => {
- const { localName, parentNode } = node;
- if (
- !KEYS_FORM_PS_DISABLED.has(localName) &&
- !isCustomElement(node, { formAssociated: true })
- ) {
- return false;
- }
- let isDisabled = false;
- if (node.disabled || node.hasAttribute('disabled')) {
- isDisabled = true;
- } else if (localName === 'option') {
- if (
- parentNode &&
- parentNode.localName === 'optgroup' &&
- (parentNode.disabled || parentNode.hasAttribute('disabled'))
- ) {
- isDisabled = true;
- }
- } else if (localName !== 'optgroup') {
- let current = parentNode;
- while (current) {
- if (
- current.localName === 'fieldset' &&
- (current.disabled || current.hasAttribute('disabled'))
- ) {
- // The first <legend> in a disabled <fieldset> is not disabled.
- let legend;
- let element = current.firstElementChild;
- while (element) {
- if (element.localName === 'legend') {
- legend = element;
- break;
- }
- element = element.nextElementSibling;
- }
- if (!legend || !legend.contains(node)) {
- isDisabled = true;
- }
- // Found the containing fieldset, stop searching up.
- break;
- }
- current = current.parentNode;
- }
- }
- if (astName === 'disabled') {
- return isDisabled;
- }
- return !isDisabled;
-};
-
-/**
- * Match the :read-only and :read-write pseudo-classes
- * @param {string} astName - pseudo-class name
- * @param {object} node - Element node
- * @returns {boolean} - True if matched
- */
-export const matchReadOnlyPseudoClass = (astName, node) => {
- const { localName } = node;
- let isReadOnly = false;
- switch (localName) {
- case 'textarea':
- case 'input': {
- const isEditableInput = !node.type || KEYS_INPUT_EDIT.has(node.type);
- if (localName === 'textarea' || isEditableInput) {
- isReadOnly =
- node.readOnly ||
- node.hasAttribute('readonly') ||
- node.disabled ||
- node.hasAttribute('disabled');
- } else {
- // Non-editable input types are always read-only
- isReadOnly = true;
- }
- break;
- }
- default: {
- isReadOnly = !isContentEditable(node);
- }
- }
- if (astName === 'read-only') {
- return isReadOnly;
- }
- return !isReadOnly;
-};
-
-/**
- * Matches an attribute selector against an element.
- * This function handles various attribute matchers like '=', '~=', '^=', etc.,
- * and considers namespaces and case sensitivity based on document type.
- * @param {object} ast - The AST for the attribute selector.
- * @param {object} node - The element node to match against.
- * @param {object} [opt] - Optional parameters.
- * @param {boolean} [opt.check] - True if running in an internal check.
- * @param {boolean} [opt.forgive] - True to forgive certain syntax errors.
- * @returns {boolean} - True if the attribute selector matches, otherwise false.
- */
-export const matchAttributeSelector = (ast, node, opt = {}) => {
- const {
- flags: astFlags,
- matcher: astMatcher,
- name: astName,
- value: astValue
- } = ast;
- const { check, forgive, globalObject } = opt;
- // Validate selector flags ('i' or 's').
- if (typeof astFlags === 'string' && !/^[is]$/i.test(astFlags) && !forgive) {
- const css = generateCSS(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- const { attributes } = node;
- // An element with no attributes cannot match.
- if (!attributes || !attributes.length) {
- return false;
- }
- // Determine case sensitivity based on document type and flags.
- const contentType = node.ownerDocument.contentType;
- let caseInsensitive;
- if (contentType === 'text/html') {
- if (typeof astFlags === 'string' && /^s$/i.test(astFlags)) {
- caseInsensitive = false;
- } else {
- caseInsensitive = true;
- }
- } else if (typeof astFlags === 'string' && /^i$/i.test(astFlags)) {
- caseInsensitive = true;
- } else {
- caseInsensitive = false;
- }
- // Prepare the attribute name from the selector for matching.
- let astAttrName = unescapeSelector(astName.name);
- if (caseInsensitive) {
- astAttrName = astAttrName.toLowerCase();
- }
- // A set to store the values of attributes whose names match.
- const attrValues = new Set();
- // Handle namespaced attribute names (e.g., [*|attr], [ns|attr]).
- if (astAttrName.indexOf('|') > -1) {
- const { prefix: astPrefix, localName: astLocalName } =
- parseAstName(astAttrName);
- for (const item of attributes) {
- let { name: itemName, value: itemValue } = item;
- if (caseInsensitive) {
- itemName = itemName.toLowerCase();
- itemValue = itemValue.toLowerCase();
- }
- switch (astPrefix) {
- case '': {
- if (astLocalName === itemName) {
- attrValues.add(itemValue);
- }
- break;
- }
- case '*': {
- if (itemName.indexOf(':') > -1) {
- const [, ...restItemName] = itemName.split(':');
- const itemLocalName = restItemName.join(':').replace(/^:/, '');
- if (itemLocalName === astLocalName) {
- attrValues.add(itemValue);
- }
- } else if (astLocalName === itemName) {
- attrValues.add(itemValue);
- }
- break;
- }
- default: {
- if (!check) {
- if (forgive) {
- return false;
- }
- const css = generateCSS(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- if (itemName.indexOf(':') > -1) {
- const [itemPrefix, ...restItemName] = itemName.split(':');
- const itemLocalName = restItemName.join(':').replace(/^:/, '');
- // Ignore the 'xml:lang' attribute.
- if (itemPrefix === 'xml' && itemLocalName === 'lang') {
- continue;
- } else if (
- astPrefix === itemPrefix &&
- astLocalName === itemLocalName
- ) {
- const namespaceDeclared = isNamespaceDeclared(astPrefix, node);
- if (namespaceDeclared) {
- attrValues.add(itemValue);
- }
- }
- }
- }
- }
- }
- // Handle non-namespaced attribute names.
- } else {
- for (let { name: itemName, value: itemValue } of attributes) {
- if (caseInsensitive) {
- itemName = itemName.toLowerCase();
- itemValue = itemValue.toLowerCase();
- }
- if (itemName.indexOf(':') > -1) {
- const [itemPrefix, ...restItemName] = itemName.split(':');
- const itemLocalName = restItemName.join(':').replace(/^:/, '');
- // The attribute is starting with ':'.
- if (!itemPrefix && astAttrName === `:${itemLocalName}`) {
- attrValues.add(itemValue);
- // Ignore the 'xml:lang' attribute.
- } else if (itemPrefix === 'xml' && itemLocalName === 'lang') {
- continue;
- } else if (astAttrName === itemLocalName) {
- attrValues.add(itemValue);
- }
- } else if (astAttrName === itemName) {
- attrValues.add(itemValue);
- }
- }
- }
- if (!attrValues.size) {
- return false;
- }
- // Prepare the value from the selector's RHS for comparison.
- const { name: astIdentValue, value: astStringValue } = astValue ?? {};
- let attrValue;
- if (astIdentValue) {
- if (caseInsensitive) {
- attrValue = astIdentValue.toLowerCase();
- } else {
- attrValue = astIdentValue;
- }
- } else if (astStringValue) {
- if (caseInsensitive) {
- attrValue = astStringValue.toLowerCase();
- } else {
- attrValue = astStringValue;
- }
- } else if (astStringValue === '') {
- attrValue = astStringValue;
- }
- // Perform the final match based on the specified matcher.
- switch (astMatcher) {
- case '=': {
- return typeof attrValue === 'string' && attrValues.has(attrValue);
- }
- case '~=': {
- if (attrValue && typeof attrValue === 'string') {
- for (const value of attrValues) {
- const item = new Set(value.split(/\s+/));
- if (item.has(attrValue)) {
- return true;
- }
- }
- }
- return false;
- }
- case '|=': {
- if (attrValue && typeof attrValue === 'string') {
- for (const value of attrValues) {
- if (value === attrValue || value.startsWith(`${attrValue}-`)) {
- return true;
- }
- }
- }
- return false;
- }
- case '^=': {
- if (attrValue && typeof attrValue === 'string') {
- for (const value of attrValues) {
- if (value.startsWith(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case '$=': {
- if (attrValue && typeof attrValue === 'string') {
- for (const value of attrValues) {
- if (value.endsWith(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case '*=': {
- if (attrValue && typeof attrValue === 'string') {
- for (const value of attrValues) {
- if (value.includes(`${attrValue}`)) {
- return true;
- }
- }
- }
- return false;
- }
- case null:
- default: {
- // This case handles attribute existence checks (e.g., '[disabled]').
- return true;
- }
- }
-};
-
-/**
- * match type selector
- * @param {object} ast - AST
- * @param {object} node - Element node
- * @param {object} [opt] - options
- * @param {boolean} [opt.check] - running in internal check()
- * @param {boolean} [opt.forgive] - forgive undeclared namespace
- * @returns {boolean} - result
- */
-export const matchTypeSelector = (ast, node, opt = {}) => {
- const astName = unescapeSelector(ast.name);
- const { localName, namespaceURI, prefix } = node;
- const { check, forgive, globalObject } = opt;
- let { prefix: astPrefix, localName: astLocalName } = parseAstName(
- astName,
- node
- );
- if (
- node.ownerDocument.contentType === 'text/html' &&
- (!namespaceURI || namespaceURI === 'http://www.w3.org/1999/xhtml') &&
- REG_TAG_NAME.test(localName)
- ) {
- astPrefix = astPrefix.toLowerCase();
- astLocalName = astLocalName.toLowerCase();
- }
- let nodePrefix;
- let nodeLocalName;
- // just in case that the namespaced content is parsed as text/html
- if (localName.indexOf(':') > -1) {
- [nodePrefix, nodeLocalName] = localName.split(':');
- } else {
- nodePrefix = prefix || '';
- nodeLocalName = localName;
- }
- switch (astPrefix) {
- case '': {
- if (
- !nodePrefix &&
- !namespaceURI &&
- (astLocalName === '*' || astLocalName === nodeLocalName)
- ) {
- return true;
- }
- return false;
- }
- case '*': {
- if (astLocalName === '*' || astLocalName === nodeLocalName) {
- return true;
- }
- return false;
- }
- default: {
- if (!check) {
- if (forgive) {
- return false;
- }
- const css = generateCSS(ast);
- throw generateException(
- `Invalid selector ${css}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- const astNS = node.lookupNamespaceURI(astPrefix);
- const nodeNS = node.lookupNamespaceURI(nodePrefix);
- if (astNS === nodeNS && astPrefix === nodePrefix) {
- if (astLocalName === '*' || astLocalName === nodeLocalName) {
- return true;
- }
- return false;
- } else if (!forgive && !astNS) {
- throw generateException(
- `Undeclared namespace ${astPrefix}`,
- SYNTAX_ERR,
- globalObject
- );
- }
- return false;
- }
- }
-};
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/parser.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/parser.js
deleted file mode 100644
index bf06d9f..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/parser.js
+++ /dev/null
@@ -1,431 +0,0 @@
-/**
- * parser.js
- */
-
-/* import */
-import * as cssTree from 'css-tree';
-import { getType } from './utility.js';
-
-/* constants */
-import {
- ATTR_SELECTOR,
- BIT_01,
- BIT_02,
- BIT_04,
- BIT_08,
- BIT_16,
- BIT_32,
- BIT_FFFF,
- CLASS_SELECTOR,
- DUO,
- HEX,
- ID_SELECTOR,
- KEYS_LOGICAL,
- NTH,
- PS_CLASS_SELECTOR,
- PS_ELEMENT_SELECTOR,
- SELECTOR,
- SYNTAX_ERR,
- TYPE_SELECTOR
-} from './constant.js';
-const AST_SORT_ORDER = new Map([
- [PS_ELEMENT_SELECTOR, BIT_01],
- [ID_SELECTOR, BIT_02],
- [CLASS_SELECTOR, BIT_04],
- [TYPE_SELECTOR, BIT_08],
- [ATTR_SELECTOR, BIT_16],
- [PS_CLASS_SELECTOR, BIT_32]
-]);
-const KEYS_PS_CLASS_STATE = new Set([
- 'checked',
- 'closed',
- 'disabled',
- 'empty',
- 'enabled',
- 'in-range',
- 'indeterminate',
- 'invalid',
- 'open',
- 'out-of-range',
- 'placeholder-shown',
- 'read-only',
- 'read-write',
- 'valid'
-]);
-const KEYS_SHADOW_HOST = new Set(['host', 'host-context']);
-const REG_EMPTY_PS_FUNC =
- /(?<=:(?:dir|has|host(?:-context)?|is|lang|not|nth-(?:last-)?(?:child|of-type)|where))\(\s+\)/g;
-const REG_SHADOW_PS_ELEMENT = /^part|slotted$/;
-const U_FFFD = '\uFFFD';
-
-/**
- * Unescapes a CSS selector string.
- * @param {string} selector - The CSS selector to unescape.
- * @returns {string} The unescaped selector string.
- */
-export const unescapeSelector = (selector = '') => {
- if (typeof selector === 'string' && selector.indexOf('\\', 0) >= 0) {
- const arr = selector.split('\\');
- const selectorItems = [arr[0]];
- const l = arr.length;
- for (let i = 1; i < l; i++) {
- const item = arr[i];
- if (item === '' && i === l - 1) {
- selectorItems.push(U_FFFD);
- } else {
- const hexExists = /^([\da-f]{1,6}\s?)/i.exec(item);
- if (hexExists) {
- const [, hex] = hexExists;
- let str;
- try {
- const low = parseInt('D800', HEX);
- const high = parseInt('DFFF', HEX);
- const deci = parseInt(hex, HEX);
- if (deci === 0 || (deci >= low && deci <= high)) {
- str = U_FFFD;
- } else {
- str = String.fromCodePoint(deci);
- }
- } catch (e) {
- str = U_FFFD;
- }
- let postStr = '';
- if (item.length > hex.length) {
- postStr = item.substring(hex.length);
- }
- selectorItems.push(`${str}${postStr}`);
- // whitespace
- } else if (/^[\n\r\f]/.test(item)) {
- selectorItems.push(`\\${item}`);
- } else {
- selectorItems.push(item);
- }
- }
- }
- return selectorItems.join('');
- }
- return selector;
-};
-
-/**
- * Preprocesses a selector string according to the specification.
- * @see https://drafts.csswg.org/css-syntax-3/#input-preprocessing
- * @param {string} value - The value to preprocess.
- * @returns {string} The preprocessed selector string.
- */
-export const preprocess = value => {
- // Non-string values will be converted to string.
- if (typeof value !== 'string') {
- if (value === undefined || value === null) {
- return getType(value).toLowerCase();
- } else if (Array.isArray(value)) {
- return value.join(',');
- } else if (Object.hasOwn(value, 'toString')) {
- return value.toString();
- } else {
- throw new DOMException(`Invalid selector ${value}`, SYNTAX_ERR);
- }
- }
- let selector = value;
- let index = 0;
- while (index >= 0) {
- // @see https://drafts.csswg.org/selectors/#id-selectors
- index = selector.indexOf('#', index);
- if (index < 0) {
- break;
- }
- const preHash = selector.substring(0, index + 1);
- let postHash = selector.substring(index + 1);
- const codePoint = postHash.codePointAt(0);
- if (codePoint > BIT_FFFF) {
- const str = `\\${codePoint.toString(HEX)} `;
- if (postHash.length === DUO) {
- postHash = str;
- } else {
- postHash = `${str}${postHash.substring(DUO)}`;
- }
- }
- selector = `${preHash}${postHash}`;
- index++;
- }
- return selector
- .replace(/\f|\r\n?/g, '\n')
- .replace(/[\0\uD800-\uDFFF]|\\$/g, U_FFFD)
- .replace(/\x26/g, ':scope');
-};
-
-/**
- * Creates an Abstract Syntax Tree (AST) from a CSS selector string.
- * @param {string} sel - The CSS selector string.
- * @returns {object} The parsed AST object.
- */
-export const parseSelector = sel => {
- const selector = preprocess(sel);
- // invalid selectors
- if (/^$|^\s*>|,\s*$/.test(selector)) {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- try {
- const ast = cssTree.parse(selector, {
- context: 'selectorList',
- parseCustomProperty: true
- });
- return cssTree.toPlainObject(ast);
- } catch (e) {
- const { message } = e;
- if (
- /^(?:"\]"|Attribute selector [()\s,=~^$*|]+) is expected$/.test(
- message
- ) &&
- !selector.endsWith(']')
- ) {
- const index = selector.lastIndexOf('[');
- const selPart = selector.substring(index);
- if (selPart.includes('"')) {
- const quotes = selPart.match(/"/g).length;
- if (quotes % 2) {
- return parseSelector(`${selector}"]`);
- }
- return parseSelector(`${selector}]`);
- }
- return parseSelector(`${selector}]`);
- } else if (message === '")" is expected') {
- // workaround for https://github.com/csstree/csstree/issues/283
- if (REG_EMPTY_PS_FUNC.test(selector)) {
- return parseSelector(`${selector.replaceAll(REG_EMPTY_PS_FUNC, '()')}`);
- } else if (!selector.endsWith(')')) {
- return parseSelector(`${selector})`);
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- }
-};
-
-/**
- * Walks the provided AST to collect selector branches and gather information
- * about its contents.
- * @param {object} ast - The AST to traverse.
- * @returns {{branches: Array<object>, info: object}} An object containing the selector branches and info.
- */
-export const walkAST = (ast = {}) => {
- const branches = new Set();
- const info = {
- hasForgivenPseudoFunc: false,
- hasHasPseudoFunc: false,
- hasLogicalPseudoFunc: false,
- hasNotPseudoFunc: false,
- hasNthChildOfSelector: false,
- hasNestedSelector: false,
- hasStatePseudoClass: false
- };
- const opt = {
- enter(node) {
- switch (node.type) {
- case CLASS_SELECTOR: {
- if (/^-?\d/.test(node.name)) {
- throw new DOMException(
- `Invalid selector .${node.name}`,
- SYNTAX_ERR
- );
- }
- break;
- }
- case ID_SELECTOR: {
- if (/^-?\d/.test(node.name)) {
- throw new DOMException(
- `Invalid selector #${node.name}`,
- SYNTAX_ERR
- );
- }
- break;
- }
- case PS_CLASS_SELECTOR: {
- if (KEYS_LOGICAL.has(node.name)) {
- info.hasNestedSelector = true;
- info.hasLogicalPseudoFunc = true;
- if (node.name === 'has') {
- info.hasHasPseudoFunc = true;
- } else if (node.name === 'not') {
- info.hasNotPseudoFunc = true;
- } else {
- info.hasForgivenPseudoFunc = true;
- }
- } else if (KEYS_PS_CLASS_STATE.has(node.name)) {
- info.hasStatePseudoClass = true;
- } else if (
- KEYS_SHADOW_HOST.has(node.name) &&
- Array.isArray(node.children) &&
- node.children.length
- ) {
- info.hasNestedSelector = true;
- }
- break;
- }
- case PS_ELEMENT_SELECTOR: {
- if (REG_SHADOW_PS_ELEMENT.test(node.name)) {
- info.hasNestedSelector = true;
- }
- break;
- }
- case NTH: {
- if (node.selector) {
- info.hasNestedSelector = true;
- info.hasNthChildOfSelector = true;
- }
- break;
- }
- case SELECTOR: {
- branches.add(node.children);
- break;
- }
- default:
- }
- }
- };
- cssTree.walk(ast, opt);
- if (info.hasNestedSelector === true) {
- cssTree.findAll(ast, (node, item, list) => {
- if (list) {
- if (node.type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(node.name)) {
- const itemList = list.filter(i => {
- const { name, type } = i;
- return type === PS_CLASS_SELECTOR && KEYS_LOGICAL.has(name);
- });
- for (const { children } of itemList) {
- // SelectorList
- for (const { children: grandChildren } of children) {
- // Selector
- for (const { children: greatGrandChildren } of grandChildren) {
- if (branches.has(greatGrandChildren)) {
- branches.delete(greatGrandChildren);
- }
- }
- }
- }
- } else if (
- node.type === PS_CLASS_SELECTOR &&
- KEYS_SHADOW_HOST.has(node.name) &&
- Array.isArray(node.children) &&
- node.children.length
- ) {
- const itemList = list.filter(i => {
- const { children, name, type } = i;
- const res =
- type === PS_CLASS_SELECTOR &&
- KEYS_SHADOW_HOST.has(name) &&
- Array.isArray(children) &&
- children.length;
- return res;
- });
- for (const { children } of itemList) {
- // Selector
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- } else if (
- node.type === PS_ELEMENT_SELECTOR &&
- REG_SHADOW_PS_ELEMENT.test(node.name)
- ) {
- const itemList = list.filter(i => {
- const { name, type } = i;
- const res =
- type === PS_ELEMENT_SELECTOR && REG_SHADOW_PS_ELEMENT.test(name);
- return res;
- });
- for (const { children } of itemList) {
- // Selector
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- } else if (node.type === NTH && node.selector) {
- const itemList = list.filter(i => {
- const { selector, type } = i;
- const res = type === NTH && selector;
- return res;
- });
- for (const { selector } of itemList) {
- const { children } = selector;
- // Selector
- for (const { children: grandChildren } of children) {
- if (branches.has(grandChildren)) {
- branches.delete(grandChildren);
- }
- }
- }
- }
- }
- });
- }
- return {
- info,
- branches: [...branches]
- };
-};
-
-/**
- * Comparison function for sorting AST nodes based on specificity.
- * @param {object} a - The first AST node.
- * @param {object} b - The second AST node.
- * @returns {number} -1, 0 or 1, depending on the sort order.
- */
-export const compareASTNodes = (a, b) => {
- const bitA = AST_SORT_ORDER.get(a.type);
- const bitB = AST_SORT_ORDER.get(b.type);
- if (bitA === bitB) {
- return 0;
- } else if (bitA > bitB) {
- return 1;
- } else {
- return -1;
- }
-};
-
-/**
- * Sorts a collection of AST nodes based on CSS specificity rules.
- * @param {Array<object>} asts - A collection of AST nodes to sort.
- * @returns {Array<object>} A new array containing the sorted AST nodes.
- */
-export const sortAST = asts => {
- const arr = [...asts];
- if (arr.length > 1) {
- arr.sort(compareASTNodes);
- }
- return arr;
-};
-
-/**
- * Parses a type selector's name, which may include a namespace prefix.
- * @param {string} selector - The type selector name (e.g., 'ns|E' or 'E').
- * @returns {{prefix: string, localName: string}} An object with `prefix` and
- * `localName` properties.
- */
-export const parseAstName = selector => {
- let prefix;
- let localName;
- if (selector && typeof selector === 'string') {
- if (selector.indexOf('|') > -1) {
- [prefix, localName] = selector.split('|');
- } else {
- prefix = '*';
- localName = selector;
- }
- } else {
- throw new DOMException(`Invalid selector ${selector}`, SYNTAX_ERR);
- }
- return {
- prefix,
- localName
- };
-};
-
-/* Re-exported from css-tree. */
-export { find as findAST, generate as generateCSS } from 'css-tree';
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/utility.js b/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/utility.js
deleted file mode 100644
index ce141a4..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/src/js/utility.js
+++ /dev/null
@@ -1,1107 +0,0 @@
-/**
- * utility.js
- */
-
-/* import */
-import nwsapi from '@asamuzakjp/nwsapi';
-import bidiFactory from 'bidi-js';
-import * as cssTree from 'css-tree';
-import isCustomElementName from 'is-potential-custom-element-name';
-
-/* constants */
-import {
- ATRULE,
- COMBO,
- COMPOUND_I,
- DESCEND,
- DOCUMENT_FRAGMENT_NODE,
- DOCUMENT_NODE,
- DOCUMENT_POSITION_CONTAINS,
- DOCUMENT_POSITION_PRECEDING,
- ELEMENT_NODE,
- HAS_COMPOUND,
- INPUT_BUTTON,
- INPUT_EDIT,
- INPUT_LTR,
- INPUT_TEXT,
- KEYS_LOGICAL,
- LOGIC_COMPLEX,
- LOGIC_COMPOUND,
- N_TH,
- PSEUDO_CLASS,
- RULE,
- SCOPE,
- SELECTOR_LIST,
- SIBLING,
- TARGET_ALL,
- TARGET_FIRST,
- TEXT_NODE,
- TYPE_FROM,
- TYPE_TO
-} from './constant.js';
-const KEYS_DIR_AUTO = new Set([...INPUT_BUTTON, ...INPUT_TEXT, 'hidden']);
-const KEYS_DIR_LTR = new Set(INPUT_LTR);
-const KEYS_INPUT_EDIT = new Set(INPUT_EDIT);
-const KEYS_NODE_DIR_EXCLUDE = new Set(['bdi', 'script', 'style', 'textarea']);
-const KEYS_NODE_FOCUSABLE = new Set(['button', 'select', 'textarea']);
-const KEYS_NODE_FOCUSABLE_SVG = new Set([
- 'clipPath',
- 'defs',
- 'desc',
- 'linearGradient',
- 'marker',
- 'mask',
- 'metadata',
- 'pattern',
- 'radialGradient',
- 'script',
- 'style',
- 'symbol',
- 'title'
-]);
-const REG_EXCLUDE_BASIC =
- /[|\\]|::|[^\u0021-\u007F\s]|\[\s*[\w$*=^|~-]+(?:(?:"[\w$*=^|~\s'-]+"|'[\w$*=^|~\s"-]+')?(?:\s+[\w$*=^|~-]+)+|"[^"\]]{1,255}|'[^'\]]{1,255})\s*\]|:(?:is|where)\(\s*\)/;
-const REG_COMPLEX = new RegExp(`${COMPOUND_I}${COMBO}${COMPOUND_I}`, 'i');
-const REG_DESCEND = new RegExp(`${COMPOUND_I}${DESCEND}${COMPOUND_I}`, 'i');
-const REG_SIBLING = new RegExp(`${COMPOUND_I}${SIBLING}${COMPOUND_I}`, 'i');
-const REG_LOGIC_COMPLEX = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPLEX})`
-);
-const REG_LOGIC_COMPOUND = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND})`
-);
-const REG_LOGIC_HAS_COMPOUND = new RegExp(
- `:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND}|${HAS_COMPOUND})`
-);
-const REG_END_WITH_HAS = new RegExp(`:${HAS_COMPOUND}$`);
-const REG_WO_LOGICAL = new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH})`);
-const REG_IS_HTML = /^(?:application\/xhtml\+x|text\/ht)ml$/;
-const REG_IS_XML =
- /^(?:application\/(?:[\w\-.]+\+)?|image\/[\w\-.]+\+|text\/)xml$/;
-
-/**
- * Manages state for extracting nested selectors from a CSS AST.
- */
-class SelectorExtractor {
- constructor() {
- this.selectors = [];
- this.isScoped = false;
- }
-
- /**
- * Walker enter function.
- * @param {object} node - The AST node.
- */
- enter(node) {
- switch (node.type) {
- case ATRULE: {
- if (node.name === 'scope') {
- this.isScoped = true;
- }
- break;
- }
- case SCOPE: {
- const { children, type } = node.root;
- const arr = [];
- if (type === SELECTOR_LIST) {
- for (const child of children) {
- const selector = cssTree.generate(child);
- arr.push(selector);
- }
- this.selectors.push(arr);
- }
- break;
- }
- case RULE: {
- const { children, type } = node.prelude;
- const arr = [];
- if (type === SELECTOR_LIST) {
- let hasAmp = false;
- for (const child of children) {
- const selector = cssTree.generate(child);
- if (this.isScoped && !hasAmp) {
- hasAmp = /\x26/.test(selector);
- }
- arr.push(selector);
- }
- if (this.isScoped) {
- if (hasAmp) {
- this.selectors.push(arr);
- /* FIXME:
- } else {
- this.selectors = arr;
- this.isScoped = false;
- */
- }
- } else {
- this.selectors.push(arr);
- }
- }
- }
- }
- }
-
- /**
- * Walker leave function.
- * @param {object} node - The AST node.
- */
- leave(node) {
- if (node.type === ATRULE) {
- if (node.name === 'scope') {
- this.isScoped = false;
- }
- }
- }
-}
-
-/**
- * Get type of an object.
- * @param {object} o - Object to check.
- * @returns {string} - Type of the object.
- */
-export const getType = o =>
- Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);
-
-/**
- * Verify array contents.
- * @param {Array} arr - The array.
- * @param {string} type - Expected type, e.g. 'String'.
- * @throws {TypeError} - Throws if array or its items are of unexpected type.
- * @returns {Array} - The verified array.
- */
-export const verifyArray = (arr, type) => {
- if (!Array.isArray(arr)) {
- throw new TypeError(`Unexpected type ${getType(arr)}`);
- }
- if (typeof type !== 'string') {
- throw new TypeError(`Unexpected type ${getType(type)}`);
- }
- for (const item of arr) {
- if (getType(item) !== type) {
- throw new TypeError(`Unexpected type ${getType(item)}`);
- }
- }
- return arr;
-};
-
-/**
- * Generate a DOMException.
- * @param {string} msg - The error message.
- * @param {string} name - The error name.
- * @param {object} globalObject - The global object (e.g., window).
- * @returns {DOMException} The generated DOMException object.
- */
-export const generateException = (msg, name, globalObject = globalThis) => {
- return new globalObject.DOMException(msg, name);
-};
-
-/**
- * Find a nested :has() pseudo-class.
- * @param {object} leaf - The AST leaf to check.
- * @returns {?object} The leaf if it's :has, otherwise null.
- */
-export const findNestedHas = leaf => {
- return leaf.name === 'has';
-};
-
-/**
- * Find a logical pseudo-class that contains a nested :has().
- * @param {object} leaf - The AST leaf to check.
- * @returns {?object} The leaf if it matches, otherwise null.
- */
-export const findLogicalWithNestedHas = leaf => {
- if (KEYS_LOGICAL.has(leaf.name) && cssTree.find(leaf, findNestedHas)) {
- return leaf;
- }
- return null;
-};
-
-/**
- * Filter a list of nodes based on An+B logic
- * @param {Array.<object>} nodes - array of nodes to filter
- * @param {object} anb - An+B options
- * @param {number} anb.a - a
- * @param {number} anb.b - b
- * @param {boolean} [anb.reverse] - reverse order
- * @returns {Array.<object>} - array of matched nodes
- */
-export const filterNodesByAnB = (nodes, anb) => {
- const { a, b, reverse } = anb;
- const processedNodes = reverse ? [...nodes].reverse() : nodes;
- const l = nodes.length;
- const matched = [];
- if (a === 0) {
- if (b > 0 && b <= l) {
- matched.push(processedNodes[b - 1]);
- }
- return matched;
- }
- let startIndex = b - 1;
- if (a > 0) {
- while (startIndex < 0) {
- startIndex += a;
- }
- for (let i = startIndex; i < l; i += a) {
- matched.push(processedNodes[i]);
- }
- } else if (startIndex >= 0) {
- for (let i = startIndex; i >= 0; i += a) {
- matched.push(processedNodes[i]);
- }
- return matched.reverse();
- }
- return matched;
-};
-
-/**
- * Resolve content document, root node, and check if it's in a shadow DOM.
- * @param {object} node - Document, DocumentFragment, or Element node.
- * @returns {Array.<object|boolean>} - [document, root, isInShadow].
- */
-export const resolveContent = node => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- let document;
- let root;
- let shadow;
- switch (node.nodeType) {
- case DOCUMENT_NODE: {
- document = node;
- root = node;
- break;
- }
- case DOCUMENT_FRAGMENT_NODE: {
- const { host, mode, ownerDocument } = node;
- document = ownerDocument;
- root = node;
- shadow = host && (mode === 'close' || mode === 'open');
- break;
- }
- case ELEMENT_NODE: {
- document = node.ownerDocument;
- let refNode = node;
- while (refNode) {
- const { host, mode, nodeType, parentNode } = refNode;
- if (nodeType === DOCUMENT_FRAGMENT_NODE) {
- shadow = host && (mode === 'close' || mode === 'open');
- break;
- } else if (parentNode) {
- refNode = parentNode;
- } else {
- break;
- }
- }
- root = refNode;
- break;
- }
- default: {
- throw new TypeError(`Unexpected node ${node.nodeName}`);
- }
- }
- return [document, root, !!shadow];
-};
-
-/**
- * Traverse node tree with a TreeWalker.
- * @param {object} node - The target node.
- * @param {object} walker - The TreeWalker instance.
- * @param {boolean} [force] - Traverse only to the next node.
- * @returns {?object} - The current node if found, otherwise null.
- */
-export const traverseNode = (node, walker, force = false) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (!walker) {
- return null;
- }
- let refNode = walker.currentNode;
- if (refNode === node) {
- return refNode;
- } else if (force || refNode.contains(node)) {
- refNode = walker.nextNode();
- while (refNode) {
- if (refNode === node) {
- break;
- }
- refNode = walker.nextNode();
- }
- return refNode;
- } else {
- if (refNode !== walker.root) {
- let bool;
- while (refNode) {
- if (refNode === node) {
- bool = true;
- break;
- } else if (refNode === walker.root || refNode.contains(node)) {
- break;
- }
- refNode = walker.parentNode();
- }
- if (bool) {
- return refNode;
- }
- }
- if (node.nodeType === ELEMENT_NODE) {
- let bool;
- while (refNode) {
- if (refNode === node) {
- bool = true;
- break;
- }
- refNode = walker.nextNode();
- }
- if (bool) {
- return refNode;
- }
- }
- }
- return null;
-};
-
-/**
- * Check if a node is a custom element.
- * @param {object} node - The Element node.
- * @param {object} [opt] - Options.
- * @returns {boolean} - True if it's a custom element.
- */
-export const isCustomElement = (node, opt = {}) => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const { localName, ownerDocument } = node;
- const { formAssociated } = opt;
- const window = ownerDocument.defaultView;
- let elmConstructor;
- const attr = node.getAttribute('is');
- if (attr) {
- elmConstructor =
- isCustomElementName(attr) && window.customElements.get(attr);
- } else {
- elmConstructor =
- isCustomElementName(localName) && window.customElements.get(localName);
- }
- if (elmConstructor) {
- if (formAssociated) {
- return !!elmConstructor.formAssociated;
- }
- return true;
- }
- return false;
-};
-
-/**
- * Get slotted text content.
- * @param {object} node - The Element node (likely a <slot>).
- * @returns {?string} - The text content.
- */
-export const getSlottedTextContent = node => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (typeof node.assignedNodes !== 'function') {
- return null;
- }
- const nodes = node.assignedNodes();
- if (nodes.length) {
- let text = '';
- const l = nodes.length;
- for (let i = 0; i < l; i++) {
- const item = nodes[i];
- text = item.textContent.trim();
- if (text) {
- break;
- }
- }
- return text;
- }
- return node.textContent.trim();
-};
-
-/**
- * Get directionality of a node.
- * @see https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
- * @param {object} node - The Element node.
- * @returns {?string} - 'ltr' or 'rtl'.
- */
-export const getDirectionality = node => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { dir: dirAttr, localName, parentNode } = node;
- const { getEmbeddingLevels } = bidiFactory();
- if (dirAttr === 'ltr' || dirAttr === 'rtl') {
- return dirAttr;
- } else if (dirAttr === 'auto') {
- let text = '';
- switch (localName) {
- case 'input': {
- if (!node.type || KEYS_DIR_AUTO.has(node.type)) {
- text = node.value;
- } else if (KEYS_DIR_LTR.has(node.type)) {
- return 'ltr';
- }
- break;
- }
- case 'slot': {
- text = getSlottedTextContent(node);
- break;
- }
- case 'textarea': {
- text = node.value;
- break;
- }
- default: {
- const items = [].slice.call(node.childNodes);
- for (const item of items) {
- const {
- dir: itemDir,
- localName: itemLocalName,
- nodeType: itemNodeType,
- textContent: itemTextContent
- } = item;
- if (itemNodeType === TEXT_NODE) {
- text = itemTextContent.trim();
- } else if (
- itemNodeType === ELEMENT_NODE &&
- !KEYS_NODE_DIR_EXCLUDE.has(itemLocalName) &&
- (!itemDir || (itemDir !== 'ltr' && itemDir !== 'rtl'))
- ) {
- if (itemLocalName === 'slot') {
- text = getSlottedTextContent(item);
- } else {
- text = itemTextContent.trim();
- }
- }
- if (text) {
- break;
- }
- }
- }
- }
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return 'rtl';
- }
- } else if (parentNode) {
- const { nodeType: parentNodeType } = parentNode;
- if (parentNodeType === ELEMENT_NODE) {
- return getDirectionality(parentNode);
- }
- }
- } else if (localName === 'input' && node.type === 'tel') {
- return 'ltr';
- } else if (localName === 'bdi') {
- const text = node.textContent.trim();
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return 'rtl';
- }
- }
- } else if (parentNode) {
- if (localName === 'slot') {
- const text = getSlottedTextContent(node);
- if (text) {
- const {
- paragraphs: [{ level }]
- } = getEmbeddingLevels(text);
- if (level % 2 === 1) {
- return 'rtl';
- }
- return 'ltr';
- }
- }
- const { nodeType: parentNodeType } = parentNode;
- if (parentNodeType === ELEMENT_NODE) {
- return getDirectionality(parentNode);
- }
- }
- return 'ltr';
-};
-
-/**
- * Traverses up the DOM tree to find the language attribute for a node.
- * It checks for 'lang' in HTML and 'xml:lang' in XML contexts.
- * @param {object} node - The starting element node.
- * @returns {string|null} The language attribute value, or null if not found.
- */
-export const getLanguageAttribute = node => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { contentType } = node.ownerDocument;
- const isHtml = REG_IS_HTML.test(contentType);
- const isXml = REG_IS_XML.test(contentType);
- let isShadow = false;
- // Traverse up from the current node to the root.
- let current = node;
- while (current) {
- // Check if the current node is an element.
- switch (current.nodeType) {
- case ELEMENT_NODE: {
- // Check for and return the language attribute if present.
- if (isHtml && current.hasAttribute('lang')) {
- return current.getAttribute('lang');
- } else if (isXml && current.hasAttribute('xml:lang')) {
- return current.getAttribute('xml:lang');
- }
- break;
- }
- case DOCUMENT_FRAGMENT_NODE: {
- // Continue traversal if the current node is a shadow root.
- if (current.host) {
- isShadow = true;
- }
- break;
- }
- case DOCUMENT_NODE:
- default: {
- // Stop if we reach the root document node.
- return null;
- }
- }
- if (isShadow) {
- current = current.host;
- isShadow = false;
- } else if (current.parentNode) {
- current = current.parentNode;
- } else {
- break;
- }
- }
- // No language attribute was found in the hierarchy.
- return null;
-};
-
-/**
- * Check if content is editable.
- * NOTE: Not implemented in jsdom https://github.com/jsdom/jsdom/issues/1670
- * @param {object} node - The Element node.
- * @returns {boolean} - True if content is editable.
- */
-export const isContentEditable = node => {
- if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (node.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (typeof node.isContentEditable === 'boolean') {
- return node.isContentEditable;
- } else if (node.ownerDocument.designMode === 'on') {
- return true;
- } else {
- let attr;
- if (node.hasAttribute('contenteditable')) {
- attr = node.getAttribute('contenteditable');
- } else {
- attr = 'inherit';
- }
- switch (attr) {
- case '':
- case 'true': {
- return true;
- }
- case 'plaintext-only': {
- // FIXME:
- // @see https://github.com/w3c/editing/issues/470
- // @see https://github.com/whatwg/html/issues/10651
- return true;
- }
- case 'false': {
- return false;
- }
- default: {
- if (node?.parentNode?.nodeType === ELEMENT_NODE) {
- return isContentEditable(node.parentNode);
- }
- return false;
- }
- }
- }
-};
-
-/**
- * Check if a node is visible.
- * @param {object} node - The Element node.
- * @returns {boolean} - True if the node is visible.
- */
-export const isVisible = node => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const window = node.ownerDocument.defaultView;
- const { display, visibility } = window.getComputedStyle(node);
- if (display !== 'none' && visibility === 'visible') {
- return true;
- }
- return false;
-};
-
-/**
- * Check if focus is visible on the node.
- * @param {object} node - The Element node.
- * @returns {boolean} - True if focus is visible.
- */
-export const isFocusVisible = node => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const { localName, type } = node;
- switch (localName) {
- case 'input': {
- if (!type || KEYS_INPUT_EDIT.has(type)) {
- return true;
- }
- return false;
- }
- case 'textarea': {
- return true;
- }
- default: {
- return isContentEditable(node);
- }
- }
-};
-
-/**
- * Check if an area is focusable.
- * @param {object} node - The Element node.
- * @returns {boolean} - True if the area is focusable.
- */
-export const isFocusableArea = node => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (!node.isConnected) {
- return false;
- }
- const window = node.ownerDocument.defaultView;
- if (node instanceof window.HTMLElement) {
- if (Number.isInteger(parseInt(node.getAttribute('tabindex')))) {
- return true;
- }
- if (isContentEditable(node)) {
- return true;
- }
- const { localName, parentNode } = node;
- switch (localName) {
- case 'a': {
- if (node.href || node.hasAttribute('href')) {
- return true;
- }
- return false;
- }
- case 'iframe': {
- return true;
- }
- case 'input': {
- if (
- node.disabled ||
- node.hasAttribute('disabled') ||
- node.hidden ||
- node.hasAttribute('hidden')
- ) {
- return false;
- }
- return true;
- }
- case 'summary': {
- if (parentNode.localName === 'details') {
- let child = parentNode.firstElementChild;
- let bool = false;
- while (child) {
- if (child.localName === 'summary') {
- bool = child === node;
- break;
- }
- child = child.nextElementSibling;
- }
- return bool;
- }
- return false;
- }
- default: {
- if (
- KEYS_NODE_FOCUSABLE.has(localName) &&
- !(node.disabled || node.hasAttribute('disabled'))
- ) {
- return true;
- }
- }
- }
- } else if (node instanceof window.SVGElement) {
- if (Number.isInteger(parseInt(node.getAttributeNS(null, 'tabindex')))) {
- const ns = 'http://www.w3.org/2000/svg';
- let bool;
- let refNode = node;
- while (refNode.namespaceURI === ns) {
- bool = KEYS_NODE_FOCUSABLE_SVG.has(refNode.localName);
- if (bool) {
- break;
- }
- if (refNode?.parentNode?.namespaceURI === ns) {
- refNode = refNode.parentNode;
- } else {
- break;
- }
- }
- if (bool) {
- return false;
- }
- return true;
- }
- if (
- node.localName === 'a' &&
- (node.href || node.hasAttributeNS(null, 'href'))
- ) {
- return true;
- }
- }
- return false;
-};
-
-/**
- * Check if a node is focusable.
- * NOTE: Not applied, needs fix in jsdom itself.
- * @see https://github.com/whatwg/html/pull/8392
- * @see https://phabricator.services.mozilla.com/D156219
- * @see https://github.com/jsdom/jsdom/issues/3029
- * @see https://github.com/jsdom/jsdom/issues/3464
- * @param {object} node - The Element node.
- * @returns {boolean} - True if the node is focusable.
- */
-export const isFocusable = node => {
- if (node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const window = node.ownerDocument.defaultView;
- let refNode = node;
- let res = true;
- while (refNode) {
- if (refNode.disabled || refNode.hasAttribute('disabled')) {
- res = false;
- break;
- }
- if (refNode.hidden || refNode.hasAttribute('hidden')) {
- res = false;
- }
- const { contentVisibility, display, visibility } =
- window.getComputedStyle(refNode);
- if (
- display === 'none' ||
- visibility !== 'visible' ||
- (contentVisibility === 'hidden' && refNode !== node)
- ) {
- res = false;
- } else {
- res = true;
- }
- if (res && refNode?.parentNode?.nodeType === ELEMENT_NODE) {
- refNode = refNode.parentNode;
- } else {
- break;
- }
- }
- return res;
-};
-
-/**
- * Get namespace URI.
- * @param {string} ns - The namespace prefix.
- * @param {object} node - The Element node.
- * @returns {?string} - The namespace URI.
- */
-export const getNamespaceURI = (ns, node) => {
- if (typeof ns !== 'string') {
- throw new TypeError(`Unexpected type ${getType(ns)}`);
- } else if (!node?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(node)}`);
- }
- if (!ns || node.nodeType !== ELEMENT_NODE) {
- return null;
- }
- const { attributes } = node;
- let res;
- for (const attr of attributes) {
- const { name, namespaceURI, prefix, value } = attr;
- if (name === `xmlns:${ns}`) {
- res = value;
- } else if (prefix === ns) {
- res = namespaceURI;
- }
- if (res) {
- break;
- }
- }
- return res ?? null;
-};
-
-/**
- * Check if a namespace is declared.
- * @param {string} ns - The namespace.
- * @param {object} node - The Element node.
- * @returns {boolean} - True if the namespace is declared.
- */
-export const isNamespaceDeclared = (ns = '', node = {}) => {
- if (!ns || typeof ns !== 'string' || node?.nodeType !== ELEMENT_NODE) {
- return false;
- }
- if (node.lookupNamespaceURI(ns)) {
- return true;
- }
- const root = node.ownerDocument.documentElement;
- let parent = node;
- let res;
- while (parent) {
- res = getNamespaceURI(ns, parent);
- if (res || parent === root) {
- break;
- }
- parent = parent.parentNode;
- }
- return !!res;
-};
-
-/**
- * Check if nodeA precedes and/or contains nodeB.
- * @param {object} nodeA - The first Element node.
- * @param {object} nodeB - The second Element node.
- * @returns {boolean} - True if nodeA precedes nodeB.
- */
-export const isPreceding = (nodeA, nodeB) => {
- if (!nodeA?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(nodeA)}`);
- } else if (!nodeB?.nodeType) {
- throw new TypeError(`Unexpected type ${getType(nodeB)}`);
- }
- if (nodeA.nodeType !== ELEMENT_NODE || nodeB.nodeType !== ELEMENT_NODE) {
- return false;
- }
- const posBit = nodeB.compareDocumentPosition(nodeA);
- const res =
- posBit & DOCUMENT_POSITION_PRECEDING || posBit & DOCUMENT_POSITION_CONTAINS;
- return !!res;
-};
-
-/**
- * Comparison function for sorting nodes based on document position.
- * @param {object} a - The first node.
- * @param {object} b - The second node.
- * @returns {number} - Sort order.
- */
-export const compareNodes = (a, b) => {
- if (isPreceding(b, a)) {
- return 1;
- }
- return -1;
-};
-
-/**
- * Sort a collection of nodes.
- * @param {Array.<object>|Set.<object>} nodes - Collection of nodes.
- * @returns {Array.<object>} - Collection of sorted nodes.
- */
-export const sortNodes = (nodes = []) => {
- const arr = [...nodes];
- if (arr.length > 1) {
- arr.sort(compareNodes);
- }
- return arr;
-};
-
-/**
- * Concat an array of nested selectors into an equivalent single selector.
- * @param {Array.<Array.<string>>} selectors - [parents, children, ...].
- * @returns {string} - The concatenated selector.
- */
-export const concatNestedSelectors = selectors => {
- if (!Array.isArray(selectors)) {
- throw new TypeError(`Unexpected type ${getType(selectors)}`);
- }
- let selector = '';
- if (selectors.length) {
- const revSelectors = selectors.toReversed();
- let child = verifyArray(revSelectors.shift(), 'String');
- if (child.length === 1) {
- [child] = child;
- }
- while (revSelectors.length) {
- const parentArr = verifyArray(revSelectors.shift(), 'String');
- if (!parentArr.length) {
- continue;
- }
- let parent;
- if (parentArr.length === 1) {
- [parent] = parentArr;
- if (!/^[>~+]/.test(parent) && /[\s>~+]/.test(parent)) {
- parent = `:is(${parent})`;
- }
- } else {
- parent = `:is(${parentArr.join(', ')})`;
- }
- if (selector.includes('\x26')) {
- selector = selector.replace(/\x26/g, parent);
- }
- if (Array.isArray(child)) {
- const items = [];
- for (let item of child) {
- if (item.includes('\x26')) {
- if (/^[>~+]/.test(item)) {
- item = `${parent} ${item.replace(/\x26/g, parent)} ${selector}`;
- } else {
- item = `${item.replace(/\x26/g, parent)} ${selector}`;
- }
- } else {
- item = `${parent} ${item} ${selector}`;
- }
- items.push(item.trim());
- }
- selector = items.join(', ');
- } else if (revSelectors.length) {
- selector = `${child} ${selector}`;
- } else {
- if (child.includes('\x26')) {
- if (/^[>~+]/.test(child)) {
- selector = `${parent} ${child.replace(/\x26/g, parent)} ${selector}`;
- } else {
- selector = `${child.replace(/\x26/g, parent)} ${selector}`;
- }
- } else {
- selector = `${parent} ${child} ${selector}`;
- }
- }
- selector = selector.trim();
- if (revSelectors.length) {
- child = parentArr.length > 1 ? parentArr : parent;
- } else {
- break;
- }
- }
- selector = selector.replace(/\x26/g, ':scope').trim();
- }
- return selector;
-};
-
-/**
- * Extract nested selectors from CSSRule.cssText.
- * @param {string} css - CSSRule.cssText.
- * @returns {Array.<Array.<string>>} - Array of nested selectors.
- */
-export const extractNestedSelectors = css => {
- const ast = cssTree.parse(css, {
- context: 'rule'
- });
- const extractor = new SelectorExtractor();
- cssTree.walk(ast, {
- enter: extractor.enter.bind(extractor),
- leave: extractor.leave.bind(extractor)
- });
- return extractor.selectors;
-};
-
-/**
- * Initialize nwsapi.
- * @param {object} window - The Window object.
- * @param {object} document - The Document object.
- * @returns {object} - The nwsapi instance.
- */
-export const initNwsapi = (window, document) => {
- if (!window?.DOMException) {
- throw new TypeError(`Unexpected global object ${getType(window)}`);
- }
- if (document?.nodeType !== DOCUMENT_NODE) {
- document = window.document;
- }
- const nw = nwsapi({
- document,
- DOMException: window.DOMException
- });
- nw.configure({
- LOGERRORS: false
- });
- return nw;
-};
-
-/**
- * Filter a selector for use with nwsapi.
- * @param {string} selector - The selector string.
- * @param {string} target - The target type.
- * @returns {boolean} - True if the selector is valid for nwsapi.
- */
-export const filterSelector = (selector, target) => {
- const isQuerySelectorType = target === TARGET_FIRST || target === TARGET_ALL;
- if (
- !selector ||
- typeof selector !== 'string' ||
- /null|undefined/.test(selector)
- ) {
- return false;
- }
- // Exclude missing close square bracket.
- if (selector.includes('[')) {
- const index = selector.lastIndexOf('[');
- const sel = selector.substring(index);
- if (sel.indexOf(']') < 0) {
- return false;
- }
- }
- // Exclude various complex or unsupported selectors.
- // - selectors containing '/'
- // - namespaced selectors
- // - escaped selectors
- // - pseudo-element selectors
- // - selectors containing non-ASCII
- // - selectors containing control character other than whitespace
- // - attribute selectors with case flag, e.g. [attr i]
- // - attribute selectors with unclosed quotes
- // - empty :is() or :where()
- if (selector.includes('/') || REG_EXCLUDE_BASIC.test(selector)) {
- return false;
- }
- // Include pseudo-classes that are known to work correctly.
- if (selector.includes(':')) {
- let complex = false;
- if (target !== isQuerySelectorType) {
- complex = REG_COMPLEX.test(selector);
- }
- if (
- isQuerySelectorType &&
- REG_DESCEND.test(selector) &&
- !REG_SIBLING.test(selector)
- ) {
- return false;
- } else if (!isQuerySelectorType && /:has\(/.test(selector)) {
- if (!complex || REG_LOGIC_HAS_COMPOUND.test(selector)) {
- return false;
- }
- return REG_END_WITH_HAS.test(selector);
- } else if (/:(?:is|not)\(/.test(selector)) {
- if (complex) {
- return !REG_LOGIC_COMPLEX.test(selector);
- } else {
- return !REG_LOGIC_COMPOUND.test(selector);
- }
- } else {
- return !REG_WO_LOGICAL.test(selector);
- }
- }
- return true;
-};
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/index.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/index.d.ts
deleted file mode 100644
index d6ebaa4..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/index.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export class DOMSelector {
- constructor(window: Window, document: Document, opt?: object);
- clear: () => void;
- check: (selector: string, node: Element, opt?: object) => CheckResult;
- matches: (selector: string, node: Element, opt?: object) => boolean;
- closest: (selector: string, node: Element, opt?: object) => Element | null;
- querySelector: (selector: string, node: Document | DocumentFragment | Element, opt?: object) => Element | null;
- querySelectorAll: (selector: string, node: Document | DocumentFragment | Element, opt?: object) => Array<Element>;
- #private;
-}
-export type CheckResult = {
- match: boolean;
- pseudoElement: string | null;
-};
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/constant.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/constant.d.ts
deleted file mode 100644
index f999a78..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/constant.d.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-export const ATRULE: "Atrule";
-export const ATTR_SELECTOR: "AttributeSelector";
-export const CLASS_SELECTOR: "ClassSelector";
-export const COMBINATOR: "Combinator";
-export const IDENT: "Identifier";
-export const ID_SELECTOR: "IdSelector";
-export const NOT_SUPPORTED_ERR: "NotSupportedError";
-export const NTH: "Nth";
-export const OPERATOR: "Operator";
-export const PS_CLASS_SELECTOR: "PseudoClassSelector";
-export const PS_ELEMENT_SELECTOR: "PseudoElementSelector";
-export const RULE: "Rule";
-export const SCOPE: "Scope";
-export const SELECTOR: "Selector";
-export const SELECTOR_LIST: "SelectorList";
-export const STRING: "String";
-export const SYNTAX_ERR: "SyntaxError";
-export const TARGET_ALL: "all";
-export const TARGET_FIRST: "first";
-export const TARGET_LINEAL: "lineal";
-export const TARGET_SELF: "self";
-export const TYPE_SELECTOR: "TypeSelector";
-export const BIT_01: 1;
-export const BIT_02: 2;
-export const BIT_04: 4;
-export const BIT_08: 8;
-export const BIT_16: 16;
-export const BIT_32: 32;
-export const BIT_FFFF: 65535;
-export const DUO: 2;
-export const HEX: 16;
-export const TYPE_FROM: 8;
-export const TYPE_TO: -1;
-export const ELEMENT_NODE: 1;
-export const TEXT_NODE: 3;
-export const DOCUMENT_NODE: 9;
-export const DOCUMENT_FRAGMENT_NODE: 11;
-export const DOCUMENT_POSITION_PRECEDING: 2;
-export const DOCUMENT_POSITION_CONTAINS: 8;
-export const DOCUMENT_POSITION_CONTAINED_BY: 16;
-export const SHOW_ALL: 4294967295;
-export const SHOW_CONTAINER: 1281;
-export const SHOW_DOCUMENT: 256;
-export const SHOW_DOCUMENT_FRAGMENT: 1024;
-export const SHOW_ELEMENT: 1;
-export const ALPHA_NUM: "[A-Z\\d]+";
-export const CHILD_IDX: "(?:first|last|only)-(?:child|of-type)";
-export const DIGIT: "(?:0|[1-9]\\d*)";
-export const LANG_PART: "(?:-[A-Z\\d]+)*";
-export const PSEUDO_CLASS: "(?:any-)?link|(?:first|last|only)-(?:child|of-type)|checked|empty|indeterminate|read-(?:only|write)|target";
-export const ANB: "[+-]?(?:(?:0|[1-9]\\d*)n?|n)|(?:[+-]?(?:0|[1-9]\\d*))?n\\s*[+-]\\s*(?:0|[1-9]\\d*)";
-export const COMBO: "\\s?[\\s>~+]\\s?";
-export const DESCEND: "\\s?[\\s>]\\s?";
-export const SIBLING: "\\s?[+~]\\s?";
-export const LOGIC_IS: ":is\\(\\s*[^)]+\\s*\\)";
-export const N_TH: "nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|[+-]?(?:(?:0|[1-9]\\d*)n?|n)|(?:[+-]?(?:0|[1-9]\\d*))?n\\s*[+-]\\s*(?:0|[1-9]\\d*))\\s*\\)";
-export const SUB_TYPE: "\\[[^|\\]]+\\]|[#.:][\\w-]+";
-export const SUB_TYPE_WO_PSEUDO: "\\[[^|\\]]+\\]|[#.][\\w-]+";
-export const TAG_TYPE: "\\*|[A-Za-z][\\w-]*";
-export const TAG_TYPE_I: "\\*|[A-Z][\\w-]*";
-export const COMPOUND: "(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+)+)";
-export const COMPOUND_L: "(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+)";
-export const COMPOUND_I: "(?:\\*|[A-Z][\\w-]*|(?:\\*|[A-Z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+)+)";
-export const COMPOUND_WO_PSEUDO: "(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.][\\w-]+)+)";
-export const COMPLEX: "(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+)+)(?:\\s?[\\s>~+]\\s?(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+)+))*";
-export const COMPLEX_L: "(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+)(?:\\s?[\\s>~+]\\s?(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+))*";
-export const HAS_COMPOUND: "has\\([\\s>]?\\s*(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.][\\w-]+)+)\\s*\\)";
-export const LOGIC_COMPOUND: "(?:is|not)\\(\\s*(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+)(?:\\s*,\\s*(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+))*\\s*\\)";
-export const LOGIC_COMPLEX: "(?:is|not)\\(\\s*(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+)(?:\\s?[\\s>~+]\\s?(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+))*(?:\\s*,\\s*(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+)(?:\\s?[\\s>~+]\\s?(?:\\*|[A-Za-z][\\w-]*|(?:\\*|[A-Za-z][\\w-]*)?(?:\\[[^|\\]]+\\]|[#.:][\\w-]+|:is\\(\\s*[^)]+\\s*\\))+))*)*\\s*\\)";
-export const FORM_PARTS: readonly string[];
-export const INPUT_BUTTON: readonly string[];
-export const INPUT_CHECK: readonly string[];
-export const INPUT_DATE: readonly string[];
-export const INPUT_TEXT: readonly string[];
-export const INPUT_EDIT: readonly string[];
-export const INPUT_LTR: readonly string[];
-export const KEYS_LOGICAL: Set<string>;
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/finder.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/finder.d.ts
deleted file mode 100644
index d88572f..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/finder.d.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-export class Finder {
- constructor(window: object);
- onError: (e: Error, opt?: {
- noexcept?: boolean;
- }) => void;
- setup: (selector: string, node: object, opt?: {
- check?: boolean;
- noexcept?: boolean;
- warn?: boolean;
- }) => object;
- clearResults: (all?: boolean) => void;
- private _handleFocusEvent;
- private _handleKeyboardEvent;
- private _handleMouseEvent;
- private _registerEventListeners;
- private _processSelectorBranches;
- private _correspond;
- private _createTreeWalker;
- private _getSelectorBranches;
- private _getFilteredChildren;
- private _collectNthChild;
- private _collectNthOfType;
- private _matchAnPlusB;
- private _matchHasPseudoFunc;
- private _evaluateHasPseudo;
- private _matchLogicalPseudoFunc;
- private _matchPseudoClassSelector;
- private _evaluateHostPseudo;
- private _evaluateHostContextPseudo;
- private _matchShadowHostPseudoClass;
- private _matchSelectorForElement;
- private _matchSelectorForShadowRoot;
- private _matchSelector;
- private _matchLeaves;
- private _traverseAllDescendants;
- private _findDescendantNodes;
- private _matchDescendantCombinator;
- private _matchChildCombinator;
- private _matchAdjacentSiblingCombinator;
- private _matchGeneralSiblingCombinator;
- private _matchCombinator;
- private _traverseAndCollectNodes;
- private _findPrecede;
- private _findNodeWalker;
- private _matchSelf;
- private _findLineal;
- private _findEntryNodesForPseudoElement;
- private _findEntryNodesForId;
- private _findEntryNodesForClass;
- private _findEntryNodesForType;
- private _findEntryNodesForOther;
- private _findEntryNodes;
- private _determineTraversalStrategy;
- private _processPendingItems;
- private _collectNodes;
- private _getCombinedNodes;
- private _matchNodeNext;
- private _matchNodePrev;
- private _processComplexBranchAll;
- private _processComplexBranchFirst;
- find: (targetType: string) => Set<object>;
- #private;
-}
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/matcher.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/matcher.d.ts
deleted file mode 100644
index e1966b0..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/matcher.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export function matchPseudoElementSelector(astName: string, astType: string, opt?: {
- forgive?: boolean;
- warn?: boolean;
-}): void;
-export function matchDirectionPseudoClass(ast: object, node: object): boolean;
-export function matchLanguagePseudoClass(ast: object, node: object): boolean;
-export function matchDisabledPseudoClass(astName: string, node: object): boolean;
-export function matchReadOnlyPseudoClass(astName: string, node: object): boolean;
-export function matchAttributeSelector(ast: object, node: object, opt?: {
- check?: boolean;
- forgive?: boolean;
-}): boolean;
-export function matchTypeSelector(ast: object, node: object, opt?: {
- check?: boolean;
- forgive?: boolean;
-}): boolean;
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/parser.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/parser.d.ts
deleted file mode 100644
index f0b6da4..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/parser.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export function unescapeSelector(selector?: string): string;
-export function preprocess(value: string): string;
-export function parseSelector(sel: string): object;
-export function walkAST(ast?: object): {
- branches: Array<object>;
- info: object;
-};
-export function compareASTNodes(a: object, b: object): number;
-export function sortAST(asts: Array<object>): Array<object>;
-export function parseAstName(selector: string): {
- prefix: string;
- localName: string;
-};
-export { find as findAST, generate as generateCSS } from "css-tree";
diff --git a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/utility.d.ts b/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/utility.d.ts
deleted file mode 100644
index fe62759..0000000
--- a/vanilla/node_modules/@asamuzakjp/dom-selector/types/js/utility.d.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-export function getType(o: object): string;
-export function verifyArray(arr: any[], type: string): any[];
-export function generateException(msg: string, name: string, globalObject?: object): DOMException;
-export function findNestedHas(leaf: object): object | null;
-export function findLogicalWithNestedHas(leaf: object): object | null;
-export function filterNodesByAnB(nodes: Array<object>, anb: {
- a: number;
- b: number;
- reverse?: boolean;
-}): Array<object>;
-export function resolveContent(node: object): Array<object | boolean>;
-export function traverseNode(node: object, walker: object, force?: boolean): object | null;
-export function isCustomElement(node: object, opt?: object): boolean;
-export function getSlottedTextContent(node: object): string | null;
-export function getDirectionality(node: object): string | null;
-export function getLanguageAttribute(node: object): string | null;
-export function isContentEditable(node: object): boolean;
-export function isVisible(node: object): boolean;
-export function isFocusVisible(node: object): boolean;
-export function isFocusableArea(node: object): boolean;
-export function isFocusable(node: object): boolean;
-export function getNamespaceURI(ns: string, node: object): string | null;
-export function isNamespaceDeclared(ns?: string, node?: object): boolean;
-export function isPreceding(nodeA: object, nodeB: object): boolean;
-export function compareNodes(a: object, b: object): number;
-export function sortNodes(nodes?: Array<object> | Set<object>): Array<object>;
-export function concatNestedSelectors(selectors: Array<Array<string>>): string;
-export function extractNestedSelectors(css: string): Array<Array<string>>;
-export function initNwsapi(window: object, document: object): object;
-export function filterSelector(selector: string, target: string): boolean;