@whitesev/utils 2.8.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +176 -176
  2. package/dist/index.amd.js +893 -874
  3. package/dist/index.amd.js.map +1 -1
  4. package/dist/index.cjs.js +893 -874
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.esm.js +893 -874
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.iife.js +893 -874
  9. package/dist/index.iife.js.map +1 -1
  10. package/dist/index.system.js +893 -874
  11. package/dist/index.system.js.map +1 -1
  12. package/dist/index.umd.js +893 -874
  13. package/dist/index.umd.js.map +1 -1
  14. package/dist/types/src/CommonUtil.d.ts +59 -59
  15. package/dist/types/src/DOMUtils.d.ts +1 -1
  16. package/dist/types/src/Dictionary.d.ts +1 -1
  17. package/dist/types/src/Httpx.d.ts +2 -2
  18. package/dist/types/src/Progress.d.ts +0 -4
  19. package/dist/types/src/TryCatch.d.ts +2 -2
  20. package/dist/types/src/Utils.d.ts +365 -365
  21. package/dist/types/src/UtilsGMCookie.d.ts +2 -2
  22. package/dist/types/src/UtilsGMMenu.d.ts +1 -1
  23. package/dist/types/src/indexedDB.d.ts +3 -3
  24. package/dist/types/src/types/Event.d.ts +188 -188
  25. package/dist/types/src/types/Httpx.d.ts +1344 -1343
  26. package/dist/types/src/types/Log.d.ts +19 -19
  27. package/dist/types/src/types/Progress.d.ts +20 -20
  28. package/dist/types/src/types/React.d.ts +119 -119
  29. package/dist/types/src/types/TryCatch.d.ts +9 -9
  30. package/dist/types/src/types/UtilsGMCookie.d.ts +93 -93
  31. package/dist/types/src/types/UtilsGMMenu.d.ts +77 -77
  32. package/dist/types/src/types/Vue2.d.ts +166 -166
  33. package/dist/types/src/types/WindowApi.d.ts +14 -14
  34. package/dist/types/src/types/ajaxHooker.d.ts +151 -151
  35. package/dist/types/src/types/env.d.ts +7 -2
  36. package/dist/types/src/types/global.d.ts +31 -31
  37. package/package.json +16 -7
  38. package/src/ColorConversion.ts +105 -106
  39. package/src/CommonUtil.ts +280 -279
  40. package/src/DOMUtils.ts +251 -272
  41. package/src/Dictionary.ts +153 -154
  42. package/src/GBKEncoder.ts +108 -112
  43. package/src/Hooks.ts +73 -81
  44. package/src/Httpx.ts +1457 -1466
  45. package/src/LockFunction.ts +62 -62
  46. package/src/Log.ts +258 -259
  47. package/src/ModuleRaid.js +1 -0
  48. package/src/Progress.ts +108 -114
  49. package/src/TryCatch.ts +86 -86
  50. package/src/Utils.ts +4772 -4825
  51. package/src/UtilsCommon.ts +14 -14
  52. package/src/UtilsGMCookie.ts +254 -261
  53. package/src/UtilsGMMenu.ts +445 -454
  54. package/src/Vue.ts +233 -229
  55. package/src/WindowApi.ts +59 -59
  56. package/src/ajaxHooker/ajaxHooker.js +1 -0
  57. package/src/indexedDB.ts +497 -502
  58. package/src/types/Event.d.ts +188 -188
  59. package/src/types/Httpx.d.ts +1344 -1343
  60. package/src/types/Log.d.ts +19 -19
  61. package/src/types/Progress.d.ts +20 -20
  62. package/src/types/React.d.ts +119 -119
  63. package/src/types/TryCatch.d.ts +9 -9
  64. package/src/types/UtilsGMCookie.d.ts +93 -93
  65. package/src/types/UtilsGMMenu.d.ts +77 -77
  66. package/src/types/Vue2.d.ts +166 -166
  67. package/src/types/WindowApi.d.ts +14 -14
  68. package/src/types/ajaxHooker.d.ts +151 -151
  69. package/src/types/env.d.ts +7 -2
  70. package/src/types/global.d.ts +31 -31
package/src/DOMUtils.ts CHANGED
@@ -1,272 +1,251 @@
1
- import type { WindowApiOption } from "./types/WindowApi";
2
- import { WindowApi } from "./WindowApi";
3
-
4
- class DOMUtils {
5
- private windowApi: typeof WindowApi.prototype;
6
- constructor(option?: WindowApiOption) {
7
- this.windowApi = new WindowApi(option);
8
- }
9
- /**
10
- * 选择器,可使用以下的额外语法
11
- *
12
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
13
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
14
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
15
- * @param selector 选择器
16
- * @param parent 指定父元素
17
- * @example
18
- * DOMUtils.selector("div:contains('测试')")
19
- * > div.xxx
20
- * @example
21
- * DOMUtils.selector("div:empty")
22
- * > div.xxx
23
- * @example
24
- * DOMUtils.selector("div:regexp('^xxxx$')")
25
- * > div.xxx
26
- */
27
- selector<K extends keyof HTMLElementTagNameMap>(
28
- selector: K,
29
- parent?: Element | Document | DocumentFragment | ShadowRoot
30
- ): HTMLElementTagNameMap[K] | undefined;
31
- selector<E extends Element = Element>(
32
- selector: string,
33
- parent?: Element | Document | DocumentFragment | ShadowRoot
34
- ): E | undefined;
35
- selector<E extends Element = Element>(
36
- selector: string,
37
- parent?: Element | Document | DocumentFragment | ShadowRoot
38
- ) {
39
- return this.selectorAll<E>(selector, parent)[0];
40
- }
41
- /**
42
- * 选择器,可使用以下的额外语法
43
- *
44
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
45
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
46
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
47
- * @param selector 选择器
48
- * @param parent 指定父元素
49
- * @example
50
- * DOMUtils.selectorAll("div:contains('测试')")
51
- * > [div.xxx]
52
- * @example
53
- * DOMUtils.selectorAll("div:empty")
54
- * > [div.xxx]
55
- * @example
56
- * DOMUtils.selectorAll("div:regexp('^xxxx$')")
57
- * > [div.xxx]
58
- * @example
59
- * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
60
- * > [div.xxx]
61
- */
62
- selectorAll<K extends keyof HTMLElementTagNameMap>(
63
- selector: K,
64
- parent?: Element | Document | DocumentFragment | ShadowRoot
65
- ): HTMLElementTagNameMap[K][];
66
- selectorAll<E extends Element = Element>(
67
- selector: string,
68
- parent?: Element | Document | DocumentFragment | ShadowRoot
69
- ): E[];
70
- selectorAll<E extends Element = Element>(
71
- selector: string,
72
- parent?: Element | Document | DocumentFragment | ShadowRoot
73
- ) {
74
- const context = this;
75
- parent = parent || context.windowApi.document;
76
- selector = selector.trim();
77
- if (selector.match(/[^\s]{1}:empty$/gi)) {
78
- // empty 语法
79
- selector = selector.replace(/:empty$/gi, "");
80
- return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
81
- return $ele?.innerHTML?.trim() === "";
82
- });
83
- } else if (
84
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
85
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
86
- ) {
87
- // contains 语法
88
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
89
- let text = textMatch![2];
90
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
91
- return Array.from(parent.querySelectorAll<HTMLElement>(selector)).filter(($ele) => {
92
- return ($ele?.textContent || $ele?.innerText)?.includes(text);
93
- });
94
- } else if (
95
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
96
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
97
- ) {
98
- // regexp 语法
99
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
100
- let pattern = textMatch![2];
101
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
102
- let flags = "";
103
- if (flagMatch) {
104
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
105
- flags = flagMatch[3];
106
- }
107
- let regexp = new RegExp(pattern, flags);
108
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
109
- return Array.from(parent.querySelectorAll<HTMLElement>(selector)).filter(($ele) => {
110
- return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
111
- });
112
- } else {
113
- // 普通语法
114
- return Array.from(parent.querySelectorAll<E>(selector));
115
- }
116
- }
117
- /**
118
- * 匹配元素,可使用以下的额外语法
119
- *
120
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
121
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
122
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
123
- * @param $el 元素
124
- * @param selector 选择器
125
- * @example
126
- * DOMUtils.matches("div:contains('测试')")
127
- * > true
128
- * @example
129
- * DOMUtils.matches("div:empty")
130
- * > true
131
- * @example
132
- * DOMUtils.matches("div:regexp('^xxxx$')")
133
- * > true
134
- * @example
135
- * DOMUtils.matches("div:regexp(/^xxx/ig)")
136
- * > false
137
- */
138
- matches($el: HTMLElement | Element | null | undefined, selector: string): boolean {
139
- selector = selector.trim();
140
- if ($el == null) {
141
- return false;
142
- }
143
-
144
- if (selector.match(/[^\s]{1}:empty$/gi)) {
145
- // empty 语法
146
- selector = selector.replace(/:empty$/gi, "");
147
- return $el.matches(selector) && $el?.innerHTML?.trim() === "";
148
- } else if (
149
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
150
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
151
- ) {
152
- // contains 语法
153
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
154
- let text = textMatch![2];
155
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
156
- let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
157
- if (typeof content !== "string") {
158
- content = "";
159
- }
160
- return $el.matches(selector) && content?.includes(text);
161
- } else if (
162
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
163
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
164
- ) {
165
- // regexp 语法
166
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
167
- let pattern = textMatch![2];
168
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
169
- let flags = "";
170
- if (flagMatch) {
171
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
172
- flags = flagMatch[3];
173
- }
174
- let regexp = new RegExp(pattern, flags);
175
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
176
- let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
177
- if (typeof content !== "string") {
178
- content = "";
179
- }
180
- return $el.matches(selector) && Boolean(content?.match(regexp));
181
- } else {
182
- // 普通语法
183
- return $el.matches(selector);
184
- }
185
- }
186
- /**
187
- * 根据选择器获取上层元素,可使用以下的额外语法
188
- *
189
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
190
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
191
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
192
- * @param $el 元素
193
- * @param selector 选择器
194
- * @example
195
- * DOMUtils.closest("div:contains('测试')")
196
- * > div.xxx
197
- * @example
198
- * DOMUtils.closest("div:empty")
199
- * > div.xxx
200
- * @example
201
- * DOMUtils.closest("div:regexp('^xxxx$')")
202
- * > div.xxxx
203
- * @example
204
- * DOMUtils.closest("div:regexp(/^xxx/ig)")
205
- * > null
206
- */
207
- closest<K extends keyof HTMLElementTagNameMap>(
208
- $el: HTMLElement | Element,
209
- selector: string
210
- ): HTMLElementTagNameMap[K] | null;
211
- closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null;
212
- closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null {
213
- selector = selector.trim();
214
-
215
- if (selector.match(/[^\s]{1}:empty$/gi)) {
216
- // empty 语法
217
- selector = selector.replace(/:empty$/gi, "");
218
- let $closest = $el?.closest<E>(selector);
219
- if ($closest && $closest?.innerHTML?.trim() === "") {
220
- return $closest;
221
- }
222
- return null;
223
- } else if (
224
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
225
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
226
- ) {
227
- // contains 语法
228
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
229
- let text = textMatch![2];
230
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
231
- let $closest = $el?.closest<E>(selector);
232
- if ($closest) {
233
- let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
234
- if (typeof content === "string" && content.includes(text)) {
235
- return $closest;
236
- }
237
- }
238
- return null;
239
- } else if (
240
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
241
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
242
- ) {
243
- // regexp 语法
244
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
245
- let pattern = textMatch![2];
246
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
247
- let flags = "";
248
- if (flagMatch) {
249
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
250
- flags = flagMatch[3];
251
- }
252
- let regexp = new RegExp(pattern, flags);
253
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
254
- let $closest = $el?.closest<E>(selector);
255
- if ($closest) {
256
- let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
257
- if (typeof content === "string" && content.match(regexp)) {
258
- return $closest;
259
- }
260
- }
261
- return null;
262
- } else {
263
- // 普通语法
264
- let $closest = $el?.closest<E>(selector);
265
- return $closest;
266
- }
267
- }
268
- }
269
-
270
- let domUtils = new DOMUtils();
271
-
272
- export { domUtils };
1
+ import type { WindowApiOption } from "./types/WindowApi";
2
+ import { WindowApi } from "./WindowApi";
3
+
4
+ class DOMUtils {
5
+ private windowApi: typeof WindowApi.prototype;
6
+ constructor(option?: WindowApiOption) {
7
+ this.windowApi = new WindowApi(option);
8
+ }
9
+ /**
10
+ * 选择器,可使用以下的额外语法
11
+ *
12
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
13
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
14
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
15
+ * @param selector 选择器
16
+ * @param parent 指定父元素
17
+ * @example
18
+ * DOMUtils.selector("div:contains('测试')")
19
+ * > div.xxx
20
+ * @example
21
+ * DOMUtils.selector("div:empty")
22
+ * > div.xxx
23
+ * @example
24
+ * DOMUtils.selector("div:regexp('^xxxx$')")
25
+ * > div.xxx
26
+ */
27
+ selector<K extends keyof HTMLElementTagNameMap>(
28
+ selector: K,
29
+ parent?: Element | Document | DocumentFragment | ShadowRoot
30
+ ): HTMLElementTagNameMap[K] | undefined;
31
+ selector<E extends Element = Element>(
32
+ selector: string,
33
+ parent?: Element | Document | DocumentFragment | ShadowRoot
34
+ ): E | undefined;
35
+ selector<E extends Element = Element>(selector: string, parent?: Element | Document | DocumentFragment | ShadowRoot) {
36
+ return this.selectorAll<E>(selector, parent)[0];
37
+ }
38
+ /**
39
+ * 选择器,可使用以下的额外语法
40
+ *
41
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
42
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
43
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
44
+ * @param selector 选择器
45
+ * @param parent 指定父元素
46
+ * @example
47
+ * DOMUtils.selectorAll("div:contains('测试')")
48
+ * > [div.xxx]
49
+ * @example
50
+ * DOMUtils.selectorAll("div:empty")
51
+ * > [div.xxx]
52
+ * @example
53
+ * DOMUtils.selectorAll("div:regexp('^xxxx$')")
54
+ * > [div.xxx]
55
+ * @example
56
+ * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
57
+ * > [div.xxx]
58
+ */
59
+ selectorAll<K extends keyof HTMLElementTagNameMap>(
60
+ selector: K,
61
+ parent?: Element | Document | DocumentFragment | ShadowRoot
62
+ ): HTMLElementTagNameMap[K][];
63
+ selectorAll<E extends Element = Element>(
64
+ selector: string,
65
+ parent?: Element | Document | DocumentFragment | ShadowRoot
66
+ ): E[];
67
+ selectorAll<E extends Element = Element>(
68
+ selector: string,
69
+ parent?: Element | Document | DocumentFragment | ShadowRoot
70
+ ) {
71
+ const context = this;
72
+ parent = parent || context.windowApi.document;
73
+ selector = selector.trim();
74
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
75
+ // empty 语法
76
+ selector = selector.replace(/:empty$/gi, "");
77
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
78
+ return $ele?.innerHTML?.trim() === "";
79
+ });
80
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
81
+ // contains 语法
82
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
83
+ const text = textMatch![2];
84
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
85
+ return Array.from(parent.querySelectorAll<HTMLElement>(selector)).filter(($ele) => {
86
+ return ($ele?.textContent || $ele?.innerText)?.includes(text);
87
+ });
88
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
89
+ // regexp 语法
90
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
91
+ let pattern = textMatch![2];
92
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
93
+ let flags = "";
94
+ if (flagMatch) {
95
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
96
+ flags = flagMatch[3];
97
+ }
98
+ const regexp = new RegExp(pattern, flags);
99
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
100
+ return Array.from(parent.querySelectorAll<HTMLElement>(selector)).filter(($ele) => {
101
+ return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
102
+ });
103
+ } else {
104
+ // 普通语法
105
+ return Array.from(parent.querySelectorAll<E>(selector));
106
+ }
107
+ }
108
+ /**
109
+ * 匹配元素,可使用以下的额外语法
110
+ *
111
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
112
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
113
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
114
+ * @param $el 元素
115
+ * @param selector 选择器
116
+ * @example
117
+ * DOMUtils.matches("div:contains('测试')")
118
+ * > true
119
+ * @example
120
+ * DOMUtils.matches("div:empty")
121
+ * > true
122
+ * @example
123
+ * DOMUtils.matches("div:regexp('^xxxx$')")
124
+ * > true
125
+ * @example
126
+ * DOMUtils.matches("div:regexp(/^xxx/ig)")
127
+ * > false
128
+ */
129
+ matches($el: HTMLElement | Element | null | undefined, selector: string): boolean {
130
+ selector = selector.trim();
131
+ if ($el == null) {
132
+ return false;
133
+ }
134
+
135
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
136
+ // empty 语法
137
+ selector = selector.replace(/:empty$/gi, "");
138
+ return $el.matches(selector) && $el?.innerHTML?.trim() === "";
139
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
140
+ // contains 语法
141
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
142
+ const text = textMatch![2];
143
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
144
+ let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
145
+ if (typeof content !== "string") {
146
+ content = "";
147
+ }
148
+ return $el.matches(selector) && content?.includes(text);
149
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
150
+ // regexp 语法
151
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
152
+ let pattern = textMatch![2];
153
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
154
+ let flags = "";
155
+ if (flagMatch) {
156
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
157
+ flags = flagMatch[3];
158
+ }
159
+ const regexp = new RegExp(pattern, flags);
160
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
161
+ let content = $el?.textContent || (<HTMLElement>$el)?.innerText;
162
+ if (typeof content !== "string") {
163
+ content = "";
164
+ }
165
+ return $el.matches(selector) && Boolean(content?.match(regexp));
166
+ } else {
167
+ // 普通语法
168
+ return $el.matches(selector);
169
+ }
170
+ }
171
+ /**
172
+ * 根据选择器获取上层元素,可使用以下的额外语法
173
+ *
174
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
175
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
176
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
177
+ * @param $el 元素
178
+ * @param selector 选择器
179
+ * @example
180
+ * DOMUtils.closest("div:contains('测试')")
181
+ * > div.xxx
182
+ * @example
183
+ * DOMUtils.closest("div:empty")
184
+ * > div.xxx
185
+ * @example
186
+ * DOMUtils.closest("div:regexp('^xxxx$')")
187
+ * > div.xxxx
188
+ * @example
189
+ * DOMUtils.closest("div:regexp(/^xxx/ig)")
190
+ * > null
191
+ */
192
+ closest<K extends keyof HTMLElementTagNameMap>(
193
+ $el: HTMLElement | Element,
194
+ selector: string
195
+ ): HTMLElementTagNameMap[K] | null;
196
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null;
197
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null {
198
+ selector = selector.trim();
199
+
200
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
201
+ // empty 语法
202
+ selector = selector.replace(/:empty$/gi, "");
203
+ const $closest = $el?.closest<E>(selector);
204
+ if ($closest && $closest?.innerHTML?.trim() === "") {
205
+ return $closest;
206
+ }
207
+ return null;
208
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
209
+ // contains 语法
210
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
211
+ const text = textMatch![2];
212
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
213
+ const $closest = $el?.closest<E>(selector);
214
+ if ($closest) {
215
+ const content = $el?.textContent || (<HTMLElement>$el)?.innerText;
216
+ if (typeof content === "string" && content.includes(text)) {
217
+ return $closest;
218
+ }
219
+ }
220
+ return null;
221
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
222
+ // regexp 语法
223
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
224
+ let pattern = textMatch![2];
225
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
226
+ let flags = "";
227
+ if (flagMatch) {
228
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
229
+ flags = flagMatch[3];
230
+ }
231
+ const regexp = new RegExp(pattern, flags);
232
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
233
+ const $closest = $el?.closest<E>(selector);
234
+ if ($closest) {
235
+ const content = $el?.textContent || (<HTMLElement>$el)?.innerText;
236
+ if (typeof content === "string" && content.match(regexp)) {
237
+ return $closest;
238
+ }
239
+ }
240
+ return null;
241
+ } else {
242
+ // 普通语法
243
+ const $closest = $el?.closest<E>(selector);
244
+ return $closest;
245
+ }
246
+ }
247
+ }
248
+
249
+ const domUtils = new DOMUtils();
250
+
251
+ export { domUtils };